footprint-explainable-ui 0.25.0 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/flowchart.cjs +290 -120
- package/dist/flowchart.cjs.map +1 -1
- package/dist/flowchart.d.cts +87 -13
- package/dist/flowchart.d.ts +87 -13
- package/dist/flowchart.js +226 -56
- package/dist/flowchart.js.map +1 -1
- package/dist/index.cjs +305 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -16
- package/dist/index.d.ts +15 -16
- package/dist/index.js +233 -10
- package/dist/index.js.map +1 -1
- package/package.json +31 -12
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/theme/ThemeProvider.tsx","../src/theme/tokens.ts","../src/theme/styles.ts","../src/theme/presets.ts","../src/theme/useDarkModeTokens.ts","../src/components/MemoryInspector/MemoryInspector.tsx","../src/components/NarrativeLog/NarrativeLog.tsx","../src/components/NarrativeTrace/NarrativeTrace.tsx","../src/components/GanttTimeline/GanttTimeline.tsx","../src/components/SnapshotPanel/SnapshotPanel.tsx","../src/components/ScopeDiff/ScopeDiff.tsx","../src/components/ResultPanel/ResultPanel.tsx","../src/components/StageDetailPanel/StageDetailPanel.tsx","../src/components/TimeTravelControls/TimeTravelControls.tsx","../src/components/ExplainableShell/ExplainableShell.tsx","../src/utils/narrativeSync.ts","../src/adapters/fromRuntimeSnapshot.ts","../src/components/MemoryPanel/MemoryPanel.tsx","../src/components/NarrativePanel/NarrativePanel.tsx","../src/components/StoryNarrative/StoryNarrative.tsx","../src/components/FlowchartView/SubflowTree.tsx","../src/components/FlowchartView/SubflowBreadcrumb.tsx","../src/components/FlowchartView/TracedFlow.tsx","../src/components/FlowchartView/_internal/dagreTraceLayout.ts","../src/components/FlowchartView/createTraceRuntimeOverlay.ts","../src/components/StageNode/StageNode.tsx","../src/components/FlowchartView/_internal/subflowDrill.ts","../src/components/FlowchartView/_internal/overlayProjection.ts","../src/components/FlowchartView/_internal/useSubflowDrill.ts","../src/components/FlowchartView/_internal/useChartAutoRefit.ts","../src/components/FlowchartView/SubflowBreadcrumbBar.tsx","../src/components/GroupContainerNode/GroupContainerNode.tsx","../src/components/LoopBackEdge/LoopBackEdge.tsx","../src/components/FlowchartView/_internal/loopRouting.ts","../src/components/FlowchartView/_internal/groupLayout.ts","../src/components/SmartStepEdge/SmartStepEdge.tsx","../src/components/FlowchartView/_internal/stepRouting.ts","../src/components/InspectorPanel/InspectorPanel.tsx","../src/components/DataTracePanel/DataTracePanel.tsx","../src/components/InsightPanel/InsightPanel.tsx","../src/components/CompactTimeline/CompactTimeline.tsx","../src/components/TraceViewer/TraceViewer.tsx"],"sourcesContent":["// Types\nexport type { StageSnapshot, Size, BaseComponentProps, NarrativeEntry } from \"./types\";\n\n// Theme\nexport { FootprintTheme, useFootprintTheme } from \"./theme\";\nexport { tokensToCSSVars, defaultTokens, rawDefaults } from \"./theme\";\nexport { themePresets, coolDark, coolLight, warmDark, warmLight } from \"./theme\";\nexport { useDarkModeTokens } from \"./theme\";\nexport type { ThemeTokens, ThemePresetName, DarkModeTokensOptions } from \"./theme\";\n\n// Core components (zero external deps beyond React)\nexport { MemoryInspector } from \"./components/MemoryInspector\";\nexport type { MemoryInspectorProps } from \"./components/MemoryInspector\";\n\nexport { NarrativeLog } from \"./components/NarrativeLog\";\nexport type { NarrativeLogProps } from \"./components/NarrativeLog\";\n\nexport { NarrativeTrace } from \"./components/NarrativeTrace\";\nexport type { NarrativeTraceProps } from \"./components/NarrativeTrace\";\n\nexport { GanttTimeline } from \"./components/GanttTimeline\";\nexport type { GanttTimelineProps } from \"./components/GanttTimeline\";\n\nexport { SnapshotPanel } from \"./components/SnapshotPanel\";\nexport type { SnapshotPanelProps } from \"./components/SnapshotPanel\";\n\nexport { ScopeDiff } from \"./components/ScopeDiff\";\nexport type { ScopeDiffProps, DiffEntry } from \"./components/ScopeDiff\";\n\nexport { ResultPanel } from \"./components/ResultPanel\";\nexport type { ResultPanelProps } from \"./components/ResultPanel\";\n\nexport { StageDetailPanel } from \"./components/StageDetailPanel\";\nexport type { StageDetailPanelProps, StageDetailMode, MemoryChange } from \"./components/StageDetailPanel\";\n\nexport { TimeTravelControls } from \"./components/TimeTravelControls\";\nexport type { TimeTravelControlsProps } from \"./components/TimeTravelControls\";\n\nexport { ExplainableShell } from \"./components/ExplainableShell\";\nexport type { ExplainableShellProps, RuntimeSnapshotInput, RecorderView, ShellTab, PanelLabels, DefaultExpanded } from \"./components/ExplainableShell\";\n\n// Drop-in viewer for `agentfootprint.exportTrace()` JSON\nexport { TraceViewer } from \"./components/TraceViewer/TraceViewer\";\nexport type { TraceViewerProps, AgentfootprintTrace, TraceParseError } from \"./components/TraceViewer/TraceViewer\";\n\n// Composite panels (memory + narrative — self-contained right-panel views)\nexport { MemoryPanel } from \"./components/MemoryPanel\";\nexport type { MemoryPanelProps } from \"./components/MemoryPanel\";\n\nexport { NarrativePanel } from \"./components/NarrativePanel\";\nexport type { NarrativePanelProps } from \"./components/NarrativePanel\";\n\nexport { StoryNarrative } from \"./components/StoryNarrative\";\nexport type { StoryNarrativeProps } from \"./components/StoryNarrative\";\n\n// Subflow manifest tree (no ReactFlow dependency — works standalone)\nexport { SubflowTree } from \"./components/FlowchartView/SubflowTree\";\nexport type { SubflowTreeProps, SubflowTreeEntry } from \"./components/FlowchartView/SubflowTree\";\n\n// Adapters\nexport { toVisualizationSnapshots, createSnapshots, subflowResultToSnapshots, mergeWritePatch } from \"./adapters/fromRuntimeSnapshot\";\nexport type { NarrativeEntry as AdapterNarrativeEntry } from \"./adapters/fromRuntimeSnapshot\";\n\n// Utilities — narrative sync, subflow extraction\nexport { buildEntryRangeIndex, computeRevealedEntryCount, extractSubflowNarrative } from \"./utils/narrativeSync\";\nexport type { EntryRangeIndex } from \"./utils/narrativeSync\";\n\n// ── New components (v2 layout) ──────────────────────────────────────\n\n// Inspector: State + Data Trace\nexport { InspectorPanel } from \"./components/InspectorPanel/InspectorPanel\";\nexport type { InspectorPanelProps } from \"./components/InspectorPanel/InspectorPanel\";\n\n// Data Trace: backward causal chain visualization\nexport { DataTracePanel } from \"./components/DataTracePanel/DataTracePanel\";\nexport type { DataTracePanelProps, CausalFrame } from \"./components/DataTracePanel/DataTracePanel\";\n\n// Insights: recorder tabs / grid (was \"Recorders\")\nexport { InsightPanel } from \"./components/InsightPanel/InsightPanel\";\nexport type { InsightPanelProps, InsightConfig } from \"./components/InsightPanel/InsightPanel\";\n\n// Compact Timeline: dot line → Gantt toggle\nexport { CompactTimeline } from \"./components/CompactTimeline/CompactTimeline\";\nexport type { CompactTimelineProps } from \"./components/CompactTimeline/CompactTimeline\";\n","import { createContext, useContext } from \"react\";\nimport type { ThemeTokens } from \"./tokens\";\nimport { tokensToCSSVars } from \"./tokens\";\n\nconst ThemeContext = createContext<ThemeTokens>({});\n\nexport function useFootprintTheme(): ThemeTokens {\n return useContext(ThemeContext);\n}\n\ninterface FootprintThemeProps {\n tokens?: ThemeTokens;\n children: React.ReactNode;\n}\n\n/**\n * Optional theme provider — wraps children with CSS custom properties.\n * Consumers can also just set --fp-* CSS variables directly.\n *\n * Wrapper div uses `display: contents` so it's invisible to the\n * parent's layout (flex / grid / block). This matters because themed\n * children often need to fill a parent (flex:1 / height:100% /\n * grid cells), and a regular block `<div>` here would break that\n * chain — descendants would resolve to 0 height when the parent is\n * flex-column or a grid cell with minmax(0, 1fr). `display: contents`\n * removes the box from the render tree while keeping the DOM intact,\n * so CSS custom property inheritance (which follows the DOM) still\n * flows to children.\n *\n * Trade-off: `display: contents` elements are removed from the\n * accessibility tree in some older browser versions. Our wrapper has\n * no semantic role, so this is fine.\n */\nexport function FootprintTheme({ tokens = {}, children }: FootprintThemeProps) {\n const cssVars = tokensToCSSVars(tokens);\n\n return (\n <ThemeContext.Provider value={tokens}>\n <div\n style={{ ...(cssVars as React.CSSProperties), display: \"contents\" }}\n className=\"fp-theme-root\"\n >\n {children}\n </div>\n </ThemeContext.Provider>\n );\n}\n","/** Default theme tokens — consumers override via CSS variables or ThemeProvider. */\nexport interface ThemeTokens {\n colors?: {\n primary?: string;\n success?: string;\n error?: string;\n warning?: string;\n bgPrimary?: string;\n bgSecondary?: string;\n bgTertiary?: string;\n textPrimary?: string;\n textSecondary?: string;\n textMuted?: string;\n border?: string;\n };\n radius?: string;\n fontFamily?: {\n sans?: string;\n mono?: string;\n };\n}\n\n/** Maps ThemeTokens to CSS custom property assignments. */\nexport function tokensToCSSVars(tokens: ThemeTokens): Record<string, string> {\n const vars: Record<string, string> = {};\n if (tokens.colors) {\n const c = tokens.colors;\n if (c.primary) vars[\"--fp-color-primary\"] = c.primary;\n if (c.success) vars[\"--fp-color-success\"] = c.success;\n if (c.error) vars[\"--fp-color-error\"] = c.error;\n if (c.warning) vars[\"--fp-color-warning\"] = c.warning;\n if (c.bgPrimary) vars[\"--fp-bg-primary\"] = c.bgPrimary;\n if (c.bgSecondary) vars[\"--fp-bg-secondary\"] = c.bgSecondary;\n if (c.bgTertiary) vars[\"--fp-bg-tertiary\"] = c.bgTertiary;\n if (c.textPrimary) vars[\"--fp-text-primary\"] = c.textPrimary;\n if (c.textSecondary) vars[\"--fp-text-secondary\"] = c.textSecondary;\n if (c.textMuted) vars[\"--fp-text-muted\"] = c.textMuted;\n if (c.border) vars[\"--fp-border\"] = c.border;\n }\n if (tokens.radius) vars[\"--fp-radius\"] = tokens.radius;\n if (tokens.fontFamily?.sans) vars[\"--fp-font-sans\"] = tokens.fontFamily.sans;\n if (tokens.fontFamily?.mono) vars[\"--fp-font-mono\"] = tokens.fontFamily.mono;\n return vars;\n}\n\n/** Raw fallback values — used by tokensToCSSVars() and anywhere a real color is needed. */\nexport const rawDefaults = {\n colors: {\n primary: \"#6366f1\",\n success: \"#22c55e\",\n error: \"#ef4444\",\n warning: \"#f59e0b\",\n bgPrimary: \"#0f172a\",\n bgSecondary: \"#1e293b\",\n bgTertiary: \"#334155\",\n textPrimary: \"#f8fafc\",\n textSecondary: \"#94a3b8\",\n textMuted: \"#64748b\",\n border: \"#334155\",\n },\n radius: \"8px\",\n fontFamily: {\n sans: \"Inter, system-ui, -apple-system, sans-serif\",\n mono: \"'JetBrains Mono', 'Fira Code', monospace\",\n },\n} as const;\n\n/** Default dark theme values with CSS variable references (consumers can override via CSS). */\nexport const defaultTokens: Required<{\n [K in keyof ThemeTokens]-?: Required<ThemeTokens[K]>;\n}> = {\n colors: {\n primary: `var(--fp-color-primary, ${rawDefaults.colors.primary})`,\n success: `var(--fp-color-success, ${rawDefaults.colors.success})`,\n error: `var(--fp-color-error, ${rawDefaults.colors.error})`,\n warning: `var(--fp-color-warning, ${rawDefaults.colors.warning})`,\n bgPrimary: `var(--fp-bg-primary, ${rawDefaults.colors.bgPrimary})`,\n bgSecondary: `var(--fp-bg-secondary, ${rawDefaults.colors.bgSecondary})`,\n bgTertiary: `var(--fp-bg-tertiary, ${rawDefaults.colors.bgTertiary})`,\n textPrimary: `var(--fp-text-primary, ${rawDefaults.colors.textPrimary})`,\n textSecondary: `var(--fp-text-secondary, ${rawDefaults.colors.textSecondary})`,\n textMuted: `var(--fp-text-muted, ${rawDefaults.colors.textMuted})`,\n border: `var(--fp-border, ${rawDefaults.colors.border})`,\n },\n radius: `var(--fp-radius, ${rawDefaults.radius})`,\n fontFamily: {\n sans: `var(--fp-font-sans, ${rawDefaults.fontFamily.sans})`,\n mono: `var(--fp-font-mono, ${rawDefaults.fontFamily.mono})`,\n },\n};\n","import type { Size } from \"../types\";\n\n/**\n * Helper to resolve a CSS variable with a fallback.\n * Usage: v(\"--fp-color-primary\", \"#6366f1\")\n */\nexport function v(varName: string, fallback: string): string {\n return `var(${varName}, ${fallback})`;\n}\n\n/** Shorthand for common theme variables */\nexport const theme = {\n primary: v(\"--fp-color-primary\", \"#6366f1\"),\n success: v(\"--fp-color-success\", \"#22c55e\"),\n error: v(\"--fp-color-error\", \"#ef4444\"),\n warning: v(\"--fp-color-warning\", \"#f59e0b\"),\n bgPrimary: v(\"--fp-bg-primary\", \"#0f172a\"),\n bgSecondary: v(\"--fp-bg-secondary\", \"#1e293b\"),\n bgTertiary: v(\"--fp-bg-tertiary\", \"#334155\"),\n textPrimary: v(\"--fp-text-primary\", \"#f8fafc\"),\n textSecondary: v(\"--fp-text-secondary\", \"#94a3b8\"),\n textMuted: v(\"--fp-text-muted\", \"#64748b\"),\n border: v(\"--fp-border\", \"#334155\"),\n radius: v(\"--fp-radius\", \"8px\"),\n fontSans: v(\"--fp-font-sans\", \"Inter, system-ui, -apple-system, sans-serif\"),\n fontMono: v(\"--fp-font-mono\", \"'JetBrains Mono', 'Fira Code', monospace\"),\n} as const;\n\n/** Font sizes per size variant */\nexport const fontSize: Record<Size, { label: number; body: number; small: number }> = {\n compact: { label: 10, body: 11, small: 9 },\n default: { label: 11, body: 12, small: 10 },\n detailed: { label: 12, body: 13, small: 11 },\n};\n\n/** Padding per size variant */\nexport const padding: Record<Size, number> = {\n compact: 8,\n default: 12,\n detailed: 16,\n};\n","import type { ThemeTokens } from \"./tokens\";\n\n/** Cool dark theme (the library default) */\nexport const coolDark: ThemeTokens = {\n colors: {\n primary: \"#6366f1\",\n success: \"#22c55e\",\n error: \"#ef4444\",\n warning: \"#f59e0b\",\n bgPrimary: \"#0f172a\",\n bgSecondary: \"#1e293b\",\n bgTertiary: \"#334155\",\n textPrimary: \"#f8fafc\",\n textSecondary: \"#94a3b8\",\n textMuted: \"#64748b\",\n border: \"#334155\",\n },\n radius: \"8px\",\n fontFamily: {\n sans: \"Inter, system-ui, -apple-system, sans-serif\",\n mono: \"'JetBrains Mono', 'Fira Code', monospace\",\n },\n};\n\n/** Warm dark theme — charcoal-purple palette */\nexport const warmDark: ThemeTokens = {\n colors: {\n primary: \"#7c6cf0\",\n success: \"#3dd68c\",\n error: \"#f06292\",\n warning: \"#ffb74d\",\n bgPrimary: \"#1e1a2e\",\n bgSecondary: \"#2a2540\",\n bgTertiary: \"#3a3455\",\n textPrimary: \"#f0e6d6\",\n textSecondary: \"#a89eb4\",\n textMuted: \"#6e6480\",\n border: \"#3a3455\",\n },\n radius: \"8px\",\n fontFamily: {\n sans: \"Inter, system-ui, -apple-system, sans-serif\",\n mono: \"'JetBrains Mono', 'Fira Code', monospace\",\n },\n};\n\n/** Warm light theme — cream/peach palette */\nexport const warmLight: ThemeTokens = {\n colors: {\n primary: \"#7c6cf0\",\n success: \"#22a860\",\n error: \"#d94452\",\n warning: \"#e09030\",\n bgPrimary: \"#faf5ef\",\n bgSecondary: \"#f0e6d6\",\n bgTertiary: \"#e4d5c3\",\n textPrimary: \"#2e2938\",\n textSecondary: \"#5c5468\",\n textMuted: \"#8a7e96\",\n border: \"#d6c8b4\",\n },\n radius: \"8px\",\n fontFamily: {\n sans: \"Inter, system-ui, -apple-system, sans-serif\",\n mono: \"'JetBrains Mono', 'Fira Code', monospace\",\n },\n};\n\n/** Cool light theme — neutral grays, matches Tailwind zinc palette */\nexport const coolLight: ThemeTokens = {\n colors: {\n primary: \"#6366f1\",\n success: \"#22c55e\",\n error: \"#ef4444\",\n warning: \"#f59e0b\",\n bgPrimary: \"#ffffff\",\n bgSecondary: \"#f9fafb\",\n bgTertiary: \"#e5e7eb\",\n textPrimary: \"#18181b\",\n textSecondary: \"#52525b\",\n textMuted: \"#a1a1aa\",\n border: \"#e5e7eb\",\n },\n radius: \"8px\",\n fontFamily: {\n sans: \"Inter, system-ui, -apple-system, sans-serif\",\n mono: \"'JetBrains Mono', 'Fira Code', monospace\",\n },\n};\n\n/** All built-in theme presets */\nexport const themePresets = {\n coolDark,\n coolLight,\n warmDark,\n warmLight,\n} as const;\n\nexport type ThemePresetName = keyof typeof themePresets;\n","/**\n * useDarkModeTokens — Auto-bridge between CSS class-based dark mode and FootprintTheme.\n *\n * Watches for a `.dark` class on <html> (Tailwind convention) and returns\n * the appropriate ThemeTokens preset. Pairs with FootprintTheme:\n *\n * import { FootprintTheme, useDarkModeTokens } from 'footprint-explainable-ui';\n *\n * function MyApp() {\n * const tokens = useDarkModeTokens();\n * return (\n * <FootprintTheme tokens={tokens}>\n * <NarrativeTrace ... />\n * </FootprintTheme>\n * );\n * }\n *\n * Consumers can override the light/dark presets:\n *\n * const tokens = useDarkModeTokens({ light: warmLight, dark: warmDark });\n */\n\nimport { useState, useEffect } from \"react\";\nimport type { ThemeTokens } from \"./tokens\";\nimport { coolDark } from \"./presets\";\nimport { coolLight } from \"./presets\";\n\nexport interface DarkModeTokensOptions {\n /** Tokens to use in light mode. Defaults to coolLight. */\n light?: ThemeTokens;\n /** Tokens to use in dark mode. Defaults to coolDark. */\n dark?: ThemeTokens;\n /** CSS selector to watch for dark mode. Defaults to checking .dark on documentElement. */\n selector?: string;\n}\n\nexport function useDarkModeTokens(options?: DarkModeTokensOptions): ThemeTokens {\n const lightTokens = options?.light ?? coolLight;\n const darkTokens = options?.dark ?? coolDark;\n\n const [isDark, setIsDark] = useState(\n () => document.documentElement.classList.contains(options?.selector ?? \"dark\"),\n );\n\n useEffect(() => {\n const cls = options?.selector ?? \"dark\";\n const obs = new MutationObserver(() => {\n setIsDark(document.documentElement.classList.contains(cls));\n });\n obs.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => obs.disconnect();\n }, [options?.selector]);\n\n return isDark ? darkTokens : lightTokens;\n}\n","import { useMemo, useRef } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\nexport interface MemoryInspectorProps extends BaseComponentProps {\n /** Single memory object or snapshots (will accumulate up to selectedIndex) */\n data?: Record<string, unknown>;\n /** When using snapshots mode, pass these instead of data */\n snapshots?: StageSnapshot[];\n /** Index to accumulate up to (for time-travel) */\n selectedIndex?: number;\n /** Show data types alongside values */\n showTypes?: boolean;\n /** Highlight keys that are new at this step */\n highlightNew?: boolean;\n}\n\n/** Cache for incremental memory accumulation — avoids O(n) rebuild on every slider scrub. */\ninterface MemoryCache {\n snapshots: StageSnapshot[];\n index: number;\n accumulated: Record<string, unknown>;\n}\n\n/**\n * Displays pipeline memory state as formatted JSON.\n * Supports both static (data prop) and time-travel (snapshots + selectedIndex) modes.\n */\nexport function MemoryInspector({\n data,\n snapshots,\n selectedIndex = 0,\n showTypes = false,\n highlightNew = true,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: MemoryInspectorProps) {\n // Incremental cache: accumulate forward from last known index instead of rebuilding from 0\n const cacheRef = useRef<MemoryCache | null>(null);\n\n const { memory, newKeys } = useMemo(() => {\n if (data) {\n return { memory: data, newKeys: new Set<string>() };\n }\n if (!snapshots || snapshots.length === 0) {\n return { memory: {}, newKeys: new Set<string>() };\n }\n\n const safeIdx = Math.min(selectedIndex, snapshots.length - 1);\n let merged: Record<string, unknown>;\n const cache = cacheRef.current;\n\n if (cache && cache.snapshots === snapshots && cache.index <= safeIdx) {\n // Forward scrub: extend from cached state\n merged = { ...cache.accumulated };\n for (let i = cache.index + 1; i <= safeIdx; i++) {\n Object.assign(merged, snapshots[i]?.memory);\n }\n } else {\n // Backward scrub or new snapshots: rebuild from scratch\n merged = {};\n for (let i = 0; i <= safeIdx; i++) {\n Object.assign(merged, snapshots[i]?.memory);\n }\n }\n\n // Update cache\n cacheRef.current = { snapshots, index: safeIdx, accumulated: merged };\n\n const nk = new Set<string>();\n if (highlightNew && safeIdx > 0) {\n // Previous state is cache at safeIdx-1, or rebuild if needed\n let prev: Record<string, unknown>;\n if (cache && cache.snapshots === snapshots && cache.index === safeIdx - 1) {\n prev = cache.accumulated;\n } else {\n prev = {};\n for (let i = 0; i < safeIdx; i++) {\n Object.assign(prev, snapshots[i]?.memory);\n }\n }\n const current = snapshots[safeIdx]?.memory ?? {};\n for (const k of Object.keys(current)) {\n if (!(k in prev)) nk.add(k);\n }\n } else if (highlightNew && safeIdx === 0 && snapshots[0]) {\n for (const k of Object.keys(snapshots[0].memory)) nk.add(k);\n }\n\n return { memory: merged, newKeys: nk };\n }, [data, snapshots, selectedIndex, highlightNew]);\n\n const entries = Object.entries(memory);\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"memory-inspector\" role=\"region\" aria-label=\"Memory state\">\n <div data-fp=\"memory-label\">Memory State</div>\n <pre data-fp=\"memory-json\">\n <code>{JSON.stringify(memory, null, 2)}</code>\n </pre>\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n padding: pad,\n fontFamily: theme.fontSans,\n ...style,\n }}\n data-fp=\"memory-inspector\"\n role=\"region\"\n aria-label=\"Memory state\"\n >\n <span\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n }}\n >\n Memory State\n </span>\n <div\n style={{\n marginTop: 8,\n background: theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: theme.radius,\n padding: `${pad}px ${pad + 4}px`,\n fontFamily: theme.fontMono,\n fontSize: fs.body,\n lineHeight: 1.8,\n }}\n >\n <span style={{ color: theme.textMuted }}>{\"{\"}</span>\n {entries.length === 0 && (\n <div\n style={{\n paddingLeft: 16,\n color: theme.textMuted,\n fontStyle: \"italic\",\n }}\n >\n {\"// empty\"}\n </div>\n )}\n {entries.map(([key, value], i) => {\n const isNew = newKeys.has(key);\n const isLast = i === entries.length - 1;\n return (\n <div\n key={key}\n style={{\n paddingLeft: 16,\n background: isNew\n ? `color-mix(in srgb, ${theme.success} 10%, transparent)`\n : \"transparent\",\n borderRadius: 4,\n marginLeft: -4,\n marginRight: -4,\n paddingRight: 4,\n }}\n >\n <span style={{ color: theme.primary }}>"{key}"</span>\n <span style={{ color: theme.textMuted }}>: </span>\n <span style={{ color: theme.success }}>\n {formatValue(value)}\n </span>\n {showTypes && (\n <span\n style={{\n color: theme.textMuted,\n fontSize: fs.small,\n marginLeft: 8,\n opacity: 0.6,\n }}\n >\n ({typeof value})\n </span>\n )}\n {!isLast && <span style={{ color: theme.textMuted }}>,</span>}\n </div>\n );\n })}\n <span style={{ color: theme.textMuted }}>{\"}\"}</span>\n </div>\n </div>\n );\n}\n\nfunction formatValue(value: unknown): string {\n if (typeof value === \"string\") return `\"${value}\"`;\n if (typeof value === \"object\" && value !== null) return JSON.stringify(value);\n return String(value);\n}\n","import { useMemo } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\nexport interface NarrativeLogProps extends BaseComponentProps {\n /** Snapshots to display narratives from */\n snapshots: StageSnapshot[];\n /** Show narratives up to this index (for time-travel sync) */\n selectedIndex?: number;\n /** Show a single narrative string (simple mode) */\n narrative?: string;\n}\n\n/**\n * Timeline-style execution log showing what happened at each stage.\n * Supports both full snapshots mode and single-narrative mode.\n */\nexport function NarrativeLog({\n snapshots,\n selectedIndex,\n narrative,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: NarrativeLogProps) {\n const entries = useMemo(() => {\n if (narrative) {\n return [{ label: \"Output\", text: narrative, isCurrent: true }];\n }\n const idx = selectedIndex ?? snapshots.length - 1;\n return snapshots.slice(0, idx + 1).map((s, i) => ({\n label: s.stageLabel,\n text: s.narrative,\n isCurrent: i === idx,\n }));\n }, [snapshots, selectedIndex, narrative]);\n\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"narrative-log\">\n {entries.map((entry, i) => (\n <div key={i} data-fp=\"narrative-entry\" data-current={entry.isCurrent}>\n <strong>{entry.label}</strong>\n <p>{entry.text}</p>\n </div>\n ))}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{ padding: pad, fontFamily: theme.fontSans, ...style }}\n data-fp=\"narrative-log\"\n >\n <span\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n }}\n >\n Execution Log\n </span>\n <div style={{ marginTop: 8, display: \"flex\", flexDirection: \"column\" }}>\n {entries.map((entry, i) => (\n <div\n key={i}\n style={{\n display: \"flex\",\n gap: 10,\n padding: `${pad}px 0`,\n borderBottom:\n i < entries.length - 1 ? `1px solid ${theme.border}` : \"none\",\n }}\n >\n {/* Timeline dot + line */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n width: 12,\n flexShrink: 0,\n paddingTop: 5,\n }}\n >\n <div\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: entry.isCurrent ? theme.primary : theme.success,\n flexShrink: 0,\n }}\n />\n {i < entries.length - 1 && (\n <div\n style={{\n width: 1,\n flex: 1,\n background: theme.border,\n marginTop: 4,\n }}\n />\n )}\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, minWidth: 0 }}>\n <span\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: entry.isCurrent ? theme.primary : theme.textMuted,\n }}\n >\n {entry.label}\n </span>\n <div\n style={{\n fontSize: fs.body,\n lineHeight: 1.5,\n color: entry.isCurrent ? theme.textPrimary : theme.textSecondary,\n marginTop: 2,\n }}\n >\n {entry.text}\n </div>\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { useState, useCallback, useMemo, useEffect, useRef } from \"react\";\nimport type { BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface NarrativeGroup {\n header: string;\n headerIdx: number;\n steps: { text: string; idx: number }[];\n}\n\nexport interface NarrativeTraceProps extends BaseComponentProps {\n /** All narrative lines (full trace) */\n narrative: string[];\n /** Number of lines currently revealed (for progressive reveal). Defaults to all. */\n revealedCount?: number;\n /** Start with all groups collapsed */\n defaultCollapsed?: boolean;\n /** Called when user clicks a stage header */\n onStageClick?: (headerIndex: number) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction parseGroups(lines: string[]): NarrativeGroup[] {\n const groups: NarrativeGroup[] = [];\n let current: NarrativeGroup | null = null;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trimStart();\n const isStep = trimmed.startsWith(\"Step \") || /^\\s/.test(line);\n\n if (!isStep || !current) {\n current = { header: line, headerIdx: i, steps: [] };\n groups.push(current);\n } else {\n current.steps.push({ text: trimmed, idx: i });\n }\n }\n\n return groups;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function NarrativeTrace({\n narrative,\n revealedCount,\n defaultCollapsed = false,\n onStageClick,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: NarrativeTraceProps) {\n const revealed = revealedCount != null ? narrative.slice(0, revealedCount) : narrative;\n const future = revealedCount != null ? narrative.slice(revealedCount) : [];\n\n const revealedGroups = useMemo(() => parseGroups(revealed), [revealed]);\n const futureGroups = useMemo(() => parseGroups(future), [future]);\n\n const [collapsedSet, setCollapsedSet] = useState<Set<number>>(() => {\n if (!defaultCollapsed) return new Set();\n return new Set(parseGroups(narrative).map((g) => g.headerIdx));\n });\n\n const latestRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n latestRef.current?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }, [revealedGroups.length]);\n\n const toggle = useCallback((idx: number) => {\n setCollapsedSet((prev) => {\n const next = new Set(prev);\n if (next.has(idx)) next.delete(idx);\n else next.add(idx);\n return next;\n });\n }, []);\n\n const lastIdx = revealedGroups.length - 1;\n const fs = fontSize[size];\n const pad = padding[size];\n\n // ── Unstyled mode ──\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"narrative-trace\">\n {revealedGroups.map((group, gi) => (\n <div key={group.headerIdx} data-fp=\"narrative-group\" data-latest={gi === lastIdx}>\n <div\n data-fp=\"narrative-header\"\n data-collapsible={group.steps.length > 0}\n data-collapsed={collapsedSet.has(group.headerIdx)}\n role={group.steps.length > 0 ? \"button\" : undefined}\n tabIndex={group.steps.length > 0 ? 0 : undefined}\n aria-expanded={group.steps.length > 0 ? !collapsedSet.has(group.headerIdx) : undefined}\n aria-label={`Stage ${gi + 1}, ${group.steps.length} steps${gi === lastIdx ? \", current\" : \"\"}`}\n onClick={() => {\n if (group.steps.length > 0) toggle(group.headerIdx);\n onStageClick?.(group.headerIdx);\n }}\n onKeyDown={(e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n if (group.steps.length > 0) toggle(group.headerIdx);\n onStageClick?.(group.headerIdx);\n }\n }}\n >\n {group.header}\n </div>\n {!collapsedSet.has(group.headerIdx) &&\n group.steps.map((step) => (\n <div key={step.idx} data-fp=\"narrative-step\">\n {step.text}\n </div>\n ))}\n </div>\n ))}\n {futureGroups.length > 0 && (\n <div data-fp=\"narrative-future-hint\">\n {futureGroups.length} more {futureGroups.length === 1 ? \"stage\" : \"stages\"} ahead...\n </div>\n )}\n </div>\n );\n }\n\n // ── Styled mode ──\n return (\n <div\n className={className}\n style={{\n flex: 1,\n overflow: \"auto\",\n padding: pad,\n fontFamily: theme.fontMono,\n ...style,\n }}\n data-fp=\"narrative-trace\"\n >\n {revealedGroups.map((group, gi) => {\n const isLatest = gi === lastIdx;\n const isCollapsed = collapsedSet.has(group.headerIdx);\n const hasSteps = group.steps.length > 0;\n\n return (\n <div\n key={group.headerIdx}\n ref={isLatest ? latestRef : undefined}\n style={{ marginBottom: 2 }}\n data-fp=\"narrative-group\"\n >\n {/* Stage header */}\n <div\n role={hasSteps ? \"button\" : undefined}\n tabIndex={hasSteps ? 0 : undefined}\n aria-expanded={hasSteps ? !isCollapsed : undefined}\n aria-label={`Stage ${gi + 1}, ${group.steps.length} steps${isLatest ? \", current\" : \", completed\"}`}\n onClick={() => {\n if (hasSteps) toggle(group.headerIdx);\n onStageClick?.(group.headerIdx);\n }}\n onKeyDown={(e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n if (hasSteps) toggle(group.headerIdx);\n onStageClick?.(group.headerIdx);\n }\n }}\n style={{\n fontSize: fs.body,\n lineHeight: 1.7,\n color: isLatest ? theme.textPrimary : theme.textSecondary,\n padding: `4px ${pad - 4}px`,\n borderRadius: 4,\n background: isLatest ? theme.bgTertiary : \"transparent\",\n borderLeft: isLatest\n ? `3px solid ${theme.primary}`\n : `3px solid ${theme.success}`,\n cursor: hasSteps ? \"pointer\" : \"default\",\n fontWeight: 600,\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n userSelect: \"none\",\n transition: \"all 0.15s ease\",\n }}\n >\n {hasSteps && (\n <span\n style={{\n fontSize: fs.small - 1,\n color: theme.textMuted,\n transition: \"transform 0.15s ease\",\n transform: isCollapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n width: 10,\n flexShrink: 0,\n }}\n >\n ▼\n </span>\n )}\n {!hasSteps && <span style={{ width: 10, flexShrink: 0 }} />}\n <span>{group.header}</span>\n </div>\n\n {/* Step lines */}\n {!isCollapsed &&\n group.steps.map((step) => (\n <div\n key={step.idx}\n style={{\n fontSize: fs.small,\n lineHeight: 1.6,\n color: isLatest ? theme.textSecondary : theme.textMuted,\n padding: `2px ${pad - 4}px 2px ${pad + 20}px`,\n opacity: isLatest ? 0.9 : 0.7,\n transition: \"all 0.15s ease\",\n }}\n data-fp=\"narrative-step\"\n >\n {step.text}\n </div>\n ))}\n </div>\n );\n })}\n\n {/* Future groups — show count hint only, skip full rendering for performance */}\n {futureGroups.length > 0 && (\n <div style={{\n opacity: 0.3,\n fontSize: fs.small,\n color: theme.textMuted,\n padding: `8px ${pad}px`,\n fontStyle: \"italic\",\n }}>\n {futureGroups.length} more {futureGroups.length === 1 ? \"stage\" : \"stages\"} ahead...\n </div>\n )}\n </div>\n );\n}\n","import { useState, useMemo, useRef, useEffect } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\nexport interface GanttTimelineProps extends BaseComponentProps {\n /** Stage snapshots with timing info */\n snapshots: StageSnapshot[];\n /** Currently selected stage index */\n selectedIndex?: number;\n /** Callback when a stage bar is clicked */\n onSelect?: (index: number) => void;\n /** Max visible rows before collapsing (0 = no collapse). Default: 5 */\n maxVisibleRows?: number;\n}\n\n/**\n * Horizontal Gantt-style timeline showing stage durations and overlap.\n * Collapses to `maxVisibleRows` with expand/collapse toggle.\n * Auto-scrolls to keep the active stage visible when collapsed.\n */\nexport function GanttTimeline({\n snapshots,\n selectedIndex = 0,\n onSelect,\n size = \"default\",\n unstyled = false,\n className,\n style,\n maxVisibleRows = 5,\n}: GanttTimelineProps) {\n const [expanded, setExpanded] = useState(false);\n const activeRowRef = useRef<HTMLDivElement | null>(null);\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n\n const totalWallTime = useMemo(\n () => Math.max(...snapshots.map((s) => s.startMs + s.durationMs), 1),\n [snapshots]\n );\n\n const fs = fontSize[size];\n const pad = padding[size];\n const labelWidth = size === \"compact\" ? 50 : size === \"detailed\" ? 100 : 80;\n const msWidth = size === \"compact\" ? 28 : 36;\n const rowHeight = size === \"compact\" ? 18 : 22;\n\n const collapsible = maxVisibleRows > 0 && snapshots.length > maxVisibleRows;\n const showAll = expanded || !collapsible;\n\n // Auto-scroll to active row when collapsed\n useEffect(() => {\n if (!showAll && activeRowRef.current && scrollContainerRef.current) {\n activeRowRef.current.scrollIntoView({\n block: \"nearest\",\n behavior: \"smooth\",\n });\n }\n }, [selectedIndex, showAll]);\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"gantt-timeline\" role=\"listbox\" aria-label=\"Execution timeline\">\n {snapshots.map((snap, idx) => (\n <div\n key={`${snap.stageName}-${idx}`}\n data-fp=\"gantt-bar\"\n data-selected={idx === selectedIndex}\n data-visible={idx <= selectedIndex}\n role=\"option\"\n aria-selected={idx === selectedIndex}\n aria-label={`${snap.stageLabel}, ${snap.durationMs}ms`}\n onClick={() => onSelect?.(idx)}\n >\n <span data-fp=\"gantt-label\">{snap.stageLabel}</span>\n <span data-fp=\"gantt-duration\">{snap.durationMs}ms</span>\n </div>\n ))}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{ padding: pad, fontFamily: theme.fontSans, ...style }}\n data-fp=\"gantt-timeline\"\n >\n {/* Header with collapse toggle */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n }}\n >\n <span\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n }}\n >\n {size === \"compact\" ? \"Timeline\" : \"Execution Timeline\"}\n </span>\n {collapsible && (\n <button\n onClick={() => setExpanded((e) => !e)}\n style={{\n background: \"none\",\n border: `1px solid ${theme.border}`,\n borderRadius: 4,\n color: theme.textSecondary,\n fontSize: fs.small,\n padding: \"2px 8px\",\n cursor: \"pointer\",\n fontFamily: theme.fontSans,\n }}\n >\n {expanded\n ? \"Collapse\"\n : `${snapshots.length - maxVisibleRows} more...`}\n </button>\n )}\n </div>\n\n {/* Scrollable rows container */}\n <div\n ref={scrollContainerRef}\n role=\"listbox\"\n aria-label=\"Execution timeline\"\n style={{\n marginTop: 8,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 4,\n ...(showAll\n ? {}\n : {\n maxHeight: maxVisibleRows * (rowHeight + 4),\n overflowY: \"auto\",\n scrollbarWidth: \"thin\",\n }),\n }}\n >\n {snapshots.map((snap, idx) => {\n const leftPct = (snap.startMs / totalWallTime) * 100;\n const widthPct = Math.max((snap.durationMs / totalWallTime) * 100, 1);\n const isSelected = idx === selectedIndex;\n const isVisible = idx <= selectedIndex;\n\n return (\n <div\n key={`${snap.stageName}-${idx}`}\n ref={isSelected ? activeRowRef : undefined}\n role=\"option\"\n aria-selected={isSelected}\n aria-label={`${snap.stageLabel}, ${snap.durationMs}ms`}\n onClick={() => onSelect?.(idx)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: size === \"compact\" ? 4 : 8,\n cursor: onSelect ? \"pointer\" : \"default\",\n opacity: isVisible ? 1 : 0.3,\n transition: \"opacity 0.3s ease\",\n height: rowHeight,\n flexShrink: 0,\n }}\n >\n <span\n title={snap.stageLabel}\n style={{\n width: labelWidth,\n fontSize: fs.small,\n color: isSelected ? theme.primary : theme.textMuted,\n fontWeight: isSelected ? 600 : 400,\n textAlign: \"right\",\n flexShrink: 0,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {snap.stageLabel}\n </span>\n <div\n style={{\n flex: 1,\n height: size === \"compact\" ? 6 : 8,\n position: \"relative\",\n background: theme.bgTertiary,\n borderRadius: 3,\n }}\n >\n {isVisible && (\n <div\n style={{\n position: \"absolute\",\n left: `${leftPct}%`,\n top: 0,\n width: `${widthPct}%`,\n height: \"100%\",\n borderRadius: 3,\n background: isSelected ? theme.primary : theme.success,\n transition: \"width 0.3s ease\",\n }}\n />\n )}\n </div>\n <span\n style={{\n fontSize: fs.small,\n color: theme.textMuted,\n fontFamily: theme.fontMono,\n width: msWidth,\n flexShrink: 0,\n }}\n >\n {snap.durationMs}ms\n </span>\n </div>\n );\n })}\n </div>\n\n {/* Time axis */}\n <div\n style={{\n marginTop: 4,\n marginLeft: labelWidth + (size === \"compact\" ? 4 : 8),\n marginRight: msWidth + (size === \"compact\" ? 4 : 8),\n display: \"flex\",\n justifyContent: \"space-between\",\n fontSize: fs.small - 1,\n color: theme.textMuted,\n fontFamily: theme.fontMono,\n }}\n >\n <span>0ms</span>\n {size !== \"compact\" && (\n <span>{(totalWallTime / 2).toFixed(1)}ms</span>\n )}\n <span>{totalWallTime.toFixed(1)}ms</span>\n </div>\n </div>\n );\n}\n","import { useState } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\nimport { MemoryInspector } from \"../MemoryInspector\";\nimport { NarrativeLog } from \"../NarrativeLog\";\nimport { GanttTimeline } from \"../GanttTimeline\";\n\nexport interface SnapshotPanelProps extends BaseComponentProps {\n /** Stage snapshots from pipeline execution */\n snapshots: StageSnapshot[];\n /** Show the Gantt timeline */\n showGantt?: boolean;\n /** Show the time-travel scrubber */\n showScrubber?: boolean;\n /** Title override */\n title?: string;\n}\n\n/**\n * All-in-one panel: time-travel scrubber + memory inspector + narrative log + gantt.\n * Drop this into any page to make a pipeline run inspectable.\n */\nexport function SnapshotPanel({\n snapshots,\n showGantt = true,\n showScrubber = true,\n title = \"Pipeline Inspector\",\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: SnapshotPanelProps) {\n const [selectedIndex, setSelectedIndex] = useState(0);\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (snapshots.length === 0) {\n return (\n <div\n className={className}\n style={{\n padding: pad * 2,\n textAlign: \"center\",\n color: unstyled ? undefined : theme.textMuted,\n fontSize: fs.body,\n ...style,\n }}\n data-fp=\"snapshot-panel\"\n >\n No snapshots to display\n </div>\n );\n }\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"snapshot-panel\">\n <h3>{title}</h3>\n {showScrubber && (\n <input\n type=\"range\"\n min={0}\n max={snapshots.length - 1}\n value={selectedIndex}\n onChange={(e) => setSelectedIndex(parseInt(e.target.value))}\n />\n )}\n <MemoryInspector\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n unstyled\n />\n <NarrativeLog\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n unstyled\n />\n {showGantt && (\n <GanttTimeline\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n onSelect={setSelectedIndex}\n unstyled\n />\n )}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n background: theme.bgPrimary,\n fontFamily: theme.fontSans,\n overflow: \"hidden\",\n ...style,\n }}\n data-fp=\"snapshot-panel\"\n >\n {/* Header with title + scrubber */}\n <div\n style={{\n padding: `${pad}px ${pad + 4}px`,\n borderBottom: `1px solid ${theme.border}`,\n background: theme.bgSecondary,\n flexShrink: 0,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n marginBottom: showScrubber ? 8 : 0,\n }}\n >\n <span\n style={{\n fontSize: fs.body + 2,\n fontWeight: 600,\n color: theme.textPrimary,\n }}\n >\n {title}\n </span>\n <span\n style={{\n fontSize: fs.small,\n color: theme.textMuted,\n fontFamily: theme.fontMono,\n }}\n >\n {selectedIndex + 1}/{snapshots.length}\n </span>\n </div>\n\n {showScrubber && (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <ScrubButton\n label=\"\\u25C0\"\n disabled={selectedIndex === 0}\n onClick={() => setSelectedIndex((i) => Math.max(0, i - 1))}\n />\n <input\n type=\"range\"\n min={0}\n max={snapshots.length - 1}\n value={selectedIndex}\n onChange={(e) => setSelectedIndex(parseInt(e.target.value))}\n style={{\n flex: 1,\n height: 4,\n accentColor: theme.primary,\n cursor: \"pointer\",\n }}\n />\n <ScrubButton\n label=\"\\u25B6\"\n disabled={selectedIndex === snapshots.length - 1}\n onClick={() =>\n setSelectedIndex((i) => Math.min(snapshots.length - 1, i + 1))\n }\n />\n </div>\n )}\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, overflow: \"auto\" }}>\n <MemoryInspector\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n size={size}\n />\n <div\n style={{\n height: 1,\n background: theme.border,\n margin: `0 ${pad}px`,\n }}\n />\n <NarrativeLog\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n size={size}\n />\n </div>\n\n {/* Gantt footer */}\n {showGantt && (\n <div\n style={{\n borderTop: `1px solid ${theme.border}`,\n background: theme.bgSecondary,\n flexShrink: 0,\n }}\n >\n <GanttTimeline\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n onSelect={setSelectedIndex}\n size={size}\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction ScrubButton({\n label,\n disabled,\n onClick,\n}: {\n label: string;\n disabled: boolean;\n onClick: () => void;\n}) {\n return (\n <button\n onClick={onClick}\n disabled={disabled}\n style={{\n background: theme.bgTertiary,\n border: `1px solid ${theme.border}`,\n color: disabled ? theme.textMuted : theme.textPrimary,\n borderRadius: 6,\n width: 28,\n height: 28,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n opacity: disabled ? 0.5 : 1,\n fontSize: 12,\n flexShrink: 0,\n }}\n >\n {label}\n </button>\n );\n}\n","import { useMemo } from \"react\";\nimport type { BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface DiffEntry {\n key: string;\n type: \"added\" | \"removed\" | \"changed\" | \"unchanged\";\n oldValue?: unknown;\n newValue?: unknown;\n}\n\nexport interface ScopeDiffProps extends BaseComponentProps {\n /** Memory state before the current stage */\n previous: Record<string, unknown> | null;\n /** Memory state after the current stage */\n current: Record<string, unknown>;\n /** Hide unchanged keys (default: false) */\n hideUnchanged?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction computeDiff(\n prev: Record<string, unknown> | null,\n curr: Record<string, unknown>\n): DiffEntry[] {\n const entries: DiffEntry[] = [];\n const allKeys = new Set([...Object.keys(prev ?? {}), ...Object.keys(curr)]);\n\n for (const key of allKeys) {\n const inPrev = prev != null && key in prev;\n const inCurr = key in curr;\n const oldVal = prev?.[key];\n const newVal = curr[key];\n\n if (!inPrev && inCurr) {\n entries.push({ key, type: \"added\", newValue: newVal });\n } else if (inPrev && !inCurr) {\n entries.push({ key, type: \"removed\", oldValue: oldVal });\n } else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {\n entries.push({ key, type: \"changed\", oldValue: oldVal, newValue: newVal });\n } else {\n entries.push({ key, type: \"unchanged\", newValue: newVal });\n }\n }\n\n const order = { added: 0, changed: 1, removed: 2, unchanged: 3 };\n entries.sort((a, b) => order[a.type] - order[b.type]);\n return entries;\n}\n\nfunction fmt(v: unknown): string {\n if (typeof v === \"string\") return `\"${v}\"`;\n if (typeof v === \"object\" && v !== null) return JSON.stringify(v, null, 2);\n return String(v);\n}\n\nconst diffColors: Record<DiffEntry[\"type\"], { bg: string; fg: string; icon: string }> = {\n added: { bg: `color-mix(in srgb, ${theme.success} 10%, transparent)`, fg: theme.success, icon: \"+\" },\n removed: { bg: `color-mix(in srgb, ${theme.error} 10%, transparent)`, fg: theme.error, icon: \"-\" },\n changed: { bg: `color-mix(in srgb, ${theme.warning} 10%, transparent)`, fg: theme.warning, icon: \"~\" },\n unchanged: { bg: \"transparent\", fg: \"\", icon: \" \" },\n};\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function ScopeDiff({\n previous,\n current,\n hideUnchanged = false,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: ScopeDiffProps) {\n const entries = useMemo(() => computeDiff(previous, current), [previous, current]);\n const visible = hideUnchanged ? entries.filter((e) => e.type !== \"unchanged\") : entries;\n\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"scope-diff\">\n {visible.map((e) => (\n <div key={e.key} data-fp=\"diff-entry\" data-type={e.type}>\n <span data-fp=\"diff-key\">{e.key}</span>\n {e.type === \"changed\" && (\n <>\n <span data-fp=\"diff-old\">{fmt(e.oldValue)}</span>\n <span data-fp=\"diff-new\">{fmt(e.newValue)}</span>\n </>\n )}\n {(e.type === \"added\" || e.type === \"unchanged\") && (\n <span data-fp=\"diff-value\">{fmt(e.newValue)}</span>\n )}\n {e.type === \"removed\" && (\n <span data-fp=\"diff-value\">{fmt(e.oldValue)}</span>\n )}\n </div>\n ))}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{ padding: pad, fontFamily: theme.fontMono, ...style }}\n data-fp=\"scope-diff\"\n >\n {visible.length === 0 && (\n <div style={{ fontSize: fs.body, color: theme.textMuted, fontStyle: \"italic\" }}>\n No changes\n </div>\n )}\n {visible.map((entry) => {\n const dc = diffColors[entry.type];\n return (\n <div\n key={entry.key}\n style={{\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: 8,\n padding: `4px ${pad - 4}px`,\n marginBottom: 2,\n borderRadius: 4,\n background: dc.bg,\n fontSize: fs.body,\n lineHeight: 1.5,\n }}\n data-fp=\"diff-entry\"\n >\n <span\n style={{\n width: 16,\n flexShrink: 0,\n fontWeight: 700,\n color: dc.fg || theme.textMuted,\n textAlign: \"center\",\n }}\n >\n {dc.icon}\n </span>\n <span style={{ color: theme.primary, fontWeight: 600, flexShrink: 0 }}>\n {entry.key}\n </span>\n <span style={{ color: theme.textMuted }}>=</span>\n {entry.type === \"changed\" ? (\n <span>\n <span\n style={{\n color: theme.error,\n textDecoration: \"line-through\",\n opacity: 0.7,\n }}\n >\n {fmt(entry.oldValue)}\n </span>\n <span style={{ color: theme.textMuted, margin: \"0 4px\" }}>→</span>\n <span style={{ color: theme.success }}>{fmt(entry.newValue)}</span>\n </span>\n ) : (\n <span\n style={{\n color:\n entry.type === \"added\"\n ? theme.success\n : entry.type === \"removed\"\n ? theme.error\n : theme.textPrimary,\n }}\n >\n {fmt(entry.type === \"removed\" ? entry.oldValue : entry.newValue)}\n </span>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","import type { BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\nexport interface ResultPanelProps extends BaseComponentProps {\n /** Final pipeline output / shared state */\n data: Record<string, unknown> | null;\n /** Optional console log lines */\n logs?: string[];\n /** Hide console section (default: false) */\n hideConsole?: boolean;\n}\n\nexport function ResultPanel({\n data,\n logs = [],\n hideConsole = false,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: ResultPanelProps) {\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"result-panel\">\n <div data-fp=\"result-data\">\n <pre>{data ? JSON.stringify(data, null, 2) : \"No data\"}</pre>\n </div>\n {!hideConsole && (\n <div data-fp=\"result-console\">\n {logs.map((line, i) => (\n <div key={i} data-fp=\"console-line\" data-error={line.startsWith(\"ERROR\")}>\n {line}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n ...style,\n }}\n data-fp=\"result-panel\"\n >\n {data && (\n <div style={{ flex: 1, overflow: \"auto\", padding: pad }}>\n <div\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n marginBottom: 8,\n }}\n >\n {size === \"compact\" ? \"Result\" : \"Business Result (Scope)\"}\n </div>\n <pre\n style={{\n fontSize: fs.body,\n fontFamily: theme.fontMono,\n color: theme.textPrimary,\n background: theme.bgSecondary,\n padding: pad,\n borderRadius: theme.radius,\n overflow: \"auto\",\n margin: 0,\n }}\n >\n {JSON.stringify(data, null, 2)}\n </pre>\n </div>\n )}\n\n {!hideConsole && (\n <div\n style={{\n borderTop: `1px solid ${theme.border}`,\n padding: pad,\n overflow: \"auto\",\n maxHeight: \"40%\",\n flexShrink: 0,\n }}\n >\n <div\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n marginBottom: 8,\n }}\n >\n Console\n </div>\n {logs.length === 0 && (\n <div style={{ fontSize: fs.body, color: theme.textMuted, fontStyle: \"italic\" }}>\n No console output\n </div>\n )}\n {logs.map((line, i) => (\n <div\n key={i}\n style={{\n fontSize: fs.body,\n fontFamily: theme.fontMono,\n color: line.startsWith(\"ERROR\") ? theme.error : theme.textPrimary,\n padding: \"2px 0\",\n borderBottom: `1px solid ${theme.bgSecondary}`,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n }}\n >\n {line}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import { useState, useMemo, useCallback } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type StageDetailMode = \"simple\" | \"dev\";\n\nexport interface MemoryChange {\n key: string;\n type: \"added\" | \"updated\" | \"removed\";\n oldValue?: unknown;\n newValue?: unknown;\n}\n\n/** Keys that are footprint engine internals — hidden by default in dev mode. */\nexport const DEFAULT_EXCLUDED_KEYS = new Set<string>([]);\n\nexport interface StageDetailPanelProps extends BaseComponentProps {\n /** Stage snapshots for time-travel */\n snapshots: StageSnapshot[];\n /** Current snapshot index */\n selectedIndex: number;\n /** Display mode: \"simple\" (description + narrative) or \"dev\" (memory story) */\n mode?: StageDetailMode;\n /** Show a toggle to switch between simple/dev modes (default: false) */\n showToggle?: boolean;\n /** Called when user toggles mode via built-in toggle */\n onModeChange?: (mode: StageDetailMode) => void;\n /** Keys to exclude from memory display (default: engine internals). Pass empty set to show all. */\n excludeKeys?: Set<string>;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction computeChanges(\n prev: Record<string, unknown> | null,\n curr: Record<string, unknown>,\n): MemoryChange[] {\n const changes: MemoryChange[] = [];\n const allKeys = new Set([...Object.keys(prev ?? {}), ...Object.keys(curr)]);\n\n for (const key of allKeys) {\n const inPrev = prev != null && key in prev;\n const inCurr = key in curr;\n const oldVal = prev?.[key];\n const newVal = curr[key];\n\n if (!inPrev && inCurr) {\n changes.push({ key, type: \"added\", newValue: newVal });\n } else if (inPrev && !inCurr) {\n changes.push({ key, type: \"removed\", oldValue: oldVal });\n } else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {\n changes.push({ key, type: \"updated\", oldValue: oldVal, newValue: newVal });\n }\n }\n\n const order = { added: 0, updated: 1, removed: 2 };\n changes.sort((a, b) => order[a.type] - order[b.type]);\n return changes;\n}\n\nfunction fmt(v: unknown): string {\n if (typeof v === \"string\") return `\"${v}\"`;\n if (typeof v === \"object\" && v !== null) return JSON.stringify(v, null, 2);\n return String(v);\n}\n\nconst changeBadge: Record<MemoryChange[\"type\"], { bg: string; fg: string; label: string }> = {\n added: { bg: \"rgba(34,197,94,0.12)\", fg: \"#22c55e\", label: \"ADD\" },\n updated: { bg: \"rgba(245,158,11,0.12)\", fg: \"#f59e0b\", label: \"UPD\" },\n removed: { bg: \"rgba(239,68,68,0.12)\", fg: \"#ef4444\", label: \"DEL\" },\n};\n\n// ---------------------------------------------------------------------------\n// Simple Mode — description + narrative\n// ---------------------------------------------------------------------------\n\nfunction SimpleView({\n snapshot,\n fs,\n pad,\n}: {\n snapshot: StageSnapshot;\n fs: { label: number; body: number; small: number };\n pad: number;\n}) {\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n {/* Stage header */}\n <div>\n <div\n style={{\n fontSize: fs.label + 2,\n fontWeight: 700,\n color: theme.textPrimary,\n }}\n >\n {snapshot.stageLabel}\n </div>\n {snapshot.description && (\n <div\n style={{\n fontSize: fs.body,\n color: theme.textSecondary,\n marginTop: 4,\n lineHeight: 1.5,\n }}\n >\n {snapshot.description}\n </div>\n )}\n </div>\n\n {/* Status badge */}\n {snapshot.status && (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n <div\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background:\n snapshot.status === \"done\"\n ? theme.success\n : snapshot.status === \"active\"\n ? theme.primary\n : snapshot.status === \"error\"\n ? theme.error\n : theme.textMuted,\n }}\n />\n <span\n style={{\n fontSize: fs.small,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.05em\",\n }}\n >\n {snapshot.status}\n </span>\n </div>\n )}\n\n {/* Narrative — what happened */}\n {snapshot.narrative && (\n <div>\n <div\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n marginBottom: 6,\n }}\n >\n What happened\n </div>\n <div\n style={{\n fontSize: fs.body,\n lineHeight: 1.6,\n color: theme.textPrimary,\n background: theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: theme.radius,\n padding: pad,\n }}\n >\n {snapshot.narrative}\n </div>\n </div>\n )}\n\n {/* Duration */}\n {snapshot.durationMs > 0 && (\n <div\n style={{\n fontSize: fs.small,\n color: theme.textMuted,\n }}\n >\n Completed in {snapshot.durationMs < 1 ? \"<1\" : snapshot.durationMs}ms\n </div>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Dev Mode — memory story (browser DevTools style)\n// ---------------------------------------------------------------------------\n\n/** A row in the full memory ledger: either a changed key or an unchanged one. */\ntype MemoryRow =\n | { kind: \"change\"; change: MemoryChange }\n | { kind: \"unchanged\"; key: string; value: unknown };\n\nfunction buildMemoryRows(\n currMemory: Record<string, unknown>,\n changes: MemoryChange[],\n): MemoryRow[] {\n const changeMap = new Map(changes.map((c) => [c.key, c]));\n const rows: MemoryRow[] = [];\n\n // Changed keys first (ADD → UPD → DEL)\n for (const change of changes) {\n rows.push({ kind: \"change\", change });\n }\n\n // Then unchanged keys (sorted alphabetically)\n const unchangedKeys = Object.keys(currMemory)\n .filter((k) => !changeMap.has(k))\n .sort();\n for (const key of unchangedKeys) {\n rows.push({ kind: \"unchanged\", key, value: currMemory[key] });\n }\n\n return rows;\n}\n\nfunction DevView({\n snapshot,\n changes,\n currMemory,\n fs,\n pad,\n}: {\n snapshot: StageSnapshot;\n changes: MemoryChange[];\n currMemory: Record<string, unknown>;\n fs: { label: number; body: number; small: number };\n pad: number;\n}) {\n const rows = useMemo(() => buildMemoryRows(currMemory, changes), [currMemory, changes]);\n const totalKeys = Object.keys(currMemory).length;\n\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n {/* Stage header with label */}\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <span\n style={{\n fontSize: fs.label + 2,\n fontWeight: 700,\n color: theme.textPrimary,\n fontFamily: theme.fontMono,\n }}\n >\n {snapshot.stageLabel}\n </span>\n {snapshot.durationMs > 0 && (\n <span\n style={{\n fontSize: fs.small,\n color: theme.textMuted,\n fontFamily: theme.fontMono,\n }}\n >\n {snapshot.durationMs}ms\n </span>\n )}\n </div>\n\n {/* Memory state section header */}\n <div\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n }}\n >\n Memory\n <span style={{ fontWeight: 400, marginLeft: 6 }}>\n ({totalKeys} key{totalKeys !== 1 ? \"s\" : \"\"}\n {changes.length > 0 && `, ${changes.length} changed`})\n </span>\n </div>\n\n {/* Full memory ledger */}\n {rows.length === 0 ? (\n <div\n style={{\n fontSize: fs.body,\n color: theme.textMuted,\n fontStyle: \"italic\",\n fontFamily: theme.fontMono,\n padding: `${pad}px`,\n background: theme.bgSecondary,\n borderRadius: theme.radius,\n }}\n >\n Empty memory\n </div>\n ) : (\n <div\n style={{\n fontFamily: theme.fontMono,\n fontSize: fs.body,\n background: theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: theme.radius,\n overflow: \"hidden\",\n }}\n >\n {rows.map((row) => {\n if (row.kind === \"change\") {\n const { change } = row;\n const badge = changeBadge[change.type];\n return (\n <div\n key={change.key}\n style={{\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: 8,\n padding: `6px ${pad}px`,\n borderBottom: `1px solid ${theme.border}`,\n background: badge.bg,\n }}\n data-fp=\"memory-change\"\n data-type={change.type}\n >\n <span\n style={{\n fontSize: fs.small,\n fontWeight: 700,\n color: badge.fg,\n width: 28,\n flexShrink: 0,\n textAlign: \"center\",\n lineHeight: 1.8,\n }}\n >\n {badge.label}\n </span>\n <span\n style={{\n color: theme.primary,\n fontWeight: 600,\n flexShrink: 0,\n lineHeight: 1.8,\n }}\n >\n {change.key}\n </span>\n <div style={{ flex: 1, minWidth: 0, lineHeight: 1.8 }}>\n {change.type === \"updated\" ? (\n <>\n <span\n style={{\n color: theme.error,\n textDecoration: \"line-through\",\n opacity: 0.7,\n }}\n >\n {fmt(change.oldValue)}\n </span>\n <span style={{ color: theme.textMuted, margin: \"0 4px\" }}>→</span>\n <span style={{ color: theme.success }}>{fmt(change.newValue)}</span>\n </>\n ) : change.type === \"added\" ? (\n <span style={{ color: theme.success }}>{fmt(change.newValue)}</span>\n ) : (\n <span style={{ color: theme.error, textDecoration: \"line-through\" }}>\n {fmt(change.oldValue)}\n </span>\n )}\n </div>\n </div>\n );\n }\n\n // Unchanged key — dimmed, no badge\n return (\n <div\n key={row.key}\n style={{\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: 8,\n padding: `6px ${pad}px`,\n borderBottom: `1px solid ${theme.border}`,\n opacity: 0.5,\n }}\n data-fp=\"memory-unchanged\"\n >\n <span\n style={{\n width: 28,\n flexShrink: 0,\n lineHeight: 1.8,\n }}\n />\n <span\n style={{\n color: theme.textSecondary,\n fontWeight: 500,\n flexShrink: 0,\n lineHeight: 1.8,\n }}\n >\n {row.key}\n </span>\n <div style={{ flex: 1, minWidth: 0, lineHeight: 1.8, color: theme.textMuted }}>\n {fmt(row.value)}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Unstyled Mode\n// ---------------------------------------------------------------------------\n\nfunction UnstyledSimpleView({ snapshot }: { snapshot: StageSnapshot }) {\n return (\n <div data-fp=\"stage-detail-simple\">\n <div data-fp=\"stage-label\">{snapshot.stageLabel}</div>\n {snapshot.description && (\n <div data-fp=\"stage-description\">{snapshot.description}</div>\n )}\n {snapshot.status && <div data-fp=\"stage-status\">{snapshot.status}</div>}\n {snapshot.narrative && (\n <div data-fp=\"stage-narrative\">{snapshot.narrative}</div>\n )}\n </div>\n );\n}\n\nfunction UnstyledDevView({\n snapshot,\n changes,\n currMemory,\n}: {\n snapshot: StageSnapshot;\n changes: MemoryChange[];\n currMemory: Record<string, unknown>;\n}) {\n const rows = useMemo(() => buildMemoryRows(currMemory, changes), [currMemory, changes]);\n return (\n <div data-fp=\"stage-detail-dev\">\n <div data-fp=\"stage-label\">{snapshot.stageLabel}</div>\n {rows.map((row) => {\n if (row.kind === \"change\") {\n const c = row.change;\n return (\n <div key={c.key} data-fp=\"memory-change\" data-type={c.type}>\n <span data-fp=\"change-key\">{c.key}</span>\n {c.type === \"updated\" && (\n <>\n <span data-fp=\"change-old\">{fmt(c.oldValue)}</span>\n <span data-fp=\"change-new\">{fmt(c.newValue)}</span>\n </>\n )}\n {c.type === \"added\" && (\n <span data-fp=\"change-value\">{fmt(c.newValue)}</span>\n )}\n {c.type === \"removed\" && (\n <span data-fp=\"change-value\">{fmt(c.oldValue)}</span>\n )}\n </div>\n );\n }\n return (\n <div key={row.key} data-fp=\"memory-unchanged\">\n <span data-fp=\"unchanged-key\">{row.key}</span>\n <span data-fp=\"unchanged-value\">{fmt(row.value)}</span>\n </div>\n );\n })}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Main Component\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Mode Toggle\n// ---------------------------------------------------------------------------\n\nfunction ModeToggle({\n activeMode,\n onToggle,\n fs,\n unstyled,\n}: {\n activeMode: StageDetailMode;\n onToggle: () => void;\n fs: { label: number; body: number; small: number };\n unstyled: boolean;\n}) {\n if (unstyled) {\n return (\n <button data-fp=\"mode-toggle\" data-mode={activeMode} onClick={onToggle}>\n {activeMode === \"simple\" ? \"Dev\" : \"Simple\"}\n </button>\n );\n }\n\n return (\n <div\n style={{\n display: \"inline-flex\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n overflow: \"hidden\",\n flexShrink: 0,\n }}\n data-fp=\"mode-toggle\"\n >\n {([\"simple\", \"dev\"] as const).map((m) => (\n <button\n key={m}\n onClick={m !== activeMode ? onToggle : undefined}\n style={{\n padding: \"4px 10px\",\n fontSize: fs.small,\n fontWeight: m === activeMode ? 700 : 400,\n textTransform: \"uppercase\",\n letterSpacing: \"0.05em\",\n color: m === activeMode ? theme.textPrimary : theme.textMuted,\n background: m === activeMode ? theme.bgTertiary : \"transparent\",\n border: \"none\",\n cursor: m === activeMode ? \"default\" : \"pointer\",\n }}\n >\n {m === \"simple\" ? \"Simple\" : \"Dev\"}\n </button>\n ))}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Main Component\n// ---------------------------------------------------------------------------\n\nexport function StageDetailPanel({\n snapshots,\n selectedIndex,\n mode: controlledMode,\n showToggle = false,\n onModeChange,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: StageDetailPanelProps) {\n const [internalMode, setInternalMode] = useState<StageDetailMode>(controlledMode ?? \"simple\");\n\n // Support both controlled (mode prop) and uncontrolled (internal state) usage\n const activeMode = controlledMode ?? internalMode;\n\n const handleToggle = useCallback(() => {\n const next: StageDetailMode = activeMode === \"simple\" ? \"dev\" : \"simple\";\n setInternalMode(next);\n onModeChange?.(next);\n }, [activeMode, onModeChange]);\n\n const snapshot = snapshots[selectedIndex];\n const prevMemory = selectedIndex > 0 ? snapshots[selectedIndex - 1]?.memory ?? null : null;\n const currMemory = snapshot?.memory ?? {};\n\n const changes = useMemo(\n () => computeChanges(prevMemory, currMemory),\n [prevMemory, currMemory],\n );\n\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (!snapshot) {\n return (\n <div className={className} style={style} data-fp=\"stage-detail-panel\">\n <div style={unstyled ? {} : { color: theme.textMuted, fontSize: fs.body, fontStyle: \"italic\", padding: pad }}>\n No stage selected\n </div>\n </div>\n );\n }\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"stage-detail-panel\" data-mode={activeMode}>\n {showToggle && (\n <ModeToggle activeMode={activeMode} onToggle={handleToggle} fs={fs} unstyled />\n )}\n {activeMode === \"simple\" ? (\n <UnstyledSimpleView snapshot={snapshot} />\n ) : (\n <UnstyledDevView snapshot={snapshot} changes={changes} currMemory={currMemory} />\n )}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n padding: pad,\n fontFamily: theme.fontSans,\n overflow: \"auto\",\n ...style,\n }}\n data-fp=\"stage-detail-panel\"\n data-mode={activeMode}\n >\n {showToggle && (\n <div style={{ display: \"flex\", justifyContent: \"flex-end\", marginBottom: 12 }}>\n <ModeToggle activeMode={activeMode} onToggle={handleToggle} fs={fs} unstyled={false} />\n </div>\n )}\n {activeMode === \"simple\" ? (\n <SimpleView snapshot={snapshot} fs={fs} pad={pad} />\n ) : (\n <DevView snapshot={snapshot} changes={changes} currMemory={currMemory} fs={fs} pad={pad} />\n )}\n </div>\n );\n}\n","import { useState, useEffect, useRef, useCallback } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize } from \"../../theme\";\n\nexport interface TimeTravelControlsProps extends BaseComponentProps {\n /** Stage snapshots */\n snapshots: StageSnapshot[];\n /** Currently selected stage index */\n selectedIndex: number;\n /** Callback when selected index changes */\n onIndexChange: (index: number) => void;\n /** Enable auto-play with Gantt-proportional timing */\n autoPlayable?: boolean;\n}\n\nexport function TimeTravelControls({\n snapshots,\n selectedIndex,\n onIndexChange,\n autoPlayable = true,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: TimeTravelControlsProps) {\n const [playing, setPlaying] = useState(false);\n const playRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const total = snapshots.length;\n const canPrev = selectedIndex > 0;\n const canNext = selectedIndex < total - 1;\n\n // Auto-advance with proportional timing\n useEffect(() => {\n if (!playing || !autoPlayable) return;\n if (selectedIndex >= total - 1) {\n setPlaying(false);\n return;\n }\n const stageDur = snapshots[selectedIndex]?.durationMs ?? 1;\n const totalDur = snapshots.reduce((s, snap) => s + snap.durationMs, 0) || 1;\n const fraction = stageDur / totalDur;\n const baseMs = 3000;\n const delay = Math.max(200, Math.min(fraction * baseMs, 2000));\n\n playRef.current = setTimeout(() => {\n onIndexChange(selectedIndex + 1);\n }, delay);\n\n return () => {\n if (playRef.current) clearTimeout(playRef.current);\n };\n }, [playing, selectedIndex, snapshots, total, onIndexChange, autoPlayable]);\n\n const togglePlay = useCallback(() => {\n if (playing) {\n setPlaying(false);\n } else {\n if (selectedIndex >= total - 1) onIndexChange(0);\n setPlaying(true);\n }\n }, [playing, selectedIndex, total, onIndexChange]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowLeft\" && canPrev && !playing) {\n e.preventDefault();\n setPlaying(false);\n onIndexChange(selectedIndex - 1);\n } else if (e.key === \"ArrowRight\" && canNext && !playing) {\n e.preventDefault();\n setPlaying(false);\n onIndexChange(selectedIndex + 1);\n } else if (e.key === \" \" && autoPlayable) {\n e.preventDefault();\n togglePlay();\n }\n },\n [canPrev, canNext, playing, selectedIndex, onIndexChange, autoPlayable, togglePlay]\n );\n\n const fs = fontSize[size];\n\n if (unstyled) {\n return (\n <div\n className={className}\n style={style}\n data-fp=\"time-travel-controls\"\n role=\"toolbar\"\n aria-label=\"Time travel controls\"\n tabIndex={0}\n onKeyDown={handleKeyDown}\n >\n <button\n data-fp=\"tt-prev\"\n disabled={!canPrev || playing}\n onClick={() => { setPlaying(false); onIndexChange(selectedIndex - 1); }}\n aria-label=\"Previous stage\"\n >\n Prev\n </button>\n {autoPlayable && (\n <button data-fp=\"tt-play\" onClick={togglePlay} aria-label={playing ? \"Pause\" : \"Play\"}>\n {playing ? \"Pause\" : \"Play\"}\n </button>\n )}\n <button\n data-fp=\"tt-next\"\n disabled={!canNext || playing}\n onClick={() => { setPlaying(false); onIndexChange(selectedIndex + 1); }}\n aria-label=\"Next stage\"\n >\n Next\n </button>\n <div data-fp=\"tt-ticks\">\n {snapshots.map((snap, i) => (\n <button\n key={i}\n data-fp=\"tt-tick\"\n data-active={i === selectedIndex}\n data-done={i < selectedIndex}\n onClick={() => { setPlaying(false); onIndexChange(i); }}\n title={snap.stageLabel}\n />\n ))}\n </div>\n </div>\n );\n }\n\n const btnStyle = (disabled: boolean): React.CSSProperties => ({\n background: theme.bgTertiary,\n border: `1px solid ${theme.border}`,\n color: disabled ? theme.textMuted : theme.textPrimary,\n borderRadius: \"6px\",\n padding: \"4px 12px\",\n fontSize: fs.body,\n fontWeight: 600,\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n opacity: disabled ? 0.5 : 1,\n flexShrink: 0,\n });\n\n return (\n <div\n className={className}\n style={{\n padding: \"6px 12px\",\n background: theme.bgSecondary,\n borderBottom: `1px solid ${theme.border}`,\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n flexShrink: 0,\n ...style,\n }}\n data-fp=\"time-travel-controls\"\n role=\"toolbar\"\n aria-label=\"Time travel controls\"\n tabIndex={0}\n onKeyDown={handleKeyDown}\n >\n <button\n style={btnStyle(!canPrev || playing)}\n disabled={!canPrev || playing}\n onClick={() => { setPlaying(false); onIndexChange(selectedIndex - 1); }}\n aria-label=\"Previous stage\"\n >\n ◀\n </button>\n\n {autoPlayable && (\n <button\n onClick={togglePlay}\n style={{\n background: playing ? theme.primary : theme.bgTertiary,\n border: `1px solid ${theme.border}`,\n color: playing ? \"white\" : theme.textPrimary,\n borderRadius: \"6px\",\n width: 28,\n height: 28,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n fontSize: 14,\n flexShrink: 0,\n }}\n title={playing ? \"Pause\" : \"Play\"}\n aria-label={playing ? \"Pause\" : \"Play\"}\n >\n {playing ? \"\\u23F8\" : \"\\u25B6\"}\n </button>\n )}\n\n <button\n style={btnStyle(!canNext || playing)}\n disabled={!canNext || playing}\n onClick={() => { setPlaying(false); onIndexChange(selectedIndex + 1); }}\n aria-label=\"Next stage\"\n >\n ▶\n </button>\n\n {/* Tick-mark timeline */}\n <div\n style={{\n flex: 1,\n display: \"flex\",\n alignItems: \"center\",\n gap: 2,\n padding: \"0 4px\",\n }}\n >\n {snapshots.map((snap, i) => {\n const isActive = i === selectedIndex;\n const isDone = i < selectedIndex;\n return (\n <button\n key={i}\n onClick={() => { setPlaying(false); onIndexChange(i); }}\n title={snap.stageLabel}\n style={{\n flex: 1,\n height: isActive ? 14 : 8,\n borderRadius: 3,\n border: \"none\",\n cursor: \"pointer\",\n background: isActive\n ? theme.primary\n : isDone\n ? theme.success\n : theme.bgTertiary,\n opacity: isDone || isActive ? 1 : 0.4,\n transition: \"all 0.15s ease\",\n }}\n />\n );\n })}\n </div>\n </div>\n );\n}\n","/**\n * ExplainableShell — Pure orchestrator for explainable pipeline visualization.\n *\n * Collapsible sections use the **line + centered pill** pattern:\n * - Collapsed = thin divider line with a pill button sitting on it\n * - Expanded = full content with a pill at the closing edge\n *\n * Sub-components are memo'd to minimize re-renders when scrubbing the\n * time-travel slider. Only components that depend on snapshotIdx re-render.\n *\n * Consumer controls theme via --fp-* CSS custom properties.\n */\nimport { memo, useState, useCallback, useMemo, useRef, useEffect } from \"react\";\nimport type { StageSnapshot, BaseComponentProps, NarrativeEntry } from \"../../types\";\nimport { theme } from \"../../theme\";\nimport { extractSubflowNarrative } from \"../../utils/narrativeSync\";\nimport { toVisualizationSnapshots, subflowResultToSnapshots } from \"../../adapters/fromRuntimeSnapshot\";\nimport { ResultPanel } from \"../ResultPanel\";\nimport { GanttTimeline } from \"../GanttTimeline\";\nimport { TimeTravelControls } from \"../TimeTravelControls\";\nimport { MemoryPanel } from \"../MemoryPanel\";\nimport { NarrativePanel } from \"../NarrativePanel\";\nimport { SubflowTree } from \"../FlowchartView/SubflowTree\";\nimport { SubflowBreadcrumb } from \"../FlowchartView/SubflowBreadcrumb\";\nimport { TracedFlow } from \"../FlowchartView/TracedFlow\";\n\n/**\n * Minimal subflow-walking spec shape. Used INTERNALLY by drill-down\n * resolution (which navigates `subflowStructure` to find a child chart\n * inside the parent's serialized structure). No longer used for chart\n * rendering — that happens via `traceGraph` + `<TracedFlow>` exclusively.\n *\n * Kept as a local type so the file no longer depends on any legacy\n * spec-walk module.\n */\nexport interface SpecNode {\n name: string;\n id?: string;\n description?: string;\n children?: SpecNode[];\n next?: SpecNode;\n isSubflowRoot?: boolean;\n subflowId?: string;\n subflowName?: string;\n subflowStructure?: SpecNode;\n}\nimport { InspectorPanel } from \"../InspectorPanel/InspectorPanel\";\nimport { InsightPanel } from \"../InsightPanel/InsightPanel\";\nimport { CompactTimeline } from \"../CompactTimeline/CompactTimeline\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Tab ID — \"result\", \"memory\", \"narrative\", or any custom recorder view ID. */\nexport type ShellTab = string;\n\n\ninterface SubflowLevel {\n subflowId: string;\n label: string;\n spec: SpecNode;\n snapshots: StageSnapshot[];\n}\n\ninterface DrillDownEntry extends SubflowLevel {\n parentSnapshotIdx: number;\n}\n\nexport interface PanelLabels {\n /** Left panel pill label (subflow tree). Default: \"Topology\" */\n topology?: string;\n /** Right panel pill label (memory/narrative). Default: \"Details\" */\n details?: string;\n /** Bottom panel pill label (timeline). Default: \"Timeline\" */\n timeline?: string;\n}\n\n/** Which panels start expanded. Default: `{ details: true }` (flowchart + memory). */\nexport interface DefaultExpanded {\n topology?: boolean;\n details?: boolean;\n timeline?: boolean;\n}\n\n/**\n * Raw runtime snapshot from FlowChartExecutor.getSnapshot().\n * When provided, ExplainableShell converts it internally — zero boilerplate.\n */\nexport interface RuntimeSnapshotInput {\n sharedState: Record<string, unknown>;\n executionTree: unknown;\n commitLog: unknown[];\n subflowResults?: Record<string, unknown>;\n /** Recorder snapshots from toSnapshot() — auto-generates detail tabs. */\n recorders?: Array<{\n id: string;\n name: string;\n description?: string;\n preferredOperation?: 'translate' | 'accumulate' | 'aggregate';\n data: unknown;\n }>;\n}\n\n/**\n * A recorder view that appears as a tab in the details panel.\n * Each recorder provides its own per-stage rendering.\n * Memory and Narrative are built-in defaults — add more via this prop.\n */\nexport interface RecorderView {\n /** Unique key for this view tab */\n id: string;\n /** Display label on the tab */\n name: string;\n /** Short description shown as tooltip and header for auto-detected views.\n * e.g., \"Per-step timing and I/O counts (KeyedRecorder)\" */\n description?: string;\n /**\n * Render function — receives the current snapshot index and all snapshots.\n * Return a React node to display in the details panel.\n */\n render: (props: { snapshots: StageSnapshot[]; selectedIndex: number }) => React.ReactNode;\n}\n\nexport interface ExplainableShellProps extends BaseComponentProps {\n /**\n * Pre-converted visualization snapshots. Use when you've already called\n * toVisualizationSnapshots() yourself.\n */\n snapshots?: StageSnapshot[];\n /**\n * Raw runtime snapshot from executor.getSnapshot(). The shell converts it\n * internally via toVisualizationSnapshots(). When provided, `snapshots`\n * and `resultData` are derived automatically. Pair with\n * `narrativeEntries` for rich per-stage narrative.\n *\n * Usage: `<ExplainableShell runtimeSnapshot={executor.getSnapshot()} narrativeEntries={executor.getNarrativeEntries()} spec={spec} />`\n */\n runtimeSnapshot?: RuntimeSnapshotInput | null;\n spec?: SpecNode | null;\n /**\n * Build-time graph captured live via `createTraceStructureRecorder`.\n * REQUIRED for chart rendering (v6+) — the legacy `spec` →\n * legacy spec-walk post-walk path was removed in favor of this\n * recorder-driven graph.\n *\n * Pair with `runtimeOverlay` for the full time-travel trace UI.\n * When `traceGraph` is set but `runtimeOverlay` is absent, the\n * chart renders without runtime coloring (build-time-only view).\n *\n * The `spec` prop, when also provided, is used INTERNALLY for\n * subflow drill-down resolution (navigating `subflowStructure` to\n * find a child chart inside the parent's serialized structure) —\n * NOT for rendering.\n */\n traceGraph?: import(\"../FlowchartView/traceStructureRecorder\").TraceGraph | null;\n /**\n * Runtime overlay captured live via `createTraceRuntimeOverlay`.\n * Pair with `traceGraph` to drive `<TracedFlow>` for the full\n * time-travel trace UI.\n */\n runtimeOverlay?: import(\"../FlowchartView/createTraceRuntimeOverlay\").RuntimeOverlay | null;\n title?: string;\n resultData?: Record<string, unknown> | null;\n logs?: string[];\n /** Structured narrative entries from `executor.getNarrativeEntries()`.\n * This is the only narrative input — the flat-string form was\n * removed; call `.map(e => e.text)` if you need it. */\n narrativeEntries?: NarrativeEntry[];\n tabs?: ShellTab[];\n defaultTab?: ShellTab;\n hideConsole?: boolean;\n /** Hide specific detail tabs (e.g., ['result', 'memory']). */\n hideTabs?: string[];\n /** Customize the labels on collapsible panel pills */\n panelLabels?: PanelLabels;\n /** Which panels start expanded. Default: `{ details: true }` */\n defaultExpanded?: DefaultExpanded;\n /**\n * Recorder views — each becomes a tab in the details panel.\n * Default: Memory + Narrative. Pass additional recorder views\n * to show tokens, cost, tools, permissions, or custom data.\n *\n * Usage:\n * recorderViews={[\n * { id: 'tokens', name: 'Tokens', render: ({ selectedIndex }) => <div>...</div> },\n * ]}\n */\n recorderViews?: RecorderView[];\n /**\n * Custom flowchart renderer. When omitted, ExplainableShell renders\n * via `<TracedFlow graph={traceGraph} overlay={runtimeOverlay} />` —\n * the recorder-driven path. Override to plug a custom chart UI; the\n * `spec` parameter is forwarded only for backward-compatible\n * signatures (it's the same SpecNode used for drill-down) and may\n * be `null` once consumers stop threading it in.\n */\n renderFlowchart?: (props: {\n spec: SpecNode | null;\n snapshots: StageSnapshot[];\n selectedIndex: number;\n onNodeClick?: (indexOrId: number | string) => void;\n showStageId?: boolean;\n }) => React.ReactNode;\n /**\n * When true, render each node's stable `stageId` as a small monospace\n * caption beneath the label in the default flowchart renderer.\n * Teaching aid: it reveals the key recorders use\n * (`runtimeStageId = [subflowPath/]stageId#executionIndex`) so a\n * consumer can map any recorder's per-stage data back to a node.\n * Default false.\n */\n showStageId?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Line + Pill — collapsed state is just a line with a pill centered on it\n// ---------------------------------------------------------------------------\n\n/** Horizontal line with centered pill (for top/bottom edges) */\nconst HLinePill = memo(function HLinePill({\n label,\n detail,\n expanded,\n onClick,\n}: {\n label: string;\n detail?: string;\n expanded: boolean;\n onClick: () => void;\n}) {\n return (\n <div style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 0,\n padding: \"0\",\n }}>\n <div style={{ flex: 1, height: 1, background: theme.border }} />\n <button\n onClick={onClick}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 5,\n padding: \"3px 12px\",\n margin: \"4px 0\",\n fontSize: 10,\n fontWeight: 600,\n fontFamily: \"inherit\",\n color: theme.textMuted,\n background: theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n cursor: \"pointer\",\n whiteSpace: \"nowrap\",\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n transition: \"color 0.15s ease\",\n }}\n >\n <span style={{ fontSize: 7 }}>{expanded ? \"▼\" : \"▶\"}</span>\n {label}\n {detail && <span style={{ fontWeight: 400, opacity: 0.5, fontSize: 9 }}>{detail}</span>}\n </button>\n <div style={{ flex: 1, height: 1, background: theme.border }} />\n </div>\n );\n});\n\n/** Vertical line with centered pill (for left/right edges).\n * `side` controls arrow direction:\n * - \"right\": expanded=▶ collapsed=◀ (panel is on right, collapses right)\n * - \"left\": expanded=◀ collapsed=▶ (panel is on left, collapses left)\n */\nconst VLinePill = memo(function VLinePill({\n label,\n expanded,\n side = \"right\",\n onClick,\n}: {\n label: string;\n expanded: boolean;\n side?: \"left\" | \"right\";\n onClick: () => void;\n}) {\n const arrow = side === \"right\"\n ? (expanded ? \"▶\" : \"◀\")\n : (expanded ? \"◀\" : \"▶\");\n return (\n <div style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: 0,\n padding: \"0\",\n }}>\n <div style={{ flex: 1, width: 1, background: theme.border }} />\n <button\n onClick={onClick}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"10px 4px\",\n margin: \"0 3px\",\n fontSize: 10,\n fontWeight: 600,\n fontFamily: \"inherit\",\n color: theme.textMuted,\n background: theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n cursor: \"pointer\",\n whiteSpace: \"nowrap\",\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n writingMode: \"vertical-lr\",\n transition: \"color 0.15s ease\",\n }}\n >\n <span style={{ fontSize: 7, writingMode: \"horizontal-tb\" }}>{arrow}</span>\n {label}\n </button>\n <div style={{ flex: 1, width: 1, background: theme.border }} />\n </div>\n );\n});\n\n// ---------------------------------------------------------------------------\n// KeyedRecorderView — Time-travel aware renderer for auto-detected recorders\n// ---------------------------------------------------------------------------\n\n/**\n * Detects if data has a keyed-recorder shape: an object property whose values\n * are objects with at least one numeric field. Returns { steps, keyType }.\n * keyType: 'runtimeStageId' (keys contain '#') or 'stageName' (plain names).\n */\nfunction detectKeyedSteps(data: unknown): { steps: Record<string, Record<string, unknown>>; keyType: \"runtimeStageId\" | \"stageName\" } | null {\n if (!data || typeof data !== \"object\") return null;\n const obj = data as Record<string, unknown>;\n for (const val of Object.values(obj)) {\n if (val && typeof val === \"object\" && !Array.isArray(val)) {\n const entries = Object.entries(val as Record<string, unknown>);\n if (entries.length === 0) continue;\n // Check: values must be objects with at least one numeric field\n const allObjectsWithNumbers = entries.every(([, v]) => {\n if (!v || typeof v !== \"object\" || Array.isArray(v)) return false;\n return Object.values(v as Record<string, unknown>).some((f) => typeof f === \"number\");\n });\n if (allObjectsWithNumbers) {\n const keyType = entries.some(([k]) => k.includes(\"#\")) ? \"runtimeStageId\" : \"stageName\";\n return { steps: val as Record<string, Record<string, unknown>>, keyType };\n }\n }\n }\n return null;\n}\n\n/** Extract render hints from recorder data: numericField name + grandTotal. */\nfunction extractRenderHints(data: unknown): { numericField: string; grandTotal: number } | null {\n if (!data || typeof data !== \"object\") return null;\n const obj = data as Record<string, unknown>;\n if (typeof obj.numericField === \"string\" && typeof obj.grandTotal === \"number\") {\n return { numericField: obj.numericField, grandTotal: obj.grandTotal };\n }\n return null;\n}\n\nfunction KeyedRecorderView({\n data,\n description,\n preferredOperation = \"accumulate\",\n snapshots,\n selectedIndex,\n}: {\n data: unknown;\n description?: string;\n preferredOperation?: \"translate\" | \"accumulate\" | \"aggregate\";\n snapshots: StageSnapshot[];\n selectedIndex: number;\n}) {\n const [showAggregate, setShowAggregate] = useState(false);\n\n const detected = useMemo(() => detectKeyedSteps(data), [data]);\n\n // Visible keys up to slider position — match by runtimeStageId or stageName\n const visibleKeys = useMemo(() => {\n const keys = new Set<string>();\n for (let i = 0; i <= selectedIndex && i < snapshots.length; i++) {\n const snap = snapshots[i];\n if (detected?.keyType === \"runtimeStageId\") {\n if (snap.runtimeStageId) keys.add(snap.runtimeStageId);\n } else {\n // Match by stageName or stageLabel\n if (snap.stageName) keys.add(snap.stageName);\n if (snap.stageLabel) keys.add(snap.stageLabel);\n }\n }\n return keys;\n }, [snapshots, selectedIndex, detected?.keyType]);\n\n const isAtEnd = selectedIndex >= snapshots.length - 1;\n\n if (!detected) {\n // Fallback: raw JSON for non-keyed data\n return (\n <div style={{ padding: 12, fontFamily: theme.fontMono, fontSize: 11, whiteSpace: \"pre-wrap\", overflow: \"auto\", height: \"100%\" }}>\n {typeof data === \"string\" ? data : JSON.stringify(data, null, 2)}\n </div>\n );\n }\n\n const steps = detected.steps;\n const hints = extractRenderHints(data);\n const numFieldKey = hints?.numericField ?? \"\";\n\n // Progressive entries (accumulate)\n const allKeys = Object.keys(steps);\n const visibleEntries = allKeys.filter((k) => visibleKeys.has(k));\n\n // Running total — computed from visible entries using the declared numeric field\n let runningTotal = 0;\n if (numFieldKey) {\n for (const k of visibleEntries) {\n runningTotal += (steps[k][numFieldKey] as number) ?? 0;\n }\n }\n\n // Grand total — provided by the recorder, not recomputed\n const grandTotal = hints?.grandTotal ?? 0;\n\n return (\n <div style={{ overflow: \"auto\", height: \"100%\", display: \"flex\", flexDirection: \"column\" }}>\n {description && (\n <div style={{ padding: \"6px 12px\", fontSize: 11, color: theme.textMuted, fontStyle: \"italic\", borderBottom: `1px solid ${theme.border}`, flexShrink: 0 }}>\n {description}\n </div>\n )}\n\n <div style={{ padding: 12, flex: 1, overflow: \"auto\" }}>\n {/* ── Primary: depends on preferredOperation ── */}\n\n {preferredOperation === \"aggregate\" ? (\n /* AGGREGATE: collect silently during scrub, button at end to reveal total */\n <>\n {isAtEnd ? (\n <div style={{ marginBottom: 16 }}>\n {!showAggregate ? (\n <button\n onClick={() => setShowAggregate(true)}\n style={{\n background: theme.primary, color: \"#fff\", border: \"none\", borderRadius: 8,\n padding: \"12px 20px\", fontSize: 13, fontWeight: 600, cursor: \"pointer\",\n fontFamily: \"inherit\", width: \"100%\",\n }}\n >\n Aggregate — Show Grand Total\n </button>\n ) : (\n <div style={{ padding: \"14px 16px\", background: `color-mix(in srgb, ${theme.success} 12%, transparent)`, borderRadius: 8, border: `1px solid ${theme.success}44` }}>\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", marginBottom: 6, fontWeight: 600 }}>\n Aggregate — grand total\n </div>\n {numFieldKey && (\n <div style={{ fontSize: 26, fontWeight: 700, color: theme.success }}>\n {grandTotal < 1 ? grandTotal.toFixed(3) : grandTotal.toFixed(1)}\n <span style={{ fontSize: 11, color: theme.textMuted, fontWeight: 400, marginLeft: 8 }}>{numFieldKey} · {allKeys.length} steps</span>\n </div>\n )}\n </div>\n )}\n </div>\n ) : (\n <div style={{ padding: \"10px 14px\", background: `color-mix(in srgb, ${theme.textMuted} 6%, transparent)`, borderRadius: 6, marginBottom: 16, border: `1px dashed ${theme.border}` }}>\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", fontWeight: 600 }}>\n Collecting data...\n </div>\n <div style={{ fontSize: 11, color: theme.textMuted, marginTop: 4 }}>\n {visibleEntries.length} of {allKeys.length} steps collected. Scrub to end to aggregate.\n </div>\n </div>\n )}\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", marginBottom: 6, fontWeight: 600 }}>\n Per-step detail\n </div>\n </>\n ) : preferredOperation === \"accumulate\" ? (\n /* ACCUMULATE: running total grows with slider — IS the total at end, no button */\n <>\n {numFieldKey && visibleEntries.length > 0 && (\n <div style={{ padding: \"10px 14px\", background: `color-mix(in srgb, ${theme.primary} 8%, transparent)`, borderRadius: 6, marginBottom: 16 }}>\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", marginBottom: 4, fontWeight: 600 }}>\n Accumulate — running total up to this step\n </div>\n <span style={{ fontWeight: 700, fontSize: 18, color: theme.primary }}>\n {runningTotal < 1 ? runningTotal.toFixed(3) : runningTotal.toFixed(1)}\n </span>\n <span style={{ color: theme.textMuted, marginLeft: 8, fontSize: 10 }}>\n {numFieldKey} · {visibleEntries.length} of {allKeys.length} steps\n </span>\n </div>\n )}\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", marginBottom: 6, fontWeight: 600 }}>\n Per-step detail\n </div>\n </>\n ) : (\n /* TRANSLATE: per-step entries prominent, no totals */\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", marginBottom: 6, fontWeight: 600 }}>\n Translate — per-step detail\n </div>\n )}\n\n {/* ── Per-step entries (always shown) ── */}\n {visibleEntries.map((key) => {\n const entry = steps[key];\n const label = (entry.stageName as string) ?? key;\n const numVal = numFieldKey ? (entry[numFieldKey] as number) : undefined;\n return (\n <div key={key} style={{ display: \"flex\", alignItems: \"center\", padding: \"4px 0\", fontSize: 12, fontFamily: theme.fontMono, borderBottom: `1px solid ${theme.border}22` }}>\n <span style={{ color: theme.textMuted, width: 140, flexShrink: 0, fontSize: 10 }}>{key}</span>\n <span style={{ fontWeight: 600, flex: 1 }}>{label}</span>\n {numVal !== undefined && (\n <span style={{ color: theme.primary, fontWeight: 700, marginLeft: 8 }}>\n {numVal < 1 ? numVal.toFixed(3) : numVal.toFixed(1)}\n </span>\n )}\n </div>\n );\n })}\n\n {visibleEntries.length === 0 && (\n <div style={{ color: theme.textMuted, fontSize: 11, fontStyle: \"italic\", padding: \"8px 0\" }}>\n Scrub the slider to reveal entries...\n </div>\n )}\n\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// DetailsContent — Recorder-driven tab switcher (Memory + Narrative are defaults)\n// ---------------------------------------------------------------------------\n\nconst DetailsContent = memo(function DetailsContent({\n snapshots,\n selectedIndex,\n narrativeEntries,\n size,\n fillHeight,\n extraViews,\n}: {\n snapshots: StageSnapshot[];\n selectedIndex: number;\n narrativeEntries?: NarrativeEntry[];\n size: \"compact\" | \"default\" | \"detailed\";\n fillHeight?: boolean;\n extraViews?: RecorderView[];\n}) {\n // Built-in views (always available)\n const builtInViews: RecorderView[] = [\n {\n id: \"memory\",\n name: \"Memory\",\n render: ({ snapshots: snaps, selectedIndex: idx }) => (\n <MemoryPanel snapshots={snaps} selectedIndex={idx} size={size} style={fillHeight ? { height: \"100%\" } : undefined} />\n ),\n },\n {\n id: \"narrative\",\n name: \"Narrative\",\n render: ({ snapshots: snaps, selectedIndex: idx }) => (\n <NarrativePanel snapshots={snaps} selectedIndex={idx} narrativeEntries={narrativeEntries} size={size} style={fillHeight ? { height: \"100%\" } : undefined} />\n ),\n },\n ];\n\n const allViews = [...builtInViews, ...(extraViews ?? [])];\n const [activeViewId, setActiveViewId] = useState(allViews[0]?.id ?? \"memory\");\n\n // Reset tab when available views change (e.g., recorder toggled on/off)\n const viewIds = allViews.map((v) => v.id).join(\",\");\n useEffect(() => {\n if (!allViews.find((v) => v.id === activeViewId)) {\n setActiveViewId(allViews[0]?.id ?? \"memory\");\n }\n }, [viewIds]); // eslint-disable-line react-hooks/exhaustive-deps\n const activeView = allViews.find((v) => v.id === activeViewId) ?? allViews[0];\n\n return (\n <div style={{ flex: 1, display: \"flex\", flexDirection: \"column\", overflow: \"hidden\" }}>\n {/* Tab switcher — one per recorder view */}\n <div style={{ display: \"flex\", borderBottom: `1px solid ${theme.border}`, flexShrink: 0, overflowX: \"auto\" }}>\n {allViews.map((view) => {\n const active = view.id === activeViewId;\n return (\n <button\n key={view.id}\n onClick={() => setActiveViewId(view.id)}\n style={{\n flex: allViews.length <= 3 ? 1 : undefined,\n padding: \"6px 8px\", fontSize: 11,\n fontWeight: active ? 600 : 400,\n color: active ? theme.primary : theme.textMuted,\n background: active ? `color-mix(in srgb, ${theme.primary} 8%, transparent)` : \"transparent\",\n border: \"none\",\n borderBottom: active ? `2px solid ${theme.primary}` : \"2px solid transparent\",\n cursor: \"pointer\", textTransform: \"uppercase\", letterSpacing: \"0.06em\", fontFamily: \"inherit\",\n whiteSpace: \"nowrap\",\n }}\n >\n {view.name}\n </button>\n );\n })}\n </div>\n <div style={{ flex: 1, overflow: \"auto\" }}>\n {activeView?.render({ snapshots, selectedIndex })}\n </div>\n </div>\n );\n});\n\n// ---------------------------------------------------------------------------\n// Subflow resolution helpers\n// ---------------------------------------------------------------------------\n\nfunction resolveSubflowLevel(\n parentSpec: SpecNode,\n parentSnapshots: StageSnapshot[],\n subflowNodeName: string,\n narrativeEntries?: NarrativeEntry[],\n): SubflowLevel | null {\n const specNode = findSubflowSpecNode(parentSpec, subflowNodeName);\n if (!specNode?.subflowStructure) return null;\n const parentSnap = parentSnapshots.find(\n (s) => s.stageName === subflowNodeName || s.stageLabel === subflowNodeName\n );\n if (!parentSnap?.subflowResult) return null;\n // Extract subflow narrative: prefer subflowId (structured), fall back to display name (text scan)\n const sfId = specNode.subflowId ?? subflowNodeName;\n const sfDisplayName = specNode.subflowName ?? specNode.name;\n const sfNarrative = narrativeEntries\n ? extractSubflowNarrative(narrativeEntries, sfId, sfDisplayName)\n : undefined;\n const sfSnapshots = subflowResultToSnapshots(parentSnap.subflowResult, sfNarrative);\n if (sfSnapshots.length === 0) return null;\n return {\n subflowId: specNode.subflowId ?? subflowNodeName,\n label: specNode.subflowName ?? specNode.name,\n spec: specNode.subflowStructure,\n snapshots: sfSnapshots,\n };\n}\n\nfunction findSubflowSpecNode(node: SpecNode, name: string): SpecNode | null {\n if ((node.name === name || node.id === name) && node.isSubflowRoot) return node;\n if (node.children) { for (const child of node.children) { const f = findSubflowSpecNode(child, name); if (f) return f; } }\n if (node.next) return findSubflowSpecNode(node.next, name);\n return null;\n}\n\nfunction hasSubflowNodes(node: SpecNode): boolean {\n if (!node) return false;\n if (node.isSubflowRoot) return true;\n if (node.children?.some((c) => c && hasSubflowNodes(c))) return true;\n if (node.next && hasSubflowNodes(node.next)) return true;\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Lightweight data trace — builds causal frames from commitLog without\n// importing footprintjs/trace. Uses the same backward-walk algorithm.\n// ---------------------------------------------------------------------------\n\ninterface CommitEntry {\n stage: string;\n stageId: string;\n runtimeStageId: string;\n trace: Array<{ path: string }>;\n}\n\nfunction buildDataTrace(\n commitLog: unknown[],\n targetRuntimeStageId: string,\n maxDepth = 10,\n): Array<{ runtimeStageId: string; stageId: string; stageName: string; keysWritten: string[]; linkedBy: string; depth: number }> {\n const log = commitLog as CommitEntry[];\n if (!log?.length) return [];\n\n const idxMap = new Map<string, number>();\n for (let i = 0; i < log.length; i++) idxMap.set(log[i].runtimeStageId, i);\n\n const startIdx = idxMap.get(targetRuntimeStageId);\n if (startIdx === undefined) return [];\n\n const startCommit = log[startIdx];\n const frames: Array<{ runtimeStageId: string; stageId: string; stageName: string; keysWritten: string[]; linkedBy: string; depth: number }> = [];\n const visited = new Set<string>();\n\n // BFS backward: for each commit, find what keys existed before it that it might have read\n // Simplified: trace the write chain backward — each commit's written keys link to whoever wrote the keys it implicitly depends on\n let current = startCommit;\n let currentIdx = startIdx;\n let depth = 0;\n\n while (current && depth <= maxDepth) {\n if (visited.has(current.runtimeStageId)) break;\n visited.add(current.runtimeStageId);\n\n frames.push({\n runtimeStageId: current.runtimeStageId,\n stageId: current.stageId,\n stageName: current.stage,\n keysWritten: current.trace.map((t) => t.path),\n linkedBy: depth === 0 ? \"\" : current.trace[0]?.path ?? \"\",\n depth,\n });\n\n // Find the previous commit (the one right before this one)\n if (currentIdx > 0) {\n currentIdx--;\n current = log[currentIdx];\n depth++;\n } else {\n break;\n }\n }\n\n return frames;\n}\n\n// ---------------------------------------------------------------------------\n// RightPanel — two-mode panel: Insights vs What Happened\n// ---------------------------------------------------------------------------\n\ntype RightPanelMode = \"insights\" | \"what\";\n\nconst RightPanel = memo(function RightPanel({\n mode,\n onModeChange,\n snapshots,\n selectedIndex,\n runtimeSnapshot,\n spec,\n activeTab,\n allTabs,\n activeNarrativeEntries,\n recorderViews,\n autoRecorderViews,\n size,\n onNavigateToStage,\n}: {\n mode: RightPanelMode;\n onModeChange: (mode: RightPanelMode) => void;\n snapshots: StageSnapshot[];\n selectedIndex: number;\n runtimeSnapshot?: RuntimeSnapshotInput | null;\n spec?: SpecNode | null;\n activeTab: string;\n allTabs: Array<{ id: string; name: string; description?: string }>;\n activeNarrativeEntries?: NarrativeEntry[];\n recorderViews?: RecorderView[];\n autoRecorderViews: Array<{ id: string; name: string; description?: string; preferredOperation?: string; data: unknown }>;\n size: \"compact\" | \"default\" | \"detailed\";\n onNavigateToStage: (id: string) => void;\n}) {\n return (\n <>\n {/* Mode toggle */}\n <div style={{\n display: \"flex\",\n borderBottom: `1px solid ${theme.border}`,\n flexShrink: 0,\n background: theme.bgSecondary,\n }}>\n {([\"insights\", \"what\"] as const).map((m) => (\n <button\n key={m}\n onClick={() => onModeChange(m)}\n style={{\n flex: 1,\n padding: \"7px 12px\",\n fontSize: 11,\n fontWeight: mode === m ? 700 : 500,\n textTransform: \"uppercase\",\n letterSpacing: \"0.06em\",\n color: mode === m ? theme.primary : theme.textMuted,\n background: \"transparent\",\n border: \"none\",\n borderBottom: mode === m ? `2px solid ${theme.primary}` : \"2px solid transparent\",\n cursor: \"pointer\",\n fontFamily: \"inherit\",\n }}\n >\n {m === \"insights\" ? \"Insights\" : \"Inspector\"}\n </button>\n ))}\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, overflow: \"hidden\" }}>\n {mode === \"insights\" ? (\n <InsightPanel\n mode=\"tabs\"\n expandedId={activeTab}\n insights={allTabs.filter((t) => t.id !== \"result\" && t.id !== \"memory\").map((tab) => ({\n id: tab.id,\n name: insightName(tab.name),\n render: () => {\n if (tab.id === \"narrative\") return <NarrativePanel snapshots={snapshots} selectedIndex={selectedIndex} narrativeEntries={activeNarrativeEntries} runtimeSnapshot={runtimeSnapshot} spec={spec} size={size} style={{ height: \"100%\" }} />;\n const customView = recorderViews?.find((v) => v.id === tab.id);\n if (customView?.render) return customView.render({ snapshots, selectedIndex });\n const autoView = autoRecorderViews.find((v) => v.id === tab.id);\n if (autoView) return <KeyedRecorderView data={autoView.data} description={autoView.description} preferredOperation={autoView.preferredOperation as any} snapshots={snapshots} selectedIndex={selectedIndex} />;\n return null;\n },\n }))}\n />\n ) : (\n <InspectorPanel\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n dataTraceFrames={runtimeSnapshot?.commitLog ? buildDataTrace(runtimeSnapshot.commitLog, snapshots[selectedIndex]?.runtimeStageId ?? '') : []}\n selectedStageId={snapshots[selectedIndex]?.runtimeStageId}\n onNavigateToStage={onNavigateToStage}\n />\n )}\n </div>\n </>\n );\n});\n\n/** Map internal recorder names to user-facing Insight names. */\nfunction insightName(name: string): string {\n const map: Record<string, string> = {\n \"Narrative\": \"Story\",\n \"Memory\": \"State\",\n \"Metrics\": \"Performance\",\n \"Quality\": \"Quality\",\n \"Cost\": \"Cost\",\n };\n return map[name] ?? name;\n}\n\nexport function ExplainableShell({\n snapshots: snapshotsProp,\n runtimeSnapshot,\n spec,\n title,\n resultData: resultDataProp,\n logs = [],\n narrativeEntries,\n tabs = [\"result\", \"explainable\"],\n defaultTab,\n hideConsole = false,\n hideTabs: hideTabsProp,\n panelLabels,\n defaultExpanded,\n recorderViews,\n renderFlowchart,\n showStageId = false,\n traceGraph,\n runtimeOverlay,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: ExplainableShellProps) {\n // Convert runtimeSnapshot → visualization snapshots (zero-boilerplate mode)\n const derivedFromRuntime = useMemo(() => {\n if (!runtimeSnapshot) return null;\n try {\n const snaps = toVisualizationSnapshots(runtimeSnapshot as any, narrativeEntries as any);\n return { snapshots: snaps, resultData: runtimeSnapshot.sharedState };\n } catch {\n return null;\n }\n }, [runtimeSnapshot, narrativeEntries]);\n\n // Use derived data when runtimeSnapshot is provided, otherwise use explicit props\n const snapshots = snapshotsProp ?? derivedFromRuntime?.snapshots ?? [];\n const resultData = resultDataProp ?? derivedFromRuntime?.resultData ?? null;\n\n // Flowchart renderer selection (v6+ — recorder-driven only):\n // - explicit `renderFlowchart` always wins (consumer override)\n // - `traceGraph` → render via `<TracedFlow>` (event-driven graph\n // + optional runtime overlay, no spec-tree post-walk)\n //\n // Consumers MUST pass `traceGraph` for chart visualization. The\n // legacy `spec={...}` → post-walk fallback was removed when the\n // recorder gained convergence-edge expansion (post-fork `next`\n // fires N edges, one per branch child) — the recorder graph is now\n // the single source of truth.\n const tracedFlowRenderer = useMemo(() => {\n if (!traceGraph) return undefined;\n return ({ selectedIndex, snapshots, onNodeClick }: {\n spec: SpecNode | null; snapshots: StageSnapshot[]; selectedIndex: number;\n onNodeClick?: (indexOrId: number | string) => void;\n showStageId?: boolean;\n }) => {\n // The shell's `selectedIndex` indexes into `snapshots[]` (which\n // may be filtered to a drill-down subset). The overlay's\n // `executionOrder` is the FULL execution timeline (all stages\n // including subflow internals). When the two arrays have\n // different lengths, passing selectedIndex straight through\n // misaligns the chart's active highlight.\n //\n // Translate: take the runtimeStageId at snapshots[selectedIndex]\n // and find the matching position in overlay.executionOrder.\n // Fall back to selectedIndex when no overlay or no match\n // (charts without subflows have aligned indexes anyway).\n const activeRsid = snapshots[selectedIndex]?.runtimeStageId;\n let overlayIdx = selectedIndex;\n if (activeRsid && runtimeOverlay) {\n const i = runtimeOverlay.executionOrder.findIndex(\n (s) => s.runtimeStageId === activeRsid,\n );\n if (i >= 0) overlayIdx = i;\n }\n return (\n <TracedFlow\n graph={traceGraph}\n overlay={runtimeOverlay ?? undefined}\n scrubIndex={overlayIdx}\n onNodeClick={(stageId) => onNodeClick?.(stageId)}\n onSubflowChange={(mountId) => {\n // Forward chart's drill state to the shell's drill-down\n // stack so memory/narrative/timeline panels follow the\n // chart into/out of subflows. We route through the same\n // onNodeClick channel — it already triggers drill-down\n // for subflow mount nodes via the shell's handleNodeClick\n // → handleDrillDown path.\n //\n // The `mountId === null` case (popping back to top) is\n // intentionally NOT auto-triggered here: the shell's\n // breadcrumb-back button is the right user gesture for\n // navigating UP from a subflow. Auto-popping on scrub\n // would surprise users who manually drilled in.\n if (mountId !== null) onNodeClick?.(mountId);\n }}\n />\n );\n };\n }, [traceGraph, runtimeOverlay]);\n const effectiveRenderFlowchart = renderFlowchart ?? tracedFlowRenderer;\n const leftLabel = panelLabels?.topology ?? \"Topology\";\n const rightLabel = panelLabels?.details ?? \"Details\";\n const bottomLabel = panelLabels?.timeline ?? \"Timeline\";\n\n // Responsive: detect narrow container + notify children of size changes\n const shellRef = useRef<HTMLDivElement>(null);\n const [isNarrow, setIsNarrow] = useState(false);\n const [isMedium, setIsMedium] = useState(false);\n useEffect(() => {\n const el = shellRef.current;\n if (!el) return;\n const ro = new ResizeObserver(([entry]) => {\n const w = entry.contentRect.width;\n setIsNarrow(w < 640);\n setIsMedium(w >= 640 && w < 960);\n // Notify ReactFlow (and other layout-sensitive children) that our container resized\n window.dispatchEvent(new Event(\"resize\"));\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n // Auto-detect recorder views from runtimeSnapshot.recorders\n const autoRecorderViews = useMemo(() => {\n const recorders = (runtimeSnapshot as any)?.recorders as Array<{ id: string; name: string; description?: string; preferredOperation?: string; data: unknown }> | undefined;\n if (!recorders?.length) return [];\n // Don't auto-generate for IDs that have explicit recorderViews\n const explicitIds = new Set((recorderViews ?? []).map((v) => v.id));\n return recorders\n .filter((r) => !explicitIds.has(r.id))\n .map((r) => ({ id: r.id, name: r.name, description: r.description, preferredOperation: r.preferredOperation, data: r.data }));\n }, [runtimeSnapshot, recorderViews]);\n\n // Build tab list: Result + Memory (always), Narrative (when data exists),\n // explicit recorder views, auto-detected recorder views\n const hasNarrative = !!narrativeEntries?.length;\n const allTabs = useMemo(() => {\n const tabs: Array<{ id: string; name: string; description?: string }> = [\n { id: \"result\", name: \"Result\", description: \"Final output and console logs\" },\n { id: \"memory\", name: \"Memory\", description: \"Accumulator — progressive shared state at each stage\" },\n ];\n if (hasNarrative) {\n tabs.push({ id: \"narrative\", name: \"Narrative\", description: \"Translator (SequenceRecorder) — interleaved flow + data narrative per execution step\" });\n }\n for (const v of recorderViews ?? []) {\n tabs.push({ id: v.id, name: v.name, description: v.description });\n }\n for (const v of autoRecorderViews) {\n tabs.push({ id: v.id, name: v.name, description: v.description });\n }\n // Filter hidden tabs\n const hideSet = new Set(hideTabsProp ?? []);\n return hideSet.size > 0 ? tabs.filter((t) => !hideSet.has(t.id)) : tabs;\n }, [hasNarrative, recorderViews, autoRecorderViews, hideTabsProp]);\n\n const validTabIds = new Set(allTabs.map((t) => t.id));\n const resolvedDefault = defaultTab && validTabIds.has(defaultTab) ? defaultTab : allTabs[0]?.id ?? \"result\";\n const [activeTab, setActiveTab] = useState<string>(resolvedDefault);\n const [snapshotIdx, setSnapshotIdx] = useState(0);\n const [drillDownStack, setDrillDownStack] = useState<DrillDownEntry[]>([]);\n const [rightExpanded, setRightExpanded] = useState(defaultExpanded?.details ?? true);\n const [rightPanelMode, setRightPanelMode] = useState<\"insights\" | \"what\">(\"insights\");\n const [leftExpanded, setLeftExpanded] = useState(defaultExpanded?.topology ?? false);\n const [timelineExpanded, setTimelineExpanded] = useState(defaultExpanded?.timeline ?? false);\n\n // Auto-collapse all panels when switching to narrow (mobile)\n useEffect(() => {\n if (isNarrow) {\n setLeftExpanded(false);\n setRightExpanded(false);\n setTimelineExpanded(false);\n }\n }, [isNarrow]);\n\n // Notify ReactFlow (and any ResizeObserver-based children) when panels toggle\n const triggerReflow = useCallback(() => {\n // Fire twice: once immediately for fast response, once after CSS transition ends\n requestAnimationFrame(() => window.dispatchEvent(new Event(\"resize\")));\n setTimeout(() => window.dispatchEvent(new Event(\"resize\")), 320);\n }, []);\n const toggleLeft = useCallback((v: boolean) => { setLeftExpanded(v); triggerReflow(); }, [triggerReflow]);\n const toggleRight = useCallback((v: boolean) => { setRightExpanded(v); triggerReflow(); }, [triggerReflow]);\n const toggleTimeline = useCallback(() => { setTimelineExpanded((p) => !p); triggerReflow(); }, [triggerReflow]);\n\n const isInSubflow = drillDownStack.length > 0;\n\n const currentLevel = useMemo(() => {\n if (drillDownStack.length > 0) {\n const top = drillDownStack[drillDownStack.length - 1];\n return { spec: top.spec, snapshots: top.snapshots };\n }\n return { spec: spec ?? null, snapshots };\n }, [drillDownStack, spec, snapshots]);\n\n const activeSnapshots = currentLevel.snapshots;\n const activeSpec = currentLevel.spec;\n const safeIdx = activeSnapshots.length > 0\n ? Math.max(0, Math.min(snapshotIdx, activeSnapshots.length - 1))\n : 0;\n\n const activeNarrativeEntries = isInSubflow ? undefined : narrativeEntries;\n\n const breadcrumbs = useMemo(() => {\n const root = { label: title || \"Flowchart\", spec: spec!, description: spec?.description };\n return [root, ...drillDownStack.map((e) => ({ label: e.label, spec: e.spec, description: undefined as string | undefined }))];\n }, [spec, title, drillDownStack]);\n\n // Recorder-driven: derive subflow presence from the build-time graph.\n // Falls back to the legacy spec walk only when traceGraph is absent\n // (e.g., a consumer still threading raw spec). When both are absent,\n // the tree sidebar is hidden.\n const showTreeSidebar = useMemo(() => {\n if (traceGraph?.nodes?.length) {\n return traceGraph.nodes.some((n) => n.data?.isSubflow === true);\n }\n return !!spec && hasSubflowNodes(spec);\n }, [traceGraph, spec]);\n\n const rootOverlay = useMemo(() => {\n if (isInSubflow || !snapshots.length) return { activeStage: undefined, doneStages: undefined };\n const doneStages = new Set(snapshots.slice(0, safeIdx).map((s) => s.stageLabel));\n const activeStage = snapshots[safeIdx]?.stageLabel ?? null;\n return { activeStage, doneStages };\n }, [isInSubflow, snapshots, safeIdx]);\n\n // ── Handlers ──\n const handleTabChange = useCallback((tab: ShellTab) => {\n setActiveTab(tab);\n setDrillDownStack([]);\n }, []);\n\n const handleSnapshotChange = useCallback((idx: number | string) => {\n if (typeof idx === \"number\") setSnapshotIdx(idx);\n }, []);\n\n const handleDrillDown = useCallback(\n (nodeName: string) => {\n if (!activeSpec) return;\n const entry = resolveSubflowLevel(activeSpec, activeSnapshots, nodeName, narrativeEntries);\n if (entry) {\n setDrillDownStack((prev) => [...prev, { ...entry, parentSnapshotIdx: snapshotIdx }]);\n setSnapshotIdx(0);\n }\n },\n [activeSpec, activeSnapshots, narrativeEntries, snapshotIdx]\n );\n\n const handleBreadcrumbNavigate = useCallback((level: number) => {\n setDrillDownStack((prev) => {\n const popped = level === 0 ? prev[0] : prev[level];\n if (popped) setSnapshotIdx(popped.parentSnapshotIdx);\n return level === 0 ? [] : prev.slice(0, level);\n });\n }, []);\n\n const handleNodeClick = useCallback(\n (indexOrId: number | string) => {\n if (typeof indexOrId === \"number\") { setSnapshotIdx(indexOrId); return; }\n if (activeSpec) {\n const sfNode = findSubflowSpecNode(activeSpec, indexOrId);\n if (sfNode?.subflowStructure) { handleDrillDown(indexOrId); return; }\n }\n const idx = activeSnapshots.findIndex((s) => s.stageLabel === indexOrId);\n if (idx >= 0) setSnapshotIdx(idx);\n },\n [activeSpec, activeSnapshots, handleDrillDown]\n );\n\n const handleTreeNodeSelect = useCallback(\n (name: string, isSubflow: boolean) => {\n if (isSubflow && spec) {\n setDrillDownStack([]);\n const entry = resolveSubflowLevel(spec, snapshots, name, narrativeEntries);\n if (entry) { setDrillDownStack([{ ...entry, parentSnapshotIdx: snapshotIdx }]); setSnapshotIdx(0); }\n } else {\n setDrillDownStack([]);\n const idx = snapshots.findIndex((s) => s.stageLabel === name);\n if (idx >= 0) setSnapshotIdx(idx);\n }\n },\n [spec, snapshots, narrativeEntries, snapshotIdx]\n );\n\n // Map tab id → label for rendering\n const tabLabels = new Map(allTabs.map((t) => [t.id, t.name]));\n\n // ── Unstyled mode ──\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"explainable-shell\">\n <div data-fp=\"shell-tabs\">\n {allTabs.map((tab) => (\n <button key={tab.id} data-fp=\"shell-tab\" data-active={tab.id === activeTab} onClick={() => handleTabChange(tab.id)}>{tab.name}</button>\n ))}\n </div>\n <div data-fp=\"shell-content\" data-tab={activeTab}>\n {activeTab === \"result\" && <ResultPanel data={resultData ?? null} logs={logs} hideConsole={hideConsole} unstyled />}\n {(activeTab === \"explainable\" || activeTab === \"ai-compatible\") && (\n <>\n <TimeTravelControls snapshots={activeSnapshots} selectedIndex={safeIdx} onIndexChange={handleSnapshotChange} unstyled />\n {isInSubflow && <SubflowBreadcrumb breadcrumbs={breadcrumbs} onNavigate={handleBreadcrumbNavigate} />}\n {activeSpec && effectiveRenderFlowchart?.({ spec: activeSpec, snapshots: activeSnapshots, selectedIndex: safeIdx, onNodeClick: handleNodeClick, showStageId })}\n <MemoryPanel snapshots={activeSnapshots} selectedIndex={safeIdx} unstyled />\n <NarrativePanel snapshots={activeSnapshots} selectedIndex={safeIdx} narrativeEntries={activeNarrativeEntries} unstyled />\n <GanttTimeline snapshots={activeSnapshots} selectedIndex={safeIdx} onSelect={handleSnapshotChange} unstyled />\n </>\n )}\n </div>\n </div>\n );\n }\n\n // ── Styled mode ──\n\n // Show topology when spec has subflows\n const showTopology = !!effectiveRenderFlowchart && !!activeSpec;\n\n // Render the active details tab content\n const detailsContent = useMemo(() => {\n if (activeTab === \"result\") {\n return <ResultPanel data={resultData ?? null} logs={logs} hideConsole={hideConsole} size={size} />;\n }\n if (activeTab === \"memory\") {\n return <MemoryPanel snapshots={activeSnapshots} selectedIndex={safeIdx} size={size} style={{ height: \"100%\" }} />;\n }\n if (activeTab === \"narrative\") {\n return <NarrativePanel snapshots={activeSnapshots} selectedIndex={safeIdx} narrativeEntries={activeNarrativeEntries} size={size} style={{ height: \"100%\" }} />;\n }\n const customView = recorderViews?.find((v) => v.id === activeTab);\n if (customView?.render) {\n return customView.render({ snapshots: activeSnapshots, selectedIndex: safeIdx });\n }\n // Auto-detected recorder view — time-travel aware for keyed recorders, JSON fallback\n const autoView = autoRecorderViews.find((v) => v.id === activeTab);\n if (autoView) {\n return (\n <KeyedRecorderView\n data={autoView.data}\n description={autoView.description}\n preferredOperation={autoView.preferredOperation as \"translate\" | \"accumulate\" | \"aggregate\" | undefined}\n snapshots={activeSnapshots}\n selectedIndex={safeIdx}\n />\n );\n }\n return null;\n }, [activeTab, resultData, logs, hideConsole, size, activeSnapshots, safeIdx, activeNarrativeEntries, recorderViews, autoRecorderViews]);\n\n // Details panel with internal tabs\n const detailsPanel = (\n <div style={{ display: \"flex\", flexDirection: \"column\", height: \"100%\", overflow: \"hidden\" }}>\n {/* Tab bar inside details panel */}\n <div style={{\n display: \"flex\",\n borderBottom: `1px solid ${theme.border}`,\n background: theme.bgSecondary,\n flexShrink: 0,\n overflowX: \"auto\",\n }}>\n {allTabs.map((tab) => {\n const active = tab.id === activeTab;\n return (\n <button\n key={tab.id}\n onClick={() => handleTabChange(tab.id as ShellTab)}\n title={tab.description}\n style={{\n padding: \"6px 14px\",\n fontSize: 11,\n fontWeight: active ? 700 : 500,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n color: active ? theme.primary : theme.textMuted,\n background: \"transparent\",\n border: \"none\",\n borderBottom: active ? `2px solid ${theme.primary}` : \"2px solid transparent\",\n cursor: \"pointer\",\n fontFamily: \"inherit\",\n whiteSpace: \"nowrap\",\n }}\n >\n {tab.name}\n </button>\n );\n })}\n </div>\n {/* Tab content */}\n <div style={{ flex: 1, overflow: \"auto\" }}>\n {detailsContent}\n </div>\n </div>\n );\n\n return (\n <div\n ref={shellRef}\n className={className}\n style={{\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n background: theme.bgPrimary,\n color: theme.textPrimary,\n fontFamily: theme.fontSans,\n fontSize: 12,\n ...style,\n }}\n data-fp=\"explainable-shell\"\n >\n {/* Time-travel slider */}\n <TimeTravelControls\n snapshots={activeSnapshots}\n selectedIndex={safeIdx}\n onIndexChange={handleSnapshotChange}\n size={size}\n />\n\n {/* Breadcrumb */}\n {isInSubflow && (\n <SubflowBreadcrumb breadcrumbs={breadcrumbs} onNavigate={handleBreadcrumbNavigate} />\n )}\n\n {/* Content */}\n <div style={{ flex: 1, overflow: isNarrow ? \"auto\" : \"hidden\", display: \"flex\", flexDirection: \"column\" }}>\n {isNarrow ? (\n /* ── Mobile: stacked vertical ── */\n <>\n {/* Flowchart — only when topology is relevant */}\n {showTopology && (\n <div style={{ height: 350, flexShrink: 0, overflow: \"hidden\" }}>\n {effectiveRenderFlowchart!({\n spec: activeSpec!,\n snapshots: activeSnapshots,\n selectedIndex: safeIdx,\n onNodeClick: handleNodeClick,\n showStageId,\n })}\n </div>\n )}\n\n {/* Topology (subflow tree) — collapsible */}\n {showTreeSidebar && (\n <>\n <HLinePill label={leftLabel} expanded={leftExpanded} onClick={() => toggleLeft(!leftExpanded)} />\n {leftExpanded && (\n <div style={{ maxHeight: 180, overflow: \"auto\", flexShrink: 0 }}>\n <SubflowTree\n graph={traceGraph ?? { nodes: [], edges: [] }}\n activeStage={rootOverlay.activeStage}\n doneStages={rootOverlay.doneStages}\n onNodeSelect={handleTreeNodeSelect}\n />\n </div>\n )}\n </>\n )}\n\n {/* Details panel with tabs */}\n <HLinePill label={rightLabel} expanded={rightExpanded} onClick={() => toggleRight(!rightExpanded)} />\n {rightExpanded && (\n <div style={{ maxHeight: 350, flexShrink: 0, overflow: \"hidden\" }}>\n {detailsPanel}\n </div>\n )}\n\n {/* Timeline */}\n <HLinePill label={bottomLabel} detail={`${activeSnapshots.length} stages`} expanded={timelineExpanded} onClick={toggleTimeline} />\n {timelineExpanded && (\n <div style={{ flexShrink: 0, overflow: \"hidden\" }}>\n <GanttTimeline snapshots={activeSnapshots} selectedIndex={safeIdx} onSelect={handleSnapshotChange} size={size} />\n </div>\n )}\n </>\n ) : (\n /* ── Desktop: two-column — Flowchart | Right Panel ── */\n <>\n <div style={{ flex: 1, display: \"flex\", overflow: \"hidden\" }}>\n\n {/* SubflowTree sidebar (only when subflows exist) */}\n {showTreeSidebar && (\n leftExpanded ? (\n <div style={{ width: 180, flexShrink: 0, display: \"flex\", flexDirection: \"row\", overflow: \"hidden\" }}>\n <div style={{ flex: 1, overflow: \"auto\" }}>\n <SubflowTree\n graph={traceGraph ?? { nodes: [], edges: [] }}\n activeStage={rootOverlay.activeStage}\n doneStages={rootOverlay.doneStages}\n onNodeSelect={handleTreeNodeSelect}\n />\n </div>\n <VLinePill label=\"Topology\" expanded={true} side=\"left\" onClick={() => toggleLeft(false)} />\n </div>\n ) : (\n <VLinePill label=\"Topology\" expanded={false} side=\"left\" onClick={() => toggleLeft(true)} />\n )\n )}\n\n {/* Center: Flowchart — flex:1, shares horizontal space with\n the Details panel sibling when expanded. The chart's\n TracedFlow refits itself via ResizeObserver whenever\n this container's size changes (so opening/closing\n Details re-runs xyflow's fitView automatically). */}\n {showTopology ? (\n <div style={{ flex: 1, overflow: \"hidden\", minWidth: 0 }}>\n {effectiveRenderFlowchart!({\n spec: activeSpec!,\n snapshots: activeSnapshots,\n selectedIndex: safeIdx,\n onNodeClick: handleNodeClick,\n showStageId,\n })}\n </div>\n ) : (\n <div style={{ flex: 1 }} />\n )}\n\n {/* VLinePill divider between flowchart and right panel */}\n <VLinePill label=\"Details\" expanded={rightExpanded} onClick={() => toggleRight(!rightExpanded)} />\n\n {/* Right: Two-mode panel — Insights vs Inspector */}\n {rightExpanded && (\n <div style={{ width: \"42%\", minWidth: 320, maxWidth: 550, display: \"flex\", flexDirection: \"column\", overflow: \"hidden\" }}>\n <RightPanel\n mode={rightPanelMode}\n onModeChange={setRightPanelMode}\n snapshots={activeSnapshots}\n selectedIndex={safeIdx}\n runtimeSnapshot={runtimeSnapshot}\n spec={spec}\n activeTab={activeTab}\n allTabs={allTabs}\n activeNarrativeEntries={activeNarrativeEntries}\n recorderViews={recorderViews}\n autoRecorderViews={autoRecorderViews}\n size={size}\n onNavigateToStage={(id) => {\n const idx = activeSnapshots.findIndex((s) => s.runtimeStageId === id);\n if (idx >= 0) setSnapshotIdx(idx);\n }}\n />\n </div>\n )}\n </div>\n\n {/* Bottom: Compact Timeline */}\n <CompactTimeline\n snapshots={activeSnapshots}\n selectedIndex={safeIdx}\n defaultExpanded={timelineExpanded}\n />\n </>\n )}\n </div>\n </div>\n );\n}\n","/**\n * Narrative sync utilities — shared logic for mapping timeline position\n * to narrative entries. Used by NarrativePanel and available to consumers\n * building custom visualization shells.\n */\nimport type { StageSnapshot, NarrativeEntry } from \"../types\";\n\n// ── Entry Range Index ───────────────────────────────────────────────────────\n\n/**\n * Range index: runtimeStageId → half-open range [firstIdx, endIdx) in entries array.\n *\n * This is the same shape as `SequenceRecorder.getEntryRanges()` in footprintjs.\n * When you have recorder access, pass `recorder.getEntryRanges()` directly.\n * When you only have the flat array, use `buildEntryRangeIndex()` to build it.\n */\nexport type EntryRangeIndex = ReadonlyMap<string, { readonly firstIdx: number; readonly endIdx: number }>;\n\n/**\n * Build a range index from a flat entries array for O(1) per-step lookups.\n * Equivalent to `SequenceRecorder.getEntryRanges()` but works on detached arrays.\n *\n * Call once when narrativeEntries changes, then pass to `computeRevealedEntryCount`.\n *\n * @param entries — structured entries (from CombinedNarrativeRecorder.getEntries() or getNarrativeEntries())\n * @returns range index for fast slider sync\n */\nexport function buildEntryRangeIndex(entries: Pick<NarrativeEntry, \"runtimeStageId\">[]): EntryRangeIndex {\n const ranges = new Map<string, { firstIdx: number; endIdx: number }>();\n let lastId: string | undefined;\n\n for (let i = 0; i < entries.length; i++) {\n const id = entries[i].runtimeStageId;\n if (id) {\n const existing = ranges.get(id);\n if (!existing) {\n ranges.set(id, { firstIdx: i, endIdx: i + 1 });\n } else {\n existing.endIdx = i + 1;\n }\n lastId = id;\n } else if (lastId) {\n // Structural marker — extend preceding step's range\n ranges.get(lastId)!.endIdx = i + 1;\n }\n }\n\n return ranges;\n}\n\n// ── Revealed Entry Count ────────────────────────────────────────────────────\n\n/**\n * Compute how many narrative entries to reveal at a given slider position.\n *\n * **With range index (preferred):** O(selectedIndex) — one Map lookup per snapshot.\n * **Without index (convenience):** O(entries) forward scan.\n *\n * The range index can come from:\n * - `SequenceRecorder.getEntryRanges()` (when you have recorder access)\n * - `buildEntryRangeIndex(entries)` (when you only have the flat array)\n *\n * @param narrativeEntries — structured entries from CombinedNarrativeRecorder\n * @param snapshots — execution timeline (from adapter)\n * @param selectedIndex — current slider position (0-based)\n * @param rangeIndex — optional precomputed range index for O(1) lookups\n * @returns number of entries to reveal (0 to narrativeEntries.length)\n */\nexport function computeRevealedEntryCount(\n narrativeEntries: NarrativeEntry[],\n snapshots: Pick<StageSnapshot, \"runtimeStageId\">[],\n selectedIndex: number,\n rangeIndex?: EntryRangeIndex,\n): number {\n if (!narrativeEntries.length || snapshots.length === 0) return 0;\n\n if (rangeIndex) {\n // Fast path: O(selectedIndex) with Map lookups\n let maxEndIdx = 0;\n for (let si = 0; si <= selectedIndex && si < snapshots.length; si++) {\n const targetId = snapshots[si].runtimeStageId;\n if (!targetId) continue;\n const range = rangeIndex.get(targetId);\n if (range && range.endIdx > maxEndIdx) {\n maxEndIdx = range.endIdx;\n }\n }\n return maxEndIdx;\n }\n\n // Fallback: forward scan (no index provided)\n let entryIdx = 0;\n for (let si = 0; si <= selectedIndex && si < snapshots.length; si++) {\n const targetId = snapshots[si].runtimeStageId;\n if (!targetId) continue;\n\n let found = false;\n for (let j = entryIdx; j < narrativeEntries.length; j++) {\n if (narrativeEntries[j].runtimeStageId === targetId) {\n found = true;\n entryIdx = j;\n break;\n }\n }\n if (!found) continue;\n\n while (entryIdx < narrativeEntries.length) {\n const eId = narrativeEntries[entryIdx].runtimeStageId;\n if (eId && eId !== targetId) break;\n entryIdx++;\n }\n }\n return entryIdx;\n}\n\n// ── Subflow Extraction ──────────────────────────────────────────────────────\n\n/**\n * Extract narrative entries belonging to a specific subflow.\n *\n * Three-tier matching (most reliable first):\n * 1. `stageName` prefix match (e.g., entries with `stageName` starting with `\"sf-pay/\"`)\n * 2. `subflowId` field match\n * 3. `direction` field on subflow entry/exit markers (renderer-agnostic)\n *\n * @param entries — all narrative entries from the execution\n * @param subflowId — subflow identifier to extract\n * @param subflowName — optional display name for fallback matching\n * @returns entries belonging to the subflow\n */\nexport function extractSubflowNarrative(\n entries: NarrativeEntry[],\n subflowId: string,\n subflowName?: string,\n): NarrativeEntry[] {\n // Primary: filter by stageName prefix\n const prefix = subflowId + \"/\";\n const byPrefix = entries.filter((e) => e.stageName?.startsWith(prefix));\n if (byPrefix.length > 0) return byPrefix;\n\n // Fallback: structured subflowId field\n const byId = entries.filter((e) => e.subflowId === subflowId);\n if (byId.length > 0) return byId;\n\n // Last resort: use direction field on subflow entries (renderer-agnostic)\n const result: NarrativeEntry[] = [];\n const searchName = subflowName ?? subflowId;\n let inside = false;\n for (const entry of entries) {\n if (entry.type === \"subflow\" && entry.direction === \"entry\" && entry.stageName === searchName) { inside = true; continue; }\n if (inside && entry.type === \"subflow\" && entry.direction === \"exit\" && entry.stageName === searchName) break;\n if (inside) result.push(entry);\n }\n return result;\n}\n","import type { StageSnapshot, NarrativeEntry } from \"../types\";\n\n/**\n * Shape of FootPrint's RuntimeSnapshot (from FlowChartExecutor.getSnapshot()).\n * We define it here instead of importing to avoid a hard dependency on footprintjs.\n */\ninterface RuntimeStageSnapshot {\n id: string;\n /** `stageId#executionIndex` — the universal per-execution key. Joins this\n * tree node to its commit-log bundles for cumulative-memory replay. */\n runtimeStageId?: string;\n name?: string;\n isDecider?: boolean;\n isFork?: boolean;\n /** User-level writes made by this stage (pre-namespace keys → values). */\n stageWrites?: Record<string, unknown>;\n logs: Record<string, unknown>;\n errors: Record<string, unknown>;\n metrics: Record<string, unknown>;\n evals: Record<string, unknown>;\n flowMessages?: unknown[];\n description?: string;\n subflowId?: string;\n next?: RuntimeStageSnapshot;\n children?: RuntimeStageSnapshot[];\n}\n\ninterface RecorderSnapshot {\n id: string;\n name: string;\n data: unknown;\n}\n\ninterface RuntimeSnapshot {\n sharedState: Record<string, unknown>;\n executionTree: RuntimeStageSnapshot;\n commitLog: unknown[];\n /** Per-subflow execution results (keyed by subflowId). */\n subflowResults?: Record<string, unknown>;\n /** Snapshots from recorders that implement toSnapshot() (e.g. MetricRecorder). */\n recorders?: RecorderSnapshot[];\n}\n\n// NarrativeEntry: canonical definition lives in types.ts.\n// Re-export here for backward compatibility (index.ts re-exports as AdapterNarrativeEntry).\nexport type { NarrativeEntry } from '../types';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Cumulative-memory accumulation — commit-bundle replay + deep patch merge\n// ─────────────────────────────────────────────────────────────────────────────\n//\n// Why whole-key overwrite of `stageWrites` is NOT enough: footprintjs's\n// change-only commit semantics record a deep write (`scope.applicant.address\n// .zip = ...`) as a net-change PATCH (`{applicant: {address: {zip}}}`), and\n// `StageSnapshot.stageWrites` keeps only the LAST write per key — so a\n// set-then-deep-write stage surfaces only the patch and the per-stage memory\n// view dropped sibling fields (`applicant.name`) that the engine's\n// `sharedState` correctly holds.\n//\n// The faithful source is `RuntimeSnapshot.commitLog`: each `CommitBundle`\n// carries the stage's `overwrite` (full values for `set` paths), `updates`\n// (accumulated deltas for `merge` paths), and the ordered `trace`\n// (`[{path, verb}]`) — the same triple footprintjs's own `applySmartMerge`\n// replays onto live state. We mirror that replay onto the cumulative memory\n// view, keyed by `runtimeStageId` (tree node ↔ commit bundle join). When no\n// bundle is available (older snapshots, subflow drill-down histories with\n// empty runtimeStageIds), we fall back to `stageWrites` accumulation,\n// upgraded from whole-key overwrite to `mergeWritePatch` so patches no\n// longer erase siblings.\n\n/** Path delimiter used by footprintjs's commit `trace` entries\n * (`normalisePath` joins segments with U+001F UNIT SEPARATOR). */\nconst COMMIT_PATH_DELIM = \"\\u001F\";\n\n/** Keys that must never be assigned via bracket-write on a plain object —\n * `obj['__proto__'] = x` mutates the prototype, not an own property. */\nconst UNSAFE_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\n/** Duck-typed slice of footprintjs's `CommitBundle` the replay consumes. */\ninterface CommitBundleLike {\n runtimeStageId?: string;\n overwrite?: Record<string, unknown>;\n updates?: Record<string, unknown>;\n trace?: { path: string; verb: string }[];\n}\n\n/** `__writeSummary` / `__readSummary` marker objects (footprintjs's\n * `writeTracking: 'summary'` dial) are ATOMIC placeholders, not data —\n * the merge passes them through and never recurses into them. */\nfunction isSummaryMarker(value: unknown): boolean {\n return (\n value !== null &&\n typeof value === \"object\" &&\n ((value as Record<string, unknown>).__writeSummary === true ||\n (value as Record<string, unknown>).__readSummary === true)\n );\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/**\n * Deep-merges a net-change write PATCH into a base value for the\n * cumulative-memory VIEW — the visualization-side mirror of footprintjs's\n * `deepSmartMerge` (the `merge`-verb arm of `applySmartMerge`).\n *\n * Semantics:\n * - plain objects: object-spread per level — patch keys win, base\n * siblings survive (the gap this helper closes)\n * - **arrays: REPLACE, not union-merge.** Deliberate divergence from\n * footprintjs's `deepSmartMerge` (which unions non-empty arrays with\n * reference-equality dedup). A memory VIEW should show the array a\n * consumer would read at that moment: the dominant array-write path\n * (TypedScope copy-on-write push / `$batchArray`) commits as a `set`\n * of the full final array anyway, and union-replay of the rare\n * `merge`-verb array delta can fabricate element mixes (reference\n * dedup never dedupes deep-equal objects) that the display has no\n * way to reconcile. Replace is predictable and loses nothing the\n * patch didn't carry.\n * - summary markers (`__writeSummary`/`__readSummary`): atomic — a marker\n * patch replaces the key wholesale, and nothing merges INTO a marker\n * - primitives / null / type mismatches: patch wins\n *\n * Pure: never mutates `base` or `patch`; merged branches are fresh objects.\n */\nexport function mergeWritePatch(base: unknown, patch: unknown): unknown {\n if (isSummaryMarker(patch)) return patch;\n if (patch === null || typeof patch !== \"object\") return patch;\n if (Array.isArray(patch)) return patch; // arrays REPLACE (see JSDoc)\n if (isSummaryMarker(base) || !isPlainRecord(base)) {\n // Nothing mergeable underneath — take the patch (fresh copy so later\n // in-place view writes never reach the caller's object).\n base = {};\n }\n const out: Record<string, unknown> = { ...(base as Record<string, unknown>) };\n for (const [key, value] of Object.entries(patch)) {\n if (UNSAFE_KEYS.has(key)) continue;\n out[key] = mergeWritePatch(out[key], value);\n }\n return out;\n}\n\n/** Reads a delimited commit path out of a patch object. Undefined-safe. */\nfunction getPath(root: unknown, segs: string[]): unknown {\n let cur: unknown = root;\n for (const seg of segs) {\n if (!isPlainRecord(cur) && !Array.isArray(cur)) return undefined;\n cur = (cur as Record<string, unknown>)[seg];\n }\n return cur;\n}\n\n/**\n * Writes `value` at a delimited commit path, copy-on-write along the way:\n * every container on the path is cloned before mutation so sibling stage\n * snapshots (which share nested refs via the per-stage shallow copy) are\n * never retroactively edited.\n */\nfunction setPath(memory: Record<string, unknown>, segs: string[], value: unknown): void {\n if (segs.some((s) => UNSAFE_KEYS.has(s))) return;\n let obj: Record<string, unknown> = memory;\n for (let i = 0; i < segs.length - 1; i++) {\n const cur = obj[segs[i]!];\n const next: Record<string, unknown> = Array.isArray(cur)\n ? (cur.slice() as unknown as Record<string, unknown>)\n : isPlainRecord(cur) && !isSummaryMarker(cur)\n ? { ...cur }\n : {};\n obj[segs[i]!] = next;\n obj = next;\n }\n const last = segs[segs.length - 1]!;\n if (value === undefined) {\n delete obj[last];\n } else {\n obj[last] = value;\n }\n}\n\n/**\n * Replays one commit bundle onto the cumulative memory view — mirrors\n * footprintjs's `applySmartMerge` verb arms:\n * - `set` → overwrite with the full final value from `overwrite[path]`\n * (`undefined` = the historical delete-flattened-to-set —\n * removes the key)\n * - `merge` → `mergeWritePatch` the accumulated `updates[path]` delta in\n * - `append` → concat the recorded tail onto the current array; degrade\n * to a direct set when either side isn't an array (matches\n * upstream's redaction/corrupt-base behavior)\n * - `delete` → remove the key\n * Bundles without a `trace` (older engines) degrade to: apply every\n * `overwrite` key as a set, then deep-merge every `updates` key.\n */\nfunction applyCommitBundle(memory: Record<string, unknown>, bundle: CommitBundleLike): void {\n const trace = Array.isArray(bundle.trace) ? bundle.trace : undefined;\n if (trace) {\n for (const op of trace) {\n if (!op || typeof op.path !== \"string\") continue;\n const segs = op.path.split(COMMIT_PATH_DELIM);\n if (op.verb === \"merge\") {\n setPath(memory, segs, mergeWritePatch(getPath(memory, segs), getPath(bundle.updates, segs)));\n } else if (op.verb === \"append\") {\n const tail = getPath(bundle.overwrite, segs);\n const current = getPath(memory, segs);\n setPath(memory, segs, Array.isArray(current) && Array.isArray(tail) ? [...current, ...tail] : tail);\n } else if (op.verb === \"delete\") {\n setPath(memory, segs, undefined);\n } else {\n // 'set' (and unknown verbs — treat as the terminal overwrite)\n setPath(memory, segs, getPath(bundle.overwrite, segs));\n }\n }\n return;\n }\n if (isPlainRecord(bundle.overwrite)) {\n for (const [key, value] of Object.entries(bundle.overwrite)) setPath(memory, [key], value);\n }\n if (isPlainRecord(bundle.updates)) {\n for (const [key, value] of Object.entries(bundle.updates)) {\n setPath(memory, [key], mergeWritePatch(memory[key], value));\n }\n }\n}\n\n/**\n * Indexes commit bundles by `runtimeStageId`. A stage execution can emit\n * MORE than one bundle (e.g. a subflow mount commits the outputMapper\n * result, then an empty boundary bundle) — all are kept, in log order.\n * Entries without a non-empty `runtimeStageId` (subflow drill-down\n * histories) are skipped; those trees fall back to `stageWrites`.\n */\nfunction indexCommitLog(commitLog: unknown[] | undefined): Map<string, CommitBundleLike[]> {\n const index = new Map<string, CommitBundleLike[]>();\n if (!Array.isArray(commitLog)) return index;\n for (const entry of commitLog) {\n if (!isPlainRecord(entry)) continue;\n const bundle = entry as CommitBundleLike;\n if (typeof bundle.runtimeStageId !== \"string\" || bundle.runtimeStageId.length === 0) continue;\n if (!isPlainRecord(bundle.overwrite) && !isPlainRecord(bundle.updates) && !Array.isArray(bundle.trace)) {\n continue;\n }\n const list = index.get(bundle.runtimeStageId);\n if (list) list.push(bundle);\n else index.set(bundle.runtimeStageId, [bundle]);\n }\n return index;\n}\n\n/**\n * Converts a FootPrint RuntimeSnapshot into a flat array of StageSnapshots\n * suitable for visualization components.\n *\n * The `narrativeEntries` parameter (from `executor.getNarrativeEntries()`)\n * distributes the library's rich combined narrative per-stage.\n * When narrative is not enabled, stages get \"Narrative not available\" —\n * this adapter reflects what the library produces, nothing more.\n *\n * Usage:\n * ```ts\n * const executor = new FlowChartExecutor(chart);\n * await executor.run();\n * const snapshots = toVisualizationSnapshots(\n * executor.getSnapshot(),\n * executor.getNarrativeEntries(),\n * );\n * ```\n */\nexport function toVisualizationSnapshots(\n runtime: RuntimeSnapshot,\n narrativeEntries?: NarrativeEntry[],\n): StageSnapshot[] {\n const stageNarrativeMap = narrativeEntries?.length\n ? buildStageNarrativeMap(narrativeEntries)\n : new Map<string, string[]>();\n\n // Extract per-stage timings from MetricRecorder if present in snapshot.recorders.\n const stageTimings = extractStageTimings(runtime.recorders);\n\n // Commit-bundle index for faithful cumulative-memory replay (see the\n // accumulation rationale above). Empty map when the snapshot carries no\n // usable commitLog — stages then fall back to stageWrites accumulation.\n const commitIndex = indexCommitLog(runtime.commitLog);\n\n const snapshots: StageSnapshot[] = [];\n flattenTree(runtime.executionTree, snapshots, runtime.sharedState, 0, runtime.subflowResults, {}, stageNarrativeMap, stageTimings, commitIndex);\n return snapshots;\n}\n\n/**\n * Extracts per-stage duration data from recorder snapshots.\n *\n * Post-KeyedRecorder MetricRecorder serializes as\n * { name: 'Metrics', data: { steps: { [runtimeStageId]: { stageName, duration, ... } } } }\n *\n * Older versions emitted `data.stages[stageName].totalDuration` directly;\n * we still accept that shape for back-compat when loading old snapshots.\n *\n * Stages that ran multiple times (e.g. CallLLM inside a loop) have one\n * entry per invocation keyed by runtimeStageId — sum their durations by\n * stageName so the GanttTimeline shows cumulative wall time per stage.\n */\nfunction extractStageTimings(recorders?: RecorderSnapshot[]): Map<string, number> {\n const timings = new Map<string, number>();\n if (!recorders) return timings;\n for (const rec of recorders) {\n if (rec.name !== 'Metrics' || !rec.data || typeof rec.data !== 'object') continue;\n const data = rec.data as {\n steps?: Record<string, { stageName?: string; duration?: number }>;\n stages?: Record<string, { totalDuration?: number }>;\n };\n // New shape: data.steps[runtimeStageId] = { stageName, duration, ... }\n if (data.steps) {\n for (const step of Object.values(data.steps)) {\n const name = step?.stageName;\n const d = step?.duration;\n if (!name || typeof d !== 'number' || d <= 0) continue;\n timings.set(name, Math.round((timings.get(name) ?? 0) + d));\n }\n }\n // Legacy shape: data.stages[stageName].totalDuration\n if (data.stages) {\n for (const [stageName, metrics] of Object.entries(data.stages)) {\n if (typeof metrics.totalDuration === 'number' && metrics.totalDuration > 0) {\n timings.set(stageName, Math.round(metrics.totalDuration));\n }\n }\n }\n }\n return timings;\n}\n\n/**\n * Groups narrative entries by stage name, preserving non-stage entries\n * (conditions, forks) attached to the preceding stage.\n */\nfunction buildStageNarrativeMap(entries: NarrativeEntry[]): Map<string, string[]> {\n const map = new Map<string, string[]>();\n let currentStageName: string | undefined;\n\n for (const entry of entries) {\n if (entry.stageName) {\n currentStageName = entry.stageName;\n }\n\n if (currentStageName) {\n if (!map.has(currentStageName)) {\n map.set(currentStageName, []);\n }\n const indent = ' '.repeat(entry.depth);\n map.get(currentStageName)!.push(`${indent}${entry.text}`);\n }\n }\n\n\n return map;\n}\n\nfunction flattenTree(\n node: RuntimeStageSnapshot,\n out: StageSnapshot[],\n sharedState: Record<string, unknown>,\n accumulatedMs: number = 0,\n subflowResults?: Record<string, unknown>,\n cumulativeMemory: Record<string, unknown> = {},\n stageNarrativeMap: Map<string, string[]> = new Map(),\n stageTimings: Map<string, number> = new Map(),\n commitIndex: Map<string, CommitBundleLike[]> = new Map(),\n): number {\n // Prefer MetricRecorder timing (real wall-clock), then scope.$metric('durationMs'), then 0.\n const stageName = node.name ?? node.id;\n const durationMs =\n (stageName ? stageTimings.get(stageName) : undefined) ??\n (typeof node.metrics?.durationMs === \"number\" ? node.metrics.durationMs : 0);\n\n const startMs = accumulatedMs;\n // Use id for matching (stable, matches spec node ids).\n // name may carry display prefixes like \"[service-name] STAGE\".\n const stageId = node.id || node.name || 'unknown';\n const displayName = node.name || node.id || 'unknown';\n\n // Narrative comes from the library. When not available (e.g. subflow internals\n // where the root recorder only captures enter/exit markers), build a basic\n // narrative from the stage name, description, and data operations.\n // Try id first, then name — narrative entries use node.name (may be prefixed)\n // while snapshot uses node.id (stable). Both need to match for subflows.\n const stageLines = stageNarrativeMap.get(stageId) ?? stageNarrativeMap.get(displayName);\n let narrative: string;\n if (stageLines) {\n narrative = stageLines.join('\\n');\n } else {\n const parts: string[] = [`${displayName} executed.`];\n if (node.description) parts.push(node.description);\n if (node.stageWrites) {\n const keys = Object.keys(node.stageWrites);\n if (keys.length > 0) parts.push(`Wrote: ${keys.join(', ')}`);\n }\n narrative = parts.join('\\n');\n }\n\n // Build cumulative memory. Preferred source: this execution's commit\n // bundles (replayed with engine verb semantics — set/merge/append/delete —\n // so deep-write patches keep sibling fields, exactly like the engine's\n // sharedState). Fallback: stageWrites, deep-merged via mergeWritePatch\n // (whole-key overwrite would erase siblings on net-change patches).\n const memory = { ...cumulativeMemory };\n const bundles = node.runtimeStageId ? commitIndex.get(node.runtimeStageId) : undefined;\n if (bundles && bundles.length > 0) {\n for (const bundle of bundles) applyCommitBundle(memory, bundle);\n } else if (node.stageWrites) {\n for (const [key, value] of Object.entries(node.stageWrites)) {\n if (UNSAFE_KEYS.has(key)) continue;\n if (value === undefined) {\n delete memory[key];\n } else {\n memory[key] = mergeWritePatch(memory[key], value);\n }\n }\n }\n\n // Prefer the per-iteration result keyed by this node's UNIQUE runtimeStageId, falling back to\n // the subflow PATH key. A LOOPING subflow re-enters with the same `subflowId`, so the path key\n // holds only the LAST iteration — keying by `runtimeStageId` gives THIS iteration's drill-down\n // (footprintjs dual-keys subflowResults; see docs/design/subflow-commit-visibility.md). The\n // fallback keeps non-looping subflows and older snapshots working unchanged.\n const sfResult =\n (node.runtimeStageId ? subflowResults?.[node.runtimeStageId] : undefined) ??\n subflowResults?.[node.subflowId ?? stageId];\n\n out.push({\n stageName: displayName,\n stageLabel: stageId,\n runtimeStageId: node.runtimeStageId ?? undefined,\n memory,\n narrative,\n startMs,\n durationMs,\n status: \"done\",\n ...(node.description ? { description: node.description } : undefined),\n ...(node.subflowId ? { subflowId: node.subflowId } : undefined),\n ...(sfResult ? { subflowResult: sfResult } : undefined),\n });\n\n let nextMs = startMs + durationMs;\n\n // Handle parallel children (fork)\n if (node.children && node.children.length > 0) {\n let maxChildEnd = nextMs;\n for (const child of node.children) {\n const childEnd = flattenTree(child, out, sharedState, nextMs, subflowResults, memory, stageNarrativeMap, stageTimings, commitIndex);\n maxChildEnd = Math.max(maxChildEnd, childEnd);\n }\n nextMs = maxChildEnd;\n }\n\n // Handle linear continuation\n if (node.next) {\n nextMs = flattenTree(node.next, out, sharedState, nextMs, subflowResults, memory, stageNarrativeMap, stageTimings, commitIndex);\n }\n\n return nextMs;\n}\n\n/**\n * Converts a footprintjs SubflowResult (stored on StageSnapshot.subflowResult)\n * into visualization snapshots for drill-down views.\n *\n * SubflowResult shape (from footprintjs):\n * { subflowId, subflowName, treeContext: { globalContext, stageContexts, history }, parentStageId }\n *\n * Returns empty array if the input is not a valid SubflowResult.\n */\nexport function subflowResultToSnapshots(\n subflowResult: unknown,\n narrativeEntries?: NarrativeEntry[],\n): StageSnapshot[] {\n if (!subflowResult || typeof subflowResult !== 'object') return [];\n const sf = subflowResult as {\n subflowId?: string;\n treeContext?: {\n globalContext?: Record<string, unknown>;\n stageContexts?: unknown;\n history?: unknown[];\n };\n };\n if (!sf.treeContext?.stageContexts) return [];\n\n const runtime: RuntimeSnapshot = {\n sharedState: sf.treeContext.globalContext ?? {},\n executionTree: sf.treeContext.stageContexts as RuntimeStageSnapshot,\n commitLog: sf.treeContext.history ?? [],\n };\n\n const snapshots = toVisualizationSnapshots(runtime, narrativeEntries);\n\n // Strip subflow prefix from stage names so they match the spec node names.\n // Runtime names are prefixed (e.g., \"analyze/SeedScope\") but spec nodes\n // use unprefixed names (e.g., \"SeedScope\").\n const prefix = sf.subflowId ? `${sf.subflowId}/` : '';\n if (prefix) {\n for (const snap of snapshots) {\n if (snap.stageName.startsWith(prefix)) {\n snap.stageName = snap.stageName.slice(prefix.length);\n }\n if (snap.stageLabel.startsWith(prefix)) {\n snap.stageLabel = snap.stageLabel.slice(prefix.length);\n }\n }\n }\n\n return snapshots;\n}\n\n/**\n * Creates StageSnapshots from simple arrays (when you don't have a RuntimeSnapshot).\n * Useful for testing or custom data sources.\n */\nexport function createSnapshots(\n stages: Array<{\n name: string;\n label?: string;\n memory?: Record<string, unknown>;\n narrative?: string;\n durationMs?: number;\n description?: string;\n subflowId?: string;\n }>\n): StageSnapshot[] {\n let accMs = 0;\n return stages.map((s) => {\n const duration = s.durationMs ?? 1;\n const snap: StageSnapshot = {\n stageName: s.name,\n stageLabel: s.label ?? s.name,\n memory: s.memory ?? {},\n narrative: s.narrative ?? `${s.label ?? s.name} completed.`,\n startMs: accMs,\n durationMs: duration,\n status: \"done\",\n ...(s.description ? { description: s.description } : undefined),\n ...(s.subflowId ? { subflowId: s.subflowId } : undefined),\n };\n accMs += duration;\n return snap;\n });\n}\n","/**\n * MemoryPanel — Commit-history based view of pipeline state.\n *\n * Shows accumulated memory at the selected snapshot + what changed.\n * Data source: Scope Recorder (transactional state from SharedMemory).\n *\n * This is a thin composition of MemoryInspector + ScopeDiff — no logic\n * of its own, just correct data derivation from snapshots + index.\n */\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme } from \"../../theme\";\nimport { MemoryInspector } from \"../MemoryInspector\";\nimport { ScopeDiff } from \"../ScopeDiff\";\n\nexport interface MemoryPanelProps extends BaseComponentProps {\n snapshots: StageSnapshot[];\n selectedIndex: number;\n}\n\nexport function MemoryPanel({\n snapshots,\n selectedIndex,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: MemoryPanelProps) {\n const prevMemory = selectedIndex > 0\n ? snapshots[selectedIndex - 1]?.memory ?? null\n : null;\n const currMemory = snapshots[selectedIndex]?.memory ?? {};\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"memory-panel\">\n <MemoryInspector snapshots={snapshots} selectedIndex={selectedIndex} unstyled />\n <ScopeDiff previous={prevMemory} current={currMemory} unstyled />\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n overflow: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n ...style,\n }}\n data-fp=\"memory-panel\"\n >\n <MemoryInspector snapshots={snapshots} selectedIndex={selectedIndex} size={size} />\n <div style={{ borderTop: `1px solid ${theme.border}` }}>\n <ScopeDiff previous={prevMemory} current={currMemory} hideUnchanged size={size} />\n </div>\n </div>\n );\n}\n","/**\n * NarrativePanel — Recorder-based view of pipeline execution.\n *\n * Renders the execution narrative with progressive reveal synced to\n * snapshot index. Consumes structured NarrativeEntries (from\n * CombinedNarrativeRecorder) — the primary data source. Falls back to\n * per-stage `snapshot.narrative` fields (built by the runtime adapter)\n * when no entries are supplied.\n *\n * Data source: FlowRecorder (fires AFTER stage execution)\n */\nimport { useMemo, useState, useCallback } from \"react\";\nimport type { StageSnapshot, NarrativeEntry, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\nimport { buildEntryRangeIndex, computeRevealedEntryCount } from \"../../utils/narrativeSync\";\nimport { StoryNarrative } from \"../StoryNarrative\";\nimport { NarrativeTrace } from \"../NarrativeTrace\";\n\n/**\n * JSON.stringify with a circular-ref sentinel and a size cap — snapshots\n * can contain cycles (runtime stages reference each other) and can grow\n * multi-megabyte. A strict JSON.stringify would throw; the clipboard cap\n * stops \"Copy for LLM\" from dumping 20MB of tool history into a paste.\n */\nfunction safeJsonStringify(value: unknown): string {\n const seen = new WeakSet<object>();\n const MAX_CHARS = 500_000;\n try {\n let text = JSON.stringify(\n value,\n (_key, v) => {\n if (typeof v === \"object\" && v !== null) {\n if (seen.has(v as object)) return \"[Circular]\";\n seen.add(v as object);\n }\n return v;\n },\n 2,\n );\n if (text && text.length > MAX_CHARS) {\n text = text.slice(0, MAX_CHARS) + `\\n... [truncated at ${MAX_CHARS} chars]`;\n }\n return text ?? \"undefined\";\n } catch (err) {\n return `[stringify error: ${err instanceof Error ? err.message : String(err)}]`;\n }\n}\n\nexport interface NarrativePanelProps extends BaseComponentProps {\n snapshots: StageSnapshot[];\n selectedIndex: number;\n /** Structured narrative entries (primary source — richer rendering).\n * When absent, falls back to per-stage `snapshot.narrative` lines. */\n narrativeEntries?: NarrativeEntry[];\n /**\n * Full runtime snapshot from the runner (executor.getSnapshot() /\n * agent.getSnapshot()). When present, \"Copy for LLM\" includes the\n * commit log, final shared state, and recorder snapshots alongside\n * the rendered narrative. Without it, only the rendered text is\n * copied — useful but misses the tool-call payloads and state\n * transitions needed to debug why a run failed.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n runtimeSnapshot?: any;\n /**\n * Flowchart spec from the runner (executor.getSpec() / agent.getSpec()).\n * When present, \"Copy for LLM\" appends the topology so the LLM can\n * see which node was running at each step — not just the narrative.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n spec?: any;\n}\n\nexport function NarrativePanel({\n snapshots,\n selectedIndex,\n narrativeEntries,\n runtimeSnapshot,\n spec,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: NarrativePanelProps) {\n const fs = fontSize[size];\n const pad = padding[size];\n\n // Build plain narrative lines from per-stage snapshot.narrative.\n // Used as fallback when narrativeEntries is empty, and for the\n // progressive-reveal text view in the legacy code path.\n const narrative = useMemo<string[]>(() => {\n const lines: string[] = [];\n for (const snap of snapshots) {\n const stageLines = (snap.narrative ?? \"\").split(\"\\n\").filter(Boolean);\n lines.push(...stageLines);\n }\n return lines;\n }, [snapshots]);\n\n // Progressive reveal for plain narrative\n const revealedCount = useMemo(() => {\n if (snapshots.length === 0 || narrative.length === 0) return narrative.length;\n const stageBoundaries: number[] = [];\n for (let i = 0; i < narrative.length; i++) {\n const trimmed = narrative[i].trimStart();\n if (trimmed.startsWith(\"Stage \") && !trimmed.match(/^Stage\\s+\\d+:\\s*Step\\s/)) {\n stageBoundaries.push(i);\n }\n }\n if (stageBoundaries.length === 0) {\n const ratio = (selectedIndex + 1) / snapshots.length;\n return Math.max(1, Math.ceil(narrative.length * ratio));\n }\n const groupsToShow = Math.min(selectedIndex + 1, stageBoundaries.length);\n const endIdx = groupsToShow < stageBoundaries.length\n ? stageBoundaries[groupsToShow]\n : narrative.length;\n return Math.max(1, endIdx);\n }, [snapshots.length, selectedIndex, narrative]);\n\n // Precompute range index once when entries change — O(n) build, then O(1) per slider tick.\n // Same shape as SequenceRecorder.getEntryRanges() in footprintjs.\n const rangeIndex = useMemo(\n () => narrativeEntries?.length ? buildEntryRangeIndex(narrativeEntries) : undefined,\n [narrativeEntries],\n );\n\n // Exact sync via runtimeStageId — O(selectedIndex) with precomputed index.\n const revealedEntryCount = useMemo(\n () => narrativeEntries?.length ? computeRevealedEntryCount(narrativeEntries, snapshots, selectedIndex, rangeIndex) : 0,\n [narrativeEntries, snapshots, selectedIndex, rangeIndex],\n );\n\n const hasStructured = narrativeEntries && narrativeEntries.length > 0;\n\n // ── Copy as LLM-ready text ─────────────────────────────────────────────\n const [copied, setCopied] = useState(false);\n\n const buildLLMNarrative = useCallback(() => {\n if (!narrativeEntries?.length) {\n return narrative.join(\"\\n\");\n }\n\n // ── Partition entries: root vs subflow internals ─────────────────\n // Root includes: stages, subflow entry/exit markers, decisions, loops, breaks\n // Subflow internals: entries with subflowId that aren't entry/exit markers\n const root: NarrativeEntry[] = [];\n const subflows = new Map<string, NarrativeEntry[]>();\n const subflowNames = new Map<string, string>(); // sfId → display name\n\n for (const entry of narrativeEntries) {\n const sfId = entry.subflowId;\n if (!sfId) {\n root.push(entry);\n } else {\n // Subflow ENTRY markers go in root (show WHEN the subflow ran).\n // Exit markers are noise — the next stage implies completion.\n if (entry.type === \"subflow\") {\n const isExit = entry.direction === 'exit';\n if (!isExit) {\n root.push(entry);\n }\n // Track name for the subflow details header\n if (entry.stageName && !isExit) {\n subflowNames.set(sfId, entry.stageName);\n }\n } else {\n // Internal subflow entries go in the subflow detail section\n if (!subflows.has(sfId)) subflows.set(sfId, []);\n subflows.get(sfId)!.push(entry);\n }\n }\n }\n\n // ── Render a list of entries as numbered text ────────────────────\n // Uses only entry.text (already rendered by the NarrativeRenderer).\n // No type prefix — the renderer output IS the narrative.\n const renderEntries = (entries: NarrativeEntry[], opts?: { inSubflow?: string }): string => {\n let counter = 0;\n const lines: string[] = [];\n\n for (const e of entries) {\n // Skip subflow entry/exit in subflow details (redundant — we're already in the section)\n if (opts?.inSubflow && e.type === \"subflow\") continue;\n\n let text = e.text;\n\n // Strip subflow path prefix from stage names inside subflow details.\n // e.g., \"[sf-system-prompt/ResolvePrompt]\" → \"[ResolvePrompt]\"\n // The section header already identifies the subflow.\n // Uses literal string replacement (not regex) to avoid injection from special characters.\n if (opts?.inSubflow) {\n const prefix = `[${opts.inSubflow}/`;\n const idx = text.indexOf(prefix);\n if (idx !== -1) {\n text = text.slice(0, idx) + \"[\" + text.slice(idx + prefix.length);\n }\n }\n\n const isHeading = e.type === \"stage\" || e.type === \"subflow\" || e.type === \"fork\" || e.type === \"selector\";\n\n if (isHeading) {\n counter++;\n // For subflow markers in root, append the subflow ID for drill-down\n const sfId = (e as { subflowId?: string }).subflowId;\n const idSuffix = e.type === \"subflow\" && sfId ? ` [→ ${sfId}]` : \"\";\n lines.push(`${counter}. ${text}${idSuffix}`);\n } else {\n // Sub-items (steps, conditions, loops, breaks, errors) — indented\n lines.push(` ${text}`);\n }\n }\n\n return lines.join(\"\\n\");\n };\n\n // ── Assemble the full LLM-ready document ────────────────────────\n const sections: string[] = [];\n sections.push(\"## Execution Narrative\\n\");\n sections.push(renderEntries(root));\n\n if (subflows.size > 0) {\n sections.push(\"\\n\\n## Subflow Details\");\n sections.push(\"Use the subflow IDs above to look up details below.\\n\");\n for (const [sfId, entries] of subflows) {\n const name = subflowNames.get(sfId) ?? sfId;\n sections.push(`### ${name} (${sfId})\\n`);\n sections.push(renderEntries(entries, { inSubflow: sfId }));\n sections.push(\"\");\n }\n }\n\n // ── Append the full debug bundle when caller provided snapshot/spec ──\n // Everything below the narrative is for LLM debugging: final state,\n // per-stage commit log (shows EXACTLY what each stage wrote), spec\n // topology, and any recorder snapshots (metrics, tokens, instructions,\n // emit events). Without these the story has no payloads to reason over.\n if (runtimeSnapshot) {\n const snap = runtimeSnapshot as {\n sharedState?: unknown;\n commitLog?: unknown;\n recorders?: unknown;\n subflowResults?: unknown;\n };\n\n if (snap.sharedState !== undefined) {\n sections.push(\"\\n\\n## Final Shared State\");\n sections.push(\"```json\");\n sections.push(safeJsonStringify(snap.sharedState));\n sections.push(\"```\");\n }\n\n if (Array.isArray(snap.commitLog) && snap.commitLog.length > 0) {\n sections.push(\"\\n\\n## Commit Log\");\n sections.push(\n \"Each entry = one stage execution's writes to shared state. \" +\n \"`rsid` is the runtimeStageId (use it to correlate with narrative + executionTree).\\n\",\n );\n sections.push(\"```json\");\n sections.push(safeJsonStringify(snap.commitLog));\n sections.push(\"```\");\n }\n\n if (snap.recorders && typeof snap.recorders === \"object\") {\n sections.push(\"\\n\\n## Recorder Snapshots\");\n sections.push(\n \"Per-recorder data captured DURING the run (metrics, tokens, instructions, emit events).\\n\",\n );\n sections.push(\"```json\");\n sections.push(safeJsonStringify(snap.recorders));\n sections.push(\"```\");\n }\n\n if (snap.subflowResults && typeof snap.subflowResults === \"object\") {\n const keys = Object.keys(snap.subflowResults as Record<string, unknown>);\n if (keys.length > 0) {\n sections.push(\"\\n\\n## Subflow Results\");\n sections.push(\"```json\");\n sections.push(safeJsonStringify(snap.subflowResults));\n sections.push(\"```\");\n }\n }\n }\n\n if (spec) {\n sections.push(\"\\n\\n## Flowchart Spec (topology)\");\n sections.push(\n \"Node + edge metadata for the chart that ran. Useful for 'where in \" +\n \"the graph did step N happen?' questions.\\n\",\n );\n sections.push(\"```json\");\n sections.push(safeJsonStringify(spec));\n sections.push(\"```\");\n }\n\n return sections.join(\"\\n\");\n }, [narrativeEntries, narrative, runtimeSnapshot, spec]);\n\n const handleCopy = useCallback(async () => {\n const text = buildLLMNarrative();\n await navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [buildLLMNarrative]);\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"narrative-panel\">\n {hasStructured ? (\n <StoryNarrative entries={narrativeEntries!} revealedEntryCount={revealedEntryCount} unstyled />\n ) : (\n <NarrativeTrace narrative={narrative} revealedCount={revealedCount} unstyled />\n )}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n overflow: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n ...style,\n }}\n data-fp=\"narrative-panel\"\n >\n {/* Intro + Copy button */}\n <div\n style={{\n padding: `${pad - 4}px ${pad}px`,\n fontSize: fs.small,\n color: theme.textMuted,\n borderBottom: `1px solid ${theme.border}`,\n flexShrink: 0,\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span style={{ fontStyle: \"italic\" }}>\n What happened at each stage, what data flowed, what decisions were made, and why.\n </span>\n <button\n onClick={handleCopy}\n title=\"Copy narrative as LLM-ready text (includes subflow details)\"\n style={{\n background: copied ? theme.success : theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: 4,\n padding: \"2px 8px\",\n fontSize: fs.small,\n color: copied ? \"#fff\" : theme.textSecondary,\n cursor: \"pointer\",\n flexShrink: 0,\n marginLeft: 8,\n transition: \"all 0.2s\",\n }}\n >\n {copied ? \"Copied!\" : \"Copy for LLM\"}\n </button>\n </div>\n {hasStructured ? (\n <StoryNarrative\n entries={narrativeEntries!}\n revealedEntryCount={revealedEntryCount}\n size={size}\n style={{ flex: 1 }}\n />\n ) : (\n <NarrativeTrace\n narrative={narrative}\n revealedCount={revealedCount}\n size={size}\n style={{ flex: 1 }}\n />\n )}\n </div>\n );\n}\n","/**\n * StoryNarrative — Rich rendering of structured narrative entries.\n *\n * Recorder-based view: renders CombinedNarrativeRecorder output with\n * progressive reveal synced to snapshot index. Each entry is typed\n * (stage, step, condition, fork, subflow, loop, break, error) and\n * rendered with appropriate icon + indentation.\n *\n * Data source: FlowRecorder (fires AFTER stage execution)\n */\nimport { useMemo, useRef, useEffect } from \"react\";\nimport type { NarrativeEntry, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\nexport interface StoryNarrativeProps extends BaseComponentProps {\n /** Structured narrative entries from CombinedNarrativeRecorder */\n entries: NarrativeEntry[];\n /** Number of entries to reveal (position-based sync from NarrativePanel) */\n revealedEntryCount: number;\n}\n\nconst ENTRY_ICONS: Record<string, { icon: string; color: string; label: string }> = {\n stage: { icon: \"▸\", color: theme.primary, label: \"Stage\" },\n step: { icon: \"·\", color: theme.textMuted, label: \"Data operation\" },\n condition: { icon: \"◇\", color: theme.warning, label: \"Decision\" },\n fork: { icon: \"⑃\", color: theme.primary, label: \"Parallel\" },\n selector: { icon: \"⑃\", color: theme.primary, label: \"Selector\" },\n subflow: { icon: \"↳\", color: theme.textSecondary, label: \"Subflow\" },\n loop: { icon: \"↻\", color: theme.warning, label: \"Loop\" },\n break: { icon: \"■\", color: theme.error, label: \"Break\" },\n error: { icon: \"✗\", color: theme.error, label: \"Error\" },\n};\n\nexport function StoryNarrative({\n entries,\n revealedEntryCount,\n size = \"default\",\n unstyled = false,\n className,\n style: outerStyle,\n}: StoryNarrativeProps) {\n const fs = fontSize[size];\n const pad = padding[size];\n\n // Position-based reveal: NarrativePanel computes the cut point based on\n // section boundaries (stage entries). This handles loops (same stageId,\n // different iterations) and subflow repeats correctly.\n const revealedCount = revealedEntryCount;\n\n // Filter revealed entries: show root-level entries + subflow Entering/Exiting markers.\n // Subflow internal entries (stage, step, condition inside a subflow) are hidden —\n // they appear in the drill-down view.\n const revealed = useMemo(() => {\n const raw = entries.slice(0, revealedCount);\n return raw.filter((e) => {\n const sfId = (e as { subflowId?: string }).subflowId;\n if (!sfId) return true; // root-level — always show\n if (e.type === \"subflow\") return true; // Entering/Exiting markers — show\n return false; // internal subflow entries — hide (drill-down only)\n });\n }, [entries, revealedCount]);\n // Future count: only count entries that would actually be shown (same filter as revealed)\n const futureCount = useMemo(() => {\n let count = 0;\n for (let i = revealedCount; i < entries.length; i++) {\n const e = entries[i] as { subflowId?: string };\n if (!e.subflowId || entries[i].type === \"subflow\") count++;\n }\n return count;\n }, [entries, revealedCount]);\n\n const latestRef = useRef<HTMLDivElement>(null);\n useEffect(() => {\n latestRef.current?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }, [revealed.length]);\n\n // Compute heading numbers for each revealed entry.\n // Flat sequential counter matching flowchart traversal (DFS visit order):\n // 1. [Stage: Seed] ...\n // 2. [Subflow: SystemPrompt] ...\n // 3. [Subflow: Messages] ...\n // 4. [Stage: ApplyPreparedMessages] ...\n //\n // Counter increments on: stage, subflow entry, condition, first fork in sequence.\n // No counter on: step, subflow exit, loop, break, error, subsequent forks.\n const numberedEntries = useMemo(() => {\n let counter = 0;\n // Track subflow enter/exit: first occurrence of type=subflow per stageId = enter, second = exit.\n const subflowSeen = new Set<string>();\n let prevType = \"\";\n\n return revealed.map((entry) => {\n // Strip legacy \"Stage N: \" prefix from text (default renderer)\n let cleanText = entry.text;\n cleanText = cleanText.replace(/^Stage \\d+:\\s*/, \"\");\n // Detect fork type BEFORE stripping prefix\n const isSelector = entry.type === \"fork\" && entry.text.includes(\"[Selected]\");\n cleanText = cleanText.replace(/^\\[(Selected|Parallel)\\]:\\s*/, \"\");\n\n // ── Subflow: detect enter vs exit by toggle ──\n if (entry.type === \"subflow\") {\n // Use stageId as toggle key (unique per subflow visit).\n // Fall back to text for renderers that don't set stageId.\n const toggleKey = (entry as { stageId?: string }).stageId ?? entry.text;\n const isExit = subflowSeen.has(toggleKey);\n if (!isExit) {\n subflowSeen.add(toggleKey);\n counter++;\n return {\n ...entry,\n heading: `${counter}`,\n headingType: \"Subflow\",\n text: cleanText,\n isHeading: true,\n isSubflow: true,\n };\n }\n // Exit marker — no heading, will be hidden in render\n return { ...entry, heading: null, isHeading: false, isSubflowExit: true };\n }\n\n // ── Stage ──\n if (entry.type === \"stage\") {\n counter++;\n return { ...entry, heading: `${counter}`, headingType: \"Stage\", text: cleanText, isHeading: true };\n }\n\n // ── Condition (decision) — nested under the preceding stage, no separate number ──\n if (entry.type === \"condition\") {\n return { ...entry, heading: null, headingType: \"Decision\", text: cleanText, isHeading: false };\n }\n\n // ── Fork / Selector — first in sequence gets number ──\n if (entry.type === \"fork\" || entry.type === \"selector\") {\n const isForkHeading = prevType !== \"fork\" && prevType !== \"selector\";\n prevType = entry.type;\n if (isForkHeading) {\n counter++;\n const typeLabel = entry.type === \"selector\" || isSelector ? \"Selector\" : \"Fork\";\n return { ...entry, heading: `${counter}`, headingType: typeLabel, text: cleanText, isHeading: true };\n }\n return { ...entry, heading: null, isHeading: false, text: cleanText };\n }\n\n prevType = entry.type;\n // loop, break, step, error — no heading number\n // Loop is a back-edge (not a new node), break is termination signal\n return { ...entry, heading: null, isHeading: false };\n });\n }, [revealed]);\n\n if (unstyled) {\n return (\n <div className={className} style={outerStyle} data-fp=\"story-narrative\" role=\"log\">\n {numberedEntries.map((entry, i) => {\n if ((entry as any).isSubflowExit) return null;\n const ht = (entry as any).headingType;\n return (\n <div key={i} data-fp=\"narrative-entry\" data-type={entry.type}>\n {entry.heading\n ? entry.text.startsWith('[')\n ? `${entry.heading}. ${entry.text}`\n : `${entry.heading}. [${ht}: ${entry.stageName ?? ''}] ${entry.text}`\n : entry.text}\n </div>\n );\n })}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n flex: 1,\n overflow: \"auto\",\n padding: pad,\n fontFamily: theme.fontSans,\n ...outerStyle,\n }}\n data-fp=\"story-narrative\"\n role=\"log\"\n aria-label=\"Execution narrative\"\n >\n {numberedEntries.map((entry, i) => {\n // Skip subflow exit markers — entry marker is enough\n if ((entry as any).isSubflowExit) return null;\n\n const meta = ENTRY_ICONS[entry.type] ?? ENTRY_ICONS.step;\n const isHeading = entry.isHeading;\n const isDecision = entry.type === \"condition\";\n const isError = entry.type === \"error\";\n const isBreak = entry.type === \"break\";\n const isSubflow = (entry as any).isSubflow;\n const isLast = i === numberedEntries.length - 1;\n const headingType = (entry as any).headingType as string | undefined;\n\n return (\n <div\n key={i}\n ref={isLast ? latestRef : undefined}\n style={{\n display: \"flex\",\n gap: 8,\n padding: isHeading ? `${pad - 4}px 0` : `2px 0`,\n marginLeft: entry.depth * 16,\n borderBottom: isHeading ? `1px solid ${theme.border}` : undefined,\n marginTop: isHeading && i > 0 ? 8 : 0,\n }}\n >\n <span\n style={{\n color: meta.color,\n fontWeight: 700,\n fontSize: isHeading ? fs.body : fs.small,\n width: 16,\n textAlign: \"center\",\n flexShrink: 0,\n }}\n title={meta.label}\n aria-label={meta.label}\n >\n {meta.icon}\n </span>\n <span\n style={{\n fontSize: isHeading ? fs.body : fs.small,\n fontWeight: isHeading ? 600 : 400,\n color: isError || isBreak\n ? theme.error\n : isDecision\n ? theme.warning\n : isHeading\n ? theme.textPrimary\n : theme.textSecondary,\n lineHeight: 1.6,\n fontFamily: entry.type === \"step\" ? theme.fontMono : theme.fontSans,\n }}\n >\n {entry.heading && headingType ? (\n entry.text.startsWith('[') ? (\n <>\n <strong>{entry.heading}.</strong>\n {' '}{entry.text}\n </>\n ) : (\n <>\n <strong>{entry.heading}. [{headingType}{entry.stageName ? `: ${entry.stageName}` : ''}]</strong>\n {' '}{entry.text}\n </>\n )\n ) : entry.text}\n </span>\n </div>\n );\n })}\n\n {/* Future entries — show count hint only, skip full rendering for performance */}\n {futureCount > 0 && (\n <div style={{\n opacity: 0.3,\n fontSize: fs.small,\n color: theme.textMuted,\n padding: `8px 0`,\n fontStyle: \"italic\",\n }}>\n {futureCount} more {futureCount === 1 ? \"entry\" : \"entries\"} ahead...\n </div>\n )}\n </div>\n );\n}\n","/**\n * SubflowTree — collapsible sidebar listing mounted subflows.\n *\n * Recorder-driven (v6+): derives the tree from a `TraceGraph` produced\n * by `createTraceStructureRecorder`. Filters nodes by\n * `data.isSubflow === true` and lists them as `SubflowTreeEntry[]`\n * keyed by `subflowId`.\n *\n * Limitation (intentional — recorder graph is flat / mount-only):\n * Subflow-within-subflow nesting is NOT represented. The\n * StructureRecorder records the MOUNT of each subflow in the parent\n * chart, not the inner structure of each child chart. Rendering the\n * nested tree requires a separate recorder attached to each child\n * chart instance (deferred — see TODO below).\n *\n * Shared navigation layer — humans click through the tree just like\n * LLMs call getSubflowManifest() / getSubflowSpec().\n *\n * TODO(recorder-driven-nesting): when child charts attach their own\n * `traceStructureRecorder` and surface those graphs via a parent\n * registry, accept `Map<subflowId, TraceGraph>` and recurse to\n * restore the nested rendering the legacy SpecNode-walk supported.\n *\n * All colors come from `--fp-*` CSS variables set by the consumer.\n */\nimport { memo, useState, useCallback, useMemo } from \"react\";\nimport { theme } from \"../../theme\";\nimport type { TraceGraph } from \"./traceStructureRecorder\";\nimport type { BaseComponentProps } from \"../../types\";\n\nexport interface SubflowTreeEntry {\n /** Node name / identifier */\n name: string;\n /** Human-readable description */\n description?: string;\n /** Subflow ID (when this node represents a subflow) */\n subflowId?: string;\n /** Whether this node is a subflow root (has nested structure) */\n isSubflow?: boolean;\n /** Nested children (subflow stages) — always undefined in the\n * current recorder-driven implementation; see file-level TODO. */\n children?: SubflowTreeEntry[];\n}\n\nexport interface SubflowTreeProps extends BaseComponentProps {\n /** Recorder-captured graph from `createTraceStructureRecorder().getGraph()`. */\n graph: TraceGraph;\n /** Currently active stage name (highlights in tree) */\n activeStage?: string | null;\n /** Set of completed stage names */\n doneStages?: Set<string>;\n /** Called when a tree node is clicked */\n onNodeSelect?: (name: string, isSubflow: boolean) => void;\n}\n\n/** Extracts subflow entries from a recorder graph. Insertion-order preserving. */\nexport function graphToSubflowEntries(graph: TraceGraph): SubflowTreeEntry[] {\n if (!graph?.nodes?.length) return [];\n const entries: SubflowTreeEntry[] = [];\n for (const node of graph.nodes) {\n if (!node.data?.isSubflow) continue;\n const entry: SubflowTreeEntry = {\n name: typeof node.data.label === \"string\" ? node.data.label : node.id,\n isSubflow: true,\n };\n if (typeof node.data.description === \"string\") entry.description = node.data.description;\n if (typeof node.data.subflowId === \"string\") entry.subflowId = node.data.subflowId;\n entries.push(entry);\n }\n return entries;\n}\n\n/** Single tree node row */\nconst TreeNode = memo(function TreeNode({\n entry,\n depth,\n activeStage,\n doneStages,\n onNodeSelect,\n}: {\n entry: SubflowTreeEntry;\n depth: number;\n activeStage?: string | null;\n doneStages?: Set<string>;\n onNodeSelect?: (name: string, isSubflow: boolean) => void;\n}) {\n const [expanded, setExpanded] = useState(true);\n const hasChildren = entry.children && entry.children.length > 0;\n const isActive = activeStage === entry.name;\n const isDone = doneStages?.has(entry.name);\n\n const handleClick = useCallback(() => {\n if (hasChildren) {\n setExpanded((prev) => !prev);\n }\n onNodeSelect?.(entry.name, !!entry.isSubflow);\n }, [hasChildren, onNodeSelect, entry.name, entry.isSubflow]);\n\n return (\n <>\n <button\n onClick={handleClick}\n data-fp=\"subflow-tree-node\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n width: \"100%\",\n border: \"none\",\n background: isActive\n ? `color-mix(in srgb, ${theme.primary} 15%, transparent)`\n : \"transparent\",\n cursor: \"pointer\",\n padding: `4px 8px 4px ${8 + depth * 16}px`,\n fontFamily: theme.fontSans,\n fontSize: 12,\n textAlign: \"left\",\n borderRadius: 4,\n transition: \"background 0.15s\",\n }}\n onMouseEnter={(e) => {\n if (!isActive) {\n e.currentTarget.style.background = `color-mix(in srgb, ${theme.textMuted} 10%, transparent)`;\n }\n }}\n onMouseLeave={(e) => {\n if (!isActive) {\n e.currentTarget.style.background = \"transparent\";\n }\n }}\n >\n {/* Expand/collapse chevron for subflows */}\n {hasChildren ? (\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n width: 12,\n textAlign: \"center\",\n flexShrink: 0,\n transition: \"transform 0.15s\",\n transform: expanded ? \"rotate(90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n ▶\n </span>\n ) : (\n <span style={{ width: 12, flexShrink: 0 }} />\n )}\n\n {/* Status dot */}\n <span\n style={{\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n flexShrink: 0,\n background: isActive\n ? theme.primary\n : isDone\n ? theme.success\n : theme.border,\n }}\n />\n\n {/* Label + description */}\n <span style={{ display: \"flex\", flexDirection: \"column\", minWidth: 0 }}>\n <span\n style={{\n color: isActive\n ? theme.primary\n : isDone\n ? theme.textPrimary\n : theme.textSecondary,\n fontWeight: isActive ? 600 : entry.isSubflow ? 500 : 400,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {entry.name}\n {entry.isSubflow && (\n <span style={{ opacity: 0.5, marginLeft: 4, fontSize: 10 }}>⊞</span>\n )}\n </span>\n {entry.description && (\n <span\n style={{\n color: theme.textMuted,\n fontSize: 10,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {entry.description}\n </span>\n )}\n </span>\n </button>\n\n {/* Children */}\n {hasChildren && expanded && (\n <div>\n {entry.children!.map((child, i) => (\n <TreeNode\n key={child.subflowId ?? `${child.name}-${i}`}\n entry={child}\n depth={depth + 1}\n activeStage={activeStage}\n doneStages={doneStages}\n onNodeSelect={onNodeSelect}\n />\n ))}\n </div>\n )}\n </>\n );\n});\n\n/** Section label used for \"Flowchart\" and \"Subflows\" headings. */\nconst SectionLabel = memo(function SectionLabel({ children }: { children: string }) {\n return (\n <div\n style={{\n padding: \"4px 12px 8px\",\n fontSize: 10,\n fontWeight: 600,\n textTransform: \"uppercase\",\n letterSpacing: \"0.05em\",\n color: theme.textMuted,\n }}\n >\n {children}\n </div>\n );\n});\n\nexport const SubflowTree = memo(function SubflowTree({\n graph,\n activeStage,\n doneStages,\n onNodeSelect,\n unstyled = false,\n className,\n style,\n}: SubflowTreeProps) {\n const subflowStages = useMemo(() => graphToSubflowEntries(graph), [graph]);\n\n // Don't render anything if there are no subflows\n if (subflowStages.length === 0) return null;\n\n return (\n <div\n className={className}\n data-fp=\"subflow-tree\"\n style={{\n ...(unstyled\n ? {}\n : {\n fontFamily: theme.fontSans,\n fontSize: 12,\n background: theme.bgPrimary,\n borderRight: `1px solid ${theme.border}`,\n overflowY: \"auto\",\n overflowX: \"hidden\",\n padding: \"8px 0\",\n }),\n ...style,\n }}\n >\n {!unstyled && <SectionLabel>Subflows</SectionLabel>}\n {subflowStages.map((entry, i) => (\n <TreeNode\n key={entry.subflowId ?? `${entry.name}-${i}`}\n entry={entry}\n depth={0}\n activeStage={activeStage}\n doneStages={doneStages}\n onNodeSelect={onNodeSelect}\n />\n ))}\n </div>\n );\n});\n","import { memo } from \"react\";\nimport { theme } from \"../../theme\";\nimport type { BreadcrumbEntry } from \"./useSubflowNavigation\";\n\nexport interface SubflowBreadcrumbProps {\n breadcrumbs: BreadcrumbEntry[];\n onNavigate: (level: number) => void;\n}\n\n/**\n * Breadcrumb bar for subflow drill-down navigation.\n * Shows: Root > SubflowA > SubflowB — clicking any crumb navigates back.\n */\nexport const SubflowBreadcrumb = memo(function SubflowBreadcrumb({\n breadcrumbs,\n onNavigate,\n}: SubflowBreadcrumbProps) {\n if (breadcrumbs.length <= 1) return null;\n\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"6px 12px\",\n background: theme.bgSecondary,\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 12,\n fontFamily: theme.fontSans,\n flexShrink: 0,\n overflowX: \"auto\",\n }}\n >\n {breadcrumbs.map((crumb, i) => {\n const isLast = i === breadcrumbs.length - 1;\n return (\n <span key={`${crumb.label}-${i}`} style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\n {i > 0 && (\n <span style={{ color: theme.textMuted, fontSize: 10 }}>\n ›\n </span>\n )}\n {isLast ? (\n <span style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n <span\n style={{\n color: theme.primary,\n fontWeight: 600,\n }}\n >\n {crumb.label}\n </span>\n {crumb.description && (\n <span\n style={{\n color: theme.textMuted,\n fontWeight: 400,\n fontSize: 11,\n }}\n >\n — {crumb.description}\n </span>\n )}\n </span>\n ) : (\n <button\n onClick={() => onNavigate(i)}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.textSecondary,\n cursor: \"pointer\",\n padding: \"2px 4px\",\n borderRadius: 4,\n fontSize: 12,\n fontFamily: \"inherit\",\n fontWeight: 500,\n transition: \"color 0.15s\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.color = `${theme.primary}`;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.color = `${theme.textSecondary}`;\n }}\n >\n {crumb.label}\n </button>\n )}\n </span>\n );\n })}\n </div>\n );\n});\n","/**\n * TracedFlow — runtime-overlay variant of `<TraceFlow>`.\n *\n * Pairs a build-time `TraceGraph` (from `createTraceStructureRecorder`)\n * with a runtime `RuntimeOverlay` (from `createTraceRuntimeOverlay`)\n * and a scrub index → renders an xyflow chart with per-node coloring\n * (done / active / error), per-edge highlighting (executed paths),\n * loop-edge side-routing, and subflow drill-down.\n *\n * The component is orchestration only. Each responsibility lives in\n * an extracted helper / hook (see `_internal/`):\n *\n * - drill state .................. useSubflowDrill\n * - container resize → fitView ... useChartAutoRefit\n * - graph filtering by drill ..... filterGraphForDrill\n * - breadcrumb path .............. buildSubflowBreadcrumb\n * - slice id normalization ....... normalizeSliceLeafIds\n * - mount status aggregation ..... aggregateMountStatus\n * - node / edge styling .......... toStageNodeWithOverlay + styleEdgeWithOverlay\n * - breadcrumb UI ................ <SubflowBreadcrumbBar>\n *\n * @example\n * ```tsx\n * const trace = useMemo(() => createTraceStructureRecorder(), []);\n * const runtime = useMemo(() => createTraceRuntimeOverlay(), []);\n * // ... attach both to executor, run the chart ...\n * <TracedFlow\n * graph={trace.getGraph()}\n * overlay={runtime.getOverlay()}\n * scrubIndex={sliderValue}\n * onNodeClick={(stageId) => focusStage(stageId)}\n * onSubflowChange={(mountId) => syncShellDrill(mountId)}\n * />\n * ```\n */\n\nimport type * as React from \"react\";\nimport { useCallback, useMemo, useRef, useState } from \"react\";\nimport {\n ReactFlow,\n Background,\n BackgroundVariant,\n MarkerType,\n} from \"@xyflow/react\";\nimport type { Node, Edge, NodeTypes, EdgeTypes, ReactFlowInstance } from \"@xyflow/react\";\nimport type { TraceGraph, TraceNode, TraceEdge } from \"./traceStructureRecorder\";\nimport type { TraceFlowLayout } from \"./TraceFlow\";\nimport { defaultTraceFlowLayout } from \"./TraceFlow\";\nimport { dagreTraceLayout } from \"./_internal/dagreTraceLayout\";\nimport type { RuntimeOverlay } from \"./createTraceRuntimeOverlay\";\nimport { sliceOverlay } from \"./createTraceRuntimeOverlay\";\nimport { StageNode } from \"../StageNode\";\nimport type { StageNodeData } from \"../StageNode\";\nimport { rawDefaults } from \"../../theme/tokens\";\nimport type { BaseComponentProps } from \"../../types\";\nimport { filterGraphForDrill, buildSubflowBreadcrumb } from \"./_internal/subflowDrill\";\nimport { aggregateMountStatus } from \"./_internal/overlayProjection\";\nimport { useSubflowDrill } from \"./_internal/useSubflowDrill\";\nimport { useChartAutoRefit } from \"./_internal/useChartAutoRefit\";\nimport { SubflowBreadcrumbBar } from \"./SubflowBreadcrumbBar\";\nimport { GroupContainerNode } from \"../GroupContainerNode\";\nimport { LoopBackEdge } from \"../LoopBackEdge\";\nimport { SmartStepEdge } from \"../SmartStepEdge\";\nimport { applyGroupLayout, wrapInMainChartBox } from \"./_internal/groupLayout\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Theming\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface TracedFlowColors {\n /** Default (un-executed) node text + edge stroke. */\n default: string;\n /** Done — visually de-emphasised (lighter). */\n done: string;\n /** Active — current scrub position. */\n active: string;\n /** Error — node with recorded onError. */\n error: string;\n /** Loop back-edge color. */\n loop: string;\n}\n\nconst DEFAULT_COLORS: TracedFlowColors = {\n default: rawDefaults.colors.textMuted,\n done: rawDefaults.colors.success,\n active: rawDefaults.colors.primary,\n error: rawDefaults.colors.error,\n loop: rawDefaults.colors.warning,\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Per-node / per-edge styling (pure)\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Derive overlay state fields for a single node from the current\n * scrub slice. Shared between the default `stageNode` path and the\n * custom-node pass-through path so custom renderers receive the same\n * `active`/`done`/`error`/`dimmed`/`stepNumbers` shape the bundled\n * `<StageNode>` consumes.\n */\n/** Stable empty set so the nodes useMemo doesn't re-run when no co-active set is passed. */\nconst EMPTY_SET: ReadonlySet<string> = new Set<string>();\n\nfunction deriveOverlayFields(\n node: TraceNode,\n doneStageIds: ReadonlySet<string>,\n activeStageId: string | null,\n errorMessage: string | undefined,\n executedOrderIds: readonly string[],\n coActiveStageIds: ReadonlySet<string>,\n): {\n active: boolean;\n done: boolean;\n error: boolean;\n dimmed: boolean;\n errorMessage?: string;\n stepNumbers?: number[];\n} {\n const isDone = doneStageIds.has(node.id);\n // `active` is the SINGLE cursor node OR any node in the co-active set — the\n // latter lets a consumer light a whole parallel cohort (e.g. the lens lighting\n // all branches of a fork) at one cursor. Applies to BOTH stage and custom\n // nodes (custom nodes also OR consumer `data.active` below).\n const isActive = activeStageId === node.id || coActiveStageIds.has(node.id);\n const wasExecuted = isDone || isActive;\n const hasError = !!errorMessage;\n const dimmed = !wasExecuted && executedOrderIds.length > 0;\n\n // Per-stage step number(s) — a loop may visit the same node multiple times.\n let stepNumbers: number[] | undefined;\n if (executedOrderIds.length > 0) {\n const nums: number[] = [];\n for (let i = 0; i < executedOrderIds.length; i++) {\n if (executedOrderIds[i] === node.id) nums.push(i + 1);\n }\n if (nums.length > 0) stepNumbers = nums;\n }\n\n return {\n active: isActive,\n done: isDone,\n error: hasError,\n dimmed,\n ...(errorMessage && { errorMessage }),\n ...(stepNumbers && { stepNumbers }),\n };\n}\n\nfunction toStageNodeWithOverlay(\n node: TraceNode,\n doneStageIds: ReadonlySet<string>,\n activeStageId: string | null,\n errorMessage: string | undefined,\n executedOrderIds: readonly string[],\n coActiveStageIds: ReadonlySet<string>,\n): Node {\n const overlayFields = deriveOverlayFields(\n node,\n doneStageIds,\n activeStageId,\n errorMessage,\n executedOrderIds,\n coActiveStageIds,\n );\n const { dimmed } = overlayFields;\n\n // Custom-node pass-through with overlay enrichment.\n //\n // Behaviour (v0.20+): when a consumer pushes a node with a non-default\n // `type`, we return it with overlay state MERGED INTO `data`\n // (`active`, `done`, `error`, `errorMessage`, `dimmed`, `stepNumbers`).\n // The consumer's custom renderer can read those fields to style itself\n // the same way the bundled `<StageNode>` does, without re-implementing\n // the scrub-slice derivation.\n //\n // Merge semantics: OR-union with consumer `data`. The consumer may\n // ALSO want to mark a node active/done (e.g., agentfootprint-lens marks\n // its User pill active at root cursors — the User pill isn't a real\n // stage so the overlay can't compute it). When EITHER source flags a\n // node active/done/error, the renderer sees it. This composes cleanly:\n // - Pure overlay flow (no consumer override) → overlay values pass through\n // - Consumer override (lens User pill case) → consumer flag wins\n // - Both set → OR (lit either way)\n //\n // `dimmed` is mutually exclusive with `active`/`done` — when a node is\n // active or done at the current cursor it can't simultaneously be\n // \"faded because others have executed.\" We zero dimmed when active or\n // done is true regardless of source.\n if (node.type !== undefined && node.type !== \"stage\") {\n const consumerData = (node.data ?? {}) as Record<string, unknown>;\n const consumerActive = consumerData.active === true;\n const consumerDone = consumerData.done === true;\n const consumerError = consumerData.error === true;\n const finalActive = consumerActive || overlayFields.active;\n const finalDone = consumerDone || overlayFields.done;\n const finalError = consumerError || overlayFields.error;\n const finalDimmed = !finalActive && !finalDone && dimmed;\n return {\n ...node,\n data: {\n ...node.data,\n active: finalActive,\n done: finalDone,\n error: finalError,\n ...(overlayFields.errorMessage !== undefined &&\n consumerData.errorMessage === undefined && {\n errorMessage: overlayFields.errorMessage,\n }),\n ...(finalDimmed && { dimmed: true }),\n ...(overlayFields.stepNumbers && { stepNumbers: overlayFields.stepNumbers }),\n },\n ...(finalDimmed && { style: { ...(node.style ?? {}), opacity: 0.35 } }),\n } as Node;\n }\n\n const stageData: StageNodeData = {\n label: node.data.label,\n isDecider: node.data.isDecider,\n isFork: node.data.isFork,\n isSubflow: node.data.isSubflow,\n ...overlayFields,\n ...(node.data.description !== undefined && { description: node.data.description }),\n ...(node.data.icon !== undefined && { icon: node.data.icon }),\n ...(node.data.subflowId !== undefined && { subflowId: node.data.subflowId }),\n ...(node.data.isLazy === true && { isLazy: true }),\n ...(node.data.emphasis !== undefined && { emphasis: node.data.emphasis }),\n ...(node.data.size !== undefined && { size: node.data.size }),\n } as StageNodeData;\n\n return {\n ...node,\n type: \"stageNode\",\n data: stageData as unknown as Record<string, unknown>,\n ...(dimmed && { style: { opacity: 0.35 } }),\n };\n}\n\nfunction styleEdgeWithOverlay(\n edge: TraceEdge,\n doneStageIds: ReadonlySet<string>,\n activeStageId: string | null,\n colors: TracedFlowColors,\n): Edge {\n const kind = edge.data?.kind ?? \"next\";\n const sourceExecuted = doneStageIds.has(edge.source) || activeStageId === edge.source;\n const targetExecuted = doneStageIds.has(edge.target) || activeStageId === edge.target;\n const traversed = sourceExecuted && targetExecuted;\n const isLeadingEdge = activeStageId === edge.source && !doneStageIds.has(edge.target);\n\n let color: string = colors.default;\n if (kind === \"loop\") color = colors.loop;\n else if (isLeadingEdge) color = colors.active;\n else if (traversed) color = colors.done;\n\n const styled: Edge = {\n ...edge,\n // Loop back-edges use the custom `loopBack` edge — a curve routed along the\n // right margin (clear of the spine). It reads node bounds from the store\n // and anchors on right edges itself, so it needs NO dedicated loop handles\n // on the node (the old approach broke for any node missing them).\n // Every other edge uses `smartStep`: a smoothstep superset that routes a\n // RANK-SKIPPING edge around the node it skips (else identical to smoothstep).\n type: kind === \"loop\" ? \"loopBack\" : \"smartStep\",\n animated: isLeadingEdge,\n style: { stroke: color, strokeWidth: traversed ? 2 : 1.5 },\n markerEnd: { type: MarkerType.ArrowClosed, color, width: 16, height: 16 },\n };\n if (kind === \"loop\") {\n styled.style = { ...styled.style, strokeDasharray: \"4 3\" };\n }\n return styled;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Component\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface TracedFlowProps extends BaseComponentProps {\n /** Build-time graph from `createTraceStructureRecorder().getGraph()`. */\n graph: TraceGraph;\n /** Runtime overlay from `createTraceRuntimeOverlay().getOverlay()`. */\n overlay?: RuntimeOverlay;\n /** Time-travel scrub index. Defaults to the last step (latest state). */\n scrubIndex?: number;\n /** Layout function. Default: BFS tree walk over the recorder graph. */\n layout?: TraceFlowLayout | \"passthrough\";\n /** Color overrides. */\n colors?: Partial<TracedFlowColors>;\n /** Node click handler — receives stage id. */\n onNodeClick?: (stageId: string) => void;\n /**\n * Fires when the chart drills into or out of a subflow (explicit\n * user click on a mount node). Receives the mount stage id (drill\n * in) or `null` (pop back). Container shells use this to keep\n * their data panels in lock-step with the chart's drill state.\n */\n onSubflowChange?: (mountStageId: string | null) => void;\n /**\n * Consumer-supplied xyflow node types. Merged with the built-in\n * `{ stageNode: StageNode }` registry — keys you supply OVERRIDE\n * the default for that node type. Pass `{ stageNode: MyNode }` to\n * replace the default stage renderer entirely, or add new keys\n * for custom node components you push into the graph.\n *\n * v0.20+ — overlay state is injected into custom nodes' `data`\n * fields too (`active`, `done`, `error`, `errorMessage`, `dimmed`,\n * `stepNumbers`), so consumer renderers can style themselves with\n * the same scrub-driven done/active/error semantics the bundled\n * `<StageNode>` uses — without re-implementing the overlay slice\n * derivation. Consumer `data` fields pass through untouched alongside.\n */\n nodeTypes?: NodeTypes;\n /**\n * Consumer-supplied xyflow edge types. Merged with no built-in\n * defaults — pass `{ myEdge: MyEdge }` to register custom edge\n * components for edges you push into the graph with `type: 'myEdge'`.\n */\n edgeTypes?: EdgeTypes;\n /**\n * Extra chart node ids to mark `active` SIMULTANEOUSLY at the current scrub\n * position, on top of the overlay's single active node. Lets a consumer light\n * a whole parallel cohort at one cursor (e.g. the lens lighting every branch\n * of a fork together). Works for BOTH stage and custom nodes. Defaults to\n * none — single-active behaviour is unchanged.\n */\n coActiveStageIds?: ReadonlySet<string>;\n /**\n * Subflow ids to render as GROUP CONTAINER boxes — the subflow's member\n * stages render NESTED inside the box (xyflow `parentId` + `extent`),\n * instead of behind a click-to-zoom DRILL card. Per-subflow choice: any\n * subflow id NOT listed keeps drilling. Default (unset): all drill —\n * existing behavior, nothing changes.\n */\n groupedSubflows?: readonly string[];\n /**\n * Wrap the ENTIRE chart in ONE main-chart container box (the Lens model:\n * the primitive you're viewing is always one box; subflows inside stay\n * drill cards). Pass a config object to enable + label it; omit for no\n * outer box. Composes AFTER drill-filtering, so when you drill into a\n * subflow the box reframes to that subflow's contents.\n */\n mainChartBox?: { label?: string; kind?: string };\n /**\n * Children rendered INSIDE the `<ReactFlow>` element, after the\n * built-in `<Background>`. Use this slot to mount xyflow\n * accessory components like `<Controls />`, `<MiniMap />`, or a\n * custom legend. If unset, only the default Background is rendered.\n */\n children?: React.ReactNode;\n}\n\nconst DEFAULT_NODE_TYPES: NodeTypes = {\n stageNode: StageNode,\n groupContainer: GroupContainerNode,\n};\n\n// Built-in edge types. `loopBack` curves loop-back edges along the right margin\n// (see LoopBackEdge); `smartStep` routes rank-skipping edges around the node\n// they skip (see SmartStepEdge). Always registered; merged UNDER consumer\n// `edgeTypes` (consumer keys win).\nconst DEFAULT_EDGE_TYPES: EdgeTypes = { loopBack: LoopBackEdge, smartStep: SmartStepEdge };\n\nexport function TracedFlow({\n graph,\n overlay,\n scrubIndex,\n layout: layoutProp,\n colors: colorOverrides,\n onNodeClick,\n onSubflowChange,\n groupedSubflows,\n mainChartBox,\n nodeTypes: userNodeTypes,\n edgeTypes: userEdgeTypes,\n coActiveStageIds,\n children,\n className,\n style,\n}: TracedFlowProps) {\n // Dagre is the default (structure-derived spacing); override via `layout`.\n const layout = layoutProp ?? dagreTraceLayout;\n const colors = useMemo<TracedFlowColors>(\n () => ({ ...DEFAULT_COLORS, ...(colorOverrides ?? {}) }),\n [colorOverrides],\n );\n const mergedNodeTypes = useMemo<NodeTypes>(\n () => (userNodeTypes ? { ...DEFAULT_NODE_TYPES, ...userNodeTypes } : DEFAULT_NODE_TYPES),\n [userNodeTypes],\n );\n const mergedEdgeTypes = useMemo<EdgeTypes>(\n () => (userEdgeTypes ? { ...DEFAULT_EDGE_TYPES, ...userEdgeTypes } : DEFAULT_EDGE_TYPES),\n [userEdgeTypes],\n );\n\n // ── Drill state + visibility derivations ──────────────────────────\n const drill = useSubflowDrill(graph, onSubflowChange);\n const groupedSet = useMemo(() => new Set(groupedSubflows ?? []), [groupedSubflows]);\n // Drill-filter the graph, but KEEP members of grouped subflows visible:\n // a grouped subflow renders its members nested in a container box rather\n // than hidden behind a drill card, so it opts out of drill hiding.\n const filteredGraph = useMemo(() => {\n const base = filterGraphForDrill(graph, drill.currentSubflowId);\n if (groupedSet.size === 0) return base;\n const baseIds = new Set(base.nodes.map((n) => n.id));\n const extraNodes = graph.nodes.filter(\n (n) =>\n n.data?.subflowOf !== undefined &&\n groupedSet.has(n.data.subflowOf) &&\n !baseIds.has(n.id),\n );\n if (extraNodes.length === 0) return base;\n const allIds = new Set([...baseIds, ...extraNodes.map((n) => n.id)]);\n const baseEdgeIds = new Set(base.edges.map((e) => e.id));\n const extraEdges = graph.edges.filter(\n (e) => !baseEdgeIds.has(e.id) && allIds.has(e.source) && allIds.has(e.target),\n );\n return { nodes: [...base.nodes, ...extraNodes], edges: [...base.edges, ...extraEdges] };\n }, [graph, drill.currentSubflowId, groupedSet]);\n const breadcrumb = useMemo(\n () => buildSubflowBreadcrumb(graph, drill.currentSubflowId),\n [graph, drill.currentSubflowId],\n );\n const positioned = useMemo<TraceGraph>(() => {\n const realBase: TraceFlowLayout =\n layout === \"passthrough\" ? (g: TraceGraph) => g : layout;\n\n // Per-subflow group boxes (granular; not the main-chart model).\n if (groupedSet.size > 0) {\n const grouped = applyGroupLayout(filteredGraph, {\n groupedSubflowIds: [...groupedSet],\n baseLayout: realBase,\n });\n // Main box can still wrap the grouped result if both are requested.\n return mainChartBox\n ? wrapInMainChartBox(grouped, { baseLayout: (g) => g, ...mainChartBox })\n : grouped;\n }\n\n // Main-chart box: wrap the whole (drill-filtered) chart in ONE box.\n // The base layout positions the contents; the box frames them.\n if (mainChartBox) {\n return wrapInMainChartBox(filteredGraph, { baseLayout: realBase, ...mainChartBox });\n }\n\n return layout === \"passthrough\" ? filteredGraph : layout(filteredGraph);\n }, [filteredGraph, layout, groupedSet, mainChartBox]);\n\n // ── Runtime overlay slice → mount aggregation ────\n // Overlay stage ids are path-qualified (`subflowPath/stageId`, parsed\n // from runtimeStageId) and structure node ids are ALSO path-qualified\n // now (walkSubflowSpecInto), so they match directly — no leaf-stripping.\n // (The former `normalizeSliceLeafIds` step only existed because\n // structure ids used to be bare; it would now MISMATCH by stripping a\n // qualified id down to its leaf.)\n const slice = useMemo(() => {\n const empty = {\n doneStageIds: new Set<string>(),\n activeStageId: null as string | null,\n executedStageIds: new Set<string>(),\n executedOrderIds: [] as string[],\n errors: new Map<string, string>(),\n };\n if (!overlay) return empty;\n const idx = scrubIndex ?? Math.max(0, overlay.executionOrder.length - 1);\n return aggregateMountStatus(sliceOverlay(overlay, idx), graph, drill.currentSubflowId);\n }, [overlay, scrubIndex, graph, drill.currentSubflowId]);\n\n // ── xyflow nodes + edges (re-run per scrub tick) ──────────────────\n const reactFlowNodes = useMemo<Node[]>(\n () =>\n positioned.nodes.map((n) =>\n toStageNodeWithOverlay(\n n,\n slice.doneStageIds,\n slice.activeStageId,\n slice.errors.get(n.id),\n slice.executedOrderIds,\n coActiveStageIds ?? EMPTY_SET,\n ),\n ),\n [positioned.nodes, slice, coActiveStageIds],\n );\n const reactFlowEdges = useMemo<Edge[]>(\n () =>\n positioned.edges.map((e) =>\n styleEdgeWithOverlay(e, slice.doneStageIds, slice.activeStageId, colors),\n ),\n [positioned.edges, slice, colors],\n );\n\n // ── Click handling: drill on subflow mount click, propagate click ─\n const handleNodeClick = useCallback(\n (_: unknown, node: Node) => {\n const data = (node.data ?? {}) as StageNodeData;\n // Grouped subflows render inline (no drill) — only drill the ones\n // still in card mode.\n if (data.isSubflow && data.subflowId && !groupedSet.has(data.subflowId)) {\n drill.drillInto(data.subflowId);\n }\n onNodeClick?.(node.id);\n },\n [drill, onNodeClick, groupedSet],\n );\n\n // ── Container auto-refit (xyflow's fitView is mount-only) ─────────\n const wrapperRef = useRef<HTMLDivElement>(null);\n const [rfInstance, setRfInstance] = useState<ReactFlowInstance | null>(null);\n // refitKey = the drill id: drilling in/out swaps the visible subgraph, so the\n // chart must recenter + rezoom to the new content (otherwise the smaller\n // drilled graph keeps the parent's pan/zoom and sits cramped in a corner).\n useChartAutoRefit(wrapperRef, rfInstance, { refitKey: drill.currentSubflowId });\n\n return (\n <div\n ref={wrapperRef}\n className={className}\n style={{\n width: \"100%\",\n height: \"100%\",\n minHeight: 300,\n display: \"flex\",\n flexDirection: \"column\",\n ...style,\n }}\n >\n {breadcrumb.length > 1 && (\n <SubflowBreadcrumbBar\n entries={breadcrumb}\n onNavigate={drill.setCurrentSubflowId}\n />\n )}\n <div style={{ flex: 1, minHeight: 0 }}>\n <ReactFlow\n nodes={reactFlowNodes}\n edges={reactFlowEdges}\n nodeTypes={mergedNodeTypes}\n edgeTypes={mergedEdgeTypes}\n onNodeClick={handleNodeClick}\n onInit={setRfInstance}\n fitView\n proOptions={{ hideAttribution: true }}\n >\n <Background variant={BackgroundVariant.Dots} gap={20} size={1} />\n {children}\n </ReactFlow>\n </div>\n </div>\n );\n}\n","/**\n * dagreTraceLayout — professor-grade `TraceFlowLayout` backed by dagre.\n *\n * Replaces the hand-rolled BFS `defaultTraceFlowLayout` (which used FIXED\n * spacing constants — Y_STEP / X_SPREAD — and documented \"first-wins\"\n * convergence + no overlap detection). Dagre instead derives every\n * position from the STRUCTURE RELATIONS:\n *\n * - **next** (sequential): y-delta = rank depth (longest path), so a\n * convergence node lands at `max(incoming ranks) + 1` — not\n * \"deepest-branch-so-far\".\n * - **fork / selector** (N branches): x-delta = the measured SUBTREE\n * WIDTH of each branch (a wide branch pushes its siblings further; a\n * thin one barely shifts them) — scales cleanly for any N, no collisions.\n * - **merge** (join): centered under the average of its real parents.\n *\n * Compound nesting: dagre is given `parentId` as a compound-parent link,\n * so group-container children (from `applyGroupLayout` / `wrapInMainChartBox`)\n * stay inside their box. Coordinates are returned parent-RELATIVE (xyflow\n * convention), matching what the box transforms expect.\n *\n * Ported from agentfootprint-lens's proven `dagreLayout` (same dagre core),\n * re-shaped to the `TraceFlowLayout` contract: `(TraceGraph) => TraceGraph`.\n * Pure — same graph in, same positions out; no React, no I/O.\n */\n\nimport dagre from \"dagre\";\nimport type { Edge } from \"@xyflow/react\";\nimport type { TraceGraph, TraceNode, TraceEdgeData } from \"../traceStructureRecorder\";\nimport type { TraceFlowLayout } from \"../TraceFlow\";\n\n/** Explicit node footprint (px). */\nexport interface NodeFootprint {\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Consumer-supplied per-node size resolver. Receives the WHOLE node (all\n * recorder semantics: `data.isSubflow`, `data.icon`, `data.subflowId`,\n * `id`, …) and returns a footprint, or `undefined` to leave the node alone\n * (→ falls back to `style.width/height`, then the default footprint).\n *\n * The library imposes NO sizing rules — the consumer decides per node by\n * whatever criteria THEY choose. E.g. make one specific slot a slim bar\n * while another stays a full card; make the LLM-call node large; etc.\n */\nexport type NodeSizeResolver = (node: TraceNode) => NodeFootprint | undefined;\n\n/** Consumer-supplied per-edge layout-weight resolver. Higher weight pulls\n * the two endpoints into a tighter, straighter column (dagre `weight`).\n * Return `undefined` for the default (1). */\nexport type EdgeWeightResolver = (edge: Edge<TraceEdgeData>) => number | undefined;\n\n/** Consumer-supplied per-edge minimum rank-span resolver. `>1` STRETCHES an\n * edge (pushes its target that many ranks down). Note dagre cannot make an\n * edge SHORTER than one rank — `minlen` only increases. Return `undefined`\n * for the default (1). */\nexport type EdgeMinLenResolver = (edge: Edge<TraceEdgeData>) => number | undefined;\n\n/**\n * Consumer-supplied left-to-right ORDER for a node's fork/decider children.\n * Receives the source node id + its child target ids (in spec/edge-insertion\n * order); returns the SAME ids reordered left-to-right (index 0 = leftmost).\n * Ids omitted from the result keep their original relative order after the\n * listed ones. Return the input unchanged (or `undefined` from the resolver)\n * to leave a node alone.\n *\n * Use to place a specific branch on a chosen side — e.g. the looping branch on\n * the right margin where the loop-back curve lives, so the \"iterate\" path reads\n * as one side of the fork. This is a pure VISUAL/LAYOUT decision (it changes\n * which side a branch draws on, never the chart's behavior), so it belongs in\n * the renderer, not the chart spec.\n *\n * Mechanism: dagre seeds its sibling order from edge-insertion order and keeps\n * it as the tie-break for equal-barycenter siblings. We insert each source's\n * edges in the resolved order, so for the common symmetric N-branch decider the\n * result is deterministic. (For graphs where one ordering strictly reduces edge\n * crossings, dagre's crossing-minimizer may still override — best-effort, as\n * documented for any dagre ordering hint.)\n */\nexport type SiblingOrderResolver = (\n sourceId: string,\n childIds: readonly string[],\n) => readonly string[];\n\nexport interface DagreTraceLayoutOptions {\n /** Layout direction. `'TB'` (top-to-bottom) is the default — matches the\n * \"Seed → … → answer\" reading order. */\n readonly direction?: \"TB\" | \"BT\" | \"LR\" | \"RL\";\n /** Vertical spacing between rank layers (px). Surfaced as a knob — the\n * rank-gap delta. Default 80. */\n readonly rankSep?: number;\n /** Horizontal spacing between siblings within a rank (px). The\n * sibling-gap delta dagre adds ON TOP of measured subtree widths.\n * Default 60. */\n readonly nodeSep?: number;\n /** Spacing between edges (px). Default 20. */\n readonly edgeSep?: number;\n /** Fallback node footprint when a node carries no explicit size. dagre\n * needs real dimensions or arrows collapse to a point. */\n readonly nodeWidth?: number;\n readonly nodeHeight?: number;\n /** Per-node size resolver — consumer decides each node's footprint. See\n * `NodeSizeResolver`. Resolution order: resolver → `node.style` → default. */\n readonly nodeSize?: NodeSizeResolver;\n /** Per-edge pull (dagre `weight`). See `EdgeWeightResolver`. */\n readonly edgeWeight?: EdgeWeightResolver;\n /** Per-edge stretch (dagre `minlen`). See `EdgeMinLenResolver`. */\n readonly edgeMinLen?: EdgeMinLenResolver;\n /** Per-node fork/decider child ordering. See `SiblingOrderResolver`. */\n readonly siblingOrder?: SiblingOrderResolver;\n}\n\nexport const DEFAULT_NODE_W = 200;\nexport const DEFAULT_NODE_H = 80;\n\n/**\n * Resolve a node's render size. Order: consumer `nodeSize` resolver (if it\n * returns a footprint) → explicit `style.width/height` (set by the\n * group/main-box transforms) → configured fallback footprint.\n *\n * GROUP-CONTAINER EXCEPTION — style WINS over the resolver. A node flagged\n * `data.isGroupContainer` has been STAMPED with its true box footprint on\n * `style.width/height` by `applyGroupLayout` PASS 2 (or `wrapInMainChartBox`).\n * That footprint is authoritative: it is the size the box actually RENDERS at,\n * so dagre must reserve exactly it or post-container siblings rank inside the\n * box and overlap it. A consumer `nodeSize` resolver that sizes by recorder\n * semantics (e.g. \"any subflow → a 38px slim bar\") would otherwise out-rank\n * the stamp — dagre would be told 38px while the box paints ~794px, and the\n * `route`/`tool-calls`/`final` siblings would land on top of it. So for a\n * group container the resolution order flips to: `style` → resolver → default.\n *\n * Exported so the post-layout `snapLinearSuccessors` pass reconstructs each\n * node's center from the IDENTICAL width dagre placed it at, keeping snapped\n * centers geometry-exact.\n */\nexport function sizeOf(\n node: TraceNode,\n fallbackW: number,\n fallbackH: number,\n resolver?: NodeSizeResolver,\n): { width: number; height: number } {\n const style = (node.style ?? {}) as { width?: unknown; height?: unknown };\n const styleW = typeof style.width === \"number\" ? style.width : undefined;\n const styleH = typeof style.height === \"number\" ? style.height : undefined;\n\n // A stamped group container's footprint is authoritative — style beats the\n // resolver so dagre reserves the box's REAL rendered height (no sibling\n // overlap). Both dimensions must be present to use the stamp; otherwise fall\n // through to the normal order.\n if (node.data?.isGroupContainer && styleW !== undefined && styleH !== undefined) {\n return { width: styleW, height: styleH };\n }\n\n const resolved = resolver?.(node);\n if (resolved) return { width: resolved.width, height: resolved.height };\n return {\n width: styleW ?? fallbackW,\n height: styleH ?? fallbackH,\n };\n}\n\n/**\n * Reorder edges so each source node's forward (non-loop) children are fed to\n * dagre in `siblingOrder`'s left-to-right order. dagre seeds sibling order from\n * edge-insertion order (and keeps it as the equal-barycenter tie-break), so\n * inserting in the resolved order biases each fork's left-to-right layout.\n *\n * Pure. Loop edges are dropped (they never shape layout — the caller skips them\n * anyway). Sources keep first-seen order; within a source, children follow the\n * resolver, and any children the resolver omits keep their original order after\n * the listed ones. Single-child sources are returned untouched.\n */\nfunction reorderSiblingEdges<E extends { source: string; target: string; data?: { kind?: string } }>(\n edges: readonly E[],\n siblingOrder: SiblingOrderResolver,\n): E[] {\n const bySource = new Map<string, E[]>();\n for (const e of edges) {\n if (e.data?.kind === \"loop\") continue;\n const arr = bySource.get(e.source);\n if (arr) arr.push(e);\n else bySource.set(e.source, [e]);\n }\n const out: E[] = [];\n for (const [src, group] of bySource) {\n if (group.length < 2) {\n out.push(...group);\n continue;\n }\n const ordered = siblingOrder(src, group.map((e) => e.target));\n const byTarget = new Map(group.map((e) => [e.target, e]));\n const used = new Set<string>();\n for (const t of ordered) {\n const e = byTarget.get(t);\n if (e && !used.has(t)) {\n out.push(e);\n used.add(t);\n }\n }\n for (const e of group) if (!used.has(e.target)) out.push(e); // resolver omissions\n }\n return out;\n}\n\n/**\n * Lay out a `TraceGraph` with dagre. Returns a NEW graph with each node's\n * `position` set (top-left, parent-relative for nested nodes). Edges pass\n * through unchanged — xyflow routes them once nodes are placed.\n *\n * Loop back-edges (`kind: 'loop'`) are EXCLUDED from the dagre graph: they\n * are visual annotations only (invariant I1) and would otherwise create\n * cycles that distort ranking.\n */\nexport function dagreTraceLayout(\n graph: TraceGraph,\n options: DagreTraceLayoutOptions = {},\n): TraceGraph {\n if (graph.nodes.length === 0) return graph;\n\n const direction = options.direction ?? \"TB\";\n const rankSep = options.rankSep ?? 80;\n const nodeSep = options.nodeSep ?? 60;\n const edgeSep = options.edgeSep ?? 20;\n const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W;\n const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H;\n\n const g = new dagre.graphlib.Graph({ compound: true });\n g.setGraph({ rankdir: direction, ranksep: rankSep, nodesep: nodeSep, edgesep: edgeSep });\n g.setDefaultEdgeLabel(() => ({}));\n\n const sizes = new Map<string, { width: number; height: number }>();\n // Sizes the consumer resolver supplied — applied to the node's `style` so\n // xyflow RENDERS at the same footprint dagre laid out for (layout/paint\n // parity). Style-derived + default sizes are layout-only (the node already\n // renders at them), so we don't override their style.\n const resolvedStyleSizes = new Map<string, NodeFootprint>();\n for (const node of graph.nodes) {\n const resolved = options.nodeSize?.(node);\n const size = sizeOf(node, fallbackW, fallbackH, options.nodeSize);\n sizes.set(node.id, size);\n // Only re-stamp the node's `style` from the resolver when `sizeOf` actually\n // USED the resolver — i.e. the dagre size equals the resolved footprint. A\n // stamped group container ignores the resolver (style wins, see sizeOf), so\n // we must NOT overwrite its authoritative box footprint with the resolver's\n // value (that would shrink the rendered box back to e.g. a 38px slim bar).\n if (resolved && resolved.width === size.width && resolved.height === size.height) {\n resolvedStyleSizes.set(node.id, resolved);\n }\n g.setNode(node.id, { width: size.width, height: size.height });\n if (node.parentId) {\n g.setParent(node.id, node.parentId);\n }\n }\n\n // When a sibling order is requested, feed each fork's child edges to dagre in\n // that order (opt-in; the default path keeps edges byte-identical to before).\n // `reorderSiblingEdges` returns FORWARD edges only (loop edges are dropped —\n // they never shape layout, and the `kind === \"loop\"` skip below is the no-op\n // for that case). The graph's edges are returned UNCHANGED from this function\n // (see the final `return` — loop edges still reach the renderer intact).\n const layoutEdges = options.siblingOrder\n ? reorderSiblingEdges(graph.edges, options.siblingOrder)\n : graph.edges;\n for (const e of layoutEdges) {\n if (e.data?.kind === \"loop\") continue; // visual-only — never shapes layout\n if (g.hasNode(e.source) && g.hasNode(e.target)) {\n // Per-edge pull (weight) + stretch (minlen) — consumer-controlled.\n const label: { weight?: number; minlen?: number } = {};\n const weight = options.edgeWeight?.(e);\n const minlen = options.edgeMinLen?.(e);\n if (typeof weight === \"number\") label.weight = weight;\n if (typeof minlen === \"number\") label.minlen = minlen;\n g.setEdge(e.source, e.target, label);\n }\n }\n\n dagre.layout(g);\n\n // dagre returns CENTER coords; xyflow wants TOP-LEFT. Nested children get\n // coords RELATIVE to their parent's top-left (xyflow convention).\n const positioned: TraceNode[] = graph.nodes.map((node) => {\n const laidOut = g.node(node.id);\n if (!laidOut) return node; // unreached (orphan) — keep original position\n const size = sizes.get(node.id)!;\n let x = laidOut.x - size.width / 2;\n let y = laidOut.y - size.height / 2;\n if (node.parentId) {\n const parent = g.node(node.parentId);\n const parentSize = sizes.get(node.parentId);\n if (parent && parentSize) {\n x -= parent.x - parentSize.width / 2;\n y -= parent.y - parentSize.height / 2;\n }\n }\n // Apply consumer-resolved size to `style` so xyflow RENDERS at the same\n // footprint dagre placed (paint matches layout). Only for resolver-set\n // sizes — style/default-sized nodes already render correctly.\n const styleSize = resolvedStyleSizes.get(node.id);\n if (styleSize) {\n return {\n ...node,\n position: { x, y },\n style: { ...(node.style ?? {}), width: styleSize.width, height: styleSize.height },\n };\n }\n return { ...node, position: { x, y } };\n });\n\n return { nodes: positioned, edges: graph.edges };\n}\n\n/**\n * Build a `TraceFlowLayout` from dagre options. Pass to\n * `<TraceFlow layout={...}>` / `<TracedFlow layout={...}>`, or use it as a\n * `baseLayout` for the group/main-box transforms.\n */\nexport function createDagreTraceLayout(\n options: DagreTraceLayoutOptions = {},\n): TraceFlowLayout {\n return (graph: TraceGraph) => dagreTraceLayout(graph, options);\n}\n","/**\n * createTraceRuntimeOverlay — event-driven runtime overlay for `<TracedFlow>`.\n *\n * The runtime twin of `createTraceStructureRecorder` (L7.7). Where the\n * structure recorder accumulates the build-time graph SHAPE from\n * `StructureRecorder` events, this recorder accumulates the runtime\n * EXECUTION STATE (which nodes ran, current active, errors) from\n * `FlowRecorder` events. The two compose into the full time-travel\n * trace UI:\n *\n * StructureRecorder events → TraceGraph (nodes + edges, id-keyed)\n * FlowRecorder events → RuntimeOverlay (per-node state, id-keyed)\n * │\n * ▼\n * <TracedFlow graph={...} overlay={...} scrubIndex={i} />\n *\n * **Universal key**: `runtimeStageId = [subflowPath/]stageId#executionIndex`.\n * Loops re-execute the same stageId with bumping executionIndex — the\n * overlay records each execution as a distinct step in `executionOrder`\n * but updates the SAME node-by-id in `doneStageIds` (because the build-\n * time graph has one node per spec — loops re-visit it).\n *\n * Per L7.7 panel guidance: the consumer pattern mirrors recorder error\n * isolation, exposes a pub-sub `subscribe(listener)` + monotonic\n * `version()` for `useSyncExternalStore` integration, and accumulates\n * pure data with zero React coupling.\n */\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Local type aliases mirroring footprintjs FlowRecorder\n// ─────────────────────────────────────────────────────────────────────────────\n//\n// Same rationale as traceStructureRecorder.ts: explainable-ui has no\n// `footprintjs` dep declared (consumer wires it). We mirror the\n// subset of `FlowRecorder` we consume. If footprintjs changes the\n// interface, this module's types update in lockstep.\n\ninterface TraversalContext {\n readonly runtimeStageId: string;\n readonly iteration?: number;\n readonly runId?: string;\n}\n\ninterface RuntimeStageExecutedEvent {\n readonly stageName: string;\n readonly stageId?: string;\n /** Discriminator for which kind of stage completed. footprintjs v6+\n * fires this event uniformly for every stage kind (proposal #003);\n * consumers route by `stageType` without a chart-spec lookup. */\n readonly stageType: 'linear' | 'decider' | 'fork' | 'selector' | 'subflow-mount';\n readonly traversalContext: TraversalContext;\n}\n\ninterface RuntimeErrorEvent {\n readonly stageName: string;\n readonly stageId?: string;\n readonly message?: string;\n readonly traversalContext?: TraversalContext;\n}\n\ninterface RuntimeRunStartEvent {\n readonly traversalContext?: TraversalContext;\n}\n\ninterface RuntimeRunEndEvent {\n readonly traversalContext?: TraversalContext;\n}\n\n/** Minimal FlowRecorder interface mirror — see top-of-file rationale.\n *\n * As of footprintjs v6 (proposal #003), `onStageExecuted` fires\n * uniformly for ALL stage kinds — linear / decider / fork / selector\n * / subflow-mount. The event payload carries a `stageType` field for\n * consumers that need to route by kind. We no longer need separate\n * `onDecision` / `onFork` / `onSelected` handlers to track \"did this\n * stage run\" — a single `onStageExecuted` handler suffices. */\nexport interface MinimalFlowRecorder {\n readonly id: string;\n onStageExecuted?(event: RuntimeStageExecutedEvent): void;\n onError?(event: RuntimeErrorEvent): void;\n onRunStart?(event: RuntimeRunStartEvent): void;\n onRunEnd?(event: RuntimeRunEndEvent): void;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Runtime overlay shape\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * One entry in the execution timeline. `<TracedFlow>` keys time-travel\n * scrubbing on the index into this array — at index `i`, all entries\n * `0..i-1` are \"done\", entry `i` is \"active\".\n */\nexport interface RuntimeExecutionStep {\n /** `[subflowPath/]stageId#executionIndex` — universal key. */\n readonly runtimeStageId: string;\n /** Base stage id (without `#N`) — matches the `TraceGraph` node id. */\n readonly stageId: string;\n /** Human-readable label (from event.stageName). */\n readonly stageName: string;\n /** When this step recorded, in ms since recorder start. */\n readonly timestampMs: number;\n}\n\nexport interface RuntimeOverlay {\n /** Ordered execution history — drives time-travel scrubbing. */\n readonly executionOrder: readonly RuntimeExecutionStep[];\n /** Per-base-stageId error message (most-recent wins). */\n readonly errors: ReadonlyMap<string, string>;\n /** True after `onRunStart` until `onRunEnd` — useful for \"still running\" indicators. */\n readonly running: boolean;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Handle\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface TraceRuntimeOverlayHandle {\n /** The recorder to attach via `executor.attachFlowRecorder(handle.recorder)`. */\n recorder: MinimalFlowRecorder;\n /** Returns a defensive copy of the current overlay state. */\n getOverlay(): RuntimeOverlay;\n /** Pub-sub: returns unsubscribe. Designed for `useSyncExternalStore`. */\n subscribe(listener: () => void): () => void;\n /** Monotonic version counter — bumps once per overlay-mutating event. */\n version(): number;\n /** Reset for reuse across runs. Does NOT bump version or notify (matches\n * traceStructureRecorder's reset contract). */\n reset(): void;\n}\n\nexport interface CreateTraceRuntimeOverlayOptions {\n id?: string;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Internal helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport { createNotifier } from \"./_internal/notifyChange\";\n\n/**\n * Strip `#executionIndex` suffix to get the base stage id.\n *\n * **WARNING (invariant I3)**: use ONLY for DISPLAY. NEVER for matching\n * commitLog stageIds — those use the full path-prefixed id (e.g.,\n * `'sf-a/sf-b/inner'`) as emitted by the engine. Parsing back to the\n * unqualified inner name loses uniqueness across subflow instances.\n */\nfunction parseStageIdFromRuntimeStageId(runtimeStageId: string): string {\n const hashIdx = runtimeStageId.indexOf(\"#\");\n return hashIdx >= 0 ? runtimeStageId.slice(0, hashIdx) : runtimeStageId;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Factory\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport function createTraceRuntimeOverlay(\n options: CreateTraceRuntimeOverlayOptions = {},\n): TraceRuntimeOverlayHandle {\n const id = options.id ?? \"trace-runtime-overlay\";\n const startTime = performance.now();\n\n let executionOrder: RuntimeExecutionStep[] = [];\n // Defensive dedupe by runtimeStageId — should be moot post-#003\n // since the engine fires `onStageExecuted` exactly once per stage\n // execution, but a future change or a misbehaving recorder upstream\n // could still produce duplicates; keep the set as belt-and-suspenders.\n const recordedRuntimeStageIds = new Set<string>();\n const errors = new Map<string, string>();\n let running = false;\n const notifier = createNotifier(\"traceRuntimeOverlay\");\n const notifyChange = notifier.notify;\n\n function pushStep(runtimeStageId: string, stageId: string, stageName: string): void {\n if (recordedRuntimeStageIds.has(runtimeStageId)) return;\n recordedRuntimeStageIds.add(runtimeStageId);\n executionOrder.push({\n runtimeStageId,\n stageId,\n stageName,\n timestampMs: performance.now() - startTime,\n });\n notifyChange();\n }\n\n const recorder: MinimalFlowRecorder = {\n id,\n onRunStart() {\n running = true;\n notifyChange();\n },\n onRunEnd() {\n running = false;\n notifyChange();\n },\n onStageExecuted(event) {\n // footprintjs v6 (#003) fires this for EVERY stage kind —\n // linear / decider / fork / selector / subflow-mount — so\n // we no longer need separate handlers for the branching events.\n const runtimeStageId = event.traversalContext.runtimeStageId;\n const baseStageId = parseStageIdFromRuntimeStageId(runtimeStageId);\n pushStep(runtimeStageId, baseStageId, event.stageName);\n },\n onError(event) {\n const fallbackId =\n event.stageId ??\n (event.traversalContext\n ? parseStageIdFromRuntimeStageId(event.traversalContext.runtimeStageId)\n : event.stageName);\n errors.set(fallbackId, event.message ?? \"error\");\n notifyChange();\n },\n };\n\n return {\n recorder,\n getOverlay(): RuntimeOverlay {\n return {\n executionOrder: executionOrder.map((s) => ({ ...s })),\n errors: new Map(errors),\n running,\n };\n },\n subscribe: notifier.subscribe,\n version: notifier.version,\n reset(): void {\n executionOrder = [];\n recordedRuntimeStageIds.clear();\n errors.clear();\n running = false;\n // Note: reset does NOT bump version or notify (matches\n // traceStructureRecorder contract — see its `reset()` JSDoc\n // for the consumer-facing recipe).\n },\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Overlay slicing for time-travel\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Snapshot of overlay state AT a specific scrub index. Drives node\n * coloring in `<TracedFlow>`.\n */\nexport interface RuntimeOverlaySlice {\n /** Base stage ids that completed before the active scrub position. */\n readonly doneStageIds: ReadonlySet<string>;\n /** The currently-active stage id (or `null` when scrub is at 0 with no exec yet). */\n readonly activeStageId: string | null;\n /** Union of done + active — convenient for \"executed at all\" checks. */\n readonly executedStageIds: ReadonlySet<string>;\n /** The full ordered list of base stage ids up through the active position —\n * used by renderers that want to number stages by occurrence (e.g.,\n * show \"3rd loop iteration\" badges). */\n readonly executedOrderIds: readonly string[];\n /** Pass-through errors map for the renderer. */\n readonly errors: ReadonlyMap<string, string>;\n}\n\n/**\n * Slice `overlay.executionOrder` at the given index:\n *\n * - `executionOrder[0..index-1]` → \"done\"\n * - `executionOrder[index]` → \"active\"\n * - `index >= executionOrder.length` → all done, no active\n *\n * Returns an empty slice when overlay has no execution history.\n */\nexport function sliceOverlay(\n overlay: RuntimeOverlay,\n index: number,\n): RuntimeOverlaySlice {\n const order = overlay.executionOrder;\n if (order.length === 0) {\n return {\n doneStageIds: new Set(),\n activeStageId: null,\n executedStageIds: new Set(),\n executedOrderIds: [],\n errors: overlay.errors,\n };\n }\n const clampedIndex = Math.max(0, Math.min(index, order.length - 1));\n const doneStageIds = new Set<string>();\n for (let i = 0; i < clampedIndex; i++) {\n doneStageIds.add(order[i]!.stageId);\n }\n const activeStep = order[clampedIndex];\n const activeStageId = activeStep ? activeStep.stageId : null;\n const executedStageIds = new Set(doneStageIds);\n if (activeStageId) executedStageIds.add(activeStageId);\n const executedOrderIds = order.slice(0, clampedIndex + 1).map((s) => s.stageId);\n return {\n doneStageIds,\n activeStageId,\n executedStageIds,\n executedOrderIds,\n errors: overlay.errors,\n };\n}\n","import { memo, useEffect, useRef } from \"react\";\nimport { Handle, Position } from \"@xyflow/react\";\nimport type { NodeProps } from \"@xyflow/react\";\nimport { theme } from \"../../theme\";\n\nconst KEYFRAMES_ID = \"fp-stage-node-keyframes\";\nconst KEYFRAMES_CSS = `\n@media (prefers-reduced-motion: no-preference) {\n @keyframes fp-pulse {\n 0%, 100% { opacity: 0.4; transform: scale(1); }\n 50% { opacity: 0.15; transform: scale(1.06); }\n }\n @keyframes fp-blink {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.3; }\n }\n}\n@media (prefers-reduced-motion: reduce) {\n @keyframes fp-pulse { 0%, 100% { opacity: 0.3; } }\n @keyframes fp-blink { 0%, 100% { opacity: 1; } }\n}\n`;\n\nexport interface StageNodeData {\n label: string;\n active?: boolean;\n done?: boolean;\n error?: boolean;\n linked?: boolean;\n /** Semantic icon hint (e.g., \"llm\", \"tool\", \"rag\", \"start\", \"parse\", \"agent\", \"guard\") */\n icon?: string;\n /** Step numbers in execution order (shown as badges — multiple when revisited via loops) */\n stepNumbers?: number[];\n /** Node was not executed (dim it) */\n dimmed?: boolean;\n /** Node is a subflow root (show nested indicator) */\n isSubflow?: boolean;\n /** Node uses lazy resolution (dashed border + cloud icon when unresolved) */\n isLazy?: boolean;\n /** Node is a decider (renders as diamond shape per flowchart convention) */\n isDecider?: boolean;\n /** Node is a fork (parallel fan-out) */\n isFork?: boolean;\n /** Human-readable description of what this stage does */\n description?: string;\n /** Subflow identifier — set when this node belongs to a subflow */\n subflowId?: string;\n /**\n * Stable stage identifier from the spec (`SpecNode.id`). Renderable as a\n * small monospace caption under the label when `showStageId` is true —\n * useful for teaching the runtimeStageId convention and for debugging\n * which node a recorder event belongs to.\n */\n stageId?: string;\n /**\n * When true, render the `stageId` as a small monospace caption beneath\n * the label. Default false. Drives the \"Show IDs\" toggle in\n * ExplainableShell.\n */\n showStageId?: boolean;\n /**\n * Visual emphasis hint — generic, so the renderer stays domain-agnostic.\n * `hero` = a stage the viewer cares about (accent border + tint + bold);\n * `muted` = mechanism/plumbing (recedes — faded + thin border). The\n * consumer's graph builder sets this from its own semantics (e.g. the\n * agentfootprint lens maps `stageRole` → emphasis). Layers UNDER run status:\n * active/done/error colours still override during a run.\n */\n emphasis?: \"hero\" | \"muted\";\n /**\n * Size tier — scales the card's text + padding to match the footprint the\n * layout allocated (the layout's node-size resolver must scale in lockstep,\n * else the card and its laid-out box disagree). `lg` = a focal stage,\n * `sm` = a minor/plumbing stage, default `md`. Generic — no domain meaning.\n */\n size?: \"sm\" | \"md\" | \"lg\";\n [key: string]: unknown;\n}\n\n// ── Stage icon SVGs ───────────────────────────────────────────────────────\n// Inline SVGs for crisp rendering at any size. Consumers pass a string key\n// via SpecNode.icon; StageNode renders the matching mini-icon.\n\nconst ICON_SIZE = 16;\n\nfunction StageIcon({ type, color }: { type: string; color: string }) {\n const s = ICON_SIZE;\n const props = { width: s, height: s, viewBox: `0 0 ${s} ${s}`, fill: \"none\", style: { flexShrink: 0 } as const };\n\n switch (type) {\n // LLM / AI call — brain/sparkle\n case \"llm\":\n case \"ai\":\n return (\n <svg {...props}>\n <circle cx=\"8\" cy=\"8\" r=\"6\" stroke={color} strokeWidth=\"1.5\" />\n <path d=\"M5.5 8C5.5 6.5 6.5 5 8 5S10.5 6.5 10.5 8\" stroke={color} strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n <circle cx=\"8\" cy=\"9.5\" r=\"1\" fill={color} />\n <line x1=\"8\" y1=\"2\" x2=\"8\" y2=\"3.5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"12.5\" y1=\"4\" x2=\"11.2\" y2=\"5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"3.5\" y1=\"4\" x2=\"4.8\" y2=\"5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n </svg>\n );\n\n // Tool / function call — gear\n case \"tool\":\n case \"function\":\n return (\n <svg {...props}>\n <circle cx=\"8\" cy=\"8\" r=\"3\" stroke={color} strokeWidth=\"1.5\" />\n {[0, 45, 90, 135, 180, 225, 270, 315].map((angle) => {\n const rad = (angle * Math.PI) / 180;\n const x1 = 8 + Math.cos(rad) * 4.5;\n const y1 = 8 + Math.sin(rad) * 4.5;\n const x2 = 8 + Math.cos(rad) * 6;\n const y2 = 8 + Math.sin(rad) * 6;\n return <line key={angle} x1={x1} y1={y1} x2={x2} y2={y2} stroke={color} strokeWidth=\"1.5\" strokeLinecap=\"round\" />;\n })}\n </svg>\n );\n\n // RAG / retrieval — magnifying glass + doc\n case \"rag\":\n case \"search\":\n case \"retrieval\":\n return (\n <svg {...props}>\n <circle cx=\"7\" cy=\"7\" r=\"4\" stroke={color} strokeWidth=\"1.5\" />\n <line x1=\"10\" y1=\"10\" x2=\"13.5\" y2=\"13.5\" stroke={color} strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <line x1=\"5.5\" y1=\"6\" x2=\"8.5\" y2=\"6\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"5.5\" y1=\"8\" x2=\"7.5\" y2=\"8\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n </svg>\n );\n\n // Parse / process — diamond with arrows\n case \"parse\":\n case \"process\":\n case \"transform\":\n return (\n <svg {...props}>\n <rect x=\"4\" y=\"4\" width=\"8\" height=\"8\" rx=\"1.5\" stroke={color} strokeWidth=\"1.5\" transform=\"rotate(45 8 8)\" />\n </svg>\n );\n\n // Start / seed — play triangle\n case \"start\":\n case \"seed\":\n case \"init\":\n return (\n <svg {...props}>\n <path d=\"M5 3.5L12.5 8L5 12.5V3.5Z\" fill={color} opacity=\"0.8\" />\n </svg>\n );\n\n // End / finalize — stop square\n case \"end\":\n case \"finalize\":\n case \"output\":\n return (\n <svg {...props}>\n <rect x=\"4\" y=\"4\" width=\"8\" height=\"8\" rx=\"1.5\" fill={color} opacity=\"0.8\" />\n </svg>\n );\n\n // Agent — person silhouette\n case \"agent\":\n case \"orchestrator\":\n return (\n <svg {...props}>\n <circle cx=\"8\" cy=\"5\" r=\"2.5\" stroke={color} strokeWidth=\"1.5\" />\n <path d=\"M3.5 14C3.5 11 5.5 9 8 9S12.5 11 12.5 14\" stroke={color} strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n );\n\n // Swarm — multi-agent\n case \"swarm\":\n case \"multi-agent\":\n return (\n <svg {...props}>\n <circle cx=\"5\" cy=\"5\" r=\"2\" stroke={color} strokeWidth=\"1.2\" />\n <circle cx=\"11\" cy=\"5\" r=\"2\" stroke={color} strokeWidth=\"1.2\" />\n <circle cx=\"8\" cy=\"11\" r=\"2\" stroke={color} strokeWidth=\"1.2\" />\n <line x1=\"5\" y1=\"7\" x2=\"8\" y2=\"9\" stroke={color} strokeWidth=\"1\" opacity=\"0.5\" />\n <line x1=\"11\" y1=\"7\" x2=\"8\" y2=\"9\" stroke={color} strokeWidth=\"1\" opacity=\"0.5\" />\n </svg>\n );\n\n // Guard / guardrail — shield\n case \"guard\":\n case \"guardrail\":\n case \"validate\":\n return (\n <svg {...props}>\n <path d=\"M8 2L3 5V9C3 11.5 5 13.5 8 14.5C11 13.5 13 11.5 13 9V5L8 2Z\" stroke={color} strokeWidth=\"1.5\" strokeLinejoin=\"round\" />\n <path d=\"M6 8L7.5 9.5L10 6.5\" stroke={color} strokeWidth=\"1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n\n // Stream — wave\n case \"stream\":\n case \"streaming\":\n return (\n <svg {...props}>\n <path d=\"M2 8C4 5 6 11 8 8S12 5 14 8\" stroke={color} strokeWidth=\"1.5\" strokeLinecap=\"round\" fill=\"none\" />\n <path d=\"M2 11C4 8 6 14 8 11S12 8 14 11\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" fill=\"none\" opacity=\"0.5\" />\n </svg>\n );\n\n // Memory / state — database cylinder\n case \"memory\":\n case \"state\":\n case \"db\":\n return (\n <svg {...props}>\n <ellipse cx=\"8\" cy=\"4.5\" rx=\"5\" ry=\"2\" stroke={color} strokeWidth=\"1.3\" />\n <line x1=\"3\" y1=\"4.5\" x2=\"3\" y2=\"11.5\" stroke={color} strokeWidth=\"1.3\" />\n <line x1=\"13\" y1=\"4.5\" x2=\"13\" y2=\"11.5\" stroke={color} strokeWidth=\"1.3\" />\n <ellipse cx=\"8\" cy=\"11.5\" rx=\"5\" ry=\"2\" stroke={color} strokeWidth=\"1.3\" />\n </svg>\n );\n\n // System prompt — document with lines\n case \"system-prompt\":\n case \"prompt\":\n case \"instructions\":\n case \"document\":\n return (\n <svg {...props}>\n <rect x=\"3.5\" y=\"2\" width=\"9\" height=\"12\" rx=\"1.5\" stroke={color} strokeWidth=\"1.3\" fill=\"none\" />\n <line x1=\"5.5\" y1=\"5\" x2=\"10.5\" y2=\"5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"5.5\" y1=\"7.5\" x2=\"10.5\" y2=\"7.5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"5.5\" y1=\"10\" x2=\"8.5\" y2=\"10\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n </svg>\n );\n\n // Messages / conversation — chat bubble\n case \"messages\":\n case \"chat\":\n case \"conversation\":\n return (\n <svg {...props}>\n <rect x=\"2.5\" y=\"3\" width=\"11\" height=\"8\" rx=\"2\" stroke={color} strokeWidth=\"1.3\" fill=\"none\" />\n <path d=\"M5.5 11L5.5 13.5L8.5 11\" stroke={color} strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n <line x1=\"5\" y1=\"6\" x2=\"11\" y2=\"6\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"5\" y1=\"8.5\" x2=\"9\" y2=\"8.5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n </svg>\n );\n\n // Loop — circular arrow\n case \"loop\":\n case \"retry\":\n return (\n <svg {...props}>\n <path d=\"M12 8A4 4 0 1 1 8 4\" stroke={color} strokeWidth=\"1.5\" strokeLinecap=\"round\" fill=\"none\" />\n <path d=\"M8 1.5L10.5 4L8 6.5\" stroke={color} strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n </svg>\n );\n\n // Lazy / service — cloud (deferred resolution, loaded on demand)\n case \"lazy\":\n case \"service\":\n case \"cloud\":\n return (\n <svg {...props}>\n <path\n d=\"M4.5 12C2.8 12 1.5 10.7 1.5 9C1.5 7.5 2.5 6.3 3.8 6C4 4 5.8 2.5 8 2.5C9.8 2.5 11.3 3.5 11.9 5C13.9 5.2 15.5 6.8 15.5 8.8C15.5 10.8 13.9 12.5 11.8 12.5H4.5\"\n stroke={color}\n strokeWidth=\"1.3\"\n strokeLinecap=\"round\"\n fill=\"none\"\n />\n </svg>\n );\n\n // Decision — diamond (already handled by isDecider shape)\n case \"decision\":\n case \"router\":\n return (\n <svg {...props}>\n <path d=\"M8 2L14 8L8 14L2 8Z\" stroke={color} strokeWidth=\"1.5\" fill=\"none\" />\n <circle cx=\"8\" cy=\"8\" r=\"1.5\" fill={color} />\n </svg>\n );\n\n default:\n return null;\n }\n}\n\n/**\n * Custom ReactFlow node for pipeline stages.\n * All colors and fonts come from `--fp-*` CSS variables (via theme).\n * Shows execution state via color, icon, step badge, and pulse animation.\n */\nexport const StageNode = memo(function StageNode({\n data,\n}: NodeProps & { data: StageNodeData }) {\n const { label, active, done, error, linked, icon, stepNumbers, dimmed, isSubflow, isLazy, isDecider, isFork, description, stageId, showStageId } = data;\n\n // Lazy nodes show cloud icon by default (unless another icon is specified)\n const effectiveIcon = icon || (isLazy ? \"lazy\" : undefined);\n // Lazy + unresolved = dashed border\n const isLazyUnresolved = isLazy && !done && !active;\n\n // Inject keyframes once into document head\n const injectedRef = useRef(false);\n useEffect(() => {\n if (injectedRef.current) return;\n if (typeof document !== \"undefined\" && !document.getElementById(KEYFRAMES_ID)) {\n const styleEl = document.createElement(\"style\");\n styleEl.id = KEYFRAMES_ID;\n styleEl.textContent = KEYFRAMES_CSS;\n document.head.appendChild(styleEl);\n }\n injectedRef.current = true;\n }, []);\n\n const isOnPath = active || done;\n\n // Emphasis (importance hierarchy). Generic flags — no domain knowledge.\n const isHero = data.emphasis === \"hero\";\n const isMuted = data.emphasis === \"muted\";\n // Card text/padding scale — kept in step with the layout's footprint resolver.\n const sizeScale = data.size === \"lg\" ? 1.3 : data.size === \"sm\" ? 0.85 : 1;\n\n // RESTING (not-yet-run) appearance carries the importance hierarchy: heroes\n // get an accent border + faint accent tint + accent glow. Run status\n // (active/done/error) overrides these during execution.\n const restingBg = isHero\n ? `color-mix(in srgb, ${theme.primary} 12%, ${theme.bgSecondary})`\n : theme.bgSecondary;\n const restingBorder = isHero ? theme.primary : theme.border;\n const restingShadow = isHero\n ? `0 0 10px color-mix(in srgb, ${theme.primary} 22%, transparent)`\n : `0 2px 8px rgba(0,0,0,0.15)`;\n\n const bg = active\n ? theme.primary\n : done\n ? theme.success\n : error\n ? theme.error\n : restingBg;\n\n const borderColor = active\n ? theme.primary\n : done\n ? theme.success\n : error\n ? theme.error\n : restingBorder;\n\n const shadow = active\n ? `0 0 22px color-mix(in srgb, ${theme.primary} 55%, transparent)`\n : done\n ? `0 0 8px color-mix(in srgb, ${theme.success} 20%, transparent)`\n : error\n ? `0 0 12px color-mix(in srgb, ${theme.error} 30%, transparent)`\n : restingShadow;\n\n // Colored states use white for contrast; default uses consumer's text color.\n const textColor =\n active || done || error ? \"#fff\" : theme.textPrimary;\n\n return (\n <>\n <Handle type=\"target\" position={Position.Top} style={{ opacity: 0 }} />\n {/* Centering wrapper. React Flow sizes the node WRAPPER to the layout's\n allocated width (which may be WIDER than the card — e.g. uniform-width\n columns, or a NodeSizeResolver footprint stamped by the layout). The\n card below is content-sized; without this wrapper it sits at the\n wrapper's LEFT edge, so its visual center drifts left of the box\n center the layout placed it at (the wider the box, the worse the\n drift). `width:100%` + center-justify makes the card's visual center\n coincide with the node-box center, so layout centering == paint\n centering. Mirrors SlotPillNode / GroupContainerNode, which already\n fill their wrapper width. */}\n <div style={{ width: \"100%\", display: \"flex\", justifyContent: \"center\" }}>\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n // Plumbing recedes. Layers with the run-overlay `dimmed` (not-yet-run)\n // — a muted AND not-run node is faintest, which is correct.\n opacity: isMuted ? 0.5 : undefined,\n }}\n >\n {/* Step number badges — multiple when revisited via loops */}\n {stepNumbers && stepNumbers.length > 0 && isOnPath && (\n <div\n style={{\n position: \"absolute\",\n top: -10,\n left: -10,\n display: \"flex\",\n gap: 3,\n zIndex: 10,\n }}\n >\n {stepNumbers.map((num, i) => {\n const isLatest = i === stepNumbers.length - 1;\n const badgeBg = isLatest && active ? theme.primary : theme.success;\n const glow = isLatest && active\n ? `color-mix(in srgb, ${theme.primary} 50%, transparent)`\n : `color-mix(in srgb, ${theme.success} 40%, transparent)`;\n return (\n <div\n key={num}\n style={{\n width: 22,\n height: 22,\n borderRadius: \"50%\",\n background: badgeBg,\n color: \"#fff\",\n fontSize: 11,\n fontWeight: 700,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxShadow: `0 0 8px ${glow}`,\n }}\n >\n {num}\n </div>\n );\n })}\n </div>\n )}\n\n {/* Linked pulse ring */}\n {linked && (\n <div\n style={{\n position: \"absolute\",\n inset: -6,\n borderRadius: isDecider ? 0 : `calc(${theme.radius} + 4px)`,\n clipPath: isDecider ? \"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)\" : undefined,\n border: `2px solid ${theme.primary}`,\n opacity: 0.4,\n animation: \"fp-pulse 2s ease-in-out infinite\",\n }}\n />\n )}\n\n {/* Active node pulse ring */}\n {active && (\n <div\n style={{\n position: \"absolute\",\n inset: -6,\n borderRadius: isDecider ? 0 : `calc(${theme.radius} + 4px)`,\n clipPath: isDecider ? \"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)\" : undefined,\n border: `2px solid ${theme.primary}`,\n opacity: 0.3,\n animation: \"fp-pulse 1.5s ease-out infinite\",\n }}\n />\n )}\n\n {/* \"NOW\" badge — marks the step the cursor is on (the live step),\n mirroring the monitor mockup. Sits top-right so it never collides\n with the top-left step-number badge. */}\n {active && (\n <div\n style={{\n position: \"absolute\",\n top: -9,\n right: -8,\n zIndex: 11,\n background: theme.warning,\n color: \"#1a1a1a\",\n fontSize: 9,\n fontWeight: 800,\n letterSpacing: 0.6,\n padding: \"2px 6px\",\n borderRadius: 10,\n boxShadow: `0 0 10px color-mix(in srgb, ${theme.warning} 60%, transparent)`,\n }}\n >\n NOW\n </div>\n )}\n\n {/* Diamond for decider nodes — proper diamond via clip-path */}\n {isDecider ? (\n <div style={{ position: \"relative\", width: 120, height: 72 }}>\n {/* Diamond shape layer */}\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background: bg,\n clipPath: \"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)\",\n border: \"none\",\n boxShadow: shadow,\n transition: \"all 0.3s ease\",\n }}\n />\n {/* Border layer — slightly larger diamond behind */}\n <div\n style={{\n position: \"absolute\",\n inset: -2,\n clipPath: \"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)\",\n background: borderColor,\n zIndex: -1,\n ...(isLazyUnresolved ? {\n background: \"transparent\",\n // Dashed border via SVG for clip-path (CSS border doesn't work with clip-path)\n } : {}),\n }}\n />\n {/* Content — centered on top of diamond */}\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 1,\n fontFamily: theme.fontSans,\n zIndex: 1,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\n {effectiveIcon && <StageIcon type={effectiveIcon} color={textColor} />}\n {!effectiveIcon && (\n <span style={{ fontSize: 9, color: textColor }}>◇</span>\n )}\n <span\n style={{\n fontSize: 11,\n fontWeight: 600,\n color: textColor,\n whiteSpace: \"nowrap\",\n }}\n >\n {label}\n </span>\n </div>\n {description && (\n <span\n style={{\n fontSize: 8,\n fontWeight: 400,\n color: textColor,\n opacity: 0.7,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n maxWidth: 100,\n }}\n >\n {description}\n </span>\n )}\n {showStageId && stageId && (\n <span\n style={{\n fontSize: 8,\n fontFamily: \"ui-monospace, monospace\",\n color: textColor,\n opacity: 0.55,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n maxWidth: 100,\n }}\n title={`stageId: ${stageId}`}\n >\n {stageId}\n </span>\n )}\n </div>\n </div>\n ) : (\n /* Standard rectangular node */\n <div\n style={{\n background: bg,\n border: `${isHero ? \"2.5px\" : isMuted ? \"1px\" : \"2px\"} ${isLazyUnresolved ? \"dashed\" : \"solid\"} ${borderColor}`,\n borderRadius: theme.radius,\n padding: description\n ? `${Math.round(8 * sizeScale)}px ${Math.round(16 * sizeScale)}px`\n : `${Math.round(10 * sizeScale)}px ${Math.round(20 * sizeScale)}px`,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: description ? 2 : 0,\n boxShadow: shadow,\n transition: \"all 0.3s ease\",\n fontFamily: theme.fontSans,\n minWidth: 100,\n justifyContent: \"center\",\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n {/* Semantic icon (lazy nodes default to cloud icon) */}\n {effectiveIcon && <StageIcon type={effectiveIcon} color={textColor} />}\n\n {/* State icon */}\n {done && !effectiveIcon && (\n <span style={{ fontSize: 10, color: textColor }}>✓</span>\n )}\n {active && !effectiveIcon && (\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: \"#fff\",\n animation: \"fp-blink 1s ease-in-out infinite\",\n flexShrink: 0,\n }}\n />\n )}\n {error && !effectiveIcon && (\n <span style={{ fontSize: 10, color: textColor }}>✗</span>\n )}\n\n <span\n style={{\n fontSize: Math.round(13 * sizeScale),\n fontWeight: isHero ? 700 : 500,\n color: textColor,\n whiteSpace: \"nowrap\",\n }}\n >\n {label}\n </span>\n {/* Subflow indicator — nested boxes icon */}\n {isSubflow && (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 16,\n height: 16,\n borderRadius: 3,\n border: `1.5px solid ${textColor}`,\n position: \"relative\",\n opacity: 0.7,\n flexShrink: 0,\n }}\n >\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: 2,\n border: `1px solid ${textColor}`,\n }}\n />\n </span>\n )}\n </div>\n {/* Description subtitle */}\n {description && (\n <span\n style={{\n fontSize: 10,\n fontWeight: 400,\n color: textColor,\n opacity: 0.7,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n maxWidth: 160,\n }}\n >\n {description}\n </span>\n )}\n {/* Stage ID caption — toggled by `showStageId`. Teaches the\n runtimeStageId convention; recorders key their data by\n this ID so consumers can render any recorder's per-stage\n output by lookup. */}\n {showStageId && stageId && (\n <span\n style={{\n fontSize: 9,\n fontFamily: \"ui-monospace, monospace\",\n color: textColor,\n opacity: 0.55,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n maxWidth: 160,\n }}\n title={`stageId: ${stageId}`}\n >\n {stageId}\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n <Handle type=\"source\" position={Position.Bottom} style={{ opacity: 0 }} />\n </>\n );\n});\n","/**\n * Pure helpers for subflow drill-down on a `TraceGraph`.\n *\n * Filtering and breadcrumb computation are derived from the\n * `TraceNodeData.subflowOf` field that the structure recorder sets\n * at `onSubflowMounted` time. Both functions are pure (no I/O, no\n * React) so they can be unit-tested in isolation and reused by any\n * renderer.\n */\n\nimport type { TraceGraph } from \"../traceStructureRecorder\";\n\n/**\n * Filter the trace graph by drill-down scope.\n *\n * - `currentSubflowId === null` → show top-level (nodes with no\n * `subflowOf`). Subflow internals are hidden; their mount node\n * stays visible as a single clickable card.\n * - `currentSubflowId === 'X'` → show only nodes where\n * `subflowOf === 'X'` (the drilled-in subflow's internals).\n *\n * Edges follow the same filter — only edges where both endpoints\n * are in the visible set survive. When nothing would be filtered\n * out, returns the original graph reference (preserves upstream\n * memoization).\n */\nexport function filterGraphForDrill(\n graph: TraceGraph,\n currentSubflowId: string | null,\n): TraceGraph {\n if (graph.nodes.length === 0) return graph;\n const matchesScope = (subflowOf: string | undefined): boolean =>\n currentSubflowId === null ? subflowOf === undefined : subflowOf === currentSubflowId;\n const visibleIds = new Set<string>();\n for (const n of graph.nodes) {\n if (matchesScope(n.data?.subflowOf)) visibleIds.add(n.id);\n }\n if (visibleIds.size === graph.nodes.length) return graph;\n return {\n nodes: graph.nodes.filter((n) => visibleIds.has(n.id)),\n edges: graph.edges.filter((e) => visibleIds.has(e.source) && visibleIds.has(e.target)),\n };\n}\n\n/** Entry in the breadcrumb path. `subflowId === null` is the root. */\nexport interface BreadcrumbEntry {\n subflowId: string | null;\n label: string;\n}\n\n/**\n * Build the breadcrumb path for the current drill level.\n *\n * Always starts with the root `{ subflowId: null, label: 'Chart' }`.\n * When drilled into a subflow, appends one entry with the mount\n * node's display label (falling back to the subflow id). Multi-level\n * drill chains are NOT supported by the current chart UX (drill is\n * always from root or sibling — clicking a deeper subflow's mount\n * replaces the current scope), so the path has at most 2 entries.\n */\nexport function buildSubflowBreadcrumb(\n graph: TraceGraph,\n currentSubflowId: string | null,\n): BreadcrumbEntry[] {\n const out: BreadcrumbEntry[] = [{ subflowId: null, label: \"Chart\" }];\n if (currentSubflowId !== null) {\n const mount = graph.nodes.find((n) => n.data?.subflowId === currentSubflowId);\n out.push({\n subflowId: currentSubflowId,\n label: mount?.data?.label ?? currentSubflowId,\n });\n }\n return out;\n}\n","/**\n * Pure helper for projecting a raw `RuntimeOverlaySlice` into the\n * shape `<TracedFlow>` needs for per-node coloring:\n *\n * `aggregateMountStatus` — when execution is INSIDE a subflow, light\n * up the mount node in the parent view as done/active based on its\n * internals' statuses.\n *\n * Pure (no I/O, no React).\n *\n * Note: there is NO id-normalization step. Both the overlay slice and\n * the structure graph use path-QUALIFIED stage ids (`subflowPath/stageId`,\n * mirroring runtimeStageId), so they match directly. (A former\n * `normalizeSliceLeafIds` step existed only while structure ids were\n * bare; once `walkSubflowSpecInto` started qualifying inner ids, leaf-\n * stripping became a mismatch and was removed.)\n */\n\nimport type { TraceGraph } from \"../traceStructureRecorder\";\n\nexport interface OverlaySlice {\n doneStageIds: ReadonlySet<string>;\n activeStageId: string | null;\n executedStageIds: ReadonlySet<string>;\n executedOrderIds: readonly string[];\n errors: ReadonlyMap<string, string>;\n}\n\n/**\n * Aggregate subflow internals' status onto their mount nodes.\n *\n * - Mount is DONE when EVERY internal stage is done.\n * - Mount is ACTIVE only when an internal stage is CURRENTLY active\n * (not merely past-done), and only when viewing the TOP-LEVEL chart\n * (`currentSubflowId === null`). When drilled INTO a subflow, the\n * active highlight stays on the actual subflow stage, not the mount.\n * (Promoting on past-done internals let a looping subflow steal\n * \"active\" from the real live top-level node — see the inline note.)\n *\n * Pre-condition: slice has already been leaf-normalized so its\n * stage ids match `graph.nodes[].id`.\n */\nexport function aggregateMountStatus(\n slice: OverlaySlice,\n graph: TraceGraph,\n currentSubflowId: string | null,\n): OverlaySlice {\n if (graph.nodes.length === 0) return slice;\n const mounts = graph.nodes.filter((n) => n.data?.isSubflow && n.data?.subflowId);\n if (mounts.length === 0) return slice;\n const doneIds = new Set(slice.doneStageIds);\n let activeId = slice.activeStageId;\n for (const mount of mounts) {\n const sfId = mount.data!.subflowId as string;\n const members = graph.nodes.filter((n) => n.data?.subflowOf === sfId);\n if (members.length === 0) continue;\n const anyActive = members.some((m) => m.id === slice.activeStageId);\n const allDone = members.every((m) => slice.doneStageIds.has(m.id));\n if (allDone) doneIds.add(mount.id);\n // Promote \"active\" to the mount ONLY when the live node is genuinely INSIDE\n // this subflow (anyActive). Previously a mount with merely PAST-done members\n // (`anyDone`) also stole active — and once subflow internals are materialised\n // (for drill), a looping subflow's earlier-iteration done members made the\n // mount steal \"active\" from the real top-level live node (e.g. the tool\n // call), so that node's NOW highlight disappeared. The mount's own done-ness\n // still comes from its own commit + the allDone branch above.\n else if (anyActive && currentSubflowId === null) {\n activeId = mount.id;\n }\n }\n return { ...slice, doneStageIds: doneIds, activeStageId: activeId };\n}\n","/**\n * useSubflowDrill — drill state for the chart's view scope.\n *\n * - Owns `currentSubflowId: string | null` (null = top-level)\n * - Exposes `drillInto(subflowId)` and `drillUp()` for navigation\n * - Notifies the host via `onSubflowChange(mountStageId | null)`\n * whenever the drill state changes — host wires this to its own\n * drill-stack so data panels follow\n *\n * Drill changes are EXPLICIT — there's no auto-drill on scrub. The\n * mount node's status reflects \"execution is inside\" via\n * `aggregateMountStatus` (see overlayProjection.ts).\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { TraceGraph } from \"../traceStructureRecorder\";\n\nexport interface SubflowDrillHandle {\n /** Current drill scope. `null` = top-level. */\n currentSubflowId: string | null;\n /** Navigate INTO the given subflow (by `subflowId`). */\n drillInto: (subflowId: string) => void;\n /** Pop back up to the parent / top-level. */\n drillUp: () => void;\n /** Direct setter for breadcrumb navigation (any target including `null`). */\n setCurrentSubflowId: (id: string | null) => void;\n}\n\nexport function useSubflowDrill(\n graph: TraceGraph,\n onSubflowChange?: (mountStageId: string | null) => void,\n): SubflowDrillHandle {\n const [currentSubflowId, setCurrentSubflowId] = useState<string | null>(null);\n\n // Reset drill state when the graph IDENTITY changes (e.g., the\n // user switched to a different sample in the playground sidebar).\n // Without this, the drill state from sample A persists into\n // sample B's rendering — `currentSubflowId='payment'` survives the\n // chart swap, but sample B has no 'payment' subflow, so the filter\n // returns no visible nodes (blank chart).\n //\n // Also reset when the currently-drilled subflow no longer exists\n // in the new graph (defensive — graph mutations could remove a\n // subflow without changing the wrapper reference).\n const lastGraphRef = useRef<TraceGraph | null>(null);\n if (lastGraphRef.current !== graph) {\n lastGraphRef.current = graph;\n if (\n currentSubflowId !== null &&\n !graph.nodes.some((n) => n.data?.subflowId === currentSubflowId)\n ) {\n // Schedule reset for next render (can't setState during render).\n queueMicrotask(() => setCurrentSubflowId(null));\n }\n }\n\n // Notify the host when drill changes. Resolve the mount stage id\n // from the graph (the parent-chart node whose `subflowId` matches).\n const lastNotifiedRef = useRef<string | null | undefined>(undefined);\n useEffect(() => {\n if (lastNotifiedRef.current === currentSubflowId) return;\n lastNotifiedRef.current = currentSubflowId;\n if (currentSubflowId === null) {\n onSubflowChange?.(null);\n } else {\n const mount = graph.nodes.find((n) => n.data?.subflowId === currentSubflowId);\n if (mount) onSubflowChange?.(mount.id);\n }\n }, [currentSubflowId, graph, onSubflowChange]);\n\n const drillInto = useCallback((subflowId: string) => {\n setCurrentSubflowId(subflowId);\n }, []);\n const drillUp = useCallback(() => {\n setCurrentSubflowId(null);\n }, []);\n\n return { currentSubflowId, drillInto, drillUp, setCurrentSubflowId };\n}\n","/**\n * useChartAutoRefit — keep an xyflow chart fitted to its container.\n *\n * xyflow's `fitView` prop only runs on mount; it does NOT re-fit\n * when the container resizes. This hook closes that gap by:\n *\n * 1. Observing the wrapper element via `ResizeObserver` →\n * `instance.fitView({ duration, padding })` on the next animation\n * frame (so the new container size is measured first).\n * 2. Also listening to `window resize` events — `ExplainableShell`\n * dispatches synthetic resize events when its detail panels\n * toggle (those size changes may be animated and not yet\n * measurable by ResizeObserver on the first tick).\n *\n * Without this hook the chart shrinks once on Details-open and\n * never grows back when Details closes.\n *\n * It ALSO re-fits when the VISIBLE GRAPH changes (e.g. drilling into /\n * out of a subflow). xyflow only auto-fits on mount, so after a drill the\n * new, smaller subgraph keeps the parent chart's pan/zoom — leaving it\n * cramped in one corner with empty space around it. Pass a `refitKey`\n * (the drill id) so the chart recenters + rezooms to the drilled content.\n */\n\nimport { useEffect } from \"react\";\nimport type { RefObject } from \"react\";\nimport type { ReactFlowInstance } from \"@xyflow/react\";\n\nexport function useChartAutoRefit(\n wrapperRef: RefObject<HTMLElement | null>,\n rfInstance: ReactFlowInstance | null,\n options: { duration?: number; padding?: number; refitKey?: unknown } = {},\n): void {\n const duration = options.duration ?? 200;\n const padding = options.padding ?? 0.1;\n const refitKey = options.refitKey;\n\n useEffect(() => {\n const el = wrapperRef.current;\n if (!el || !rfInstance) return;\n let raf = 0;\n const refit = () => {\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n rfInstance.fitView({ duration, padding });\n });\n };\n const ro = new ResizeObserver(refit);\n ro.observe(el);\n window.addEventListener(\"resize\", refit);\n return () => {\n ro.disconnect();\n window.removeEventListener(\"resize\", refit);\n cancelAnimationFrame(raf);\n };\n }, [rfInstance, wrapperRef, duration, padding]);\n\n // Re-fit when the visible graph changes (drill in/out). Two rAFs: the first\n // lets React commit the new node set, the second lets xyflow measure the new\n // nodes' dimensions before fitView reads them — otherwise fitView centers on\n // stale/zero-size bounds and the drilled chart still lands off-center.\n useEffect(() => {\n if (!rfInstance) return;\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => {\n rfInstance.fitView({ duration, padding });\n });\n });\n return () => {\n cancelAnimationFrame(raf1);\n cancelAnimationFrame(raf2);\n };\n }, [rfInstance, refitKey, duration, padding]);\n}\n","/**\n * SubflowBreadcrumbBar — clickable trail of subflow drill levels.\n *\n * Chart › Outer Subflow › Inner Subflow\n *\n * The last entry renders disabled (you're already here). Earlier\n * entries are clickable — fire `onNavigate(subflowId)` (null = root).\n *\n * Pure presentation: takes the precomputed `entries` array (built by\n * `buildSubflowBreadcrumb` in `_internal/subflowDrill.ts`). No drill\n * state lives here.\n */\n\nimport type { BreadcrumbEntry } from \"./_internal/subflowDrill\";\nimport { rawDefaults } from \"../../theme/tokens\";\n\nexport interface SubflowBreadcrumbBarProps {\n entries: BreadcrumbEntry[];\n onNavigate: (subflowId: string | null) => void;\n}\n\nexport function SubflowBreadcrumbBar({ entries, onNavigate }: SubflowBreadcrumbBarProps) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n padding: \"6px 12px\",\n fontSize: 11,\n background: rawDefaults.colors.bgSecondary,\n borderBottom: `1px solid ${rawDefaults.colors.border}`,\n flexShrink: 0,\n }}\n aria-label=\"Subflow breadcrumb\"\n >\n {entries.map((entry, i) => {\n const isLast = i === entries.length - 1;\n return (\n <span\n key={entry.subflowId ?? \"__top__\"}\n style={{ display: \"inline-flex\", alignItems: \"center\", gap: 6 }}\n >\n <button\n type=\"button\"\n onClick={() => onNavigate(entry.subflowId)}\n disabled={isLast}\n style={{\n background: \"transparent\",\n border: \"none\",\n padding: 0,\n fontSize: 11,\n fontWeight: isLast ? 600 : 500,\n color: isLast ? rawDefaults.colors.textPrimary : rawDefaults.colors.primary,\n cursor: isLast ? \"default\" : \"pointer\",\n textDecoration: isLast ? \"none\" : \"underline\",\n fontFamily: \"inherit\",\n }}\n >\n {entry.label}\n </button>\n {!isLast && <span style={{ color: rawDefaults.colors.textMuted }}>›</span>}\n </span>\n );\n })}\n </div>\n );\n}\n","/**\n * GroupContainerNode — xyflow renderer for a subflow rendered as a GROUP\n * box (the `parentId` + `extent:'parent'` sub-flow pattern). Produced by\n * `applyGroupLayout` (it retypes a subflow mount to `groupContainer` and\n * sizes it via `style.width/height`); the subflow's member stages render\n * NESTED inside, as their own xyflow nodes positioned over this box.\n *\n * This box is therefore mostly chrome: a titled, bordered frame the member\n * nodes sit inside. It carries top/bottom handles so the parent-chain edges\n * (e.g. `context → this`, `this → message-api`) still connect to it.\n *\n * Overlay-aware: when the subflow's internals are active/done (aggregated\n * onto the mount by `aggregateMountStatus`), the frame highlights — same\n * done/active semantics the bundled `StageNode` uses.\n */\n\nimport { Handle, Position } from \"@xyflow/react\";\nimport type { NodeProps } from \"@xyflow/react\";\nimport { rawDefaults } from \"../../theme/tokens\";\n\nconst C = rawDefaults.colors;\n\nexport interface GroupContainerNodeData {\n label: string;\n isGroupContainer?: boolean;\n active?: boolean;\n done?: boolean;\n error?: boolean;\n dimmed?: boolean;\n description?: string;\n icon?: string;\n [key: string]: unknown;\n}\n\nexport function GroupContainerNode({ data }: NodeProps) {\n const d = data as GroupContainerNodeData;\n const borderColor = d.error\n ? C.error\n : d.active\n ? C.primary\n : d.done\n ? C.success\n : C.border;\n\n return (\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n boxSizing: \"border-box\",\n border: `1.5px ${d.active || d.done || d.error ? \"solid\" : \"dashed\"} ${borderColor}`,\n borderRadius: 12,\n // Translucent so the dotted background + nested children read clearly.\n background: \"rgba(148, 163, 184, 0.06)\",\n opacity: d.dimmed ? 0.4 : 1,\n position: \"relative\",\n }}\n >\n {/* Title header strip. */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n padding: \"8px 12px\",\n fontSize: 12,\n fontWeight: 600,\n color: C.textMuted,\n letterSpacing: 0.2,\n }}\n >\n {d.icon ? <span aria-hidden>{d.icon}</span> : null}\n <span>{d.label}</span>\n </div>\n\n {/* Edge handles — top target, bottom source (top→bottom flow). */}\n <Handle type=\"target\" position={Position.Top} style={{ opacity: 0 }} />\n <Handle type=\"source\" position={Position.Bottom} style={{ opacity: 0 }} />\n </div>\n );\n}\n","/**\n * LoopBackEdge — xyflow custom edge for `loopTo` back-edges, routed as a\n * CURVE along the chart's right margin instead of straight down the spine.\n *\n * WHY a custom edge (not handle-based side-routing): the prior approach asked\n * every node type to declare dedicated `loop-source` / `loop-target` handles;\n * any node missing them (custom consumer nodes, group boxes, slot pills)\n * silently fell back to the default top/bottom handles and the loop collapsed\n * back onto the spine. This component sidesteps handles entirely: it reads the\n * source/target node bounds straight from the xyflow store, anchors on their\n * RIGHT edges, and bows out to a shared lane clear of every content node. It\n * therefore works for ANY node type with zero per-node wiring — register it\n * once and every loop curves.\n *\n * The math lives in `_internal/loopRouting` (pure, unit-tested); this is the\n * thin React adapter. `style` (stroke color + dash) and `markerEnd` (arrow)\n * flow through from the renderer's edge styler unchanged.\n */\n\nimport { BaseEdge, useStore } from \"@xyflow/react\";\nimport type { CSSProperties } from \"react\";\nimport type { EdgeProps, InternalNode, ReactFlowState } from \"@xyflow/react\";\nimport { LOOP_LANE_GAP, loopBackPath, loopLaneX } from \"../FlowchartView/_internal/loopRouting\";\nimport { GROUP_CONTAINER_NODE_TYPE } from \"../FlowchartView/_internal/groupLayout\";\n\n/** A loop-back spans the whole chart height down the right margin, so a SOLID\n * line at full weight reads as a wall. We soften it — dashed + slightly muted —\n * so it registers as a \"control returns to the top\" path, not a hard edge.\n * The renderer's color/state still flows through `style`; we only ADD the dash\n * and CAP the opacity (never brighter than `softCap`, but free to dim further\n * when the edge is out of the current scrub scope). */\nconst LOOP_DASH = \"5 5\";\nconst LOOP_STROKE_OPACITY_CAP = 0.55; // muted — the long return shouldn't dominate\nconst LOOP_STROKE_WIDTH = 1.5; // thinner than a spine edge (default ~2)\nexport function softenLoopStyle(style: CSSProperties | undefined): CSSProperties {\n // Use SVG-native stroke props (strokeOpacity / strokeWidth) — they render on\n // the <path> reliably, unlike `opacity` which react-flow's BaseEdge does not\n // forward to the stroke. strokeOpacity is CAPPED (never bolder than the cap)\n // but may go lower when the renderer dims an out-of-scope edge.\n const passedStrokeOpacity =\n typeof style?.strokeOpacity === \"number\" ? style.strokeOpacity : 1;\n return {\n ...style,\n strokeDasharray: style?.strokeDasharray ?? LOOP_DASH,\n strokeOpacity: Math.min(passedStrokeOpacity, LOOP_STROKE_OPACITY_CAP),\n strokeWidth: LOOP_STROKE_WIDTH,\n };\n}\n\n/** Slightly larger corner radius than a normal step edge — a gentler, rounder\n * arc reinforces the \"soft return\" read. */\nconst LOOP_CORNER_RADIUS = 28;\n\n/** Absolute x of a node's right edge. */\nfunction rightEdge(node: InternalNode): number {\n return node.internals.positionAbsolute.x + (node.measured.width ?? 0);\n}\n\n/** Absolute y of a node's vertical center. */\nfunction centerY(node: InternalNode): number {\n return node.internals.positionAbsolute.y + (node.measured.height ?? 0) / 2;\n}\n\nexport function LoopBackEdge({ id, source, target, markerEnd, style }: EdgeProps) {\n // Derive the full SVG path inside the store selector and return it as a\n // STRING — primitive equality means the edge only re-renders when its\n // geometry actually changes (no per-tick churn, no render loop).\n const path = useStore((s: ReactFlowState) => {\n const src = s.nodeLookup.get(source);\n const tgt = s.nodeLookup.get(target);\n if (!src || !tgt) return \"\";\n\n // Lane sits right of every CONTENT node. Group containers (the frame box\n // itself) are excluded — the box spans the whole chart, so counting it\n // would always push the lane outside its own border.\n const contentRights: number[] = [];\n for (const n of s.nodeLookup.values()) {\n if (n.type === GROUP_CONTAINER_NODE_TYPE) continue;\n contentRights.push(rightEdge(n));\n }\n // Add the endpoints explicitly: when source or target IS a group container\n // (a loop into/out of a box), the loop above skipped it, so include its\n // right edge here so the lane still clears the endpoint. For ordinary\n // (content) endpoints this is a harmless duplicate — loopLaneX takes a max.\n const laneX = loopLaneX([...contentRights, rightEdge(src), rightEdge(tgt)], LOOP_LANE_GAP);\n\n return loopBackPath(\n { right: rightEdge(src), centerY: centerY(src) },\n { right: rightEdge(tgt), centerY: centerY(tgt) },\n laneX,\n LOOP_CORNER_RADIUS,\n );\n });\n\n if (!path) return null;\n return (\n <BaseEdge\n id={id}\n path={path}\n markerEnd={markerEnd}\n style={softenLoopStyle(style)}\n aria-label=\"Loop back\"\n />\n );\n}\n","/**\n * loopRouting — pure geometry for the right-margin loop-back curve.\n *\n * A `loopTo` back-edge (e.g. ReAct's `Route → Context`) must NOT be drawn\n * straight down the chart spine — it overlaps every node it passes. Instead\n * it is routed as a CURVE that exits the source node's RIGHT edge, bows out to\n * a vertical \"lane\" clear of every content node, and re-enters the target\n * node's RIGHT edge. The lane is shared by all loops so they stack tidily on\n * the right margin.\n *\n * This module is the pure core (no React, no DOM): the `LoopBackEdge`\n * component gathers node bounds from the xyflow store and calls these; the\n * `wrapInMainChartBox` layout reserves `LOOP_LANE_GAP` of right-margin width\n * so the curve renders INSIDE the chart's frame. Keeping the math here makes\n * it unit-testable and keeps the edge component a thin adapter.\n */\n\n/**\n * Horizontal gap (px) between the rightmost content node and the loop lane —\n * how far right of everything the curve bows. Shared by `LoopBackEdge` (which\n * draws to the lane) and `wrapInMainChartBox` (which reserves room for it), so\n * the curve always lands inside the frame.\n */\nexport const LOOP_LANE_GAP = 56;\n\n/** A loop endpoint: a node's right edge x and vertical center y (flow coords). */\nexport interface LoopEndpoint {\n /** Absolute x of the node's RIGHT edge (position.x + width). */\n readonly right: number;\n /** Absolute y of the node's vertical center. */\n readonly centerY: number;\n}\n\n/**\n * The x of the vertical lane the loop curve bows out to: just right of the\n * widest content node, so the curve clears every node it arcs past. Pass the\n * right-edge x of every content node (the box container itself is excluded by\n * the caller — it would otherwise always be the widest and push the lane\n * outside its own frame). Empty input → `gap` (degenerate but safe).\n */\nexport function loopLaneX(contentRights: readonly number[], gap: number = LOOP_LANE_GAP): number {\n // Empty-input fallback: `max` stays -Infinity until the loop assigns it, so\n // `!Number.isFinite` catches the no-nodes case and degrades the lane to `gap`.\n let max = -Infinity;\n for (const r of contentRights) if (r > max) max = r;\n if (!Number.isFinite(max)) max = 0;\n return max + gap;\n}\n\n/**\n * SVG path for one right-margin loop-back curve. A cubic bezier whose BOTH\n * route HUGS the lane: it leaves the source heading right, runs straight UP (or\n * down) the lane — which sits right of EVERY node — and only turns in toward the\n * target at the target's own row (the target is the chart's first node, alone at\n * the top, so the turn-in clears everything). Corners are rounded for a curved\n * feel. A pure inward-bowing bezier was abandoned because it cuts back toward\n * the target's x BEFORE the top, slicing across whatever node is rightmost in\n * the rows it passes (e.g. the tools slot).\n *\n * `radius` is the corner rounding (clamped to fit the available run/rise).\n */\nexport function loopBackPath(\n source: LoopEndpoint,\n target: LoopEndpoint,\n laneX: number,\n radius = 22,\n): string {\n const { right: sx, centerY: sy } = source;\n const { right: tx, centerY: ty } = target;\n // Corner radius can't exceed half the vertical run, nor the horizontal gap to\n // the lane on either side.\n const r = Math.max(\n 0,\n Math.min(radius, Math.abs(sy - ty) / 2, laneX - sx, laneX - tx),\n );\n const up = ty <= sy; // target above source (the normal ReAct loop)\n const vy1 = up ? sy - r : sy + r; // first corner's far-y (leaving source row)\n const vy2 = up ? ty + r : ty - r; // second corner's near-y (entering target row)\n // out to the lane → round → straight up/down the lane → round → in to target.\n return [\n `M ${sx},${sy}`,\n `L ${laneX - r},${sy}`,\n `Q ${laneX},${sy} ${laneX},${vy1}`,\n `L ${laneX},${vy2}`,\n `Q ${laneX},${ty} ${laneX - r},${ty}`,\n `L ${tx},${ty}`,\n ].join(\" \");\n}\n","/**\n * groupLayout — xyflow NATIVE container boxes for the trace chart.\n *\n * Two box mechanisms live here, plus the existing drill (elsewhere):\n *\n * - **Drill** (`subflowDrill.ts` + `useSubflowDrill`): a subflow shows as\n * ONE mount card; clicking it zooms in. The DEFAULT for every subflow.\n * - **Main-chart box** (`wrapInMainChartBox`): wrap the WHOLE chart in ONE\n * container box. This is the Lens model — the primitive you're viewing\n * (LLMCall / Agent) is always one box; every subflow inside it stays a\n * drill card. A `nodeTypes` registry then styles each inner card\n * (system-prompt / messages / tools / LLM). USE THIS for Lens.\n * - **Per-subflow group** (`applyGroupLayout`): box individual subflows\n * (mount → container, members nested inside). A more granular tool kept\n * for consumers that want specific subflows inlined as boxes rather than\n * drilled. NOT what the Lens main-chart model uses.\n *\n * All are pure `(graph, opts) => graph` (no React, no I/O) and compose with\n * `<TracedFlow>` before nodes reach `<ReactFlow>`. explainable-ui stays\n * policy-free: it offers the mechanisms; the consumer (Lens) picks.\n *\n * Pure: `(graph, opts) => graph`. No React, no I/O. Composed by `<TracedFlow>`\n * before the nodes reach `<ReactFlow>`.\n *\n * What it does, given `groupedSubflowIds`:\n * 1. For each grouped subflow that is actually present (a mount node whose\n * `subflowId` is listed AND has ≥1 member where `subflowOf === id`):\n * - lay the OUTER graph out with `baseLayout` (members excluded; the\n * mount stays as the box anchor);\n * - lay the subflow's MEMBERS out with `baseLayout` in isolation, then\n * normalise them to the box's local coordinate space;\n * - size the container box to fit the members (+ header + padding);\n * - convert the mount node to `type: 'groupContainer'` with a `style`\n * width/height, and nest each member via `parentId` + `extent`.\n * 2. Subflows NOT listed are left untouched (they continue to drill).\n *\n * Node ORDER invariant (xyflow requirement): a parent node MUST appear\n * before its children in the array. We emit all outer nodes (containers\n * included) first, then all nested members — so every container precedes\n * its members.\n */\n\nimport type { TraceGraph, TraceNode } from \"../traceStructureRecorder\";\nimport type { TraceFlowLayout } from \"../TraceFlow\";\nimport { LOOP_LANE_GAP } from \"./loopRouting\";\n\n/** xyflow node type used for the container box. Consumers register a\n * renderer for this key (explainable-ui ships a default `GroupContainerNode`). */\nexport const GROUP_CONTAINER_NODE_TYPE = \"groupContainer\";\n\nexport interface GroupLayoutOptions {\n /** Subflow ids (the mount's `subflowId`) to render as group boxes. */\n readonly groupedSubflowIds: readonly string[];\n /** Layout for both the outer graph and each subflow's interior. */\n readonly baseLayout: TraceFlowLayout;\n /** Inner padding inside the container box, in px. Default 16. */\n readonly padding?: number;\n /** Header strip height (room for the box title), in px. Default 44. */\n readonly headerHeight?: number;\n /** Assumed node footprint for box sizing (the layout sets positions, not\n * sizes). Defaults match the bundled `StageNode` footprint. */\n readonly nodeWidth?: number;\n readonly nodeHeight?: number;\n}\n\nconst DEFAULT_PADDING = 16;\nconst DEFAULT_HEADER = 44;\nconst DEFAULT_NODE_W = 200;\nconst DEFAULT_NODE_H = 80;\n\n/**\n * Resolve a node's rendered FOOTPRINT for box-sizing math.\n *\n * A node's true extent is `position + footprint`, not its top-left corner.\n * For a `groupContainer` produced by a prior pass the footprint lives on\n * `style.width/height` (e.g. a boxed subflow ~1756px wide); for a plain\n * stage card it is the configured default. Composing nested boxes therefore\n * REQUIRES reading this — otherwise a wide container is measured as a point\n * and the outer box is sized far too small to contain it.\n *\n * Mirrors `dagreTraceLayout.sizeOf` (`style.width/height` → default) so the\n * box transforms and the dagre layout agree on every node's footprint.\n */\nfunction footprintOf(\n node: TraceNode,\n fallbackW: number,\n fallbackH: number,\n): { width: number; height: number } {\n const style = (node.style ?? {}) as { width?: unknown; height?: unknown };\n const w = typeof style.width === \"number\" ? style.width : fallbackW;\n const h = typeof style.height === \"number\" ? style.height : fallbackH;\n return { width: w, height: h };\n}\n\n/**\n * Apply group-container nesting to a positioned-or-unpositioned graph.\n * Returns a NEW graph (input is not mutated). Edges pass through unchanged\n * — xyflow resolves them by node id regardless of nesting, so an edge that\n * pointed at a now-container mount still connects to the box, and\n * member↔member edges render inside it.\n */\nexport function applyGroupLayout(graph: TraceGraph, opts: GroupLayoutOptions): TraceGraph {\n const padding = opts.padding ?? DEFAULT_PADDING;\n const headerHeight = opts.headerHeight ?? DEFAULT_HEADER;\n const nodeW = opts.nodeWidth ?? DEFAULT_NODE_W;\n const nodeH = opts.nodeHeight ?? DEFAULT_NODE_H;\n const baseLayout = opts.baseLayout;\n\n // Which requested subflows are genuinely groupable: a mount node carrying\n // that subflowId AND at least one member tagged subflowOf === id.\n const requested = new Set(opts.groupedSubflowIds);\n const membersBySubflow = new Map<string, TraceNode[]>();\n for (const n of graph.nodes) {\n const of = n.data?.subflowOf;\n if (of !== undefined && requested.has(of)) {\n const arr = membersBySubflow.get(of) ?? [];\n arr.push(n);\n membersBySubflow.set(of, arr);\n }\n }\n const mountBySubflow = new Map<string, TraceNode>();\n for (const n of graph.nodes) {\n const sfId = n.data?.subflowId;\n if (n.data?.isSubflow && sfId !== undefined && requested.has(sfId) && membersBySubflow.has(sfId)) {\n mountBySubflow.set(sfId, n);\n }\n }\n // Only group subflows that have BOTH a mount and members.\n const activeGroups = new Set<string>();\n for (const sfId of mountBySubflow.keys()) activeGroups.add(sfId);\n\n // Nothing to do — return input unchanged (preserves upstream memoization).\n if (activeGroups.size === 0) {\n return graph;\n }\n\n // Member ids across all active groups (excluded from the outer layout).\n const memberIds = new Set<string>();\n for (const sfId of activeGroups) {\n for (const m of membersBySubflow.get(sfId) ?? []) memberIds.add(m.id);\n }\n\n // ── PASS 1 — lay out each group's MEMBERS and size its box FIRST. We must\n // know each container's true footprint BEFORE the outer layout runs, or\n // dagre would place the outer siblings (Route, ToolCalls, …) around the\n // mount's default 200px point and they'd collide once the box balloons.\n // (Inside-out reflow: size the inner box, then place the outer graph\n // around it at its real size.) ──\n const containerNodes: TraceNode[] = [];\n const nestedMembers: TraceNode[] = [];\n /** Per-group: box size + the normalisation origin needed when nesting. */\n const groupBox = new Map<\n string,\n { width: number; height: number; minX: number; minY: number; members: TraceNode[] }\n >();\n\n for (const sfId of activeGroups) {\n const members = membersBySubflow.get(sfId)!;\n const innerOnlyEdges = graph.edges.filter((e) => {\n const s = members.some((m) => m.id === e.source);\n const t = members.some((m) => m.id === e.target);\n return s && t;\n });\n const innerPositioned = baseLayout({ nodes: members, edges: innerOnlyEdges });\n\n // Normalise member positions to the box's local space (min → 0). Measure\n // each member's full FOOTPRINT (position + width/height), not just its\n // top-left corner — a member may itself be a sized container (nested\n // composition), and corner-only math would undersize this box around it.\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const m of innerPositioned.nodes) {\n const p = m.position;\n const { width, height } = footprintOf(m, nodeW, nodeH);\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x + width > maxX) maxX = p.x + width;\n if (p.y + height > maxY) maxY = p.y + height;\n }\n if (!Number.isFinite(minX)) {\n minX = 0;\n minY = 0;\n maxX = 0;\n maxY = 0;\n }\n\n // maxX/maxY already include each member's footprint, so the inner extent\n // is just the spanned distance (no extra nodeW/nodeH to add).\n const boxWidth = maxX - minX + padding * 2;\n const boxHeight = maxY - minY + headerHeight + padding * 2;\n groupBox.set(sfId, { width: boxWidth, height: boxHeight, minX, minY, members: innerPositioned.nodes });\n }\n\n // ── PASS 2 — lay out the OUTER graph with each mount STAMPED at its real\n // box size, so dagre reserves the correct footprint and outer siblings\n // are placed clear of the box (no overlap). ──\n const outerNodes = graph.nodes\n .filter((n) => !memberIds.has(n.id))\n .map((n) => {\n const box = n.data?.subflowId ? groupBox.get(n.data.subflowId) : undefined;\n // Stamp the box's footprint onto the mount so the dagre baseLayout\n // (which reads style.width/height via sizeOf) places siblings around it.\n // ALSO flag `data.isGroupContainer` so `sizeOf` treats this stamped\n // footprint as AUTHORITATIVE — i.e. style WINS over any consumer\n // `nodeSize` resolver. Without the flag, a resolver that sizes by\n // recorder semantics (e.g. \"any subflow → a 38px slim bar\") out-ranks\n // the stamp: dagre reserves 38px while the box renders ~794px, so the\n // post-container siblings (route / tool-calls / final) rank inside the\n // box and overlap it. The flag makes dagre reserve the box's TRUE height.\n return box\n ? {\n ...n,\n style: { ...(n.style ?? {}), width: box.width, height: box.height },\n data: { ...n.data, isGroupContainer: true },\n }\n : n;\n });\n const outerEdges = graph.edges.filter(\n (e) => !memberIds.has(e.source) && !memberIds.has(e.target),\n );\n const outerPositioned = baseLayout({ nodes: outerNodes, edges: outerEdges });\n const outerPosById = new Map(outerPositioned.nodes.map((n) => [n.id, n.position]));\n\n // ── Emit containers (at their outer position) + nest their members. ──\n for (const sfId of activeGroups) {\n const mount = mountBySubflow.get(sfId)!;\n const box = groupBox.get(sfId)!;\n const { width: boxWidth, height: boxHeight, minX, minY } = box;\n\n // Container = the mount node, retyped + sized, keeping its outer position.\n const mountPos = outerPosById.get(mount.id) ?? mount.position ?? { x: 0, y: 0 };\n containerNodes.push({\n ...mount,\n type: GROUP_CONTAINER_NODE_TYPE,\n position: mountPos,\n style: { ...(mount.style ?? {}), width: boxWidth, height: boxHeight },\n data: { ...mount.data, isGroupContainer: true },\n });\n\n // Members nested under the container, positioned in local space below\n // the header strip.\n for (const m of box.members) {\n const relX = m.position.x - minX + padding;\n const relY = m.position.y - minY + headerHeight + padding;\n nestedMembers.push({\n ...(m as TraceNode),\n parentId: mount.id,\n extent: \"parent\",\n position: { x: relX, y: relY },\n });\n }\n }\n\n // ── Reassemble: outer nodes (with containers swapped in) FIRST, then\n // nested members — guarantees every parent precedes its children. ──\n const containerById = new Map(containerNodes.map((c) => [c.id, c]));\n const outerOut: TraceNode[] = outerPositioned.nodes.map(\n (n) => containerById.get(n.id) ?? n,\n );\n\n return {\n nodes: [...outerOut, ...nestedMembers],\n edges: graph.edges,\n };\n}\n\n/**\n * Convenience: wrap a base layout into a `TraceFlowLayout` that applies\n * group containers. Pass to `<TraceFlow layout={...}>` / `<TracedFlow>`.\n */\nexport function createGroupedLayout(opts: GroupLayoutOptions): TraceFlowLayout {\n return (graph: TraceGraph) => applyGroupLayout(graph, opts);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Main-chart box — wrap the ENTIRE (drill-filtered) chart in ONE container\n// ─────────────────────────────────────────────────────────────────────────────\n//\n// The Lens model: the chart you're looking at (an LLMCall / Agent primitive)\n// is ALWAYS one box; every subflow INSIDE it is a drill card (click → zoom).\n// This is distinct from `applyGroupLayout` (which boxes individual subflows).\n// Here there's no per-subflow mount — the whole graph is the box's contents,\n// so we synthesise ONE container node and nest every top-level node under it.\n//\n// Composition contract: feed this the ALREADY drill-filtered graph (top-level\n// nodes only; subflow internals hidden behind their drill cards). Nodes that\n// already carry a `parentId` are left parented as-is (only parentId-less\n// top-level nodes get re-parented to the main box), so this composes safely\n// even if some upstream nesting exists.\n\n/** Default id for the synthesised main-chart container node. */\nexport const MAIN_CHART_BOX_ID = \"__main_chart__\";\n\nexport interface MainChartBoxOptions {\n /** Layout applied to the chart's contents before wrapping. */\n readonly baseLayout: TraceFlowLayout;\n /** Container node id. Default `__main_chart__`. */\n readonly id?: string;\n /** Box title (rendered in the container header). */\n readonly label?: string;\n /** Optional taxonomy hint surfaced on `data` (e.g. 'LLMCall' | 'Agent'). */\n readonly kind?: string;\n readonly padding?: number;\n readonly headerHeight?: number;\n readonly nodeWidth?: number;\n readonly nodeHeight?: number;\n}\n\n/**\n * Wrap an entire graph in a single main-chart container box. Pure\n * `(graph, opts) => graph`; input not mutated. Empty graph → returned\n * unchanged (nothing to wrap).\n */\nexport function wrapInMainChartBox(graph: TraceGraph, opts: MainChartBoxOptions): TraceGraph {\n if (graph.nodes.length === 0) return graph;\n\n const padding = opts.padding ?? DEFAULT_PADDING;\n const headerHeight = opts.headerHeight ?? DEFAULT_HEADER;\n const nodeW = opts.nodeWidth ?? DEFAULT_NODE_W;\n const nodeH = opts.nodeHeight ?? DEFAULT_NODE_H;\n const mainId = opts.id ?? MAIN_CHART_BOX_ID;\n\n const positioned = opts.baseLayout(graph);\n\n // Only top-level nodes (no existing parentId) get re-parented to the box;\n // already-nested nodes keep their parent (their relative position is\n // unaffected by re-parenting their ancestor — xyflow positions are\n // parent-relative).\n const topLevel = positioned.nodes.filter((n) => n.parentId === undefined);\n\n // Bounding box of the top-level nodes → container size. We measure each\n // node's full FOOTPRINT (position + width/height), not just its top-left\n // corner — a top-level node may itself be a wide group container (from a\n // prior `applyGroupLayout` pass) carrying a large `style.width`. Reading\n // only the corner would size the box as if that container were a 200px\n // node, so it would overflow the outer box (the nesting bug).\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const n of topLevel) {\n const p = n.position;\n const { width, height } = footprintOf(n, nodeW, nodeH);\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x + width > maxX) maxX = p.x + width;\n if (p.y + height > maxY) maxY = p.y + height;\n }\n if (!Number.isFinite(minX)) {\n minX = 0;\n minY = 0;\n maxX = 0;\n maxY = 0;\n }\n\n // maxX/maxY already include the widest/tallest node's footprint, so the\n // box size is just the spanned extent + padding (+ header for the title).\n // When the chart has a loop-back edge, `LoopBackEdge` bows out to a lane\n // `LOOP_LANE_GAP` right of the widest content node — reserve that width so\n // the curve renders INSIDE the frame instead of spilling past its right border.\n const hasLoopEdge = graph.edges.some((e) => e.data?.kind === \"loop\");\n const loopReserve = hasLoopEdge ? LOOP_LANE_GAP : 0;\n const boxWidth = maxX - minX + padding * 2 + loopReserve;\n const boxHeight = maxY - minY + headerHeight + padding * 2;\n\n const container: TraceNode = {\n id: mainId,\n type: GROUP_CONTAINER_NODE_TYPE,\n position: { x: 0, y: 0 },\n style: { width: boxWidth, height: boxHeight },\n data: {\n label: opts.label ?? \"Chart\",\n isDecider: false,\n isFork: false,\n isStreaming: false,\n isSubflow: false,\n isGroupContainer: true,\n isMainChart: true,\n ...(opts.kind !== undefined && { kind: opts.kind }),\n prevIds: [],\n nextIds: [],\n },\n } as TraceNode;\n\n const topLevelIds = new Set(topLevel.map((n) => n.id));\n const reparented: TraceNode[] = positioned.nodes.map((n) => {\n if (!topLevelIds.has(n.id)) return n; // already nested — leave as-is\n return {\n ...n,\n parentId: mainId,\n extent: \"parent\",\n position: {\n x: n.position.x - minX + padding,\n y: n.position.y - minY + headerHeight + padding,\n },\n };\n });\n\n // Container FIRST (xyflow parent-before-child invariant).\n return { nodes: [container, ...reparented], edges: graph.edges };\n}\n\n/**\n * Convenience: a `TraceFlowLayout` that wraps the whole chart in one\n * main-chart box. Pass to `<TraceFlow layout={...}>` / `<TracedFlow>`.\n */\nexport function createMainChartBoxLayout(opts: MainChartBoxOptions): TraceFlowLayout {\n return (graph: TraceGraph) => wrapInMainChartBox(graph, opts);\n}\n","/**\n * SmartStepEdge — a smooth-step edge that routes a RANK-SKIPPING (staggered)\n * edge AROUND the node(s) it skips, instead of bending through them.\n *\n * It is a drop-in superset of the built-in `smoothstep` edge: for an ordinary\n * adjacent edge it produces the IDENTICAL path (default midpoint bend); only\n * when the edge skips a rank — a node sits vertically between its endpoints —\n * does it move the bend into the gap below that node (see `stepRouting`).\n *\n * WHY a custom edge (not a layout tweak): which edges skip a rank depends on the\n * final laid-out geometry, which only the renderer knows. Like `LoopBackEdge`,\n * this reads node bounds straight from the xyflow store, so it works for ANY\n * staggered merge in ANY chart with zero per-node or per-chart wiring — register\n * it once as the default step edge and every staggered edge routes cleanly.\n *\n * The decision math lives in `_internal/stepRouting` (pure, unit-tested); this\n * is the thin React adapter. `style` + `markerEnd` flow through unchanged.\n */\n\nimport { BaseEdge, getSmoothStepPath, useStore } from \"@xyflow/react\";\nimport type { EdgeProps, ReactFlowState } from \"@xyflow/react\";\nimport { Position } from \"@xyflow/react\";\nimport { staggeredBendY, type VerticalBounds } from \"../FlowchartView/_internal/stepRouting\";\nimport { GROUP_CONTAINER_NODE_TYPE } from \"../FlowchartView/_internal/groupLayout\";\n\nexport function SmartStepEdge({\n id,\n source,\n target,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n markerEnd,\n style,\n}: EdgeProps) {\n // The bend y for a staggered edge, or null for an ordinary adjacent edge.\n // Derived in the store selector and returned as a NUMBER/null — primitive\n // equality means the edge only re-renders when its routing actually changes.\n const bendY = useStore((s: ReactFlowState) => {\n const src = s.nodeLookup.get(source);\n const tgt = s.nodeLookup.get(target);\n if (!src || !tgt) return null;\n const sourceBottom = src.internals.positionAbsolute.y + (src.measured.height ?? 0);\n const targetTop = tgt.internals.positionAbsolute.y;\n const others: VerticalBounds[] = [];\n for (const n of s.nodeLookup.values()) {\n if (n.id === source || n.id === target) continue;\n if (n.type === GROUP_CONTAINER_NODE_TYPE) continue; // the frame box spans everything\n const top = n.internals.positionAbsolute.y;\n others.push({ top, bottom: top + (n.measured.height ?? 0) });\n }\n return staggeredBendY(sourceBottom, targetTop, others);\n });\n\n const [path] = getSmoothStepPath({\n sourceX,\n sourceY,\n sourcePosition: sourcePosition ?? Position.Bottom,\n targetX,\n targetY,\n targetPosition: targetPosition ?? Position.Top,\n // Override the bend only for a staggered edge; otherwise let getSmoothStepPath\n // use its default centerY (== the built-in `smoothstep` path, byte-for-byte).\n ...(bendY !== null ? { centerY: bendY } : {}),\n });\n\n return <BaseEdge id={id} path={path} markerEnd={markerEnd} style={style} />;\n}\n","/**\n * stepRouting — pure geometry for the \"smart\" step edge that routes a\n * RANK-SKIPPING (staggered) edge AROUND the node(s) it skips.\n *\n * The problem: a normal smooth-step edge bends at the vertical MIDPOINT between\n * its endpoints. When an edge skips a rank (e.g. the agent merge-tree's\n * `tools → call-llm`, which bypasses `message-api`), that midpoint falls right\n * on the skipped node's row, so the horizontal segment cuts straight through it\n * — it reads as if the edge connects to the skipped node.\n *\n * The fix: place the bend in the GAP just below the lowest skipped node and\n * above the target, so the horizontal run clears every skipped node. Because the\n * bend sits below ALL skipped nodes, vertical clearance alone guarantees the\n * horizontal run never overlaps them. (The vertical run stays at the source's x;\n * for fork-join staggered merges the skipped input is laterally offset from the\n * trunk, so that run is already clear — the case this targets.)\n *\n * This module is the pure core (no React/DOM); `SmartStepEdge` is the thin\n * adapter that reads node bounds from the xyflow store and calls this. Keeping\n * the math here makes it unit-testable, mirroring `loopRouting`.\n */\n\n/** A node's vertical extent in flow coordinates (top edge .. bottom edge). */\nexport interface VerticalBounds {\n readonly top: number;\n readonly bottom: number;\n}\n\n/**\n * The y at which a step edge should bend to clear every rank it SKIPS, or `null`\n * when it skips nothing (caller then uses the default midpoint bend == ordinary\n * smooth-step).\n *\n * A node counts as \"skipped\" when its vertical CENTER lies strictly between the\n * source's bottom and the target's top. The bend is placed midway between the\n * lowest skipped node's bottom and the target's top, clamped to stay\n * `minGapFromTarget` above the target so a rounded corner still fits.\n */\nexport function staggeredBendY(\n sourceBottom: number,\n targetTop: number,\n others: readonly VerticalBounds[],\n minGapFromTarget = 8,\n): number | null {\n let lowestSkippedBottom = -Infinity;\n for (const n of others) {\n const cy = (n.top + n.bottom) / 2;\n if (cy > sourceBottom && cy < targetTop && n.bottom > lowestSkippedBottom) {\n lowestSkippedBottom = n.bottom;\n }\n }\n if (lowestSkippedBottom === -Infinity) return null; // nothing skipped → default bend\n return Math.min((lowestSkippedBottom + targetTop) / 2, targetTop - minGapFromTarget);\n}\n","/**\n * InspectorPanel — Node-specific debug view.\n *\n * Two tabs:\n * - State: scope values at the selected step (time-travel synced)\n * - Data Trace: backward causal chain from the selected node\n *\n * Like Chrome DevTools' Scope + Call Stack panels when paused at a breakpoint.\n */\nimport { memo, useState } from \"react\";\nimport { theme } from \"../../theme\";\nimport type { StageSnapshot } from \"../../types\";\nimport { MemoryPanel } from \"../MemoryPanel\";\nimport { DataTracePanel, type CausalFrame } from \"../DataTracePanel/DataTracePanel\";\n\nexport interface InspectorPanelProps {\n snapshots: StageSnapshot[];\n selectedIndex: number;\n /** Causal chain frames for the selected node (empty = no trace available). */\n dataTraceFrames: CausalFrame[];\n /** Currently selected runtimeStageId. */\n selectedStageId?: string;\n /** Navigate to a stage when clicking a Data Trace frame. */\n onNavigateToStage?: (runtimeStageId: string) => void;\n}\n\ntype InspectorTab = \"state\" | \"trace\";\n\nexport const InspectorPanel = memo(function InspectorPanel({\n snapshots,\n selectedIndex,\n dataTraceFrames,\n selectedStageId,\n onNavigateToStage,\n}: InspectorPanelProps) {\n const [tab, setTab] = useState<InspectorTab>(\"state\");\n const currentSnapshot = snapshots[selectedIndex];\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n overflow: \"hidden\",\n }}\n >\n {/* Tab bar */}\n <div\n style={{\n display: \"flex\",\n borderBottom: `1px solid ${theme.border}`,\n flexShrink: 0,\n }}\n >\n <TabButton\n active={tab === \"state\"}\n onClick={() => setTab(\"state\")}\n label=\"State\"\n />\n <TabButton\n active={tab === \"trace\"}\n onClick={() => setTab(\"trace\")}\n label=\"Data Trace\"\n badge={dataTraceFrames.length > 0 ? String(dataTraceFrames.length) : undefined}\n />\n </div>\n\n {/* Tab content */}\n <div style={{ flex: 1, overflow: \"auto\" }}>\n {tab === \"state\" && (\n <MemoryPanel\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n />\n )}\n {tab === \"trace\" && (\n <DataTracePanel\n frames={dataTraceFrames}\n selectedStageId={selectedStageId}\n onFrameClick={onNavigateToStage}\n fromStageName={currentSnapshot?.stageName}\n />\n )}\n </div>\n </div>\n );\n});\n\nfunction TabButton({\n active,\n onClick,\n label,\n badge,\n}: {\n active: boolean;\n onClick: () => void;\n label: string;\n badge?: string;\n}) {\n return (\n <button\n onClick={onClick}\n style={{\n padding: \"8px 14px\",\n border: \"none\",\n borderBottom: active\n ? \"2px solid var(--fp-accent, #6366f1)\"\n : \"2px solid transparent\",\n background: \"transparent\",\n color: active ? \"var(--fp-accent, #6366f1)\" : theme.textMuted,\n fontWeight: active ? 600 : 400,\n fontSize: 12,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n }}\n >\n {label}\n {badge && (\n <span\n style={{\n fontSize: 10,\n background: active\n ? \"var(--fp-accent, #6366f1)\"\n : theme.textMuted,\n color: \"#fff\",\n borderRadius: 8,\n padding: \"1px 5px\",\n fontWeight: 600,\n }}\n >\n {badge}\n </span>\n )}\n </button>\n );\n}\n","/**\n * DataTracePanel — Backward causal chain visualization.\n *\n * Shows the data dependency chain from the selected stage backward:\n * \"Format read processed from Process, which read input from Seed.\"\n *\n * Like Chrome DevTools' Call Stack — click a frame to navigate there.\n *\n * Uses causalChain() from footprintjs/trace internally. The commitLog\n * and keysRead data come from props (collected during traversal).\n */\nimport { memo, useMemo } from \"react\";\nimport { theme } from \"../../theme\";\nimport type { StageSnapshot } from \"../../types\";\n\n// ── Types for causal chain data ────────────────────────────────────\n\n/** A node in the causal DAG (matches footprintjs CausalNode shape). */\nexport interface CausalFrame {\n runtimeStageId: string;\n stageId: string;\n stageName: string;\n keysWritten: string[];\n linkedBy: string;\n depth: number;\n}\n\nexport interface DataTracePanelProps {\n /** Flattened causal chain frames (BFS order from causalChain + flattenCausalDAG). */\n frames: CausalFrame[];\n /** Currently selected stage's runtimeStageId. */\n selectedStageId?: string;\n /** Callback when a frame is clicked — navigate time-travel to that stage. */\n onFrameClick?: (runtimeStageId: string) => void;\n /** Optional: stage name for the \"tracing from\" header. */\n fromStageName?: string;\n}\n\n/**\n * Render the backward causal chain as a stack trace.\n * Each frame shows: stage name, what it wrote, linked by which key.\n * Click a frame to navigate the time-travel slider.\n */\nexport const DataTracePanel = memo(function DataTracePanel({\n frames,\n selectedStageId,\n onFrameClick,\n fromStageName,\n}: DataTracePanelProps) {\n if (frames.length === 0) {\n return (\n <div style={{ padding: \"14px 14px 12px\", fontSize: 13, lineHeight: 1.55 }}>\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.5px\",\n fontWeight: 600,\n marginBottom: 6,\n }}\n >\n Backward causal chain\n </div>\n <div style={{ color: theme.textSecondary, marginBottom: 10 }}>\n Trace any value back to the stage that created it — and everything upstream that\n influenced it.\n </div>\n <div style={{ color: theme.textMuted, fontSize: 12 }}>\n Select a stage above to see its dependency chain.\n </div>\n </div>\n );\n }\n\n return (\n <div style={{ padding: \"8px 0\", fontSize: 13 }}>\n {fromStageName && (\n <div style={{ padding: \"4px 12px 8px\" }}>\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.5px\",\n fontWeight: 600,\n }}\n >\n Data trace from {fromStageName}\n </div>\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n fontStyle: \"italic\",\n marginTop: 3,\n }}\n >\n Every value here was derived from the stages below.\n </div>\n </div>\n )}\n {frames.map((frame, i) => (\n <DataTraceFrame\n key={frame.runtimeStageId}\n frame={frame}\n isFirst={i === 0}\n isLast={i === frames.length - 1}\n isSelected={frame.runtimeStageId === selectedStageId}\n onClick={onFrameClick}\n />\n ))}\n </div>\n );\n});\n\nconst DataTraceFrame = memo(function DataTraceFrame({\n frame,\n isFirst,\n isLast,\n isSelected,\n onClick,\n}: {\n frame: CausalFrame;\n isFirst: boolean;\n isLast: boolean;\n isSelected: boolean;\n onClick?: (id: string) => void;\n}) {\n return (\n <button\n onClick={() => onClick?.(frame.runtimeStageId)}\n style={{\n display: \"block\",\n width: \"100%\",\n textAlign: \"left\",\n border: \"none\",\n background: isSelected\n ? \"var(--fp-accent-bg, rgba(99,102,241,0.12))\"\n : \"transparent\",\n padding: \"6px 12px 6px 16px\",\n cursor: onClick ? \"pointer\" : \"default\",\n borderLeft: isSelected\n ? \"3px solid var(--fp-accent, #6366f1)\"\n : \"3px solid transparent\",\n color: \"inherit\",\n fontSize: 13,\n }}\n >\n {/* Stage name + depth indicator */}\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n {/* Connector line */}\n {!isFirst && (\n <span style={{ color: theme.textMuted, fontSize: 11 }}>\n ↑\n </span>\n )}\n <span\n style={{\n fontWeight: isFirst ? 600 : 400,\n color: isFirst\n ? \"var(--fp-accent, #6366f1)\"\n : theme.textPrimary,\n }}\n >\n {frame.stageName}\n </span>\n {isLast && !isFirst && (\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n fontStyle: \"italic\",\n }}\n >\n (origin)\n </span>\n )}\n </div>\n\n {/* What this stage wrote */}\n {frame.keysWritten.length > 0 && (\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n paddingLeft: isFirst ? 0 : 18,\n marginTop: 2,\n }}\n >\n wrote:{\" \"}\n <span style={{ color: theme.textSecondary }}>\n {frame.keysWritten.join(\", \")}\n </span>\n </div>\n )}\n\n {/* Linked by which key */}\n {frame.linkedBy && (\n <div\n style={{\n fontSize: 11,\n color: \"var(--fp-accent, #6366f1)\",\n paddingLeft: 18,\n marginTop: 1,\n }}\n >\n ← via {frame.linkedBy}\n </div>\n )}\n </button>\n );\n});\n","/**\n * InsightPanel — Recorder outputs renamed as \"Insights\".\n *\n * Two modes:\n * - Tabs: one insight at a time (full height) — when flowchart is visible\n * - Grid: all insights visible (2x2) — when flowchart is collapsed\n *\n * Each insight maps to a recorder's toSnapshot() output.\n * User-facing names: Story, Performance, Quality, Cost.\n */\nimport { memo, useState } from \"react\";\nimport { theme } from \"../../theme\";\n\nexport interface InsightConfig {\n /** Unique ID (matches recorder id). */\n id: string;\n /** User-facing name (Story, Performance, Quality, Cost). */\n name: string;\n /** Aggregate summary for collapsed header (e.g., \"1.2ms 3R 3W\"). */\n summary?: string;\n /** Render the insight content. */\n render: () => React.ReactNode;\n}\n\nexport interface InsightPanelProps {\n insights: InsightConfig[];\n /** Which insight is expanded by default (by id). */\n expandedId?: string;\n /** Display mode: tabs (one at a time) or grid (all visible). */\n mode: \"tabs\" | \"grid\";\n}\n\nexport const InsightPanel = memo(function InsightPanel({\n insights,\n expandedId,\n mode,\n}: InsightPanelProps) {\n if (insights.length === 0) {\n return (\n <div style={{ padding: 12, color: theme.textMuted, fontSize: 13 }}>\n No insights available. Attach recorders to see data.\n </div>\n );\n }\n\n if (mode === \"grid\") {\n return <InsightGrid insights={insights} />;\n }\n\n return <InsightTabs insights={insights} defaultId={expandedId} />;\n});\n\n// ── Tabs mode (one at a time, full height) ─────────────────────────\n\nconst InsightTabs = memo(function InsightTabs({\n insights,\n defaultId,\n}: {\n insights: InsightConfig[];\n defaultId?: string;\n}) {\n const [activeId, setActiveId] = useState(defaultId ?? insights[0]?.id);\n const active = insights.find((i) => i.id === activeId) ?? insights[0];\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n overflow: \"hidden\",\n }}\n >\n {/* Tab bar */}\n <div\n style={{\n display: \"flex\",\n borderBottom: `1px solid ${theme.border}`,\n flexShrink: 0,\n overflowX: \"auto\",\n }}\n >\n {insights.map((insight) => (\n <button\n key={insight.id}\n onClick={() => setActiveId(insight.id)}\n style={{\n padding: \"8px 12px\",\n border: \"none\",\n borderBottom:\n activeId === insight.id\n ? \"2px solid var(--fp-accent, #6366f1)\"\n : \"2px solid transparent\",\n background: \"transparent\",\n color:\n activeId === insight.id\n ? \"var(--fp-accent, #6366f1)\"\n : theme.textMuted,\n fontWeight: activeId === insight.id ? 600 : 400,\n fontSize: 12,\n cursor: \"pointer\",\n whiteSpace: \"nowrap\",\n }}\n >\n {insight.name}\n </button>\n ))}\n </div>\n\n {/* Active content */}\n <div style={{ flex: 1, overflow: \"auto\" }}>\n {active?.render()}\n </div>\n </div>\n );\n});\n\n// ── Grid mode (all visible, 2x2) ──────────────────────────────────\n\nconst InsightGrid = memo(function InsightGrid({\n insights,\n}: {\n insights: InsightConfig[];\n}) {\n const cols = insights.length <= 2 ? 1 : 2;\n\n return (\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: `repeat(${cols}, 1fr)`,\n height: \"100%\",\n overflow: \"auto\",\n gap: 1,\n background: theme.border,\n }}\n >\n {insights.map((insight) => (\n <div\n key={insight.id}\n style={{\n background: \"var(--fp-bg, #1a1b26)\",\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n }}\n >\n {/* Grid cell header */}\n <div\n style={{\n padding: \"6px 10px\",\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.5px\",\n borderBottom: `1px solid ${theme.border}`,\n flexShrink: 0,\n }}\n >\n {insight.name}\n {insight.summary && (\n <span\n style={{\n marginLeft: 8,\n fontWeight: 400,\n fontSize: 10,\n color: theme.textMuted,\n }}\n >\n {insight.summary}\n </span>\n )}\n </div>\n {/* Grid cell content */}\n <div style={{ flex: 1, overflow: \"auto\" }}>\n {insight.render()}\n </div>\n </div>\n ))}\n </div>\n );\n});\n","/**\n * CompactTimeline — Collapsed = dot line, expanded = Gantt chart.\n *\n * Collapsed: single row of colored dots showing execution progress.\n * Expanded: delegates to GanttTimeline for full duration bars.\n */\nimport { memo, useState } from \"react\";\nimport { theme } from \"../../theme\";\nimport type { StageSnapshot } from \"../../types\";\nimport { GanttTimeline } from \"../GanttTimeline\";\n\nexport interface CompactTimelineProps {\n snapshots: StageSnapshot[];\n selectedIndex: number;\n /** Start expanded or collapsed. Default: collapsed. */\n defaultExpanded?: boolean;\n}\n\nexport const CompactTimeline = memo(function CompactTimeline({\n snapshots,\n selectedIndex,\n defaultExpanded = false,\n}: CompactTimelineProps) {\n const [expanded, setExpanded] = useState(defaultExpanded);\n\n if (snapshots.length === 0) return null;\n\n return (\n <div style={{ borderTop: `1px solid ${theme.border}` }}>\n {/* Toggle header */}\n <button\n onClick={() => setExpanded((e) => !e)}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"6px 12px\",\n border: \"none\",\n background: \"transparent\",\n cursor: \"pointer\",\n fontSize: 11,\n color: theme.textMuted,\n fontWeight: 600,\n textTransform: \"uppercase\",\n letterSpacing: \"0.5px\",\n }}\n >\n <span style={{ fontSize: 10 }}>{expanded ? \"▼\" : \"▸\"}</span>\n Timeline\n <span style={{ fontWeight: 400, fontSize: 10 }}>\n {snapshots.length} stages\n </span>\n\n {/* Compact dot line (visible when collapsed) */}\n {!expanded && (\n <div\n style={{\n flex: 1,\n display: \"flex\",\n alignItems: \"center\",\n gap: 2,\n marginLeft: 8,\n }}\n >\n {snapshots.map((snap, i) => (\n <div\n key={i}\n style={{\n width: i === selectedIndex ? 8 : 5,\n height: i === selectedIndex ? 8 : 5,\n borderRadius: \"50%\",\n background:\n i < selectedIndex\n ? \"var(--fp-success, #22c55e)\"\n : i === selectedIndex\n ? \"var(--fp-accent, #6366f1)\"\n : theme.textMuted + \"40\",\n transition: \"all 0.15s\",\n flexShrink: 0,\n }}\n title={snap.stageName}\n />\n ))}\n {/* Connecting line */}\n <div\n style={{\n flex: 1,\n height: 1,\n background: theme.textMuted + \"30\",\n marginLeft: -2,\n marginRight: 4,\n }}\n />\n </div>\n )}\n </button>\n\n {/* Expanded: full Gantt */}\n {expanded && (\n <div style={{ padding: \"0 12px 8px\" }}>\n <GanttTimeline\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n />\n </div>\n )}\n </div>\n );\n});\n","/**\n * TraceViewer — drop-in component that renders an `agentfootprint.exportTrace()`\n * JSON as a fully interactive Behind-the-Scenes view.\n *\n * The pattern:\n * 1. Producer side calls `agentfootprint.exportTrace(runner)` to capture\n * a portable JSON `AgentfootprintTrace` (schemaVersion 1).\n * 2. The JSON is shipped anywhere — file, HTTP, clipboard, database.\n * 3. Consumer side passes it to `<TraceViewer trace={...} />` and gets\n * the full BTS view: flowchart topology, narrative timeline, snapshot\n * memory state, recorder data — without re-executing anything.\n *\n * Accepts EITHER a parsed object OR a raw JSON string. Validates\n * `schemaVersion === 1` and surfaces parse / validation errors via the\n * optional `onError` callback. When the trace is invalid, renders the\n * `fallback` prop (or nothing if not provided).\n *\n * @example\n * ```tsx\n * import { TraceViewer } from 'footprint-explainable-ui';\n *\n * function MyDebugPage({ trace }: { trace: unknown }) {\n * return <TraceViewer trace={trace} />;\n * }\n * ```\n *\n * @example Paste-from-clipboard pattern (the playground viewer)\n * ```tsx\n * const [raw, setRaw] = useState('');\n * <textarea value={raw} onChange={(e) => setRaw(e.target.value)} />\n * <TraceViewer\n * trace={raw}\n * onError={(err) => setStatus(err)}\n * fallback={<div>Paste a trace JSON to begin.</div>}\n * />\n * ```\n *\n * The component is a thin shell over `toVisualizationSnapshots` +\n * `<ExplainableShell />` — exactly the composition consumers would write\n * by hand. Source is short on purpose; read it as the reference.\n */\nimport * as React from 'react';\nimport { useMemo } from 'react';\nimport { ExplainableShell, type ExplainableShellProps, type ShellTab } from '../ExplainableShell';\nimport { toVisualizationSnapshots } from '../../adapters/fromRuntimeSnapshot';\n\n/**\n * Schema-versioned trace shape produced by `agentfootprint.exportTrace`.\n * Pinned to `schemaVersion: 1`; future shape changes will bump the version\n * and TraceViewer will gain a multi-version dispatch table.\n */\nexport interface AgentfootprintTrace {\n readonly schemaVersion: 1;\n readonly exportedAt?: string;\n readonly redacted?: boolean;\n readonly snapshot?: unknown;\n readonly narrativeEntries?: unknown[];\n readonly spec?: unknown;\n}\n\n/**\n * Result of parsing + validating raw input. Internal — exposed via\n * `onError` so consumers can show their own error UI.\n */\nexport type TraceParseError =\n | { kind: 'invalid-json'; message: string }\n | { kind: 'not-object'; message: string }\n | { kind: 'missing-version'; message: string }\n | { kind: 'unsupported-version'; message: string; version: number };\n\nexport interface TraceViewerProps\n extends Pick<\n ExplainableShellProps,\n 'tabs' | 'defaultTab' | 'hideTabs' | 'size' | 'panelLabels' | 'recorderViews' | 'renderFlowchart'\n > {\n /**\n * Trace to render. Accepts a parsed `AgentfootprintTrace` object or a\n * raw JSON string (the component parses + validates it). `null` /\n * `undefined` / empty-string render the `fallback`.\n */\n readonly trace?: AgentfootprintTrace | string | null;\n /**\n * Called on parse / validation errors. If you need to show your own\n * error UI, capture the error here and render alongside.\n */\n readonly onError?: (error: TraceParseError) => void;\n /** Element rendered when no valid trace is available. */\n readonly fallback?: React.ReactNode;\n}\n\nfunction parseTrace(input: TraceViewerProps['trace']): {\n ok: true;\n trace: AgentfootprintTrace;\n} | { ok: false; error: TraceParseError } {\n if (input == null) {\n return {\n ok: false,\n error: { kind: 'invalid-json', message: 'No trace provided.' },\n };\n }\n\n let candidate: unknown = input;\n if (typeof input === 'string') {\n if (!input.trim()) {\n return { ok: false, error: { kind: 'invalid-json', message: 'Empty input.' } };\n }\n try {\n candidate = JSON.parse(input);\n } catch (err) {\n return {\n ok: false,\n error: { kind: 'invalid-json', message: (err as Error).message },\n };\n }\n }\n\n if (!candidate || typeof candidate !== 'object') {\n return {\n ok: false,\n error: { kind: 'not-object', message: 'Trace must be a JSON object.' },\n };\n }\n\n const t = candidate as AgentfootprintTrace;\n if (typeof t.schemaVersion !== 'number') {\n return {\n ok: false,\n error: {\n kind: 'missing-version',\n message: 'Trace is missing required field `schemaVersion`. Did you pass an exportTrace() output?',\n },\n };\n }\n if (t.schemaVersion !== 1) {\n return {\n ok: false,\n error: {\n kind: 'unsupported-version',\n message: `Unsupported schemaVersion ${t.schemaVersion}. This TraceViewer renders schemaVersion 1.`,\n version: t.schemaVersion as number,\n },\n };\n }\n\n return { ok: true, trace: t };\n}\n\nconst DEFAULT_TABS: ShellTab[] = ['explainable'];\n\nexport function TraceViewer({\n trace,\n onError,\n fallback,\n tabs = DEFAULT_TABS,\n defaultTab = 'narrative',\n hideTabs,\n size,\n panelLabels,\n recorderViews,\n renderFlowchart,\n}: TraceViewerProps): React.ReactElement | null {\n const parsed = useMemo(() => parseTrace(trace), [trace]);\n\n // Surface errors via callback; render is determined by the validity below.\n React.useEffect(() => {\n if (!parsed.ok && onError) onError(parsed.error);\n }, [parsed, onError]);\n\n const snapshots = useMemo(() => {\n if (!parsed.ok || !parsed.trace.snapshot) return [];\n try {\n return toVisualizationSnapshots(\n parsed.trace.snapshot as Parameters<typeof toVisualizationSnapshots>[0],\n (parsed.trace.narrativeEntries as Parameters<typeof toVisualizationSnapshots>[1]) ?? undefined,\n );\n } catch {\n return [];\n }\n }, [parsed]);\n\n if (!parsed.ok || snapshots.length === 0) {\n return (fallback ?? null) as React.ReactElement | null;\n }\n\n return (\n <ExplainableShell\n snapshots={snapshots}\n spec={parsed.trace.spec as ExplainableShellProps['spec']}\n narrativeEntries={parsed.trace.narrativeEntries as ExplainableShellProps['narrativeEntries']}\n tabs={tabs}\n defaultTab={defaultTab}\n hideTabs={hideTabs}\n size={size}\n panelLabels={panelLabels}\n recorderViews={recorderViews}\n renderFlowchart={renderFlowchart}\n />\n );\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","v","import_jsx_runtime","import_react","import_jsx_runtime","fmt","v","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_jsx_runtime","v","import_react","import_jsx_runtime","TreeNode","SectionLabel","SubflowTree","import_react","import_jsx_runtime","SubflowBreadcrumb","import_react","dagre","import_react","import_jsx_runtime","StageNode","import_react","import_react","padding","import_jsx_runtime","import_react","import_jsx_runtime","import_react","DEFAULT_NODE_W","DEFAULT_NODE_H","padding","padding","DEFAULT_NODE_W","DEFAULT_NODE_H","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_jsx_runtime","DataTracePanel","DataTraceFrame","import_jsx_runtime","InspectorPanel","import_react","import_jsx_runtime","InsightPanel","InsightTabs","InsightGrid","import_react","import_jsx_runtime","CompactTimeline","import_jsx_runtime","HLinePill","VLinePill","v","DetailsContent","RightPanel","snapshots","tabs","import_react","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/theme/ThemeProvider.tsx","../src/theme/tokens.ts","../src/theme/styles.ts","../src/theme/presets.ts","../src/theme/useDarkModeTokens.ts","../src/components/MemoryInspector/MemoryInspector.tsx","../src/components/NarrativeLog/NarrativeLog.tsx","../src/components/NarrativeTrace/NarrativeTrace.tsx","../src/components/GanttTimeline/GanttTimeline.tsx","../src/components/SnapshotPanel/SnapshotPanel.tsx","../src/components/ScopeDiff/ScopeDiff.tsx","../src/components/ResultPanel/ResultPanel.tsx","../src/components/StageDetailPanel/StageDetailPanel.tsx","../src/components/TimeTravelControls/TimeTravelControls.tsx","../src/components/ExplainableShell/ExplainableShell.tsx","../src/utils/narrativeSync.ts","../src/adapters/fromRuntimeSnapshot.ts","../src/components/MemoryPanel/MemoryPanel.tsx","../src/components/NarrativePanel/NarrativePanel.tsx","../src/components/StoryNarrative/StoryNarrative.tsx","../src/components/FlowchartView/SubflowTree.tsx","../src/components/FlowchartView/SubflowBreadcrumb.tsx","../src/components/FlowchartView/TracedFlow.tsx","../src/components/FlowchartView/_internal/dagreTraceLayout.ts","../src/components/FlowchartView/_internal/snapLinearSuccessors.ts","../src/components/FlowchartView/_internal/centerForkParents.ts","../src/components/FlowchartView/createTraceRuntimeOverlay.ts","../src/components/StageNode/StageNode.tsx","../src/components/FlowchartView/_internal/subflowDrill.ts","../src/components/FlowchartView/_internal/overlayProjection.ts","../src/components/FlowchartView/_internal/useSubflowDrill.ts","../src/components/FlowchartView/_internal/useChartAutoRefit.ts","../src/components/FlowchartView/SubflowBreadcrumbBar.tsx","../src/components/GroupContainerNode/GroupContainerNode.tsx","../src/components/LoopBackEdge/LoopBackEdge.tsx","../src/components/FlowchartView/_internal/loopRouting.ts","../src/components/FlowchartView/_internal/groupLayout.ts","../src/components/SmartStepEdge/SmartStepEdge.tsx","../src/components/FlowchartView/_internal/stepRouting.ts","../src/components/FlowchartView/_internal/MeasuredNodeSizes.tsx","../src/components/FlowchartView/_internal/measuredFootprints.ts","../src/components/InspectorPanel/InspectorPanel.tsx","../src/components/DataTracePanel/DataTracePanel.tsx","../src/components/InsightPanel/InsightPanel.tsx","../src/components/CompactTimeline/CompactTimeline.tsx","../src/components/TraceViewer/TraceViewer.tsx"],"sourcesContent":["// Types\nexport type { StageSnapshot, Size, BaseComponentProps, NarrativeEntry } from \"./types\";\n\n// Theme\nexport { FootprintTheme, useFootprintTheme } from \"./theme\";\nexport { tokensToCSSVars, defaultTokens, rawDefaults } from \"./theme\";\nexport { themePresets, coolDark, coolLight, warmDark, warmLight } from \"./theme\";\nexport { useDarkModeTokens } from \"./theme\";\nexport type { ThemeTokens, ThemePresetName, DarkModeTokensOptions } from \"./theme\";\n\n// Core components (zero external deps beyond React)\nexport { MemoryInspector } from \"./components/MemoryInspector\";\nexport type { MemoryInspectorProps } from \"./components/MemoryInspector\";\n\nexport { NarrativeLog } from \"./components/NarrativeLog\";\nexport type { NarrativeLogProps } from \"./components/NarrativeLog\";\n\nexport { NarrativeTrace } from \"./components/NarrativeTrace\";\nexport type { NarrativeTraceProps } from \"./components/NarrativeTrace\";\n\nexport { GanttTimeline } from \"./components/GanttTimeline\";\nexport type { GanttTimelineProps } from \"./components/GanttTimeline\";\n\nexport { SnapshotPanel } from \"./components/SnapshotPanel\";\nexport type { SnapshotPanelProps } from \"./components/SnapshotPanel\";\n\nexport { ScopeDiff } from \"./components/ScopeDiff\";\nexport type { ScopeDiffProps, DiffEntry } from \"./components/ScopeDiff\";\n\nexport { ResultPanel } from \"./components/ResultPanel\";\nexport type { ResultPanelProps } from \"./components/ResultPanel\";\n\nexport { StageDetailPanel } from \"./components/StageDetailPanel\";\nexport type { StageDetailPanelProps, StageDetailMode, MemoryChange } from \"./components/StageDetailPanel\";\n\nexport { TimeTravelControls } from \"./components/TimeTravelControls\";\nexport type { TimeTravelControlsProps } from \"./components/TimeTravelControls\";\n\nexport { ExplainableShell } from \"./components/ExplainableShell\";\nexport type { ExplainableShellProps, RuntimeSnapshotInput, RecorderView, ShellTab, PanelLabels, DefaultExpanded } from \"./components/ExplainableShell\";\n\n// Drop-in viewer for `agentfootprint.exportTrace()` JSON\nexport { TraceViewer } from \"./components/TraceViewer/TraceViewer\";\nexport type { TraceViewerProps, AgentfootprintTrace, TraceParseError } from \"./components/TraceViewer/TraceViewer\";\n\n// Composite panels (memory + narrative — self-contained right-panel views)\nexport { MemoryPanel } from \"./components/MemoryPanel\";\nexport type { MemoryPanelProps } from \"./components/MemoryPanel\";\n\nexport { NarrativePanel } from \"./components/NarrativePanel\";\nexport type { NarrativePanelProps } from \"./components/NarrativePanel\";\n\nexport { StoryNarrative } from \"./components/StoryNarrative\";\nexport type { StoryNarrativeProps } from \"./components/StoryNarrative\";\n\n// Subflow manifest tree (no ReactFlow dependency — works standalone)\nexport { SubflowTree } from \"./components/FlowchartView/SubflowTree\";\nexport type { SubflowTreeProps, SubflowTreeEntry } from \"./components/FlowchartView/SubflowTree\";\n\n// Adapters\nexport { toVisualizationSnapshots, createSnapshots, subflowResultToSnapshots, mergeWritePatch } from \"./adapters/fromRuntimeSnapshot\";\nexport type { NarrativeEntry as AdapterNarrativeEntry } from \"./adapters/fromRuntimeSnapshot\";\n\n// Utilities — narrative sync, subflow extraction\nexport { buildEntryRangeIndex, computeRevealedEntryCount, extractSubflowNarrative } from \"./utils/narrativeSync\";\nexport type { EntryRangeIndex } from \"./utils/narrativeSync\";\n\n// ── New components (v2 layout) ──────────────────────────────────────\n\n// Inspector: State + Data Trace\nexport { InspectorPanel } from \"./components/InspectorPanel/InspectorPanel\";\nexport type { InspectorPanelProps } from \"./components/InspectorPanel/InspectorPanel\";\n\n// Data Trace: backward causal chain visualization\nexport { DataTracePanel } from \"./components/DataTracePanel/DataTracePanel\";\nexport type { DataTracePanelProps, CausalFrame } from \"./components/DataTracePanel/DataTracePanel\";\n\n// Insights: recorder tabs / grid (was \"Recorders\")\nexport { InsightPanel } from \"./components/InsightPanel/InsightPanel\";\nexport type { InsightPanelProps, InsightConfig } from \"./components/InsightPanel/InsightPanel\";\n\n// Compact Timeline: dot line → Gantt toggle\nexport { CompactTimeline } from \"./components/CompactTimeline/CompactTimeline\";\nexport type { CompactTimelineProps } from \"./components/CompactTimeline/CompactTimeline\";\n","import { createContext, useContext } from \"react\";\nimport type { ThemeTokens } from \"./tokens\";\nimport { tokensToCSSVars } from \"./tokens\";\n\nconst ThemeContext = createContext<ThemeTokens>({});\n\nexport function useFootprintTheme(): ThemeTokens {\n return useContext(ThemeContext);\n}\n\ninterface FootprintThemeProps {\n tokens?: ThemeTokens;\n children: React.ReactNode;\n}\n\n/**\n * Optional theme provider — wraps children with CSS custom properties.\n * Consumers can also just set --fp-* CSS variables directly.\n *\n * Wrapper div uses `display: contents` so it's invisible to the\n * parent's layout (flex / grid / block). This matters because themed\n * children often need to fill a parent (flex:1 / height:100% /\n * grid cells), and a regular block `<div>` here would break that\n * chain — descendants would resolve to 0 height when the parent is\n * flex-column or a grid cell with minmax(0, 1fr). `display: contents`\n * removes the box from the render tree while keeping the DOM intact,\n * so CSS custom property inheritance (which follows the DOM) still\n * flows to children.\n *\n * Trade-off: `display: contents` elements are removed from the\n * accessibility tree in some older browser versions. Our wrapper has\n * no semantic role, so this is fine.\n */\nexport function FootprintTheme({ tokens = {}, children }: FootprintThemeProps) {\n const cssVars = tokensToCSSVars(tokens);\n\n return (\n <ThemeContext.Provider value={tokens}>\n <div\n style={{ ...(cssVars as React.CSSProperties), display: \"contents\" }}\n className=\"fp-theme-root\"\n >\n {children}\n </div>\n </ThemeContext.Provider>\n );\n}\n","/** Default theme tokens — consumers override via CSS variables or ThemeProvider. */\nexport interface ThemeTokens {\n colors?: {\n primary?: string;\n success?: string;\n error?: string;\n warning?: string;\n bgPrimary?: string;\n bgSecondary?: string;\n bgTertiary?: string;\n textPrimary?: string;\n textSecondary?: string;\n textMuted?: string;\n border?: string;\n };\n radius?: string;\n fontFamily?: {\n sans?: string;\n mono?: string;\n };\n}\n\n/** Maps ThemeTokens to CSS custom property assignments. */\nexport function tokensToCSSVars(tokens: ThemeTokens): Record<string, string> {\n const vars: Record<string, string> = {};\n if (tokens.colors) {\n const c = tokens.colors;\n if (c.primary) vars[\"--fp-color-primary\"] = c.primary;\n if (c.success) vars[\"--fp-color-success\"] = c.success;\n if (c.error) vars[\"--fp-color-error\"] = c.error;\n if (c.warning) vars[\"--fp-color-warning\"] = c.warning;\n if (c.bgPrimary) vars[\"--fp-bg-primary\"] = c.bgPrimary;\n if (c.bgSecondary) vars[\"--fp-bg-secondary\"] = c.bgSecondary;\n if (c.bgTertiary) vars[\"--fp-bg-tertiary\"] = c.bgTertiary;\n if (c.textPrimary) vars[\"--fp-text-primary\"] = c.textPrimary;\n if (c.textSecondary) vars[\"--fp-text-secondary\"] = c.textSecondary;\n if (c.textMuted) vars[\"--fp-text-muted\"] = c.textMuted;\n if (c.border) vars[\"--fp-border\"] = c.border;\n }\n if (tokens.radius) vars[\"--fp-radius\"] = tokens.radius;\n if (tokens.fontFamily?.sans) vars[\"--fp-font-sans\"] = tokens.fontFamily.sans;\n if (tokens.fontFamily?.mono) vars[\"--fp-font-mono\"] = tokens.fontFamily.mono;\n return vars;\n}\n\n/** Raw fallback values — used by tokensToCSSVars() and anywhere a real color is needed. */\nexport const rawDefaults = {\n colors: {\n primary: \"#6366f1\",\n success: \"#22c55e\",\n error: \"#ef4444\",\n warning: \"#f59e0b\",\n bgPrimary: \"#0f172a\",\n bgSecondary: \"#1e293b\",\n bgTertiary: \"#334155\",\n textPrimary: \"#f8fafc\",\n textSecondary: \"#94a3b8\",\n textMuted: \"#64748b\",\n border: \"#334155\",\n },\n radius: \"8px\",\n fontFamily: {\n sans: \"Inter, system-ui, -apple-system, sans-serif\",\n mono: \"'JetBrains Mono', 'Fira Code', monospace\",\n },\n} as const;\n\n/** Default dark theme values with CSS variable references (consumers can override via CSS). */\nexport const defaultTokens: Required<{\n [K in keyof ThemeTokens]-?: Required<ThemeTokens[K]>;\n}> = {\n colors: {\n primary: `var(--fp-color-primary, ${rawDefaults.colors.primary})`,\n success: `var(--fp-color-success, ${rawDefaults.colors.success})`,\n error: `var(--fp-color-error, ${rawDefaults.colors.error})`,\n warning: `var(--fp-color-warning, ${rawDefaults.colors.warning})`,\n bgPrimary: `var(--fp-bg-primary, ${rawDefaults.colors.bgPrimary})`,\n bgSecondary: `var(--fp-bg-secondary, ${rawDefaults.colors.bgSecondary})`,\n bgTertiary: `var(--fp-bg-tertiary, ${rawDefaults.colors.bgTertiary})`,\n textPrimary: `var(--fp-text-primary, ${rawDefaults.colors.textPrimary})`,\n textSecondary: `var(--fp-text-secondary, ${rawDefaults.colors.textSecondary})`,\n textMuted: `var(--fp-text-muted, ${rawDefaults.colors.textMuted})`,\n border: `var(--fp-border, ${rawDefaults.colors.border})`,\n },\n radius: `var(--fp-radius, ${rawDefaults.radius})`,\n fontFamily: {\n sans: `var(--fp-font-sans, ${rawDefaults.fontFamily.sans})`,\n mono: `var(--fp-font-mono, ${rawDefaults.fontFamily.mono})`,\n },\n};\n","import type { Size } from \"../types\";\n\n/**\n * Helper to resolve a CSS variable with a fallback.\n * Usage: v(\"--fp-color-primary\", \"#6366f1\")\n */\nexport function v(varName: string, fallback: string): string {\n return `var(${varName}, ${fallback})`;\n}\n\n/** Shorthand for common theme variables */\nexport const theme = {\n primary: v(\"--fp-color-primary\", \"#6366f1\"),\n success: v(\"--fp-color-success\", \"#22c55e\"),\n error: v(\"--fp-color-error\", \"#ef4444\"),\n warning: v(\"--fp-color-warning\", \"#f59e0b\"),\n bgPrimary: v(\"--fp-bg-primary\", \"#0f172a\"),\n bgSecondary: v(\"--fp-bg-secondary\", \"#1e293b\"),\n bgTertiary: v(\"--fp-bg-tertiary\", \"#334155\"),\n textPrimary: v(\"--fp-text-primary\", \"#f8fafc\"),\n textSecondary: v(\"--fp-text-secondary\", \"#94a3b8\"),\n textMuted: v(\"--fp-text-muted\", \"#64748b\"),\n border: v(\"--fp-border\", \"#334155\"),\n radius: v(\"--fp-radius\", \"8px\"),\n fontSans: v(\"--fp-font-sans\", \"Inter, system-ui, -apple-system, sans-serif\"),\n fontMono: v(\"--fp-font-mono\", \"'JetBrains Mono', 'Fira Code', monospace\"),\n} as const;\n\n/** Font sizes per size variant */\nexport const fontSize: Record<Size, { label: number; body: number; small: number }> = {\n compact: { label: 10, body: 11, small: 9 },\n default: { label: 11, body: 12, small: 10 },\n detailed: { label: 12, body: 13, small: 11 },\n};\n\n/** Padding per size variant */\nexport const padding: Record<Size, number> = {\n compact: 8,\n default: 12,\n detailed: 16,\n};\n","import type { ThemeTokens } from \"./tokens\";\n\n/** Cool dark theme (the library default) */\nexport const coolDark: ThemeTokens = {\n colors: {\n primary: \"#6366f1\",\n success: \"#22c55e\",\n error: \"#ef4444\",\n warning: \"#f59e0b\",\n bgPrimary: \"#0f172a\",\n bgSecondary: \"#1e293b\",\n bgTertiary: \"#334155\",\n textPrimary: \"#f8fafc\",\n textSecondary: \"#94a3b8\",\n textMuted: \"#64748b\",\n border: \"#334155\",\n },\n radius: \"8px\",\n fontFamily: {\n sans: \"Inter, system-ui, -apple-system, sans-serif\",\n mono: \"'JetBrains Mono', 'Fira Code', monospace\",\n },\n};\n\n/** Warm dark theme — charcoal-purple palette */\nexport const warmDark: ThemeTokens = {\n colors: {\n primary: \"#7c6cf0\",\n success: \"#3dd68c\",\n error: \"#f06292\",\n warning: \"#ffb74d\",\n bgPrimary: \"#1e1a2e\",\n bgSecondary: \"#2a2540\",\n bgTertiary: \"#3a3455\",\n textPrimary: \"#f0e6d6\",\n textSecondary: \"#a89eb4\",\n textMuted: \"#6e6480\",\n border: \"#3a3455\",\n },\n radius: \"8px\",\n fontFamily: {\n sans: \"Inter, system-ui, -apple-system, sans-serif\",\n mono: \"'JetBrains Mono', 'Fira Code', monospace\",\n },\n};\n\n/** Warm light theme — cream/peach palette */\nexport const warmLight: ThemeTokens = {\n colors: {\n primary: \"#7c6cf0\",\n success: \"#22a860\",\n error: \"#d94452\",\n warning: \"#e09030\",\n bgPrimary: \"#faf5ef\",\n bgSecondary: \"#f0e6d6\",\n bgTertiary: \"#e4d5c3\",\n textPrimary: \"#2e2938\",\n textSecondary: \"#5c5468\",\n textMuted: \"#8a7e96\",\n border: \"#d6c8b4\",\n },\n radius: \"8px\",\n fontFamily: {\n sans: \"Inter, system-ui, -apple-system, sans-serif\",\n mono: \"'JetBrains Mono', 'Fira Code', monospace\",\n },\n};\n\n/** Cool light theme — neutral grays, matches Tailwind zinc palette */\nexport const coolLight: ThemeTokens = {\n colors: {\n primary: \"#6366f1\",\n success: \"#22c55e\",\n error: \"#ef4444\",\n warning: \"#f59e0b\",\n bgPrimary: \"#ffffff\",\n bgSecondary: \"#f9fafb\",\n bgTertiary: \"#e5e7eb\",\n textPrimary: \"#18181b\",\n textSecondary: \"#52525b\",\n textMuted: \"#a1a1aa\",\n border: \"#e5e7eb\",\n },\n radius: \"8px\",\n fontFamily: {\n sans: \"Inter, system-ui, -apple-system, sans-serif\",\n mono: \"'JetBrains Mono', 'Fira Code', monospace\",\n },\n};\n\n/** All built-in theme presets */\nexport const themePresets = {\n coolDark,\n coolLight,\n warmDark,\n warmLight,\n} as const;\n\nexport type ThemePresetName = keyof typeof themePresets;\n","/**\n * useDarkModeTokens — Auto-bridge between CSS class-based dark mode and FootprintTheme.\n *\n * Watches for a `.dark` class on <html> (Tailwind convention) and returns\n * the appropriate ThemeTokens preset. Pairs with FootprintTheme:\n *\n * import { FootprintTheme, useDarkModeTokens } from 'footprint-explainable-ui';\n *\n * function MyApp() {\n * const tokens = useDarkModeTokens();\n * return (\n * <FootprintTheme tokens={tokens}>\n * <NarrativeTrace ... />\n * </FootprintTheme>\n * );\n * }\n *\n * Consumers can override the light/dark presets:\n *\n * const tokens = useDarkModeTokens({ light: warmLight, dark: warmDark });\n */\n\nimport { useState, useEffect } from \"react\";\nimport type { ThemeTokens } from \"./tokens\";\nimport { coolDark } from \"./presets\";\nimport { coolLight } from \"./presets\";\n\nexport interface DarkModeTokensOptions {\n /** Tokens to use in light mode. Defaults to coolLight. */\n light?: ThemeTokens;\n /** Tokens to use in dark mode. Defaults to coolDark. */\n dark?: ThemeTokens;\n /** CSS selector to watch for dark mode. Defaults to checking .dark on documentElement. */\n selector?: string;\n}\n\nexport function useDarkModeTokens(options?: DarkModeTokensOptions): ThemeTokens {\n const lightTokens = options?.light ?? coolLight;\n const darkTokens = options?.dark ?? coolDark;\n\n const [isDark, setIsDark] = useState(\n () => document.documentElement.classList.contains(options?.selector ?? \"dark\"),\n );\n\n useEffect(() => {\n const cls = options?.selector ?? \"dark\";\n const obs = new MutationObserver(() => {\n setIsDark(document.documentElement.classList.contains(cls));\n });\n obs.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => obs.disconnect();\n }, [options?.selector]);\n\n return isDark ? darkTokens : lightTokens;\n}\n","import { useMemo, useRef } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\nexport interface MemoryInspectorProps extends BaseComponentProps {\n /** Single memory object or snapshots (will accumulate up to selectedIndex) */\n data?: Record<string, unknown>;\n /** When using snapshots mode, pass these instead of data */\n snapshots?: StageSnapshot[];\n /** Index to accumulate up to (for time-travel) */\n selectedIndex?: number;\n /** Show data types alongside values */\n showTypes?: boolean;\n /** Highlight keys that are new at this step */\n highlightNew?: boolean;\n}\n\n/** Cache for incremental memory accumulation — avoids O(n) rebuild on every slider scrub. */\ninterface MemoryCache {\n snapshots: StageSnapshot[];\n index: number;\n accumulated: Record<string, unknown>;\n}\n\n/**\n * Displays pipeline memory state as formatted JSON.\n * Supports both static (data prop) and time-travel (snapshots + selectedIndex) modes.\n */\nexport function MemoryInspector({\n data,\n snapshots,\n selectedIndex = 0,\n showTypes = false,\n highlightNew = true,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: MemoryInspectorProps) {\n // Incremental cache: accumulate forward from last known index instead of rebuilding from 0\n const cacheRef = useRef<MemoryCache | null>(null);\n\n const { memory, newKeys } = useMemo(() => {\n if (data) {\n return { memory: data, newKeys: new Set<string>() };\n }\n if (!snapshots || snapshots.length === 0) {\n return { memory: {}, newKeys: new Set<string>() };\n }\n\n const safeIdx = Math.min(selectedIndex, snapshots.length - 1);\n let merged: Record<string, unknown>;\n const cache = cacheRef.current;\n\n if (cache && cache.snapshots === snapshots && cache.index <= safeIdx) {\n // Forward scrub: extend from cached state\n merged = { ...cache.accumulated };\n for (let i = cache.index + 1; i <= safeIdx; i++) {\n Object.assign(merged, snapshots[i]?.memory);\n }\n } else {\n // Backward scrub or new snapshots: rebuild from scratch\n merged = {};\n for (let i = 0; i <= safeIdx; i++) {\n Object.assign(merged, snapshots[i]?.memory);\n }\n }\n\n // Update cache\n cacheRef.current = { snapshots, index: safeIdx, accumulated: merged };\n\n const nk = new Set<string>();\n if (highlightNew && safeIdx > 0) {\n // Previous state is cache at safeIdx-1, or rebuild if needed\n let prev: Record<string, unknown>;\n if (cache && cache.snapshots === snapshots && cache.index === safeIdx - 1) {\n prev = cache.accumulated;\n } else {\n prev = {};\n for (let i = 0; i < safeIdx; i++) {\n Object.assign(prev, snapshots[i]?.memory);\n }\n }\n const current = snapshots[safeIdx]?.memory ?? {};\n for (const k of Object.keys(current)) {\n if (!(k in prev)) nk.add(k);\n }\n } else if (highlightNew && safeIdx === 0 && snapshots[0]) {\n for (const k of Object.keys(snapshots[0].memory)) nk.add(k);\n }\n\n return { memory: merged, newKeys: nk };\n }, [data, snapshots, selectedIndex, highlightNew]);\n\n const entries = Object.entries(memory);\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"memory-inspector\" role=\"region\" aria-label=\"Memory state\">\n <div data-fp=\"memory-label\">Memory State</div>\n <pre data-fp=\"memory-json\">\n <code>{JSON.stringify(memory, null, 2)}</code>\n </pre>\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n padding: pad,\n fontFamily: theme.fontSans,\n ...style,\n }}\n data-fp=\"memory-inspector\"\n role=\"region\"\n aria-label=\"Memory state\"\n >\n <span\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n }}\n >\n Memory State\n </span>\n <div\n style={{\n marginTop: 8,\n background: theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: theme.radius,\n padding: `${pad}px ${pad + 4}px`,\n fontFamily: theme.fontMono,\n fontSize: fs.body,\n lineHeight: 1.8,\n }}\n >\n <span style={{ color: theme.textMuted }}>{\"{\"}</span>\n {entries.length === 0 && (\n <div\n style={{\n paddingLeft: 16,\n color: theme.textMuted,\n fontStyle: \"italic\",\n }}\n >\n {\"// empty\"}\n </div>\n )}\n {entries.map(([key, value], i) => {\n const isNew = newKeys.has(key);\n const isLast = i === entries.length - 1;\n return (\n <div\n key={key}\n style={{\n paddingLeft: 16,\n background: isNew\n ? `color-mix(in srgb, ${theme.success} 10%, transparent)`\n : \"transparent\",\n borderRadius: 4,\n marginLeft: -4,\n marginRight: -4,\n paddingRight: 4,\n }}\n >\n <span style={{ color: theme.primary }}>"{key}"</span>\n <span style={{ color: theme.textMuted }}>: </span>\n <span style={{ color: theme.success }}>\n {formatValue(value)}\n </span>\n {showTypes && (\n <span\n style={{\n color: theme.textMuted,\n fontSize: fs.small,\n marginLeft: 8,\n opacity: 0.6,\n }}\n >\n ({typeof value})\n </span>\n )}\n {!isLast && <span style={{ color: theme.textMuted }}>,</span>}\n </div>\n );\n })}\n <span style={{ color: theme.textMuted }}>{\"}\"}</span>\n </div>\n </div>\n );\n}\n\nfunction formatValue(value: unknown): string {\n if (typeof value === \"string\") return `\"${value}\"`;\n if (typeof value === \"object\" && value !== null) return JSON.stringify(value);\n return String(value);\n}\n","import { useMemo } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\nexport interface NarrativeLogProps extends BaseComponentProps {\n /** Snapshots to display narratives from */\n snapshots: StageSnapshot[];\n /** Show narratives up to this index (for time-travel sync) */\n selectedIndex?: number;\n /** Show a single narrative string (simple mode) */\n narrative?: string;\n}\n\n/**\n * Timeline-style execution log showing what happened at each stage.\n * Supports both full snapshots mode and single-narrative mode.\n */\nexport function NarrativeLog({\n snapshots,\n selectedIndex,\n narrative,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: NarrativeLogProps) {\n const entries = useMemo(() => {\n if (narrative) {\n return [{ label: \"Output\", text: narrative, isCurrent: true }];\n }\n const idx = selectedIndex ?? snapshots.length - 1;\n return snapshots.slice(0, idx + 1).map((s, i) => ({\n label: s.stageLabel,\n text: s.narrative,\n isCurrent: i === idx,\n }));\n }, [snapshots, selectedIndex, narrative]);\n\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"narrative-log\">\n {entries.map((entry, i) => (\n <div key={i} data-fp=\"narrative-entry\" data-current={entry.isCurrent}>\n <strong>{entry.label}</strong>\n <p>{entry.text}</p>\n </div>\n ))}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{ padding: pad, fontFamily: theme.fontSans, ...style }}\n data-fp=\"narrative-log\"\n >\n <span\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n }}\n >\n Execution Log\n </span>\n <div style={{ marginTop: 8, display: \"flex\", flexDirection: \"column\" }}>\n {entries.map((entry, i) => (\n <div\n key={i}\n style={{\n display: \"flex\",\n gap: 10,\n padding: `${pad}px 0`,\n borderBottom:\n i < entries.length - 1 ? `1px solid ${theme.border}` : \"none\",\n }}\n >\n {/* Timeline dot + line */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n width: 12,\n flexShrink: 0,\n paddingTop: 5,\n }}\n >\n <div\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: entry.isCurrent ? theme.primary : theme.success,\n flexShrink: 0,\n }}\n />\n {i < entries.length - 1 && (\n <div\n style={{\n width: 1,\n flex: 1,\n background: theme.border,\n marginTop: 4,\n }}\n />\n )}\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, minWidth: 0 }}>\n <span\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: entry.isCurrent ? theme.primary : theme.textMuted,\n }}\n >\n {entry.label}\n </span>\n <div\n style={{\n fontSize: fs.body,\n lineHeight: 1.5,\n color: entry.isCurrent ? theme.textPrimary : theme.textSecondary,\n marginTop: 2,\n }}\n >\n {entry.text}\n </div>\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { useState, useCallback, useMemo, useEffect, useRef } from \"react\";\nimport type { BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface NarrativeGroup {\n header: string;\n headerIdx: number;\n steps: { text: string; idx: number }[];\n}\n\nexport interface NarrativeTraceProps extends BaseComponentProps {\n /** All narrative lines (full trace) */\n narrative: string[];\n /** Number of lines currently revealed (for progressive reveal). Defaults to all. */\n revealedCount?: number;\n /** Start with all groups collapsed */\n defaultCollapsed?: boolean;\n /** Called when user clicks a stage header */\n onStageClick?: (headerIndex: number) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction parseGroups(lines: string[]): NarrativeGroup[] {\n const groups: NarrativeGroup[] = [];\n let current: NarrativeGroup | null = null;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trimStart();\n const isStep = trimmed.startsWith(\"Step \") || /^\\s/.test(line);\n\n if (!isStep || !current) {\n current = { header: line, headerIdx: i, steps: [] };\n groups.push(current);\n } else {\n current.steps.push({ text: trimmed, idx: i });\n }\n }\n\n return groups;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function NarrativeTrace({\n narrative,\n revealedCount,\n defaultCollapsed = false,\n onStageClick,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: NarrativeTraceProps) {\n const revealed = revealedCount != null ? narrative.slice(0, revealedCount) : narrative;\n const future = revealedCount != null ? narrative.slice(revealedCount) : [];\n\n const revealedGroups = useMemo(() => parseGroups(revealed), [revealed]);\n const futureGroups = useMemo(() => parseGroups(future), [future]);\n\n const [collapsedSet, setCollapsedSet] = useState<Set<number>>(() => {\n if (!defaultCollapsed) return new Set();\n return new Set(parseGroups(narrative).map((g) => g.headerIdx));\n });\n\n const latestRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n latestRef.current?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }, [revealedGroups.length]);\n\n const toggle = useCallback((idx: number) => {\n setCollapsedSet((prev) => {\n const next = new Set(prev);\n if (next.has(idx)) next.delete(idx);\n else next.add(idx);\n return next;\n });\n }, []);\n\n const lastIdx = revealedGroups.length - 1;\n const fs = fontSize[size];\n const pad = padding[size];\n\n // ── Unstyled mode ──\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"narrative-trace\">\n {revealedGroups.map((group, gi) => (\n <div key={group.headerIdx} data-fp=\"narrative-group\" data-latest={gi === lastIdx}>\n <div\n data-fp=\"narrative-header\"\n data-collapsible={group.steps.length > 0}\n data-collapsed={collapsedSet.has(group.headerIdx)}\n role={group.steps.length > 0 ? \"button\" : undefined}\n tabIndex={group.steps.length > 0 ? 0 : undefined}\n aria-expanded={group.steps.length > 0 ? !collapsedSet.has(group.headerIdx) : undefined}\n aria-label={`Stage ${gi + 1}, ${group.steps.length} steps${gi === lastIdx ? \", current\" : \"\"}`}\n onClick={() => {\n if (group.steps.length > 0) toggle(group.headerIdx);\n onStageClick?.(group.headerIdx);\n }}\n onKeyDown={(e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n if (group.steps.length > 0) toggle(group.headerIdx);\n onStageClick?.(group.headerIdx);\n }\n }}\n >\n {group.header}\n </div>\n {!collapsedSet.has(group.headerIdx) &&\n group.steps.map((step) => (\n <div key={step.idx} data-fp=\"narrative-step\">\n {step.text}\n </div>\n ))}\n </div>\n ))}\n {futureGroups.length > 0 && (\n <div data-fp=\"narrative-future-hint\">\n {futureGroups.length} more {futureGroups.length === 1 ? \"stage\" : \"stages\"} ahead...\n </div>\n )}\n </div>\n );\n }\n\n // ── Styled mode ──\n return (\n <div\n className={className}\n style={{\n flex: 1,\n overflow: \"auto\",\n padding: pad,\n fontFamily: theme.fontMono,\n ...style,\n }}\n data-fp=\"narrative-trace\"\n >\n {revealedGroups.map((group, gi) => {\n const isLatest = gi === lastIdx;\n const isCollapsed = collapsedSet.has(group.headerIdx);\n const hasSteps = group.steps.length > 0;\n\n return (\n <div\n key={group.headerIdx}\n ref={isLatest ? latestRef : undefined}\n style={{ marginBottom: 2 }}\n data-fp=\"narrative-group\"\n >\n {/* Stage header */}\n <div\n role={hasSteps ? \"button\" : undefined}\n tabIndex={hasSteps ? 0 : undefined}\n aria-expanded={hasSteps ? !isCollapsed : undefined}\n aria-label={`Stage ${gi + 1}, ${group.steps.length} steps${isLatest ? \", current\" : \", completed\"}`}\n onClick={() => {\n if (hasSteps) toggle(group.headerIdx);\n onStageClick?.(group.headerIdx);\n }}\n onKeyDown={(e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n if (hasSteps) toggle(group.headerIdx);\n onStageClick?.(group.headerIdx);\n }\n }}\n style={{\n fontSize: fs.body,\n lineHeight: 1.7,\n color: isLatest ? theme.textPrimary : theme.textSecondary,\n padding: `4px ${pad - 4}px`,\n borderRadius: 4,\n background: isLatest ? theme.bgTertiary : \"transparent\",\n borderLeft: isLatest\n ? `3px solid ${theme.primary}`\n : `3px solid ${theme.success}`,\n cursor: hasSteps ? \"pointer\" : \"default\",\n fontWeight: 600,\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n userSelect: \"none\",\n transition: \"all 0.15s ease\",\n }}\n >\n {hasSteps && (\n <span\n style={{\n fontSize: fs.small - 1,\n color: theme.textMuted,\n transition: \"transform 0.15s ease\",\n transform: isCollapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n width: 10,\n flexShrink: 0,\n }}\n >\n ▼\n </span>\n )}\n {!hasSteps && <span style={{ width: 10, flexShrink: 0 }} />}\n <span>{group.header}</span>\n </div>\n\n {/* Step lines */}\n {!isCollapsed &&\n group.steps.map((step) => (\n <div\n key={step.idx}\n style={{\n fontSize: fs.small,\n lineHeight: 1.6,\n color: isLatest ? theme.textSecondary : theme.textMuted,\n padding: `2px ${pad - 4}px 2px ${pad + 20}px`,\n opacity: isLatest ? 0.9 : 0.7,\n transition: \"all 0.15s ease\",\n }}\n data-fp=\"narrative-step\"\n >\n {step.text}\n </div>\n ))}\n </div>\n );\n })}\n\n {/* Future groups — show count hint only, skip full rendering for performance */}\n {futureGroups.length > 0 && (\n <div style={{\n opacity: 0.3,\n fontSize: fs.small,\n color: theme.textMuted,\n padding: `8px ${pad}px`,\n fontStyle: \"italic\",\n }}>\n {futureGroups.length} more {futureGroups.length === 1 ? \"stage\" : \"stages\"} ahead...\n </div>\n )}\n </div>\n );\n}\n","import { useState, useMemo, useRef, useEffect } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\nexport interface GanttTimelineProps extends BaseComponentProps {\n /** Stage snapshots with timing info */\n snapshots: StageSnapshot[];\n /** Currently selected stage index */\n selectedIndex?: number;\n /** Callback when a stage bar is clicked */\n onSelect?: (index: number) => void;\n /** Max visible rows before collapsing (0 = no collapse). Default: 5 */\n maxVisibleRows?: number;\n}\n\n/**\n * Horizontal Gantt-style timeline showing stage durations and overlap.\n * Collapses to `maxVisibleRows` with expand/collapse toggle.\n * Auto-scrolls to keep the active stage visible when collapsed.\n */\nexport function GanttTimeline({\n snapshots,\n selectedIndex = 0,\n onSelect,\n size = \"default\",\n unstyled = false,\n className,\n style,\n maxVisibleRows = 5,\n}: GanttTimelineProps) {\n const [expanded, setExpanded] = useState(false);\n const activeRowRef = useRef<HTMLDivElement | null>(null);\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n\n const totalWallTime = useMemo(\n () => Math.max(...snapshots.map((s) => s.startMs + s.durationMs), 1),\n [snapshots]\n );\n\n const fs = fontSize[size];\n const pad = padding[size];\n const labelWidth = size === \"compact\" ? 50 : size === \"detailed\" ? 100 : 80;\n const msWidth = size === \"compact\" ? 28 : 36;\n const rowHeight = size === \"compact\" ? 18 : 22;\n\n const collapsible = maxVisibleRows > 0 && snapshots.length > maxVisibleRows;\n const showAll = expanded || !collapsible;\n\n // Auto-scroll to active row when collapsed\n useEffect(() => {\n if (!showAll && activeRowRef.current && scrollContainerRef.current) {\n activeRowRef.current.scrollIntoView({\n block: \"nearest\",\n behavior: \"smooth\",\n });\n }\n }, [selectedIndex, showAll]);\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"gantt-timeline\" role=\"listbox\" aria-label=\"Execution timeline\">\n {snapshots.map((snap, idx) => (\n <div\n key={`${snap.stageName}-${idx}`}\n data-fp=\"gantt-bar\"\n data-selected={idx === selectedIndex}\n data-visible={idx <= selectedIndex}\n role=\"option\"\n aria-selected={idx === selectedIndex}\n aria-label={`${snap.stageLabel}, ${snap.durationMs}ms`}\n onClick={() => onSelect?.(idx)}\n >\n <span data-fp=\"gantt-label\">{snap.stageLabel}</span>\n <span data-fp=\"gantt-duration\">{snap.durationMs}ms</span>\n </div>\n ))}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{ padding: pad, fontFamily: theme.fontSans, ...style }}\n data-fp=\"gantt-timeline\"\n >\n {/* Header with collapse toggle */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n }}\n >\n <span\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n }}\n >\n {size === \"compact\" ? \"Timeline\" : \"Execution Timeline\"}\n </span>\n {collapsible && (\n <button\n onClick={() => setExpanded((e) => !e)}\n style={{\n background: \"none\",\n border: `1px solid ${theme.border}`,\n borderRadius: 4,\n color: theme.textSecondary,\n fontSize: fs.small,\n padding: \"2px 8px\",\n cursor: \"pointer\",\n fontFamily: theme.fontSans,\n }}\n >\n {expanded\n ? \"Collapse\"\n : `${snapshots.length - maxVisibleRows} more...`}\n </button>\n )}\n </div>\n\n {/* Scrollable rows container */}\n <div\n ref={scrollContainerRef}\n role=\"listbox\"\n aria-label=\"Execution timeline\"\n style={{\n marginTop: 8,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 4,\n ...(showAll\n ? {}\n : {\n maxHeight: maxVisibleRows * (rowHeight + 4),\n overflowY: \"auto\",\n scrollbarWidth: \"thin\",\n }),\n }}\n >\n {snapshots.map((snap, idx) => {\n const leftPct = (snap.startMs / totalWallTime) * 100;\n const widthPct = Math.max((snap.durationMs / totalWallTime) * 100, 1);\n const isSelected = idx === selectedIndex;\n const isVisible = idx <= selectedIndex;\n\n return (\n <div\n key={`${snap.stageName}-${idx}`}\n ref={isSelected ? activeRowRef : undefined}\n role=\"option\"\n aria-selected={isSelected}\n aria-label={`${snap.stageLabel}, ${snap.durationMs}ms`}\n onClick={() => onSelect?.(idx)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: size === \"compact\" ? 4 : 8,\n cursor: onSelect ? \"pointer\" : \"default\",\n opacity: isVisible ? 1 : 0.3,\n transition: \"opacity 0.3s ease\",\n height: rowHeight,\n flexShrink: 0,\n }}\n >\n <span\n title={snap.stageLabel}\n style={{\n width: labelWidth,\n fontSize: fs.small,\n color: isSelected ? theme.primary : theme.textMuted,\n fontWeight: isSelected ? 600 : 400,\n textAlign: \"right\",\n flexShrink: 0,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {snap.stageLabel}\n </span>\n <div\n style={{\n flex: 1,\n height: size === \"compact\" ? 6 : 8,\n position: \"relative\",\n background: theme.bgTertiary,\n borderRadius: 3,\n }}\n >\n {isVisible && (\n <div\n style={{\n position: \"absolute\",\n left: `${leftPct}%`,\n top: 0,\n width: `${widthPct}%`,\n height: \"100%\",\n borderRadius: 3,\n background: isSelected ? theme.primary : theme.success,\n transition: \"width 0.3s ease\",\n }}\n />\n )}\n </div>\n <span\n style={{\n fontSize: fs.small,\n color: theme.textMuted,\n fontFamily: theme.fontMono,\n width: msWidth,\n flexShrink: 0,\n }}\n >\n {snap.durationMs}ms\n </span>\n </div>\n );\n })}\n </div>\n\n {/* Time axis */}\n <div\n style={{\n marginTop: 4,\n marginLeft: labelWidth + (size === \"compact\" ? 4 : 8),\n marginRight: msWidth + (size === \"compact\" ? 4 : 8),\n display: \"flex\",\n justifyContent: \"space-between\",\n fontSize: fs.small - 1,\n color: theme.textMuted,\n fontFamily: theme.fontMono,\n }}\n >\n <span>0ms</span>\n {size !== \"compact\" && (\n <span>{(totalWallTime / 2).toFixed(1)}ms</span>\n )}\n <span>{totalWallTime.toFixed(1)}ms</span>\n </div>\n </div>\n );\n}\n","import { useState } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\nimport { MemoryInspector } from \"../MemoryInspector\";\nimport { NarrativeLog } from \"../NarrativeLog\";\nimport { GanttTimeline } from \"../GanttTimeline\";\n\nexport interface SnapshotPanelProps extends BaseComponentProps {\n /** Stage snapshots from pipeline execution */\n snapshots: StageSnapshot[];\n /** Show the Gantt timeline */\n showGantt?: boolean;\n /** Show the time-travel scrubber */\n showScrubber?: boolean;\n /** Title override */\n title?: string;\n}\n\n/**\n * All-in-one panel: time-travel scrubber + memory inspector + narrative log + gantt.\n * Drop this into any page to make a pipeline run inspectable.\n */\nexport function SnapshotPanel({\n snapshots,\n showGantt = true,\n showScrubber = true,\n title = \"Pipeline Inspector\",\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: SnapshotPanelProps) {\n const [selectedIndex, setSelectedIndex] = useState(0);\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (snapshots.length === 0) {\n return (\n <div\n className={className}\n style={{\n padding: pad * 2,\n textAlign: \"center\",\n color: unstyled ? undefined : theme.textMuted,\n fontSize: fs.body,\n ...style,\n }}\n data-fp=\"snapshot-panel\"\n >\n No snapshots to display\n </div>\n );\n }\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"snapshot-panel\">\n <h3>{title}</h3>\n {showScrubber && (\n <input\n type=\"range\"\n min={0}\n max={snapshots.length - 1}\n value={selectedIndex}\n onChange={(e) => setSelectedIndex(parseInt(e.target.value))}\n />\n )}\n <MemoryInspector\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n unstyled\n />\n <NarrativeLog\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n unstyled\n />\n {showGantt && (\n <GanttTimeline\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n onSelect={setSelectedIndex}\n unstyled\n />\n )}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n background: theme.bgPrimary,\n fontFamily: theme.fontSans,\n overflow: \"hidden\",\n ...style,\n }}\n data-fp=\"snapshot-panel\"\n >\n {/* Header with title + scrubber */}\n <div\n style={{\n padding: `${pad}px ${pad + 4}px`,\n borderBottom: `1px solid ${theme.border}`,\n background: theme.bgSecondary,\n flexShrink: 0,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n marginBottom: showScrubber ? 8 : 0,\n }}\n >\n <span\n style={{\n fontSize: fs.body + 2,\n fontWeight: 600,\n color: theme.textPrimary,\n }}\n >\n {title}\n </span>\n <span\n style={{\n fontSize: fs.small,\n color: theme.textMuted,\n fontFamily: theme.fontMono,\n }}\n >\n {selectedIndex + 1}/{snapshots.length}\n </span>\n </div>\n\n {showScrubber && (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <ScrubButton\n label=\"\\u25C0\"\n disabled={selectedIndex === 0}\n onClick={() => setSelectedIndex((i) => Math.max(0, i - 1))}\n />\n <input\n type=\"range\"\n min={0}\n max={snapshots.length - 1}\n value={selectedIndex}\n onChange={(e) => setSelectedIndex(parseInt(e.target.value))}\n style={{\n flex: 1,\n height: 4,\n accentColor: theme.primary,\n cursor: \"pointer\",\n }}\n />\n <ScrubButton\n label=\"\\u25B6\"\n disabled={selectedIndex === snapshots.length - 1}\n onClick={() =>\n setSelectedIndex((i) => Math.min(snapshots.length - 1, i + 1))\n }\n />\n </div>\n )}\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, overflow: \"auto\" }}>\n <MemoryInspector\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n size={size}\n />\n <div\n style={{\n height: 1,\n background: theme.border,\n margin: `0 ${pad}px`,\n }}\n />\n <NarrativeLog\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n size={size}\n />\n </div>\n\n {/* Gantt footer */}\n {showGantt && (\n <div\n style={{\n borderTop: `1px solid ${theme.border}`,\n background: theme.bgSecondary,\n flexShrink: 0,\n }}\n >\n <GanttTimeline\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n onSelect={setSelectedIndex}\n size={size}\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction ScrubButton({\n label,\n disabled,\n onClick,\n}: {\n label: string;\n disabled: boolean;\n onClick: () => void;\n}) {\n return (\n <button\n onClick={onClick}\n disabled={disabled}\n style={{\n background: theme.bgTertiary,\n border: `1px solid ${theme.border}`,\n color: disabled ? theme.textMuted : theme.textPrimary,\n borderRadius: 6,\n width: 28,\n height: 28,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n opacity: disabled ? 0.5 : 1,\n fontSize: 12,\n flexShrink: 0,\n }}\n >\n {label}\n </button>\n );\n}\n","import { useMemo } from \"react\";\nimport type { BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface DiffEntry {\n key: string;\n type: \"added\" | \"removed\" | \"changed\" | \"unchanged\";\n oldValue?: unknown;\n newValue?: unknown;\n}\n\nexport interface ScopeDiffProps extends BaseComponentProps {\n /** Memory state before the current stage */\n previous: Record<string, unknown> | null;\n /** Memory state after the current stage */\n current: Record<string, unknown>;\n /** Hide unchanged keys (default: false) */\n hideUnchanged?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction computeDiff(\n prev: Record<string, unknown> | null,\n curr: Record<string, unknown>\n): DiffEntry[] {\n const entries: DiffEntry[] = [];\n const allKeys = new Set([...Object.keys(prev ?? {}), ...Object.keys(curr)]);\n\n for (const key of allKeys) {\n const inPrev = prev != null && key in prev;\n const inCurr = key in curr;\n const oldVal = prev?.[key];\n const newVal = curr[key];\n\n if (!inPrev && inCurr) {\n entries.push({ key, type: \"added\", newValue: newVal });\n } else if (inPrev && !inCurr) {\n entries.push({ key, type: \"removed\", oldValue: oldVal });\n } else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {\n entries.push({ key, type: \"changed\", oldValue: oldVal, newValue: newVal });\n } else {\n entries.push({ key, type: \"unchanged\", newValue: newVal });\n }\n }\n\n const order = { added: 0, changed: 1, removed: 2, unchanged: 3 };\n entries.sort((a, b) => order[a.type] - order[b.type]);\n return entries;\n}\n\nfunction fmt(v: unknown): string {\n if (typeof v === \"string\") return `\"${v}\"`;\n if (typeof v === \"object\" && v !== null) return JSON.stringify(v, null, 2);\n return String(v);\n}\n\nconst diffColors: Record<DiffEntry[\"type\"], { bg: string; fg: string; icon: string }> = {\n added: { bg: `color-mix(in srgb, ${theme.success} 10%, transparent)`, fg: theme.success, icon: \"+\" },\n removed: { bg: `color-mix(in srgb, ${theme.error} 10%, transparent)`, fg: theme.error, icon: \"-\" },\n changed: { bg: `color-mix(in srgb, ${theme.warning} 10%, transparent)`, fg: theme.warning, icon: \"~\" },\n unchanged: { bg: \"transparent\", fg: \"\", icon: \" \" },\n};\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function ScopeDiff({\n previous,\n current,\n hideUnchanged = false,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: ScopeDiffProps) {\n const entries = useMemo(() => computeDiff(previous, current), [previous, current]);\n const visible = hideUnchanged ? entries.filter((e) => e.type !== \"unchanged\") : entries;\n\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"scope-diff\">\n {visible.map((e) => (\n <div key={e.key} data-fp=\"diff-entry\" data-type={e.type}>\n <span data-fp=\"diff-key\">{e.key}</span>\n {e.type === \"changed\" && (\n <>\n <span data-fp=\"diff-old\">{fmt(e.oldValue)}</span>\n <span data-fp=\"diff-new\">{fmt(e.newValue)}</span>\n </>\n )}\n {(e.type === \"added\" || e.type === \"unchanged\") && (\n <span data-fp=\"diff-value\">{fmt(e.newValue)}</span>\n )}\n {e.type === \"removed\" && (\n <span data-fp=\"diff-value\">{fmt(e.oldValue)}</span>\n )}\n </div>\n ))}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{ padding: pad, fontFamily: theme.fontMono, ...style }}\n data-fp=\"scope-diff\"\n >\n {visible.length === 0 && (\n <div style={{ fontSize: fs.body, color: theme.textMuted, fontStyle: \"italic\" }}>\n No changes\n </div>\n )}\n {visible.map((entry) => {\n const dc = diffColors[entry.type];\n return (\n <div\n key={entry.key}\n style={{\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: 8,\n padding: `4px ${pad - 4}px`,\n marginBottom: 2,\n borderRadius: 4,\n background: dc.bg,\n fontSize: fs.body,\n lineHeight: 1.5,\n }}\n data-fp=\"diff-entry\"\n >\n <span\n style={{\n width: 16,\n flexShrink: 0,\n fontWeight: 700,\n color: dc.fg || theme.textMuted,\n textAlign: \"center\",\n }}\n >\n {dc.icon}\n </span>\n <span style={{ color: theme.primary, fontWeight: 600, flexShrink: 0 }}>\n {entry.key}\n </span>\n <span style={{ color: theme.textMuted }}>=</span>\n {entry.type === \"changed\" ? (\n <span>\n <span\n style={{\n color: theme.error,\n textDecoration: \"line-through\",\n opacity: 0.7,\n }}\n >\n {fmt(entry.oldValue)}\n </span>\n <span style={{ color: theme.textMuted, margin: \"0 4px\" }}>→</span>\n <span style={{ color: theme.success }}>{fmt(entry.newValue)}</span>\n </span>\n ) : (\n <span\n style={{\n color:\n entry.type === \"added\"\n ? theme.success\n : entry.type === \"removed\"\n ? theme.error\n : theme.textPrimary,\n }}\n >\n {fmt(entry.type === \"removed\" ? entry.oldValue : entry.newValue)}\n </span>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","import type { BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\nexport interface ResultPanelProps extends BaseComponentProps {\n /** Final pipeline output / shared state */\n data: Record<string, unknown> | null;\n /** Optional console log lines */\n logs?: string[];\n /** Hide console section (default: false) */\n hideConsole?: boolean;\n}\n\nexport function ResultPanel({\n data,\n logs = [],\n hideConsole = false,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: ResultPanelProps) {\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"result-panel\">\n <div data-fp=\"result-data\">\n <pre>{data ? JSON.stringify(data, null, 2) : \"No data\"}</pre>\n </div>\n {!hideConsole && (\n <div data-fp=\"result-console\">\n {logs.map((line, i) => (\n <div key={i} data-fp=\"console-line\" data-error={line.startsWith(\"ERROR\")}>\n {line}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n ...style,\n }}\n data-fp=\"result-panel\"\n >\n {data && (\n <div style={{ flex: 1, overflow: \"auto\", padding: pad }}>\n <div\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n marginBottom: 8,\n }}\n >\n {size === \"compact\" ? \"Result\" : \"Business Result (Scope)\"}\n </div>\n <pre\n style={{\n fontSize: fs.body,\n fontFamily: theme.fontMono,\n color: theme.textPrimary,\n background: theme.bgSecondary,\n padding: pad,\n borderRadius: theme.radius,\n overflow: \"auto\",\n margin: 0,\n }}\n >\n {JSON.stringify(data, null, 2)}\n </pre>\n </div>\n )}\n\n {!hideConsole && (\n <div\n style={{\n borderTop: `1px solid ${theme.border}`,\n padding: pad,\n overflow: \"auto\",\n maxHeight: \"40%\",\n flexShrink: 0,\n }}\n >\n <div\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n marginBottom: 8,\n }}\n >\n Console\n </div>\n {logs.length === 0 && (\n <div style={{ fontSize: fs.body, color: theme.textMuted, fontStyle: \"italic\" }}>\n No console output\n </div>\n )}\n {logs.map((line, i) => (\n <div\n key={i}\n style={{\n fontSize: fs.body,\n fontFamily: theme.fontMono,\n color: line.startsWith(\"ERROR\") ? theme.error : theme.textPrimary,\n padding: \"2px 0\",\n borderBottom: `1px solid ${theme.bgSecondary}`,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n }}\n >\n {line}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import { useState, useMemo, useCallback } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type StageDetailMode = \"simple\" | \"dev\";\n\nexport interface MemoryChange {\n key: string;\n type: \"added\" | \"updated\" | \"removed\";\n oldValue?: unknown;\n newValue?: unknown;\n}\n\n/** Keys that are footprint engine internals — hidden by default in dev mode. */\nexport const DEFAULT_EXCLUDED_KEYS = new Set<string>([]);\n\nexport interface StageDetailPanelProps extends BaseComponentProps {\n /** Stage snapshots for time-travel */\n snapshots: StageSnapshot[];\n /** Current snapshot index */\n selectedIndex: number;\n /** Display mode: \"simple\" (description + narrative) or \"dev\" (memory story) */\n mode?: StageDetailMode;\n /** Show a toggle to switch between simple/dev modes (default: false) */\n showToggle?: boolean;\n /** Called when user toggles mode via built-in toggle */\n onModeChange?: (mode: StageDetailMode) => void;\n /** Keys to exclude from memory display (default: engine internals). Pass empty set to show all. */\n excludeKeys?: Set<string>;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction computeChanges(\n prev: Record<string, unknown> | null,\n curr: Record<string, unknown>,\n): MemoryChange[] {\n const changes: MemoryChange[] = [];\n const allKeys = new Set([...Object.keys(prev ?? {}), ...Object.keys(curr)]);\n\n for (const key of allKeys) {\n const inPrev = prev != null && key in prev;\n const inCurr = key in curr;\n const oldVal = prev?.[key];\n const newVal = curr[key];\n\n if (!inPrev && inCurr) {\n changes.push({ key, type: \"added\", newValue: newVal });\n } else if (inPrev && !inCurr) {\n changes.push({ key, type: \"removed\", oldValue: oldVal });\n } else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {\n changes.push({ key, type: \"updated\", oldValue: oldVal, newValue: newVal });\n }\n }\n\n const order = { added: 0, updated: 1, removed: 2 };\n changes.sort((a, b) => order[a.type] - order[b.type]);\n return changes;\n}\n\nfunction fmt(v: unknown): string {\n if (typeof v === \"string\") return `\"${v}\"`;\n if (typeof v === \"object\" && v !== null) return JSON.stringify(v, null, 2);\n return String(v);\n}\n\nconst changeBadge: Record<MemoryChange[\"type\"], { bg: string; fg: string; label: string }> = {\n added: { bg: \"rgba(34,197,94,0.12)\", fg: \"#22c55e\", label: \"ADD\" },\n updated: { bg: \"rgba(245,158,11,0.12)\", fg: \"#f59e0b\", label: \"UPD\" },\n removed: { bg: \"rgba(239,68,68,0.12)\", fg: \"#ef4444\", label: \"DEL\" },\n};\n\n// ---------------------------------------------------------------------------\n// Simple Mode — description + narrative\n// ---------------------------------------------------------------------------\n\nfunction SimpleView({\n snapshot,\n fs,\n pad,\n}: {\n snapshot: StageSnapshot;\n fs: { label: number; body: number; small: number };\n pad: number;\n}) {\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n {/* Stage header */}\n <div>\n <div\n style={{\n fontSize: fs.label + 2,\n fontWeight: 700,\n color: theme.textPrimary,\n }}\n >\n {snapshot.stageLabel}\n </div>\n {snapshot.description && (\n <div\n style={{\n fontSize: fs.body,\n color: theme.textSecondary,\n marginTop: 4,\n lineHeight: 1.5,\n }}\n >\n {snapshot.description}\n </div>\n )}\n </div>\n\n {/* Status badge */}\n {snapshot.status && (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n <div\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background:\n snapshot.status === \"done\"\n ? theme.success\n : snapshot.status === \"active\"\n ? theme.primary\n : snapshot.status === \"error\"\n ? theme.error\n : theme.textMuted,\n }}\n />\n <span\n style={{\n fontSize: fs.small,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.05em\",\n }}\n >\n {snapshot.status}\n </span>\n </div>\n )}\n\n {/* Narrative — what happened */}\n {snapshot.narrative && (\n <div>\n <div\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n marginBottom: 6,\n }}\n >\n What happened\n </div>\n <div\n style={{\n fontSize: fs.body,\n lineHeight: 1.6,\n color: theme.textPrimary,\n background: theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: theme.radius,\n padding: pad,\n }}\n >\n {snapshot.narrative}\n </div>\n </div>\n )}\n\n {/* Duration */}\n {snapshot.durationMs > 0 && (\n <div\n style={{\n fontSize: fs.small,\n color: theme.textMuted,\n }}\n >\n Completed in {snapshot.durationMs < 1 ? \"<1\" : snapshot.durationMs}ms\n </div>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Dev Mode — memory story (browser DevTools style)\n// ---------------------------------------------------------------------------\n\n/** A row in the full memory ledger: either a changed key or an unchanged one. */\ntype MemoryRow =\n | { kind: \"change\"; change: MemoryChange }\n | { kind: \"unchanged\"; key: string; value: unknown };\n\nfunction buildMemoryRows(\n currMemory: Record<string, unknown>,\n changes: MemoryChange[],\n): MemoryRow[] {\n const changeMap = new Map(changes.map((c) => [c.key, c]));\n const rows: MemoryRow[] = [];\n\n // Changed keys first (ADD → UPD → DEL)\n for (const change of changes) {\n rows.push({ kind: \"change\", change });\n }\n\n // Then unchanged keys (sorted alphabetically)\n const unchangedKeys = Object.keys(currMemory)\n .filter((k) => !changeMap.has(k))\n .sort();\n for (const key of unchangedKeys) {\n rows.push({ kind: \"unchanged\", key, value: currMemory[key] });\n }\n\n return rows;\n}\n\nfunction DevView({\n snapshot,\n changes,\n currMemory,\n fs,\n pad,\n}: {\n snapshot: StageSnapshot;\n changes: MemoryChange[];\n currMemory: Record<string, unknown>;\n fs: { label: number; body: number; small: number };\n pad: number;\n}) {\n const rows = useMemo(() => buildMemoryRows(currMemory, changes), [currMemory, changes]);\n const totalKeys = Object.keys(currMemory).length;\n\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n {/* Stage header with label */}\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <span\n style={{\n fontSize: fs.label + 2,\n fontWeight: 700,\n color: theme.textPrimary,\n fontFamily: theme.fontMono,\n }}\n >\n {snapshot.stageLabel}\n </span>\n {snapshot.durationMs > 0 && (\n <span\n style={{\n fontSize: fs.small,\n color: theme.textMuted,\n fontFamily: theme.fontMono,\n }}\n >\n {snapshot.durationMs}ms\n </span>\n )}\n </div>\n\n {/* Memory state section header */}\n <div\n style={{\n fontSize: fs.label,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n }}\n >\n Memory\n <span style={{ fontWeight: 400, marginLeft: 6 }}>\n ({totalKeys} key{totalKeys !== 1 ? \"s\" : \"\"}\n {changes.length > 0 && `, ${changes.length} changed`})\n </span>\n </div>\n\n {/* Full memory ledger */}\n {rows.length === 0 ? (\n <div\n style={{\n fontSize: fs.body,\n color: theme.textMuted,\n fontStyle: \"italic\",\n fontFamily: theme.fontMono,\n padding: `${pad}px`,\n background: theme.bgSecondary,\n borderRadius: theme.radius,\n }}\n >\n Empty memory\n </div>\n ) : (\n <div\n style={{\n fontFamily: theme.fontMono,\n fontSize: fs.body,\n background: theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: theme.radius,\n overflow: \"hidden\",\n }}\n >\n {rows.map((row) => {\n if (row.kind === \"change\") {\n const { change } = row;\n const badge = changeBadge[change.type];\n return (\n <div\n key={change.key}\n style={{\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: 8,\n padding: `6px ${pad}px`,\n borderBottom: `1px solid ${theme.border}`,\n background: badge.bg,\n }}\n data-fp=\"memory-change\"\n data-type={change.type}\n >\n <span\n style={{\n fontSize: fs.small,\n fontWeight: 700,\n color: badge.fg,\n width: 28,\n flexShrink: 0,\n textAlign: \"center\",\n lineHeight: 1.8,\n }}\n >\n {badge.label}\n </span>\n <span\n style={{\n color: theme.primary,\n fontWeight: 600,\n flexShrink: 0,\n lineHeight: 1.8,\n }}\n >\n {change.key}\n </span>\n <div style={{ flex: 1, minWidth: 0, lineHeight: 1.8 }}>\n {change.type === \"updated\" ? (\n <>\n <span\n style={{\n color: theme.error,\n textDecoration: \"line-through\",\n opacity: 0.7,\n }}\n >\n {fmt(change.oldValue)}\n </span>\n <span style={{ color: theme.textMuted, margin: \"0 4px\" }}>→</span>\n <span style={{ color: theme.success }}>{fmt(change.newValue)}</span>\n </>\n ) : change.type === \"added\" ? (\n <span style={{ color: theme.success }}>{fmt(change.newValue)}</span>\n ) : (\n <span style={{ color: theme.error, textDecoration: \"line-through\" }}>\n {fmt(change.oldValue)}\n </span>\n )}\n </div>\n </div>\n );\n }\n\n // Unchanged key — dimmed, no badge\n return (\n <div\n key={row.key}\n style={{\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: 8,\n padding: `6px ${pad}px`,\n borderBottom: `1px solid ${theme.border}`,\n opacity: 0.5,\n }}\n data-fp=\"memory-unchanged\"\n >\n <span\n style={{\n width: 28,\n flexShrink: 0,\n lineHeight: 1.8,\n }}\n />\n <span\n style={{\n color: theme.textSecondary,\n fontWeight: 500,\n flexShrink: 0,\n lineHeight: 1.8,\n }}\n >\n {row.key}\n </span>\n <div style={{ flex: 1, minWidth: 0, lineHeight: 1.8, color: theme.textMuted }}>\n {fmt(row.value)}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Unstyled Mode\n// ---------------------------------------------------------------------------\n\nfunction UnstyledSimpleView({ snapshot }: { snapshot: StageSnapshot }) {\n return (\n <div data-fp=\"stage-detail-simple\">\n <div data-fp=\"stage-label\">{snapshot.stageLabel}</div>\n {snapshot.description && (\n <div data-fp=\"stage-description\">{snapshot.description}</div>\n )}\n {snapshot.status && <div data-fp=\"stage-status\">{snapshot.status}</div>}\n {snapshot.narrative && (\n <div data-fp=\"stage-narrative\">{snapshot.narrative}</div>\n )}\n </div>\n );\n}\n\nfunction UnstyledDevView({\n snapshot,\n changes,\n currMemory,\n}: {\n snapshot: StageSnapshot;\n changes: MemoryChange[];\n currMemory: Record<string, unknown>;\n}) {\n const rows = useMemo(() => buildMemoryRows(currMemory, changes), [currMemory, changes]);\n return (\n <div data-fp=\"stage-detail-dev\">\n <div data-fp=\"stage-label\">{snapshot.stageLabel}</div>\n {rows.map((row) => {\n if (row.kind === \"change\") {\n const c = row.change;\n return (\n <div key={c.key} data-fp=\"memory-change\" data-type={c.type}>\n <span data-fp=\"change-key\">{c.key}</span>\n {c.type === \"updated\" && (\n <>\n <span data-fp=\"change-old\">{fmt(c.oldValue)}</span>\n <span data-fp=\"change-new\">{fmt(c.newValue)}</span>\n </>\n )}\n {c.type === \"added\" && (\n <span data-fp=\"change-value\">{fmt(c.newValue)}</span>\n )}\n {c.type === \"removed\" && (\n <span data-fp=\"change-value\">{fmt(c.oldValue)}</span>\n )}\n </div>\n );\n }\n return (\n <div key={row.key} data-fp=\"memory-unchanged\">\n <span data-fp=\"unchanged-key\">{row.key}</span>\n <span data-fp=\"unchanged-value\">{fmt(row.value)}</span>\n </div>\n );\n })}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Main Component\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Mode Toggle\n// ---------------------------------------------------------------------------\n\nfunction ModeToggle({\n activeMode,\n onToggle,\n fs,\n unstyled,\n}: {\n activeMode: StageDetailMode;\n onToggle: () => void;\n fs: { label: number; body: number; small: number };\n unstyled: boolean;\n}) {\n if (unstyled) {\n return (\n <button data-fp=\"mode-toggle\" data-mode={activeMode} onClick={onToggle}>\n {activeMode === \"simple\" ? \"Dev\" : \"Simple\"}\n </button>\n );\n }\n\n return (\n <div\n style={{\n display: \"inline-flex\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n overflow: \"hidden\",\n flexShrink: 0,\n }}\n data-fp=\"mode-toggle\"\n >\n {([\"simple\", \"dev\"] as const).map((m) => (\n <button\n key={m}\n onClick={m !== activeMode ? onToggle : undefined}\n style={{\n padding: \"4px 10px\",\n fontSize: fs.small,\n fontWeight: m === activeMode ? 700 : 400,\n textTransform: \"uppercase\",\n letterSpacing: \"0.05em\",\n color: m === activeMode ? theme.textPrimary : theme.textMuted,\n background: m === activeMode ? theme.bgTertiary : \"transparent\",\n border: \"none\",\n cursor: m === activeMode ? \"default\" : \"pointer\",\n }}\n >\n {m === \"simple\" ? \"Simple\" : \"Dev\"}\n </button>\n ))}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Main Component\n// ---------------------------------------------------------------------------\n\nexport function StageDetailPanel({\n snapshots,\n selectedIndex,\n mode: controlledMode,\n showToggle = false,\n onModeChange,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: StageDetailPanelProps) {\n const [internalMode, setInternalMode] = useState<StageDetailMode>(controlledMode ?? \"simple\");\n\n // Support both controlled (mode prop) and uncontrolled (internal state) usage\n const activeMode = controlledMode ?? internalMode;\n\n const handleToggle = useCallback(() => {\n const next: StageDetailMode = activeMode === \"simple\" ? \"dev\" : \"simple\";\n setInternalMode(next);\n onModeChange?.(next);\n }, [activeMode, onModeChange]);\n\n const snapshot = snapshots[selectedIndex];\n const prevMemory = selectedIndex > 0 ? snapshots[selectedIndex - 1]?.memory ?? null : null;\n const currMemory = snapshot?.memory ?? {};\n\n const changes = useMemo(\n () => computeChanges(prevMemory, currMemory),\n [prevMemory, currMemory],\n );\n\n const fs = fontSize[size];\n const pad = padding[size];\n\n if (!snapshot) {\n return (\n <div className={className} style={style} data-fp=\"stage-detail-panel\">\n <div style={unstyled ? {} : { color: theme.textMuted, fontSize: fs.body, fontStyle: \"italic\", padding: pad }}>\n No stage selected\n </div>\n </div>\n );\n }\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"stage-detail-panel\" data-mode={activeMode}>\n {showToggle && (\n <ModeToggle activeMode={activeMode} onToggle={handleToggle} fs={fs} unstyled />\n )}\n {activeMode === \"simple\" ? (\n <UnstyledSimpleView snapshot={snapshot} />\n ) : (\n <UnstyledDevView snapshot={snapshot} changes={changes} currMemory={currMemory} />\n )}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n padding: pad,\n fontFamily: theme.fontSans,\n overflow: \"auto\",\n ...style,\n }}\n data-fp=\"stage-detail-panel\"\n data-mode={activeMode}\n >\n {showToggle && (\n <div style={{ display: \"flex\", justifyContent: \"flex-end\", marginBottom: 12 }}>\n <ModeToggle activeMode={activeMode} onToggle={handleToggle} fs={fs} unstyled={false} />\n </div>\n )}\n {activeMode === \"simple\" ? (\n <SimpleView snapshot={snapshot} fs={fs} pad={pad} />\n ) : (\n <DevView snapshot={snapshot} changes={changes} currMemory={currMemory} fs={fs} pad={pad} />\n )}\n </div>\n );\n}\n","import { useState, useEffect, useRef, useCallback } from \"react\";\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize } from \"../../theme\";\n\nexport interface TimeTravelControlsProps extends BaseComponentProps {\n /** Stage snapshots */\n snapshots: StageSnapshot[];\n /** Currently selected stage index */\n selectedIndex: number;\n /** Callback when selected index changes */\n onIndexChange: (index: number) => void;\n /** Enable auto-play with Gantt-proportional timing */\n autoPlayable?: boolean;\n}\n\nexport function TimeTravelControls({\n snapshots,\n selectedIndex,\n onIndexChange,\n autoPlayable = true,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: TimeTravelControlsProps) {\n const [playing, setPlaying] = useState(false);\n const playRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const total = snapshots.length;\n const canPrev = selectedIndex > 0;\n const canNext = selectedIndex < total - 1;\n\n // Auto-advance with proportional timing\n useEffect(() => {\n if (!playing || !autoPlayable) return;\n if (selectedIndex >= total - 1) {\n setPlaying(false);\n return;\n }\n const stageDur = snapshots[selectedIndex]?.durationMs ?? 1;\n const totalDur = snapshots.reduce((s, snap) => s + snap.durationMs, 0) || 1;\n const fraction = stageDur / totalDur;\n const baseMs = 3000;\n const delay = Math.max(200, Math.min(fraction * baseMs, 2000));\n\n playRef.current = setTimeout(() => {\n onIndexChange(selectedIndex + 1);\n }, delay);\n\n return () => {\n if (playRef.current) clearTimeout(playRef.current);\n };\n }, [playing, selectedIndex, snapshots, total, onIndexChange, autoPlayable]);\n\n const togglePlay = useCallback(() => {\n if (playing) {\n setPlaying(false);\n } else {\n if (selectedIndex >= total - 1) onIndexChange(0);\n setPlaying(true);\n }\n }, [playing, selectedIndex, total, onIndexChange]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowLeft\" && canPrev && !playing) {\n e.preventDefault();\n setPlaying(false);\n onIndexChange(selectedIndex - 1);\n } else if (e.key === \"ArrowRight\" && canNext && !playing) {\n e.preventDefault();\n setPlaying(false);\n onIndexChange(selectedIndex + 1);\n } else if (e.key === \" \" && autoPlayable) {\n e.preventDefault();\n togglePlay();\n }\n },\n [canPrev, canNext, playing, selectedIndex, onIndexChange, autoPlayable, togglePlay]\n );\n\n const fs = fontSize[size];\n\n if (unstyled) {\n return (\n <div\n className={className}\n style={style}\n data-fp=\"time-travel-controls\"\n role=\"toolbar\"\n aria-label=\"Time travel controls\"\n tabIndex={0}\n onKeyDown={handleKeyDown}\n >\n <button\n data-fp=\"tt-prev\"\n disabled={!canPrev || playing}\n onClick={() => { setPlaying(false); onIndexChange(selectedIndex - 1); }}\n aria-label=\"Previous stage\"\n >\n Prev\n </button>\n {autoPlayable && (\n <button data-fp=\"tt-play\" onClick={togglePlay} aria-label={playing ? \"Pause\" : \"Play\"}>\n {playing ? \"Pause\" : \"Play\"}\n </button>\n )}\n <button\n data-fp=\"tt-next\"\n disabled={!canNext || playing}\n onClick={() => { setPlaying(false); onIndexChange(selectedIndex + 1); }}\n aria-label=\"Next stage\"\n >\n Next\n </button>\n <div data-fp=\"tt-ticks\">\n {snapshots.map((snap, i) => (\n <button\n key={i}\n data-fp=\"tt-tick\"\n data-active={i === selectedIndex}\n data-done={i < selectedIndex}\n onClick={() => { setPlaying(false); onIndexChange(i); }}\n title={snap.stageLabel}\n />\n ))}\n </div>\n </div>\n );\n }\n\n const btnStyle = (disabled: boolean): React.CSSProperties => ({\n background: theme.bgTertiary,\n border: `1px solid ${theme.border}`,\n color: disabled ? theme.textMuted : theme.textPrimary,\n borderRadius: \"6px\",\n padding: \"4px 12px\",\n fontSize: fs.body,\n fontWeight: 600,\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n opacity: disabled ? 0.5 : 1,\n flexShrink: 0,\n });\n\n return (\n <div\n className={className}\n style={{\n padding: \"6px 12px\",\n background: theme.bgSecondary,\n borderBottom: `1px solid ${theme.border}`,\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n flexShrink: 0,\n ...style,\n }}\n data-fp=\"time-travel-controls\"\n role=\"toolbar\"\n aria-label=\"Time travel controls\"\n tabIndex={0}\n onKeyDown={handleKeyDown}\n >\n <button\n style={btnStyle(!canPrev || playing)}\n disabled={!canPrev || playing}\n onClick={() => { setPlaying(false); onIndexChange(selectedIndex - 1); }}\n aria-label=\"Previous stage\"\n >\n ◀\n </button>\n\n {autoPlayable && (\n <button\n onClick={togglePlay}\n style={{\n background: playing ? theme.primary : theme.bgTertiary,\n border: `1px solid ${theme.border}`,\n color: playing ? \"white\" : theme.textPrimary,\n borderRadius: \"6px\",\n width: 28,\n height: 28,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n fontSize: 14,\n flexShrink: 0,\n }}\n title={playing ? \"Pause\" : \"Play\"}\n aria-label={playing ? \"Pause\" : \"Play\"}\n >\n {playing ? \"\\u23F8\" : \"\\u25B6\"}\n </button>\n )}\n\n <button\n style={btnStyle(!canNext || playing)}\n disabled={!canNext || playing}\n onClick={() => { setPlaying(false); onIndexChange(selectedIndex + 1); }}\n aria-label=\"Next stage\"\n >\n ▶\n </button>\n\n {/* Tick-mark timeline */}\n <div\n style={{\n flex: 1,\n display: \"flex\",\n alignItems: \"center\",\n gap: 2,\n padding: \"0 4px\",\n }}\n >\n {snapshots.map((snap, i) => {\n const isActive = i === selectedIndex;\n const isDone = i < selectedIndex;\n return (\n <button\n key={i}\n onClick={() => { setPlaying(false); onIndexChange(i); }}\n title={snap.stageLabel}\n style={{\n flex: 1,\n height: isActive ? 14 : 8,\n borderRadius: 3,\n border: \"none\",\n cursor: \"pointer\",\n background: isActive\n ? theme.primary\n : isDone\n ? theme.success\n : theme.bgTertiary,\n opacity: isDone || isActive ? 1 : 0.4,\n transition: \"all 0.15s ease\",\n }}\n />\n );\n })}\n </div>\n </div>\n );\n}\n","/**\n * ExplainableShell — Pure orchestrator for explainable pipeline visualization.\n *\n * Collapsible sections use the **line + centered pill** pattern:\n * - Collapsed = thin divider line with a pill button sitting on it\n * - Expanded = full content with a pill at the closing edge\n *\n * Sub-components are memo'd to minimize re-renders when scrubbing the\n * time-travel slider. Only components that depend on snapshotIdx re-render.\n *\n * Consumer controls theme via --fp-* CSS custom properties.\n */\nimport { memo, useState, useCallback, useMemo, useRef, useEffect } from \"react\";\nimport type { StageSnapshot, BaseComponentProps, NarrativeEntry } from \"../../types\";\nimport { theme } from \"../../theme\";\nimport { extractSubflowNarrative } from \"../../utils/narrativeSync\";\nimport { toVisualizationSnapshots, subflowResultToSnapshots } from \"../../adapters/fromRuntimeSnapshot\";\nimport { ResultPanel } from \"../ResultPanel\";\nimport { GanttTimeline } from \"../GanttTimeline\";\nimport { TimeTravelControls } from \"../TimeTravelControls\";\nimport { MemoryPanel } from \"../MemoryPanel\";\nimport { NarrativePanel } from \"../NarrativePanel\";\nimport { SubflowTree } from \"../FlowchartView/SubflowTree\";\nimport { SubflowBreadcrumb } from \"../FlowchartView/SubflowBreadcrumb\";\nimport { TracedFlow } from \"../FlowchartView/TracedFlow\";\n\n/**\n * Minimal subflow-walking spec shape. Used INTERNALLY by drill-down\n * resolution (which navigates `subflowStructure` to find a child chart\n * inside the parent's serialized structure). No longer used for chart\n * rendering — that happens via `traceGraph` + `<TracedFlow>` exclusively.\n *\n * Kept as a local type so the file no longer depends on any legacy\n * spec-walk module.\n */\nexport interface SpecNode {\n name: string;\n id?: string;\n description?: string;\n children?: SpecNode[];\n next?: SpecNode;\n isSubflowRoot?: boolean;\n subflowId?: string;\n subflowName?: string;\n subflowStructure?: SpecNode;\n}\nimport { InspectorPanel } from \"../InspectorPanel/InspectorPanel\";\nimport { InsightPanel } from \"../InsightPanel/InsightPanel\";\nimport { CompactTimeline } from \"../CompactTimeline/CompactTimeline\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Tab ID — \"result\", \"memory\", \"narrative\", or any custom recorder view ID. */\nexport type ShellTab = string;\n\n\ninterface SubflowLevel {\n subflowId: string;\n label: string;\n spec: SpecNode;\n snapshots: StageSnapshot[];\n}\n\ninterface DrillDownEntry extends SubflowLevel {\n parentSnapshotIdx: number;\n}\n\nexport interface PanelLabels {\n /** Left panel pill label (subflow tree). Default: \"Topology\" */\n topology?: string;\n /** Right panel pill label (memory/narrative). Default: \"Details\" */\n details?: string;\n /** Bottom panel pill label (timeline). Default: \"Timeline\" */\n timeline?: string;\n}\n\n/** Which panels start expanded. Default: `{ details: true }` (flowchart + memory). */\nexport interface DefaultExpanded {\n topology?: boolean;\n details?: boolean;\n timeline?: boolean;\n}\n\n/**\n * Raw runtime snapshot from FlowChartExecutor.getSnapshot().\n * When provided, ExplainableShell converts it internally — zero boilerplate.\n */\nexport interface RuntimeSnapshotInput {\n sharedState: Record<string, unknown>;\n executionTree: unknown;\n commitLog: unknown[];\n subflowResults?: Record<string, unknown>;\n /** Recorder snapshots from toSnapshot() — auto-generates detail tabs. */\n recorders?: Array<{\n id: string;\n name: string;\n description?: string;\n preferredOperation?: 'translate' | 'accumulate' | 'aggregate';\n data: unknown;\n }>;\n}\n\n/**\n * A recorder view that appears as a tab in the details panel.\n * Each recorder provides its own per-stage rendering.\n * Memory and Narrative are built-in defaults — add more via this prop.\n */\nexport interface RecorderView {\n /** Unique key for this view tab */\n id: string;\n /** Display label on the tab */\n name: string;\n /** Short description shown as tooltip and header for auto-detected views.\n * e.g., \"Per-step timing and I/O counts (KeyedRecorder)\" */\n description?: string;\n /**\n * Render function — receives the current snapshot index and all snapshots.\n * Return a React node to display in the details panel.\n */\n render: (props: { snapshots: StageSnapshot[]; selectedIndex: number }) => React.ReactNode;\n}\n\nexport interface ExplainableShellProps extends BaseComponentProps {\n /**\n * Pre-converted visualization snapshots. Use when you've already called\n * toVisualizationSnapshots() yourself.\n */\n snapshots?: StageSnapshot[];\n /**\n * Raw runtime snapshot from executor.getSnapshot(). The shell converts it\n * internally via toVisualizationSnapshots(). When provided, `snapshots`\n * and `resultData` are derived automatically. Pair with\n * `narrativeEntries` for rich per-stage narrative.\n *\n * Usage: `<ExplainableShell runtimeSnapshot={executor.getSnapshot()} narrativeEntries={executor.getNarrativeEntries()} spec={spec} />`\n */\n runtimeSnapshot?: RuntimeSnapshotInput | null;\n spec?: SpecNode | null;\n /**\n * Build-time graph captured live via `createTraceStructureRecorder`.\n * REQUIRED for chart rendering (v6+) — the legacy `spec` →\n * legacy spec-walk post-walk path was removed in favor of this\n * recorder-driven graph.\n *\n * Pair with `runtimeOverlay` for the full time-travel trace UI.\n * When `traceGraph` is set but `runtimeOverlay` is absent, the\n * chart renders without runtime coloring (build-time-only view).\n *\n * The `spec` prop, when also provided, is used INTERNALLY for\n * subflow drill-down resolution (navigating `subflowStructure` to\n * find a child chart inside the parent's serialized structure) —\n * NOT for rendering.\n */\n traceGraph?: import(\"../FlowchartView/traceStructureRecorder\").TraceGraph | null;\n /**\n * Runtime overlay captured live via `createTraceRuntimeOverlay`.\n * Pair with `traceGraph` to drive `<TracedFlow>` for the full\n * time-travel trace UI.\n */\n runtimeOverlay?: import(\"../FlowchartView/createTraceRuntimeOverlay\").RuntimeOverlay | null;\n title?: string;\n resultData?: Record<string, unknown> | null;\n logs?: string[];\n /** Structured narrative entries from `executor.getNarrativeEntries()`.\n * This is the only narrative input — the flat-string form was\n * removed; call `.map(e => e.text)` if you need it. */\n narrativeEntries?: NarrativeEntry[];\n tabs?: ShellTab[];\n defaultTab?: ShellTab;\n hideConsole?: boolean;\n /** Hide specific detail tabs (e.g., ['result', 'memory']). */\n hideTabs?: string[];\n /** Customize the labels on collapsible panel pills */\n panelLabels?: PanelLabels;\n /** Which panels start expanded. Default: `{ details: true }` */\n defaultExpanded?: DefaultExpanded;\n /**\n * Recorder views — each becomes a tab in the details panel.\n * Default: Memory + Narrative. Pass additional recorder views\n * to show tokens, cost, tools, permissions, or custom data.\n *\n * Usage:\n * recorderViews={[\n * { id: 'tokens', name: 'Tokens', render: ({ selectedIndex }) => <div>...</div> },\n * ]}\n */\n recorderViews?: RecorderView[];\n /**\n * Custom flowchart renderer. When omitted, ExplainableShell renders\n * via `<TracedFlow graph={traceGraph} overlay={runtimeOverlay} />` —\n * the recorder-driven path. Override to plug a custom chart UI; the\n * `spec` parameter is forwarded only for backward-compatible\n * signatures (it's the same SpecNode used for drill-down) and may\n * be `null` once consumers stop threading it in.\n */\n renderFlowchart?: (props: {\n spec: SpecNode | null;\n snapshots: StageSnapshot[];\n selectedIndex: number;\n onNodeClick?: (indexOrId: number | string) => void;\n showStageId?: boolean;\n }) => React.ReactNode;\n /**\n * When true, render each node's stable `stageId` as a small monospace\n * caption beneath the label in the default flowchart renderer.\n * Teaching aid: it reveals the key recorders use\n * (`runtimeStageId = [subflowPath/]stageId#executionIndex`) so a\n * consumer can map any recorder's per-stage data back to a node.\n * Default false.\n */\n showStageId?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Line + Pill — collapsed state is just a line with a pill centered on it\n// ---------------------------------------------------------------------------\n\n/** Horizontal line with centered pill (for top/bottom edges) */\nconst HLinePill = memo(function HLinePill({\n label,\n detail,\n expanded,\n onClick,\n}: {\n label: string;\n detail?: string;\n expanded: boolean;\n onClick: () => void;\n}) {\n return (\n <div style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 0,\n padding: \"0\",\n }}>\n <div style={{ flex: 1, height: 1, background: theme.border }} />\n <button\n onClick={onClick}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 5,\n padding: \"3px 12px\",\n margin: \"4px 0\",\n fontSize: 10,\n fontWeight: 600,\n fontFamily: \"inherit\",\n color: theme.textMuted,\n background: theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n cursor: \"pointer\",\n whiteSpace: \"nowrap\",\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n transition: \"color 0.15s ease\",\n }}\n >\n <span style={{ fontSize: 7 }}>{expanded ? \"▼\" : \"▶\"}</span>\n {label}\n {detail && <span style={{ fontWeight: 400, opacity: 0.5, fontSize: 9 }}>{detail}</span>}\n </button>\n <div style={{ flex: 1, height: 1, background: theme.border }} />\n </div>\n );\n});\n\n/** Vertical line with centered pill (for left/right edges).\n * `side` controls arrow direction:\n * - \"right\": expanded=▶ collapsed=◀ (panel is on right, collapses right)\n * - \"left\": expanded=◀ collapsed=▶ (panel is on left, collapses left)\n */\nconst VLinePill = memo(function VLinePill({\n label,\n expanded,\n side = \"right\",\n onClick,\n}: {\n label: string;\n expanded: boolean;\n side?: \"left\" | \"right\";\n onClick: () => void;\n}) {\n const arrow = side === \"right\"\n ? (expanded ? \"▶\" : \"◀\")\n : (expanded ? \"◀\" : \"▶\");\n return (\n <div style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: 0,\n padding: \"0\",\n }}>\n <div style={{ flex: 1, width: 1, background: theme.border }} />\n <button\n onClick={onClick}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"10px 4px\",\n margin: \"0 3px\",\n fontSize: 10,\n fontWeight: 600,\n fontFamily: \"inherit\",\n color: theme.textMuted,\n background: theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n cursor: \"pointer\",\n whiteSpace: \"nowrap\",\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n writingMode: \"vertical-lr\",\n transition: \"color 0.15s ease\",\n }}\n >\n <span style={{ fontSize: 7, writingMode: \"horizontal-tb\" }}>{arrow}</span>\n {label}\n </button>\n <div style={{ flex: 1, width: 1, background: theme.border }} />\n </div>\n );\n});\n\n// ---------------------------------------------------------------------------\n// KeyedRecorderView — Time-travel aware renderer for auto-detected recorders\n// ---------------------------------------------------------------------------\n\n/**\n * Detects if data has a keyed-recorder shape: an object property whose values\n * are objects with at least one numeric field. Returns { steps, keyType }.\n * keyType: 'runtimeStageId' (keys contain '#') or 'stageName' (plain names).\n */\nfunction detectKeyedSteps(data: unknown): { steps: Record<string, Record<string, unknown>>; keyType: \"runtimeStageId\" | \"stageName\" } | null {\n if (!data || typeof data !== \"object\") return null;\n const obj = data as Record<string, unknown>;\n for (const val of Object.values(obj)) {\n if (val && typeof val === \"object\" && !Array.isArray(val)) {\n const entries = Object.entries(val as Record<string, unknown>);\n if (entries.length === 0) continue;\n // Check: values must be objects with at least one numeric field\n const allObjectsWithNumbers = entries.every(([, v]) => {\n if (!v || typeof v !== \"object\" || Array.isArray(v)) return false;\n return Object.values(v as Record<string, unknown>).some((f) => typeof f === \"number\");\n });\n if (allObjectsWithNumbers) {\n const keyType = entries.some(([k]) => k.includes(\"#\")) ? \"runtimeStageId\" : \"stageName\";\n return { steps: val as Record<string, Record<string, unknown>>, keyType };\n }\n }\n }\n return null;\n}\n\n/** Extract render hints from recorder data: numericField name + grandTotal. */\nfunction extractRenderHints(data: unknown): { numericField: string; grandTotal: number } | null {\n if (!data || typeof data !== \"object\") return null;\n const obj = data as Record<string, unknown>;\n if (typeof obj.numericField === \"string\" && typeof obj.grandTotal === \"number\") {\n return { numericField: obj.numericField, grandTotal: obj.grandTotal };\n }\n return null;\n}\n\nfunction KeyedRecorderView({\n data,\n description,\n preferredOperation = \"accumulate\",\n snapshots,\n selectedIndex,\n}: {\n data: unknown;\n description?: string;\n preferredOperation?: \"translate\" | \"accumulate\" | \"aggregate\";\n snapshots: StageSnapshot[];\n selectedIndex: number;\n}) {\n const [showAggregate, setShowAggregate] = useState(false);\n\n const detected = useMemo(() => detectKeyedSteps(data), [data]);\n\n // Visible keys up to slider position — match by runtimeStageId or stageName\n const visibleKeys = useMemo(() => {\n const keys = new Set<string>();\n for (let i = 0; i <= selectedIndex && i < snapshots.length; i++) {\n const snap = snapshots[i];\n if (detected?.keyType === \"runtimeStageId\") {\n if (snap.runtimeStageId) keys.add(snap.runtimeStageId);\n } else {\n // Match by stageName or stageLabel\n if (snap.stageName) keys.add(snap.stageName);\n if (snap.stageLabel) keys.add(snap.stageLabel);\n }\n }\n return keys;\n }, [snapshots, selectedIndex, detected?.keyType]);\n\n const isAtEnd = selectedIndex >= snapshots.length - 1;\n\n if (!detected) {\n // Fallback: raw JSON for non-keyed data\n return (\n <div style={{ padding: 12, fontFamily: theme.fontMono, fontSize: 11, whiteSpace: \"pre-wrap\", overflow: \"auto\", height: \"100%\" }}>\n {typeof data === \"string\" ? data : JSON.stringify(data, null, 2)}\n </div>\n );\n }\n\n const steps = detected.steps;\n const hints = extractRenderHints(data);\n const numFieldKey = hints?.numericField ?? \"\";\n\n // Progressive entries (accumulate)\n const allKeys = Object.keys(steps);\n const visibleEntries = allKeys.filter((k) => visibleKeys.has(k));\n\n // Running total — computed from visible entries using the declared numeric field\n let runningTotal = 0;\n if (numFieldKey) {\n for (const k of visibleEntries) {\n runningTotal += (steps[k][numFieldKey] as number) ?? 0;\n }\n }\n\n // Grand total — provided by the recorder, not recomputed\n const grandTotal = hints?.grandTotal ?? 0;\n\n return (\n <div style={{ overflow: \"auto\", height: \"100%\", display: \"flex\", flexDirection: \"column\" }}>\n {description && (\n <div style={{ padding: \"6px 12px\", fontSize: 11, color: theme.textMuted, fontStyle: \"italic\", borderBottom: `1px solid ${theme.border}`, flexShrink: 0 }}>\n {description}\n </div>\n )}\n\n <div style={{ padding: 12, flex: 1, overflow: \"auto\" }}>\n {/* ── Primary: depends on preferredOperation ── */}\n\n {preferredOperation === \"aggregate\" ? (\n /* AGGREGATE: collect silently during scrub, button at end to reveal total */\n <>\n {isAtEnd ? (\n <div style={{ marginBottom: 16 }}>\n {!showAggregate ? (\n <button\n onClick={() => setShowAggregate(true)}\n style={{\n background: theme.primary, color: \"#fff\", border: \"none\", borderRadius: 8,\n padding: \"12px 20px\", fontSize: 13, fontWeight: 600, cursor: \"pointer\",\n fontFamily: \"inherit\", width: \"100%\",\n }}\n >\n Aggregate — Show Grand Total\n </button>\n ) : (\n <div style={{ padding: \"14px 16px\", background: `color-mix(in srgb, ${theme.success} 12%, transparent)`, borderRadius: 8, border: `1px solid ${theme.success}44` }}>\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", marginBottom: 6, fontWeight: 600 }}>\n Aggregate — grand total\n </div>\n {numFieldKey && (\n <div style={{ fontSize: 26, fontWeight: 700, color: theme.success }}>\n {grandTotal < 1 ? grandTotal.toFixed(3) : grandTotal.toFixed(1)}\n <span style={{ fontSize: 11, color: theme.textMuted, fontWeight: 400, marginLeft: 8 }}>{numFieldKey} · {allKeys.length} steps</span>\n </div>\n )}\n </div>\n )}\n </div>\n ) : (\n <div style={{ padding: \"10px 14px\", background: `color-mix(in srgb, ${theme.textMuted} 6%, transparent)`, borderRadius: 6, marginBottom: 16, border: `1px dashed ${theme.border}` }}>\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", fontWeight: 600 }}>\n Collecting data...\n </div>\n <div style={{ fontSize: 11, color: theme.textMuted, marginTop: 4 }}>\n {visibleEntries.length} of {allKeys.length} steps collected. Scrub to end to aggregate.\n </div>\n </div>\n )}\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", marginBottom: 6, fontWeight: 600 }}>\n Per-step detail\n </div>\n </>\n ) : preferredOperation === \"accumulate\" ? (\n /* ACCUMULATE: running total grows with slider — IS the total at end, no button */\n <>\n {numFieldKey && visibleEntries.length > 0 && (\n <div style={{ padding: \"10px 14px\", background: `color-mix(in srgb, ${theme.primary} 8%, transparent)`, borderRadius: 6, marginBottom: 16 }}>\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", marginBottom: 4, fontWeight: 600 }}>\n Accumulate — running total up to this step\n </div>\n <span style={{ fontWeight: 700, fontSize: 18, color: theme.primary }}>\n {runningTotal < 1 ? runningTotal.toFixed(3) : runningTotal.toFixed(1)}\n </span>\n <span style={{ color: theme.textMuted, marginLeft: 8, fontSize: 10 }}>\n {numFieldKey} · {visibleEntries.length} of {allKeys.length} steps\n </span>\n </div>\n )}\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", marginBottom: 6, fontWeight: 600 }}>\n Per-step detail\n </div>\n </>\n ) : (\n /* TRANSLATE: per-step entries prominent, no totals */\n <div style={{ fontSize: 10, color: theme.textMuted, textTransform: \"uppercase\", letterSpacing: \"0.08em\", marginBottom: 6, fontWeight: 600 }}>\n Translate — per-step detail\n </div>\n )}\n\n {/* ── Per-step entries (always shown) ── */}\n {visibleEntries.map((key) => {\n const entry = steps[key];\n const label = (entry.stageName as string) ?? key;\n const numVal = numFieldKey ? (entry[numFieldKey] as number) : undefined;\n return (\n <div key={key} style={{ display: \"flex\", alignItems: \"center\", padding: \"4px 0\", fontSize: 12, fontFamily: theme.fontMono, borderBottom: `1px solid ${theme.border}22` }}>\n <span style={{ color: theme.textMuted, width: 140, flexShrink: 0, fontSize: 10 }}>{key}</span>\n <span style={{ fontWeight: 600, flex: 1 }}>{label}</span>\n {numVal !== undefined && (\n <span style={{ color: theme.primary, fontWeight: 700, marginLeft: 8 }}>\n {numVal < 1 ? numVal.toFixed(3) : numVal.toFixed(1)}\n </span>\n )}\n </div>\n );\n })}\n\n {visibleEntries.length === 0 && (\n <div style={{ color: theme.textMuted, fontSize: 11, fontStyle: \"italic\", padding: \"8px 0\" }}>\n Scrub the slider to reveal entries...\n </div>\n )}\n\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// DetailsContent — Recorder-driven tab switcher (Memory + Narrative are defaults)\n// ---------------------------------------------------------------------------\n\nconst DetailsContent = memo(function DetailsContent({\n snapshots,\n selectedIndex,\n narrativeEntries,\n size,\n fillHeight,\n extraViews,\n}: {\n snapshots: StageSnapshot[];\n selectedIndex: number;\n narrativeEntries?: NarrativeEntry[];\n size: \"compact\" | \"default\" | \"detailed\";\n fillHeight?: boolean;\n extraViews?: RecorderView[];\n}) {\n // Built-in views (always available)\n const builtInViews: RecorderView[] = [\n {\n id: \"memory\",\n name: \"Memory\",\n render: ({ snapshots: snaps, selectedIndex: idx }) => (\n <MemoryPanel snapshots={snaps} selectedIndex={idx} size={size} style={fillHeight ? { height: \"100%\" } : undefined} />\n ),\n },\n {\n id: \"narrative\",\n name: \"Narrative\",\n render: ({ snapshots: snaps, selectedIndex: idx }) => (\n <NarrativePanel snapshots={snaps} selectedIndex={idx} narrativeEntries={narrativeEntries} size={size} style={fillHeight ? { height: \"100%\" } : undefined} />\n ),\n },\n ];\n\n const allViews = [...builtInViews, ...(extraViews ?? [])];\n const [activeViewId, setActiveViewId] = useState(allViews[0]?.id ?? \"memory\");\n\n // Reset tab when available views change (e.g., recorder toggled on/off)\n const viewIds = allViews.map((v) => v.id).join(\",\");\n useEffect(() => {\n if (!allViews.find((v) => v.id === activeViewId)) {\n setActiveViewId(allViews[0]?.id ?? \"memory\");\n }\n }, [viewIds]); // eslint-disable-line react-hooks/exhaustive-deps\n const activeView = allViews.find((v) => v.id === activeViewId) ?? allViews[0];\n\n return (\n <div style={{ flex: 1, display: \"flex\", flexDirection: \"column\", overflow: \"hidden\" }}>\n {/* Tab switcher — one per recorder view */}\n <div style={{ display: \"flex\", borderBottom: `1px solid ${theme.border}`, flexShrink: 0, overflowX: \"auto\" }}>\n {allViews.map((view) => {\n const active = view.id === activeViewId;\n return (\n <button\n key={view.id}\n onClick={() => setActiveViewId(view.id)}\n style={{\n flex: allViews.length <= 3 ? 1 : undefined,\n padding: \"6px 8px\", fontSize: 11,\n fontWeight: active ? 600 : 400,\n color: active ? theme.primary : theme.textMuted,\n background: active ? `color-mix(in srgb, ${theme.primary} 8%, transparent)` : \"transparent\",\n border: \"none\",\n borderBottom: active ? `2px solid ${theme.primary}` : \"2px solid transparent\",\n cursor: \"pointer\", textTransform: \"uppercase\", letterSpacing: \"0.06em\", fontFamily: \"inherit\",\n whiteSpace: \"nowrap\",\n }}\n >\n {view.name}\n </button>\n );\n })}\n </div>\n <div style={{ flex: 1, overflow: \"auto\" }}>\n {activeView?.render({ snapshots, selectedIndex })}\n </div>\n </div>\n );\n});\n\n// ---------------------------------------------------------------------------\n// Subflow resolution helpers\n// ---------------------------------------------------------------------------\n\nfunction resolveSubflowLevel(\n parentSpec: SpecNode,\n parentSnapshots: StageSnapshot[],\n subflowNodeName: string,\n narrativeEntries?: NarrativeEntry[],\n): SubflowLevel | null {\n const specNode = findSubflowSpecNode(parentSpec, subflowNodeName);\n if (!specNode?.subflowStructure) return null;\n const parentSnap = parentSnapshots.find(\n (s) => s.stageName === subflowNodeName || s.stageLabel === subflowNodeName\n );\n if (!parentSnap?.subflowResult) return null;\n // Extract subflow narrative: prefer subflowId (structured), fall back to display name (text scan)\n const sfId = specNode.subflowId ?? subflowNodeName;\n const sfDisplayName = specNode.subflowName ?? specNode.name;\n const sfNarrative = narrativeEntries\n ? extractSubflowNarrative(narrativeEntries, sfId, sfDisplayName)\n : undefined;\n const sfSnapshots = subflowResultToSnapshots(parentSnap.subflowResult, sfNarrative);\n if (sfSnapshots.length === 0) return null;\n return {\n subflowId: specNode.subflowId ?? subflowNodeName,\n label: specNode.subflowName ?? specNode.name,\n spec: specNode.subflowStructure,\n snapshots: sfSnapshots,\n };\n}\n\nfunction findSubflowSpecNode(node: SpecNode, name: string): SpecNode | null {\n if ((node.name === name || node.id === name) && node.isSubflowRoot) return node;\n if (node.children) { for (const child of node.children) { const f = findSubflowSpecNode(child, name); if (f) return f; } }\n if (node.next) return findSubflowSpecNode(node.next, name);\n return null;\n}\n\nfunction hasSubflowNodes(node: SpecNode): boolean {\n if (!node) return false;\n if (node.isSubflowRoot) return true;\n if (node.children?.some((c) => c && hasSubflowNodes(c))) return true;\n if (node.next && hasSubflowNodes(node.next)) return true;\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Lightweight data trace — builds causal frames from commitLog without\n// importing footprintjs/trace. Uses the same backward-walk algorithm.\n// ---------------------------------------------------------------------------\n\ninterface CommitEntry {\n stage: string;\n stageId: string;\n runtimeStageId: string;\n trace: Array<{ path: string }>;\n}\n\nfunction buildDataTrace(\n commitLog: unknown[],\n targetRuntimeStageId: string,\n maxDepth = 10,\n): Array<{ runtimeStageId: string; stageId: string; stageName: string; keysWritten: string[]; linkedBy: string; depth: number }> {\n const log = commitLog as CommitEntry[];\n if (!log?.length) return [];\n\n const idxMap = new Map<string, number>();\n for (let i = 0; i < log.length; i++) idxMap.set(log[i].runtimeStageId, i);\n\n const startIdx = idxMap.get(targetRuntimeStageId);\n if (startIdx === undefined) return [];\n\n const startCommit = log[startIdx];\n const frames: Array<{ runtimeStageId: string; stageId: string; stageName: string; keysWritten: string[]; linkedBy: string; depth: number }> = [];\n const visited = new Set<string>();\n\n // BFS backward: for each commit, find what keys existed before it that it might have read\n // Simplified: trace the write chain backward — each commit's written keys link to whoever wrote the keys it implicitly depends on\n let current = startCommit;\n let currentIdx = startIdx;\n let depth = 0;\n\n while (current && depth <= maxDepth) {\n if (visited.has(current.runtimeStageId)) break;\n visited.add(current.runtimeStageId);\n\n frames.push({\n runtimeStageId: current.runtimeStageId,\n stageId: current.stageId,\n stageName: current.stage,\n keysWritten: current.trace.map((t) => t.path),\n linkedBy: depth === 0 ? \"\" : current.trace[0]?.path ?? \"\",\n depth,\n });\n\n // Find the previous commit (the one right before this one)\n if (currentIdx > 0) {\n currentIdx--;\n current = log[currentIdx];\n depth++;\n } else {\n break;\n }\n }\n\n return frames;\n}\n\n// ---------------------------------------------------------------------------\n// RightPanel — two-mode panel: Insights vs What Happened\n// ---------------------------------------------------------------------------\n\ntype RightPanelMode = \"insights\" | \"what\";\n\nconst RightPanel = memo(function RightPanel({\n mode,\n onModeChange,\n snapshots,\n selectedIndex,\n runtimeSnapshot,\n spec,\n activeTab,\n allTabs,\n activeNarrativeEntries,\n recorderViews,\n autoRecorderViews,\n size,\n onNavigateToStage,\n}: {\n mode: RightPanelMode;\n onModeChange: (mode: RightPanelMode) => void;\n snapshots: StageSnapshot[];\n selectedIndex: number;\n runtimeSnapshot?: RuntimeSnapshotInput | null;\n spec?: SpecNode | null;\n activeTab: string;\n allTabs: Array<{ id: string; name: string; description?: string }>;\n activeNarrativeEntries?: NarrativeEntry[];\n recorderViews?: RecorderView[];\n autoRecorderViews: Array<{ id: string; name: string; description?: string; preferredOperation?: string; data: unknown }>;\n size: \"compact\" | \"default\" | \"detailed\";\n onNavigateToStage: (id: string) => void;\n}) {\n return (\n <>\n {/* Mode toggle */}\n <div style={{\n display: \"flex\",\n borderBottom: `1px solid ${theme.border}`,\n flexShrink: 0,\n background: theme.bgSecondary,\n }}>\n {([\"insights\", \"what\"] as const).map((m) => (\n <button\n key={m}\n onClick={() => onModeChange(m)}\n style={{\n flex: 1,\n padding: \"7px 12px\",\n fontSize: 11,\n fontWeight: mode === m ? 700 : 500,\n textTransform: \"uppercase\",\n letterSpacing: \"0.06em\",\n color: mode === m ? theme.primary : theme.textMuted,\n background: \"transparent\",\n border: \"none\",\n borderBottom: mode === m ? `2px solid ${theme.primary}` : \"2px solid transparent\",\n cursor: \"pointer\",\n fontFamily: \"inherit\",\n }}\n >\n {m === \"insights\" ? \"Insights\" : \"Inspector\"}\n </button>\n ))}\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, overflow: \"hidden\" }}>\n {mode === \"insights\" ? (\n <InsightPanel\n mode=\"tabs\"\n expandedId={activeTab}\n insights={allTabs.filter((t) => t.id !== \"result\" && t.id !== \"memory\").map((tab) => ({\n id: tab.id,\n name: insightName(tab.name),\n render: () => {\n if (tab.id === \"narrative\") return <NarrativePanel snapshots={snapshots} selectedIndex={selectedIndex} narrativeEntries={activeNarrativeEntries} runtimeSnapshot={runtimeSnapshot} spec={spec} size={size} style={{ height: \"100%\" }} />;\n const customView = recorderViews?.find((v) => v.id === tab.id);\n if (customView?.render) return customView.render({ snapshots, selectedIndex });\n const autoView = autoRecorderViews.find((v) => v.id === tab.id);\n if (autoView) return <KeyedRecorderView data={autoView.data} description={autoView.description} preferredOperation={autoView.preferredOperation as any} snapshots={snapshots} selectedIndex={selectedIndex} />;\n return null;\n },\n }))}\n />\n ) : (\n <InspectorPanel\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n dataTraceFrames={runtimeSnapshot?.commitLog ? buildDataTrace(runtimeSnapshot.commitLog, snapshots[selectedIndex]?.runtimeStageId ?? '') : []}\n selectedStageId={snapshots[selectedIndex]?.runtimeStageId}\n onNavigateToStage={onNavigateToStage}\n />\n )}\n </div>\n </>\n );\n});\n\n/** Map internal recorder names to user-facing Insight names. */\nfunction insightName(name: string): string {\n const map: Record<string, string> = {\n \"Narrative\": \"Story\",\n \"Memory\": \"State\",\n \"Metrics\": \"Performance\",\n \"Quality\": \"Quality\",\n \"Cost\": \"Cost\",\n };\n return map[name] ?? name;\n}\n\nexport function ExplainableShell({\n snapshots: snapshotsProp,\n runtimeSnapshot,\n spec,\n title,\n resultData: resultDataProp,\n logs = [],\n narrativeEntries,\n tabs = [\"result\", \"explainable\"],\n defaultTab,\n hideConsole = false,\n hideTabs: hideTabsProp,\n panelLabels,\n defaultExpanded,\n recorderViews,\n renderFlowchart,\n showStageId = false,\n traceGraph,\n runtimeOverlay,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: ExplainableShellProps) {\n // Convert runtimeSnapshot → visualization snapshots (zero-boilerplate mode)\n const derivedFromRuntime = useMemo(() => {\n if (!runtimeSnapshot) return null;\n try {\n const snaps = toVisualizationSnapshots(runtimeSnapshot as any, narrativeEntries as any);\n return { snapshots: snaps, resultData: runtimeSnapshot.sharedState };\n } catch {\n return null;\n }\n }, [runtimeSnapshot, narrativeEntries]);\n\n // Use derived data when runtimeSnapshot is provided, otherwise use explicit props\n const snapshots = snapshotsProp ?? derivedFromRuntime?.snapshots ?? [];\n const resultData = resultDataProp ?? derivedFromRuntime?.resultData ?? null;\n\n // Flowchart renderer selection (v6+ — recorder-driven only):\n // - explicit `renderFlowchart` always wins (consumer override)\n // - `traceGraph` → render via `<TracedFlow>` (event-driven graph\n // + optional runtime overlay, no spec-tree post-walk)\n //\n // Consumers MUST pass `traceGraph` for chart visualization. The\n // legacy `spec={...}` → post-walk fallback was removed when the\n // recorder gained convergence-edge expansion (post-fork `next`\n // fires N edges, one per branch child) — the recorder graph is now\n // the single source of truth.\n const tracedFlowRenderer = useMemo(() => {\n if (!traceGraph) return undefined;\n return ({ selectedIndex, snapshots, onNodeClick }: {\n spec: SpecNode | null; snapshots: StageSnapshot[]; selectedIndex: number;\n onNodeClick?: (indexOrId: number | string) => void;\n showStageId?: boolean;\n }) => {\n // The shell's `selectedIndex` indexes into `snapshots[]` (which\n // may be filtered to a drill-down subset). The overlay's\n // `executionOrder` is the FULL execution timeline (all stages\n // including subflow internals). When the two arrays have\n // different lengths, passing selectedIndex straight through\n // misaligns the chart's active highlight.\n //\n // Translate: take the runtimeStageId at snapshots[selectedIndex]\n // and find the matching position in overlay.executionOrder.\n // Fall back to selectedIndex when no overlay or no match\n // (charts without subflows have aligned indexes anyway).\n const activeRsid = snapshots[selectedIndex]?.runtimeStageId;\n let overlayIdx = selectedIndex;\n if (activeRsid && runtimeOverlay) {\n const i = runtimeOverlay.executionOrder.findIndex(\n (s) => s.runtimeStageId === activeRsid,\n );\n if (i >= 0) overlayIdx = i;\n }\n return (\n <TracedFlow\n graph={traceGraph}\n overlay={runtimeOverlay ?? undefined}\n scrubIndex={overlayIdx}\n onNodeClick={(stageId) => onNodeClick?.(stageId)}\n onSubflowChange={(mountId) => {\n // Forward chart's drill state to the shell's drill-down\n // stack so memory/narrative/timeline panels follow the\n // chart into/out of subflows. We route through the same\n // onNodeClick channel — it already triggers drill-down\n // for subflow mount nodes via the shell's handleNodeClick\n // → handleDrillDown path.\n //\n // The `mountId === null` case (popping back to top) is\n // intentionally NOT auto-triggered here: the shell's\n // breadcrumb-back button is the right user gesture for\n // navigating UP from a subflow. Auto-popping on scrub\n // would surprise users who manually drilled in.\n if (mountId !== null) onNodeClick?.(mountId);\n }}\n />\n );\n };\n }, [traceGraph, runtimeOverlay]);\n const effectiveRenderFlowchart = renderFlowchart ?? tracedFlowRenderer;\n const leftLabel = panelLabels?.topology ?? \"Topology\";\n const rightLabel = panelLabels?.details ?? \"Details\";\n const bottomLabel = panelLabels?.timeline ?? \"Timeline\";\n\n // Responsive: detect narrow container + notify children of size changes\n const shellRef = useRef<HTMLDivElement>(null);\n const [isNarrow, setIsNarrow] = useState(false);\n const [isMedium, setIsMedium] = useState(false);\n useEffect(() => {\n const el = shellRef.current;\n if (!el) return;\n const ro = new ResizeObserver(([entry]) => {\n const w = entry.contentRect.width;\n setIsNarrow(w < 640);\n setIsMedium(w >= 640 && w < 960);\n // Notify ReactFlow (and other layout-sensitive children) that our container resized\n window.dispatchEvent(new Event(\"resize\"));\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n // Auto-detect recorder views from runtimeSnapshot.recorders\n const autoRecorderViews = useMemo(() => {\n const recorders = (runtimeSnapshot as any)?.recorders as Array<{ id: string; name: string; description?: string; preferredOperation?: string; data: unknown }> | undefined;\n if (!recorders?.length) return [];\n // Don't auto-generate for IDs that have explicit recorderViews\n const explicitIds = new Set((recorderViews ?? []).map((v) => v.id));\n return recorders\n .filter((r) => !explicitIds.has(r.id))\n .map((r) => ({ id: r.id, name: r.name, description: r.description, preferredOperation: r.preferredOperation, data: r.data }));\n }, [runtimeSnapshot, recorderViews]);\n\n // Build tab list: Result + Memory (always), Narrative (when data exists),\n // explicit recorder views, auto-detected recorder views\n const hasNarrative = !!narrativeEntries?.length;\n const allTabs = useMemo(() => {\n const tabs: Array<{ id: string; name: string; description?: string }> = [\n { id: \"result\", name: \"Result\", description: \"Final output and console logs\" },\n { id: \"memory\", name: \"Memory\", description: \"Accumulator — progressive shared state at each stage\" },\n ];\n if (hasNarrative) {\n tabs.push({ id: \"narrative\", name: \"Narrative\", description: \"Translator (SequenceRecorder) — interleaved flow + data narrative per execution step\" });\n }\n for (const v of recorderViews ?? []) {\n tabs.push({ id: v.id, name: v.name, description: v.description });\n }\n for (const v of autoRecorderViews) {\n tabs.push({ id: v.id, name: v.name, description: v.description });\n }\n // Filter hidden tabs\n const hideSet = new Set(hideTabsProp ?? []);\n return hideSet.size > 0 ? tabs.filter((t) => !hideSet.has(t.id)) : tabs;\n }, [hasNarrative, recorderViews, autoRecorderViews, hideTabsProp]);\n\n const validTabIds = new Set(allTabs.map((t) => t.id));\n const resolvedDefault = defaultTab && validTabIds.has(defaultTab) ? defaultTab : allTabs[0]?.id ?? \"result\";\n const [activeTab, setActiveTab] = useState<string>(resolvedDefault);\n const [snapshotIdx, setSnapshotIdx] = useState(0);\n const [drillDownStack, setDrillDownStack] = useState<DrillDownEntry[]>([]);\n const [rightExpanded, setRightExpanded] = useState(defaultExpanded?.details ?? true);\n const [rightPanelMode, setRightPanelMode] = useState<\"insights\" | \"what\">(\"insights\");\n const [leftExpanded, setLeftExpanded] = useState(defaultExpanded?.topology ?? false);\n const [timelineExpanded, setTimelineExpanded] = useState(defaultExpanded?.timeline ?? false);\n\n // Auto-collapse all panels when switching to narrow (mobile)\n useEffect(() => {\n if (isNarrow) {\n setLeftExpanded(false);\n setRightExpanded(false);\n setTimelineExpanded(false);\n }\n }, [isNarrow]);\n\n // Notify ReactFlow (and any ResizeObserver-based children) when panels toggle\n const triggerReflow = useCallback(() => {\n // Fire twice: once immediately for fast response, once after CSS transition ends\n requestAnimationFrame(() => window.dispatchEvent(new Event(\"resize\")));\n setTimeout(() => window.dispatchEvent(new Event(\"resize\")), 320);\n }, []);\n const toggleLeft = useCallback((v: boolean) => { setLeftExpanded(v); triggerReflow(); }, [triggerReflow]);\n const toggleRight = useCallback((v: boolean) => { setRightExpanded(v); triggerReflow(); }, [triggerReflow]);\n const toggleTimeline = useCallback(() => { setTimelineExpanded((p) => !p); triggerReflow(); }, [triggerReflow]);\n\n const isInSubflow = drillDownStack.length > 0;\n\n const currentLevel = useMemo(() => {\n if (drillDownStack.length > 0) {\n const top = drillDownStack[drillDownStack.length - 1];\n return { spec: top.spec, snapshots: top.snapshots };\n }\n return { spec: spec ?? null, snapshots };\n }, [drillDownStack, spec, snapshots]);\n\n const activeSnapshots = currentLevel.snapshots;\n const activeSpec = currentLevel.spec;\n const safeIdx = activeSnapshots.length > 0\n ? Math.max(0, Math.min(snapshotIdx, activeSnapshots.length - 1))\n : 0;\n\n const activeNarrativeEntries = isInSubflow ? undefined : narrativeEntries;\n\n const breadcrumbs = useMemo(() => {\n const root = { label: title || \"Flowchart\", spec: spec!, description: spec?.description };\n return [root, ...drillDownStack.map((e) => ({ label: e.label, spec: e.spec, description: undefined as string | undefined }))];\n }, [spec, title, drillDownStack]);\n\n // Recorder-driven: derive subflow presence from the build-time graph.\n // Falls back to the legacy spec walk only when traceGraph is absent\n // (e.g., a consumer still threading raw spec). When both are absent,\n // the tree sidebar is hidden.\n const showTreeSidebar = useMemo(() => {\n if (traceGraph?.nodes?.length) {\n return traceGraph.nodes.some((n) => n.data?.isSubflow === true);\n }\n return !!spec && hasSubflowNodes(spec);\n }, [traceGraph, spec]);\n\n const rootOverlay = useMemo(() => {\n if (isInSubflow || !snapshots.length) return { activeStage: undefined, doneStages: undefined };\n const doneStages = new Set(snapshots.slice(0, safeIdx).map((s) => s.stageLabel));\n const activeStage = snapshots[safeIdx]?.stageLabel ?? null;\n return { activeStage, doneStages };\n }, [isInSubflow, snapshots, safeIdx]);\n\n // ── Handlers ──\n const handleTabChange = useCallback((tab: ShellTab) => {\n setActiveTab(tab);\n setDrillDownStack([]);\n }, []);\n\n const handleSnapshotChange = useCallback((idx: number | string) => {\n if (typeof idx === \"number\") setSnapshotIdx(idx);\n }, []);\n\n const handleDrillDown = useCallback(\n (nodeName: string) => {\n if (!activeSpec) return;\n const entry = resolveSubflowLevel(activeSpec, activeSnapshots, nodeName, narrativeEntries);\n if (entry) {\n setDrillDownStack((prev) => [...prev, { ...entry, parentSnapshotIdx: snapshotIdx }]);\n setSnapshotIdx(0);\n }\n },\n [activeSpec, activeSnapshots, narrativeEntries, snapshotIdx]\n );\n\n const handleBreadcrumbNavigate = useCallback((level: number) => {\n setDrillDownStack((prev) => {\n const popped = level === 0 ? prev[0] : prev[level];\n if (popped) setSnapshotIdx(popped.parentSnapshotIdx);\n return level === 0 ? [] : prev.slice(0, level);\n });\n }, []);\n\n const handleNodeClick = useCallback(\n (indexOrId: number | string) => {\n if (typeof indexOrId === \"number\") { setSnapshotIdx(indexOrId); return; }\n if (activeSpec) {\n const sfNode = findSubflowSpecNode(activeSpec, indexOrId);\n if (sfNode?.subflowStructure) { handleDrillDown(indexOrId); return; }\n }\n const idx = activeSnapshots.findIndex((s) => s.stageLabel === indexOrId);\n if (idx >= 0) setSnapshotIdx(idx);\n },\n [activeSpec, activeSnapshots, handleDrillDown]\n );\n\n const handleTreeNodeSelect = useCallback(\n (name: string, isSubflow: boolean) => {\n if (isSubflow && spec) {\n setDrillDownStack([]);\n const entry = resolveSubflowLevel(spec, snapshots, name, narrativeEntries);\n if (entry) { setDrillDownStack([{ ...entry, parentSnapshotIdx: snapshotIdx }]); setSnapshotIdx(0); }\n } else {\n setDrillDownStack([]);\n const idx = snapshots.findIndex((s) => s.stageLabel === name);\n if (idx >= 0) setSnapshotIdx(idx);\n }\n },\n [spec, snapshots, narrativeEntries, snapshotIdx]\n );\n\n // Map tab id → label for rendering\n const tabLabels = new Map(allTabs.map((t) => [t.id, t.name]));\n\n // ── Unstyled mode ──\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"explainable-shell\">\n <div data-fp=\"shell-tabs\">\n {allTabs.map((tab) => (\n <button key={tab.id} data-fp=\"shell-tab\" data-active={tab.id === activeTab} onClick={() => handleTabChange(tab.id)}>{tab.name}</button>\n ))}\n </div>\n <div data-fp=\"shell-content\" data-tab={activeTab}>\n {activeTab === \"result\" && <ResultPanel data={resultData ?? null} logs={logs} hideConsole={hideConsole} unstyled />}\n {(activeTab === \"explainable\" || activeTab === \"ai-compatible\") && (\n <>\n <TimeTravelControls snapshots={activeSnapshots} selectedIndex={safeIdx} onIndexChange={handleSnapshotChange} unstyled />\n {isInSubflow && <SubflowBreadcrumb breadcrumbs={breadcrumbs} onNavigate={handleBreadcrumbNavigate} />}\n {activeSpec && effectiveRenderFlowchart?.({ spec: activeSpec, snapshots: activeSnapshots, selectedIndex: safeIdx, onNodeClick: handleNodeClick, showStageId })}\n <MemoryPanel snapshots={activeSnapshots} selectedIndex={safeIdx} unstyled />\n <NarrativePanel snapshots={activeSnapshots} selectedIndex={safeIdx} narrativeEntries={activeNarrativeEntries} unstyled />\n <GanttTimeline snapshots={activeSnapshots} selectedIndex={safeIdx} onSelect={handleSnapshotChange} unstyled />\n </>\n )}\n </div>\n </div>\n );\n }\n\n // ── Styled mode ──\n\n // Show topology when spec has subflows\n const showTopology = !!effectiveRenderFlowchart && !!activeSpec;\n\n // Render the active details tab content\n const detailsContent = useMemo(() => {\n if (activeTab === \"result\") {\n return <ResultPanel data={resultData ?? null} logs={logs} hideConsole={hideConsole} size={size} />;\n }\n if (activeTab === \"memory\") {\n return <MemoryPanel snapshots={activeSnapshots} selectedIndex={safeIdx} size={size} style={{ height: \"100%\" }} />;\n }\n if (activeTab === \"narrative\") {\n return <NarrativePanel snapshots={activeSnapshots} selectedIndex={safeIdx} narrativeEntries={activeNarrativeEntries} size={size} style={{ height: \"100%\" }} />;\n }\n const customView = recorderViews?.find((v) => v.id === activeTab);\n if (customView?.render) {\n return customView.render({ snapshots: activeSnapshots, selectedIndex: safeIdx });\n }\n // Auto-detected recorder view — time-travel aware for keyed recorders, JSON fallback\n const autoView = autoRecorderViews.find((v) => v.id === activeTab);\n if (autoView) {\n return (\n <KeyedRecorderView\n data={autoView.data}\n description={autoView.description}\n preferredOperation={autoView.preferredOperation as \"translate\" | \"accumulate\" | \"aggregate\" | undefined}\n snapshots={activeSnapshots}\n selectedIndex={safeIdx}\n />\n );\n }\n return null;\n }, [activeTab, resultData, logs, hideConsole, size, activeSnapshots, safeIdx, activeNarrativeEntries, recorderViews, autoRecorderViews]);\n\n // Details panel with internal tabs\n const detailsPanel = (\n <div style={{ display: \"flex\", flexDirection: \"column\", height: \"100%\", overflow: \"hidden\" }}>\n {/* Tab bar inside details panel */}\n <div style={{\n display: \"flex\",\n borderBottom: `1px solid ${theme.border}`,\n background: theme.bgSecondary,\n flexShrink: 0,\n overflowX: \"auto\",\n }}>\n {allTabs.map((tab) => {\n const active = tab.id === activeTab;\n return (\n <button\n key={tab.id}\n onClick={() => handleTabChange(tab.id as ShellTab)}\n title={tab.description}\n style={{\n padding: \"6px 14px\",\n fontSize: 11,\n fontWeight: active ? 700 : 500,\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n color: active ? theme.primary : theme.textMuted,\n background: \"transparent\",\n border: \"none\",\n borderBottom: active ? `2px solid ${theme.primary}` : \"2px solid transparent\",\n cursor: \"pointer\",\n fontFamily: \"inherit\",\n whiteSpace: \"nowrap\",\n }}\n >\n {tab.name}\n </button>\n );\n })}\n </div>\n {/* Tab content */}\n <div style={{ flex: 1, overflow: \"auto\" }}>\n {detailsContent}\n </div>\n </div>\n );\n\n return (\n <div\n ref={shellRef}\n className={className}\n style={{\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n background: theme.bgPrimary,\n color: theme.textPrimary,\n fontFamily: theme.fontSans,\n fontSize: 12,\n ...style,\n }}\n data-fp=\"explainable-shell\"\n >\n {/* Time-travel slider */}\n <TimeTravelControls\n snapshots={activeSnapshots}\n selectedIndex={safeIdx}\n onIndexChange={handleSnapshotChange}\n size={size}\n />\n\n {/* Breadcrumb */}\n {isInSubflow && (\n <SubflowBreadcrumb breadcrumbs={breadcrumbs} onNavigate={handleBreadcrumbNavigate} />\n )}\n\n {/* Content */}\n <div style={{ flex: 1, overflow: isNarrow ? \"auto\" : \"hidden\", display: \"flex\", flexDirection: \"column\" }}>\n {isNarrow ? (\n /* ── Mobile: stacked vertical ── */\n <>\n {/* Flowchart — only when topology is relevant */}\n {showTopology && (\n <div style={{ height: 350, flexShrink: 0, overflow: \"hidden\" }}>\n {effectiveRenderFlowchart!({\n spec: activeSpec!,\n snapshots: activeSnapshots,\n selectedIndex: safeIdx,\n onNodeClick: handleNodeClick,\n showStageId,\n })}\n </div>\n )}\n\n {/* Topology (subflow tree) — collapsible */}\n {showTreeSidebar && (\n <>\n <HLinePill label={leftLabel} expanded={leftExpanded} onClick={() => toggleLeft(!leftExpanded)} />\n {leftExpanded && (\n <div style={{ maxHeight: 180, overflow: \"auto\", flexShrink: 0 }}>\n <SubflowTree\n graph={traceGraph ?? { nodes: [], edges: [] }}\n activeStage={rootOverlay.activeStage}\n doneStages={rootOverlay.doneStages}\n onNodeSelect={handleTreeNodeSelect}\n />\n </div>\n )}\n </>\n )}\n\n {/* Details panel with tabs */}\n <HLinePill label={rightLabel} expanded={rightExpanded} onClick={() => toggleRight(!rightExpanded)} />\n {rightExpanded && (\n <div style={{ maxHeight: 350, flexShrink: 0, overflow: \"hidden\" }}>\n {detailsPanel}\n </div>\n )}\n\n {/* Timeline */}\n <HLinePill label={bottomLabel} detail={`${activeSnapshots.length} stages`} expanded={timelineExpanded} onClick={toggleTimeline} />\n {timelineExpanded && (\n <div style={{ flexShrink: 0, overflow: \"hidden\" }}>\n <GanttTimeline snapshots={activeSnapshots} selectedIndex={safeIdx} onSelect={handleSnapshotChange} size={size} />\n </div>\n )}\n </>\n ) : (\n /* ── Desktop: two-column — Flowchart | Right Panel ── */\n <>\n <div style={{ flex: 1, display: \"flex\", overflow: \"hidden\" }}>\n\n {/* SubflowTree sidebar (only when subflows exist) */}\n {showTreeSidebar && (\n leftExpanded ? (\n <div style={{ width: 180, flexShrink: 0, display: \"flex\", flexDirection: \"row\", overflow: \"hidden\" }}>\n <div style={{ flex: 1, overflow: \"auto\" }}>\n <SubflowTree\n graph={traceGraph ?? { nodes: [], edges: [] }}\n activeStage={rootOverlay.activeStage}\n doneStages={rootOverlay.doneStages}\n onNodeSelect={handleTreeNodeSelect}\n />\n </div>\n <VLinePill label=\"Topology\" expanded={true} side=\"left\" onClick={() => toggleLeft(false)} />\n </div>\n ) : (\n <VLinePill label=\"Topology\" expanded={false} side=\"left\" onClick={() => toggleLeft(true)} />\n )\n )}\n\n {/* Center: Flowchart — flex:1, shares horizontal space with\n the Details panel sibling when expanded. The chart's\n TracedFlow refits itself via ResizeObserver whenever\n this container's size changes (so opening/closing\n Details re-runs xyflow's fitView automatically). */}\n {showTopology ? (\n <div style={{ flex: 1, overflow: \"hidden\", minWidth: 0 }}>\n {effectiveRenderFlowchart!({\n spec: activeSpec!,\n snapshots: activeSnapshots,\n selectedIndex: safeIdx,\n onNodeClick: handleNodeClick,\n showStageId,\n })}\n </div>\n ) : (\n <div style={{ flex: 1 }} />\n )}\n\n {/* VLinePill divider between flowchart and right panel */}\n <VLinePill label=\"Details\" expanded={rightExpanded} onClick={() => toggleRight(!rightExpanded)} />\n\n {/* Right: Two-mode panel — Insights vs Inspector */}\n {rightExpanded && (\n <div style={{ width: \"42%\", minWidth: 320, maxWidth: 550, display: \"flex\", flexDirection: \"column\", overflow: \"hidden\" }}>\n <RightPanel\n mode={rightPanelMode}\n onModeChange={setRightPanelMode}\n snapshots={activeSnapshots}\n selectedIndex={safeIdx}\n runtimeSnapshot={runtimeSnapshot}\n spec={spec}\n activeTab={activeTab}\n allTabs={allTabs}\n activeNarrativeEntries={activeNarrativeEntries}\n recorderViews={recorderViews}\n autoRecorderViews={autoRecorderViews}\n size={size}\n onNavigateToStage={(id) => {\n const idx = activeSnapshots.findIndex((s) => s.runtimeStageId === id);\n if (idx >= 0) setSnapshotIdx(idx);\n }}\n />\n </div>\n )}\n </div>\n\n {/* Bottom: Compact Timeline */}\n <CompactTimeline\n snapshots={activeSnapshots}\n selectedIndex={safeIdx}\n defaultExpanded={timelineExpanded}\n />\n </>\n )}\n </div>\n </div>\n );\n}\n","/**\n * Narrative sync utilities — shared logic for mapping timeline position\n * to narrative entries. Used by NarrativePanel and available to consumers\n * building custom visualization shells.\n */\nimport type { StageSnapshot, NarrativeEntry } from \"../types\";\n\n// ── Entry Range Index ───────────────────────────────────────────────────────\n\n/**\n * Range index: runtimeStageId → half-open range [firstIdx, endIdx) in entries array.\n *\n * This is the same shape as `SequenceRecorder.getEntryRanges()` in footprintjs.\n * When you have recorder access, pass `recorder.getEntryRanges()` directly.\n * When you only have the flat array, use `buildEntryRangeIndex()` to build it.\n */\nexport type EntryRangeIndex = ReadonlyMap<string, { readonly firstIdx: number; readonly endIdx: number }>;\n\n/**\n * Build a range index from a flat entries array for O(1) per-step lookups.\n * Equivalent to `SequenceRecorder.getEntryRanges()` but works on detached arrays.\n *\n * Call once when narrativeEntries changes, then pass to `computeRevealedEntryCount`.\n *\n * @param entries — structured entries (from CombinedNarrativeRecorder.getEntries() or getNarrativeEntries())\n * @returns range index for fast slider sync\n */\nexport function buildEntryRangeIndex(entries: Pick<NarrativeEntry, \"runtimeStageId\">[]): EntryRangeIndex {\n const ranges = new Map<string, { firstIdx: number; endIdx: number }>();\n let lastId: string | undefined;\n\n for (let i = 0; i < entries.length; i++) {\n const id = entries[i].runtimeStageId;\n if (id) {\n const existing = ranges.get(id);\n if (!existing) {\n ranges.set(id, { firstIdx: i, endIdx: i + 1 });\n } else {\n existing.endIdx = i + 1;\n }\n lastId = id;\n } else if (lastId) {\n // Structural marker — extend preceding step's range\n ranges.get(lastId)!.endIdx = i + 1;\n }\n }\n\n return ranges;\n}\n\n// ── Revealed Entry Count ────────────────────────────────────────────────────\n\n/**\n * Compute how many narrative entries to reveal at a given slider position.\n *\n * **With range index (preferred):** O(selectedIndex) — one Map lookup per snapshot.\n * **Without index (convenience):** O(entries) forward scan.\n *\n * The range index can come from:\n * - `SequenceRecorder.getEntryRanges()` (when you have recorder access)\n * - `buildEntryRangeIndex(entries)` (when you only have the flat array)\n *\n * @param narrativeEntries — structured entries from CombinedNarrativeRecorder\n * @param snapshots — execution timeline (from adapter)\n * @param selectedIndex — current slider position (0-based)\n * @param rangeIndex — optional precomputed range index for O(1) lookups\n * @returns number of entries to reveal (0 to narrativeEntries.length)\n */\nexport function computeRevealedEntryCount(\n narrativeEntries: NarrativeEntry[],\n snapshots: Pick<StageSnapshot, \"runtimeStageId\">[],\n selectedIndex: number,\n rangeIndex?: EntryRangeIndex,\n): number {\n if (!narrativeEntries.length || snapshots.length === 0) return 0;\n\n if (rangeIndex) {\n // Fast path: O(selectedIndex) with Map lookups\n let maxEndIdx = 0;\n for (let si = 0; si <= selectedIndex && si < snapshots.length; si++) {\n const targetId = snapshots[si].runtimeStageId;\n if (!targetId) continue;\n const range = rangeIndex.get(targetId);\n if (range && range.endIdx > maxEndIdx) {\n maxEndIdx = range.endIdx;\n }\n }\n return maxEndIdx;\n }\n\n // Fallback: forward scan (no index provided)\n let entryIdx = 0;\n for (let si = 0; si <= selectedIndex && si < snapshots.length; si++) {\n const targetId = snapshots[si].runtimeStageId;\n if (!targetId) continue;\n\n let found = false;\n for (let j = entryIdx; j < narrativeEntries.length; j++) {\n if (narrativeEntries[j].runtimeStageId === targetId) {\n found = true;\n entryIdx = j;\n break;\n }\n }\n if (!found) continue;\n\n while (entryIdx < narrativeEntries.length) {\n const eId = narrativeEntries[entryIdx].runtimeStageId;\n if (eId && eId !== targetId) break;\n entryIdx++;\n }\n }\n return entryIdx;\n}\n\n// ── Subflow Extraction ──────────────────────────────────────────────────────\n\n/**\n * Extract narrative entries belonging to a specific subflow.\n *\n * Three-tier matching (most reliable first):\n * 1. `stageName` prefix match (e.g., entries with `stageName` starting with `\"sf-pay/\"`)\n * 2. `subflowId` field match\n * 3. `direction` field on subflow entry/exit markers (renderer-agnostic)\n *\n * @param entries — all narrative entries from the execution\n * @param subflowId — subflow identifier to extract\n * @param subflowName — optional display name for fallback matching\n * @returns entries belonging to the subflow\n */\nexport function extractSubflowNarrative(\n entries: NarrativeEntry[],\n subflowId: string,\n subflowName?: string,\n): NarrativeEntry[] {\n // Primary: filter by stageName prefix\n const prefix = subflowId + \"/\";\n const byPrefix = entries.filter((e) => e.stageName?.startsWith(prefix));\n if (byPrefix.length > 0) return byPrefix;\n\n // Fallback: structured subflowId field\n const byId = entries.filter((e) => e.subflowId === subflowId);\n if (byId.length > 0) return byId;\n\n // Last resort: use direction field on subflow entries (renderer-agnostic)\n const result: NarrativeEntry[] = [];\n const searchName = subflowName ?? subflowId;\n let inside = false;\n for (const entry of entries) {\n if (entry.type === \"subflow\" && entry.direction === \"entry\" && entry.stageName === searchName) { inside = true; continue; }\n if (inside && entry.type === \"subflow\" && entry.direction === \"exit\" && entry.stageName === searchName) break;\n if (inside) result.push(entry);\n }\n return result;\n}\n","import type { StageSnapshot, NarrativeEntry } from \"../types\";\n\n/**\n * Shape of FootPrint's RuntimeSnapshot (from FlowChartExecutor.getSnapshot()).\n * We define it here instead of importing to avoid a hard dependency on footprintjs.\n */\ninterface RuntimeStageSnapshot {\n id: string;\n /** `stageId#executionIndex` — the universal per-execution key. Joins this\n * tree node to its commit-log bundles for cumulative-memory replay. */\n runtimeStageId?: string;\n name?: string;\n isDecider?: boolean;\n isFork?: boolean;\n /** User-level writes made by this stage (pre-namespace keys → values). */\n stageWrites?: Record<string, unknown>;\n logs: Record<string, unknown>;\n errors: Record<string, unknown>;\n metrics: Record<string, unknown>;\n evals: Record<string, unknown>;\n flowMessages?: unknown[];\n description?: string;\n subflowId?: string;\n next?: RuntimeStageSnapshot;\n children?: RuntimeStageSnapshot[];\n}\n\ninterface RecorderSnapshot {\n id: string;\n name: string;\n data: unknown;\n}\n\ninterface RuntimeSnapshot {\n sharedState: Record<string, unknown>;\n executionTree: RuntimeStageSnapshot;\n commitLog: unknown[];\n /** Per-subflow execution results (keyed by subflowId). */\n subflowResults?: Record<string, unknown>;\n /** Snapshots from recorders that implement toSnapshot() (e.g. MetricRecorder). */\n recorders?: RecorderSnapshot[];\n}\n\n// NarrativeEntry: canonical definition lives in types.ts.\n// Re-export here for backward compatibility (index.ts re-exports as AdapterNarrativeEntry).\nexport type { NarrativeEntry } from '../types';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Cumulative-memory accumulation — commit-bundle replay + deep patch merge\n// ─────────────────────────────────────────────────────────────────────────────\n//\n// Why whole-key overwrite of `stageWrites` is NOT enough: footprintjs's\n// change-only commit semantics record a deep write (`scope.applicant.address\n// .zip = ...`) as a net-change PATCH (`{applicant: {address: {zip}}}`), and\n// `StageSnapshot.stageWrites` keeps only the LAST write per key — so a\n// set-then-deep-write stage surfaces only the patch and the per-stage memory\n// view dropped sibling fields (`applicant.name`) that the engine's\n// `sharedState` correctly holds.\n//\n// The faithful source is `RuntimeSnapshot.commitLog`: each `CommitBundle`\n// carries the stage's `overwrite` (full values for `set` paths), `updates`\n// (accumulated deltas for `merge` paths), and the ordered `trace`\n// (`[{path, verb}]`) — the same triple footprintjs's own `applySmartMerge`\n// replays onto live state. We mirror that replay onto the cumulative memory\n// view, keyed by `runtimeStageId` (tree node ↔ commit bundle join). When no\n// bundle is available (older snapshots, subflow drill-down histories with\n// empty runtimeStageIds), we fall back to `stageWrites` accumulation,\n// upgraded from whole-key overwrite to `mergeWritePatch` so patches no\n// longer erase siblings.\n\n/** Path delimiter used by footprintjs's commit `trace` entries\n * (`normalisePath` joins segments with U+001F UNIT SEPARATOR). */\nconst COMMIT_PATH_DELIM = \"\\u001F\";\n\n/** Keys that must never be assigned via bracket-write on a plain object —\n * `obj['__proto__'] = x` mutates the prototype, not an own property. */\nconst UNSAFE_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\n/** Duck-typed slice of footprintjs's `CommitBundle` the replay consumes. */\ninterface CommitBundleLike {\n runtimeStageId?: string;\n overwrite?: Record<string, unknown>;\n updates?: Record<string, unknown>;\n trace?: { path: string; verb: string }[];\n}\n\n/** `__writeSummary` / `__readSummary` marker objects (footprintjs's\n * `writeTracking: 'summary'` dial) are ATOMIC placeholders, not data —\n * the merge passes them through and never recurses into them. */\nfunction isSummaryMarker(value: unknown): boolean {\n return (\n value !== null &&\n typeof value === \"object\" &&\n ((value as Record<string, unknown>).__writeSummary === true ||\n (value as Record<string, unknown>).__readSummary === true)\n );\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/**\n * Deep-merges a net-change write PATCH into a base value for the\n * cumulative-memory VIEW — the visualization-side mirror of footprintjs's\n * `deepSmartMerge` (the `merge`-verb arm of `applySmartMerge`).\n *\n * Semantics:\n * - plain objects: object-spread per level — patch keys win, base\n * siblings survive (the gap this helper closes)\n * - **arrays: REPLACE, not union-merge.** Deliberate divergence from\n * footprintjs's `deepSmartMerge` (which unions non-empty arrays with\n * reference-equality dedup). A memory VIEW should show the array a\n * consumer would read at that moment: the dominant array-write path\n * (TypedScope copy-on-write push / `$batchArray`) commits as a `set`\n * of the full final array anyway, and union-replay of the rare\n * `merge`-verb array delta can fabricate element mixes (reference\n * dedup never dedupes deep-equal objects) that the display has no\n * way to reconcile. Replace is predictable and loses nothing the\n * patch didn't carry.\n * - summary markers (`__writeSummary`/`__readSummary`): atomic — a marker\n * patch replaces the key wholesale, and nothing merges INTO a marker\n * - primitives / null / type mismatches: patch wins\n *\n * Pure: never mutates `base` or `patch`; merged branches are fresh objects.\n */\nexport function mergeWritePatch(base: unknown, patch: unknown): unknown {\n if (isSummaryMarker(patch)) return patch;\n if (patch === null || typeof patch !== \"object\") return patch;\n if (Array.isArray(patch)) return patch; // arrays REPLACE (see JSDoc)\n if (isSummaryMarker(base) || !isPlainRecord(base)) {\n // Nothing mergeable underneath — take the patch (fresh copy so later\n // in-place view writes never reach the caller's object).\n base = {};\n }\n const out: Record<string, unknown> = { ...(base as Record<string, unknown>) };\n for (const [key, value] of Object.entries(patch)) {\n if (UNSAFE_KEYS.has(key)) continue;\n out[key] = mergeWritePatch(out[key], value);\n }\n return out;\n}\n\n/** Reads a delimited commit path out of a patch object. Undefined-safe. */\nfunction getPath(root: unknown, segs: string[]): unknown {\n let cur: unknown = root;\n for (const seg of segs) {\n if (!isPlainRecord(cur) && !Array.isArray(cur)) return undefined;\n cur = (cur as Record<string, unknown>)[seg];\n }\n return cur;\n}\n\n/**\n * Writes `value` at a delimited commit path, copy-on-write along the way:\n * every container on the path is cloned before mutation so sibling stage\n * snapshots (which share nested refs via the per-stage shallow copy) are\n * never retroactively edited.\n */\nfunction setPath(memory: Record<string, unknown>, segs: string[], value: unknown): void {\n if (segs.some((s) => UNSAFE_KEYS.has(s))) return;\n let obj: Record<string, unknown> = memory;\n for (let i = 0; i < segs.length - 1; i++) {\n const cur = obj[segs[i]!];\n const next: Record<string, unknown> = Array.isArray(cur)\n ? (cur.slice() as unknown as Record<string, unknown>)\n : isPlainRecord(cur) && !isSummaryMarker(cur)\n ? { ...cur }\n : {};\n obj[segs[i]!] = next;\n obj = next;\n }\n const last = segs[segs.length - 1]!;\n if (value === undefined) {\n delete obj[last];\n } else {\n obj[last] = value;\n }\n}\n\n/**\n * Replays one commit bundle onto the cumulative memory view — mirrors\n * footprintjs's `applySmartMerge` verb arms:\n * - `set` → overwrite with the full final value from `overwrite[path]`\n * (`undefined` = the historical delete-flattened-to-set —\n * removes the key)\n * - `merge` → `mergeWritePatch` the accumulated `updates[path]` delta in\n * - `append` → concat the recorded tail onto the current array; degrade\n * to a direct set when either side isn't an array (matches\n * upstream's redaction/corrupt-base behavior)\n * - `delete` → remove the key\n * Bundles without a `trace` (older engines) degrade to: apply every\n * `overwrite` key as a set, then deep-merge every `updates` key.\n */\nfunction applyCommitBundle(memory: Record<string, unknown>, bundle: CommitBundleLike): void {\n const trace = Array.isArray(bundle.trace) ? bundle.trace : undefined;\n if (trace) {\n for (const op of trace) {\n if (!op || typeof op.path !== \"string\") continue;\n const segs = op.path.split(COMMIT_PATH_DELIM);\n if (op.verb === \"merge\") {\n setPath(memory, segs, mergeWritePatch(getPath(memory, segs), getPath(bundle.updates, segs)));\n } else if (op.verb === \"append\") {\n const tail = getPath(bundle.overwrite, segs);\n const current = getPath(memory, segs);\n setPath(memory, segs, Array.isArray(current) && Array.isArray(tail) ? [...current, ...tail] : tail);\n } else if (op.verb === \"delete\") {\n setPath(memory, segs, undefined);\n } else {\n // 'set' (and unknown verbs — treat as the terminal overwrite)\n setPath(memory, segs, getPath(bundle.overwrite, segs));\n }\n }\n return;\n }\n if (isPlainRecord(bundle.overwrite)) {\n for (const [key, value] of Object.entries(bundle.overwrite)) setPath(memory, [key], value);\n }\n if (isPlainRecord(bundle.updates)) {\n for (const [key, value] of Object.entries(bundle.updates)) {\n setPath(memory, [key], mergeWritePatch(memory[key], value));\n }\n }\n}\n\n/**\n * Indexes commit bundles by `runtimeStageId`. A stage execution can emit\n * MORE than one bundle (e.g. a subflow mount commits the outputMapper\n * result, then an empty boundary bundle) — all are kept, in log order.\n * Entries without a non-empty `runtimeStageId` (subflow drill-down\n * histories) are skipped; those trees fall back to `stageWrites`.\n */\nfunction indexCommitLog(commitLog: unknown[] | undefined): Map<string, CommitBundleLike[]> {\n const index = new Map<string, CommitBundleLike[]>();\n if (!Array.isArray(commitLog)) return index;\n for (const entry of commitLog) {\n if (!isPlainRecord(entry)) continue;\n const bundle = entry as CommitBundleLike;\n if (typeof bundle.runtimeStageId !== \"string\" || bundle.runtimeStageId.length === 0) continue;\n if (!isPlainRecord(bundle.overwrite) && !isPlainRecord(bundle.updates) && !Array.isArray(bundle.trace)) {\n continue;\n }\n const list = index.get(bundle.runtimeStageId);\n if (list) list.push(bundle);\n else index.set(bundle.runtimeStageId, [bundle]);\n }\n return index;\n}\n\n/**\n * Converts a FootPrint RuntimeSnapshot into a flat array of StageSnapshots\n * suitable for visualization components.\n *\n * The `narrativeEntries` parameter (from `executor.getNarrativeEntries()`)\n * distributes the library's rich combined narrative per-stage.\n * When narrative is not enabled, stages get \"Narrative not available\" —\n * this adapter reflects what the library produces, nothing more.\n *\n * Usage:\n * ```ts\n * const executor = new FlowChartExecutor(chart);\n * await executor.run();\n * const snapshots = toVisualizationSnapshots(\n * executor.getSnapshot(),\n * executor.getNarrativeEntries(),\n * );\n * ```\n */\nexport function toVisualizationSnapshots(\n runtime: RuntimeSnapshot,\n narrativeEntries?: NarrativeEntry[],\n): StageSnapshot[] {\n const stageNarrativeMap = narrativeEntries?.length\n ? buildStageNarrativeMap(narrativeEntries)\n : new Map<string, string[]>();\n\n // Extract per-stage timings from MetricRecorder if present in snapshot.recorders.\n const stageTimings = extractStageTimings(runtime.recorders);\n\n // Commit-bundle index for faithful cumulative-memory replay (see the\n // accumulation rationale above). Empty map when the snapshot carries no\n // usable commitLog — stages then fall back to stageWrites accumulation.\n const commitIndex = indexCommitLog(runtime.commitLog);\n\n const snapshots: StageSnapshot[] = [];\n flattenTree(runtime.executionTree, snapshots, runtime.sharedState, 0, runtime.subflowResults, {}, stageNarrativeMap, stageTimings, commitIndex);\n return snapshots;\n}\n\n/**\n * Extracts per-stage duration data from recorder snapshots.\n *\n * Post-KeyedRecorder MetricRecorder serializes as\n * { name: 'Metrics', data: { steps: { [runtimeStageId]: { stageName, duration, ... } } } }\n *\n * Older versions emitted `data.stages[stageName].totalDuration` directly;\n * we still accept that shape for back-compat when loading old snapshots.\n *\n * Stages that ran multiple times (e.g. CallLLM inside a loop) have one\n * entry per invocation keyed by runtimeStageId — sum their durations by\n * stageName so the GanttTimeline shows cumulative wall time per stage.\n */\nfunction extractStageTimings(recorders?: RecorderSnapshot[]): Map<string, number> {\n const timings = new Map<string, number>();\n if (!recorders) return timings;\n for (const rec of recorders) {\n if (rec.name !== 'Metrics' || !rec.data || typeof rec.data !== 'object') continue;\n const data = rec.data as {\n steps?: Record<string, { stageName?: string; duration?: number }>;\n stages?: Record<string, { totalDuration?: number }>;\n };\n // New shape: data.steps[runtimeStageId] = { stageName, duration, ... }\n if (data.steps) {\n for (const step of Object.values(data.steps)) {\n const name = step?.stageName;\n const d = step?.duration;\n if (!name || typeof d !== 'number' || d <= 0) continue;\n timings.set(name, Math.round((timings.get(name) ?? 0) + d));\n }\n }\n // Legacy shape: data.stages[stageName].totalDuration\n if (data.stages) {\n for (const [stageName, metrics] of Object.entries(data.stages)) {\n if (typeof metrics.totalDuration === 'number' && metrics.totalDuration > 0) {\n timings.set(stageName, Math.round(metrics.totalDuration));\n }\n }\n }\n }\n return timings;\n}\n\n/**\n * Groups narrative entries by stage name, preserving non-stage entries\n * (conditions, forks) attached to the preceding stage.\n */\nfunction buildStageNarrativeMap(entries: NarrativeEntry[]): Map<string, string[]> {\n const map = new Map<string, string[]>();\n let currentStageName: string | undefined;\n\n for (const entry of entries) {\n if (entry.stageName) {\n currentStageName = entry.stageName;\n }\n\n if (currentStageName) {\n if (!map.has(currentStageName)) {\n map.set(currentStageName, []);\n }\n const indent = ' '.repeat(entry.depth);\n map.get(currentStageName)!.push(`${indent}${entry.text}`);\n }\n }\n\n\n return map;\n}\n\nfunction flattenTree(\n node: RuntimeStageSnapshot,\n out: StageSnapshot[],\n sharedState: Record<string, unknown>,\n accumulatedMs: number = 0,\n subflowResults?: Record<string, unknown>,\n cumulativeMemory: Record<string, unknown> = {},\n stageNarrativeMap: Map<string, string[]> = new Map(),\n stageTimings: Map<string, number> = new Map(),\n commitIndex: Map<string, CommitBundleLike[]> = new Map(),\n): number {\n // Prefer MetricRecorder timing (real wall-clock), then scope.$metric('durationMs'), then 0.\n const stageName = node.name ?? node.id;\n const durationMs =\n (stageName ? stageTimings.get(stageName) : undefined) ??\n (typeof node.metrics?.durationMs === \"number\" ? node.metrics.durationMs : 0);\n\n const startMs = accumulatedMs;\n // Use id for matching (stable, matches spec node ids).\n // name may carry display prefixes like \"[service-name] STAGE\".\n const stageId = node.id || node.name || 'unknown';\n const displayName = node.name || node.id || 'unknown';\n\n // Narrative comes from the library. When not available (e.g. subflow internals\n // where the root recorder only captures enter/exit markers), build a basic\n // narrative from the stage name, description, and data operations.\n // Try id first, then name — narrative entries use node.name (may be prefixed)\n // while snapshot uses node.id (stable). Both need to match for subflows.\n const stageLines = stageNarrativeMap.get(stageId) ?? stageNarrativeMap.get(displayName);\n let narrative: string;\n if (stageLines) {\n narrative = stageLines.join('\\n');\n } else {\n const parts: string[] = [`${displayName} executed.`];\n if (node.description) parts.push(node.description);\n if (node.stageWrites) {\n const keys = Object.keys(node.stageWrites);\n if (keys.length > 0) parts.push(`Wrote: ${keys.join(', ')}`);\n }\n narrative = parts.join('\\n');\n }\n\n // Build cumulative memory. Preferred source: this execution's commit\n // bundles (replayed with engine verb semantics — set/merge/append/delete —\n // so deep-write patches keep sibling fields, exactly like the engine's\n // sharedState). Fallback: stageWrites, deep-merged via mergeWritePatch\n // (whole-key overwrite would erase siblings on net-change patches).\n const memory = { ...cumulativeMemory };\n const bundles = node.runtimeStageId ? commitIndex.get(node.runtimeStageId) : undefined;\n if (bundles && bundles.length > 0) {\n for (const bundle of bundles) applyCommitBundle(memory, bundle);\n } else if (node.stageWrites) {\n for (const [key, value] of Object.entries(node.stageWrites)) {\n if (UNSAFE_KEYS.has(key)) continue;\n if (value === undefined) {\n delete memory[key];\n } else {\n memory[key] = mergeWritePatch(memory[key], value);\n }\n }\n }\n\n // Prefer the per-iteration result keyed by this node's UNIQUE runtimeStageId, falling back to\n // the subflow PATH key. A LOOPING subflow re-enters with the same `subflowId`, so the path key\n // holds only the LAST iteration — keying by `runtimeStageId` gives THIS iteration's drill-down\n // (footprintjs dual-keys subflowResults; see docs/design/subflow-commit-visibility.md). The\n // fallback keeps non-looping subflows and older snapshots working unchanged.\n const sfResult =\n (node.runtimeStageId ? subflowResults?.[node.runtimeStageId] : undefined) ??\n subflowResults?.[node.subflowId ?? stageId];\n\n out.push({\n stageName: displayName,\n stageLabel: stageId,\n runtimeStageId: node.runtimeStageId ?? undefined,\n memory,\n narrative,\n startMs,\n durationMs,\n status: \"done\",\n ...(node.description ? { description: node.description } : undefined),\n ...(node.subflowId ? { subflowId: node.subflowId } : undefined),\n ...(sfResult ? { subflowResult: sfResult } : undefined),\n });\n\n let nextMs = startMs + durationMs;\n\n // Handle parallel children (fork)\n if (node.children && node.children.length > 0) {\n let maxChildEnd = nextMs;\n for (const child of node.children) {\n const childEnd = flattenTree(child, out, sharedState, nextMs, subflowResults, memory, stageNarrativeMap, stageTimings, commitIndex);\n maxChildEnd = Math.max(maxChildEnd, childEnd);\n }\n nextMs = maxChildEnd;\n }\n\n // Handle linear continuation\n if (node.next) {\n nextMs = flattenTree(node.next, out, sharedState, nextMs, subflowResults, memory, stageNarrativeMap, stageTimings, commitIndex);\n }\n\n return nextMs;\n}\n\n/**\n * Converts a footprintjs SubflowResult (stored on StageSnapshot.subflowResult)\n * into visualization snapshots for drill-down views.\n *\n * SubflowResult shape (from footprintjs):\n * { subflowId, subflowName, treeContext: { globalContext, stageContexts, history }, parentStageId }\n *\n * Returns empty array if the input is not a valid SubflowResult.\n */\nexport function subflowResultToSnapshots(\n subflowResult: unknown,\n narrativeEntries?: NarrativeEntry[],\n): StageSnapshot[] {\n if (!subflowResult || typeof subflowResult !== 'object') return [];\n const sf = subflowResult as {\n subflowId?: string;\n treeContext?: {\n globalContext?: Record<string, unknown>;\n stageContexts?: unknown;\n history?: unknown[];\n };\n };\n if (!sf.treeContext?.stageContexts) return [];\n\n const runtime: RuntimeSnapshot = {\n sharedState: sf.treeContext.globalContext ?? {},\n executionTree: sf.treeContext.stageContexts as RuntimeStageSnapshot,\n commitLog: sf.treeContext.history ?? [],\n };\n\n const snapshots = toVisualizationSnapshots(runtime, narrativeEntries);\n\n // Strip subflow prefix from stage names so they match the spec node names.\n // Runtime names are prefixed (e.g., \"analyze/SeedScope\") but spec nodes\n // use unprefixed names (e.g., \"SeedScope\").\n const prefix = sf.subflowId ? `${sf.subflowId}/` : '';\n if (prefix) {\n for (const snap of snapshots) {\n if (snap.stageName.startsWith(prefix)) {\n snap.stageName = snap.stageName.slice(prefix.length);\n }\n if (snap.stageLabel.startsWith(prefix)) {\n snap.stageLabel = snap.stageLabel.slice(prefix.length);\n }\n }\n }\n\n return snapshots;\n}\n\n/**\n * Creates StageSnapshots from simple arrays (when you don't have a RuntimeSnapshot).\n * Useful for testing or custom data sources.\n */\nexport function createSnapshots(\n stages: Array<{\n name: string;\n label?: string;\n memory?: Record<string, unknown>;\n narrative?: string;\n durationMs?: number;\n description?: string;\n subflowId?: string;\n }>\n): StageSnapshot[] {\n let accMs = 0;\n return stages.map((s) => {\n const duration = s.durationMs ?? 1;\n const snap: StageSnapshot = {\n stageName: s.name,\n stageLabel: s.label ?? s.name,\n memory: s.memory ?? {},\n narrative: s.narrative ?? `${s.label ?? s.name} completed.`,\n startMs: accMs,\n durationMs: duration,\n status: \"done\",\n ...(s.description ? { description: s.description } : undefined),\n ...(s.subflowId ? { subflowId: s.subflowId } : undefined),\n };\n accMs += duration;\n return snap;\n });\n}\n","/**\n * MemoryPanel — Commit-history based view of pipeline state.\n *\n * Shows accumulated memory at the selected snapshot + what changed.\n * Data source: Scope Recorder (transactional state from SharedMemory).\n *\n * This is a thin composition of MemoryInspector + ScopeDiff — no logic\n * of its own, just correct data derivation from snapshots + index.\n */\nimport type { StageSnapshot, BaseComponentProps } from \"../../types\";\nimport { theme } from \"../../theme\";\nimport { MemoryInspector } from \"../MemoryInspector\";\nimport { ScopeDiff } from \"../ScopeDiff\";\n\nexport interface MemoryPanelProps extends BaseComponentProps {\n snapshots: StageSnapshot[];\n selectedIndex: number;\n}\n\nexport function MemoryPanel({\n snapshots,\n selectedIndex,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: MemoryPanelProps) {\n const prevMemory = selectedIndex > 0\n ? snapshots[selectedIndex - 1]?.memory ?? null\n : null;\n const currMemory = snapshots[selectedIndex]?.memory ?? {};\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"memory-panel\">\n <MemoryInspector snapshots={snapshots} selectedIndex={selectedIndex} unstyled />\n <ScopeDiff previous={prevMemory} current={currMemory} unstyled />\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n overflow: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n ...style,\n }}\n data-fp=\"memory-panel\"\n >\n <MemoryInspector snapshots={snapshots} selectedIndex={selectedIndex} size={size} />\n <div style={{ borderTop: `1px solid ${theme.border}` }}>\n <ScopeDiff previous={prevMemory} current={currMemory} hideUnchanged size={size} />\n </div>\n </div>\n );\n}\n","/**\n * NarrativePanel — Recorder-based view of pipeline execution.\n *\n * Renders the execution narrative with progressive reveal synced to\n * snapshot index. Consumes structured NarrativeEntries (from\n * CombinedNarrativeRecorder) — the primary data source. Falls back to\n * per-stage `snapshot.narrative` fields (built by the runtime adapter)\n * when no entries are supplied.\n *\n * Data source: FlowRecorder (fires AFTER stage execution)\n */\nimport { useMemo, useState, useCallback } from \"react\";\nimport type { StageSnapshot, NarrativeEntry, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\nimport { buildEntryRangeIndex, computeRevealedEntryCount } from \"../../utils/narrativeSync\";\nimport { StoryNarrative } from \"../StoryNarrative\";\nimport { NarrativeTrace } from \"../NarrativeTrace\";\n\n/**\n * JSON.stringify with a circular-ref sentinel and a size cap — snapshots\n * can contain cycles (runtime stages reference each other) and can grow\n * multi-megabyte. A strict JSON.stringify would throw; the clipboard cap\n * stops \"Copy for LLM\" from dumping 20MB of tool history into a paste.\n */\nfunction safeJsonStringify(value: unknown): string {\n const seen = new WeakSet<object>();\n const MAX_CHARS = 500_000;\n try {\n let text = JSON.stringify(\n value,\n (_key, v) => {\n if (typeof v === \"object\" && v !== null) {\n if (seen.has(v as object)) return \"[Circular]\";\n seen.add(v as object);\n }\n return v;\n },\n 2,\n );\n if (text && text.length > MAX_CHARS) {\n text = text.slice(0, MAX_CHARS) + `\\n... [truncated at ${MAX_CHARS} chars]`;\n }\n return text ?? \"undefined\";\n } catch (err) {\n return `[stringify error: ${err instanceof Error ? err.message : String(err)}]`;\n }\n}\n\nexport interface NarrativePanelProps extends BaseComponentProps {\n snapshots: StageSnapshot[];\n selectedIndex: number;\n /** Structured narrative entries (primary source — richer rendering).\n * When absent, falls back to per-stage `snapshot.narrative` lines. */\n narrativeEntries?: NarrativeEntry[];\n /**\n * Full runtime snapshot from the runner (executor.getSnapshot() /\n * agent.getSnapshot()). When present, \"Copy for LLM\" includes the\n * commit log, final shared state, and recorder snapshots alongside\n * the rendered narrative. Without it, only the rendered text is\n * copied — useful but misses the tool-call payloads and state\n * transitions needed to debug why a run failed.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n runtimeSnapshot?: any;\n /**\n * Flowchart spec from the runner (executor.getSpec() / agent.getSpec()).\n * When present, \"Copy for LLM\" appends the topology so the LLM can\n * see which node was running at each step — not just the narrative.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n spec?: any;\n}\n\nexport function NarrativePanel({\n snapshots,\n selectedIndex,\n narrativeEntries,\n runtimeSnapshot,\n spec,\n size = \"default\",\n unstyled = false,\n className,\n style,\n}: NarrativePanelProps) {\n const fs = fontSize[size];\n const pad = padding[size];\n\n // Build plain narrative lines from per-stage snapshot.narrative.\n // Used as fallback when narrativeEntries is empty, and for the\n // progressive-reveal text view in the legacy code path.\n const narrative = useMemo<string[]>(() => {\n const lines: string[] = [];\n for (const snap of snapshots) {\n const stageLines = (snap.narrative ?? \"\").split(\"\\n\").filter(Boolean);\n lines.push(...stageLines);\n }\n return lines;\n }, [snapshots]);\n\n // Progressive reveal for plain narrative\n const revealedCount = useMemo(() => {\n if (snapshots.length === 0 || narrative.length === 0) return narrative.length;\n const stageBoundaries: number[] = [];\n for (let i = 0; i < narrative.length; i++) {\n const trimmed = narrative[i].trimStart();\n if (trimmed.startsWith(\"Stage \") && !trimmed.match(/^Stage\\s+\\d+:\\s*Step\\s/)) {\n stageBoundaries.push(i);\n }\n }\n if (stageBoundaries.length === 0) {\n const ratio = (selectedIndex + 1) / snapshots.length;\n return Math.max(1, Math.ceil(narrative.length * ratio));\n }\n const groupsToShow = Math.min(selectedIndex + 1, stageBoundaries.length);\n const endIdx = groupsToShow < stageBoundaries.length\n ? stageBoundaries[groupsToShow]\n : narrative.length;\n return Math.max(1, endIdx);\n }, [snapshots.length, selectedIndex, narrative]);\n\n // Precompute range index once when entries change — O(n) build, then O(1) per slider tick.\n // Same shape as SequenceRecorder.getEntryRanges() in footprintjs.\n const rangeIndex = useMemo(\n () => narrativeEntries?.length ? buildEntryRangeIndex(narrativeEntries) : undefined,\n [narrativeEntries],\n );\n\n // Exact sync via runtimeStageId — O(selectedIndex) with precomputed index.\n const revealedEntryCount = useMemo(\n () => narrativeEntries?.length ? computeRevealedEntryCount(narrativeEntries, snapshots, selectedIndex, rangeIndex) : 0,\n [narrativeEntries, snapshots, selectedIndex, rangeIndex],\n );\n\n const hasStructured = narrativeEntries && narrativeEntries.length > 0;\n\n // ── Copy as LLM-ready text ─────────────────────────────────────────────\n const [copied, setCopied] = useState(false);\n\n const buildLLMNarrative = useCallback(() => {\n if (!narrativeEntries?.length) {\n return narrative.join(\"\\n\");\n }\n\n // ── Partition entries: root vs subflow internals ─────────────────\n // Root includes: stages, subflow entry/exit markers, decisions, loops, breaks\n // Subflow internals: entries with subflowId that aren't entry/exit markers\n const root: NarrativeEntry[] = [];\n const subflows = new Map<string, NarrativeEntry[]>();\n const subflowNames = new Map<string, string>(); // sfId → display name\n\n for (const entry of narrativeEntries) {\n const sfId = entry.subflowId;\n if (!sfId) {\n root.push(entry);\n } else {\n // Subflow ENTRY markers go in root (show WHEN the subflow ran).\n // Exit markers are noise — the next stage implies completion.\n if (entry.type === \"subflow\") {\n const isExit = entry.direction === 'exit';\n if (!isExit) {\n root.push(entry);\n }\n // Track name for the subflow details header\n if (entry.stageName && !isExit) {\n subflowNames.set(sfId, entry.stageName);\n }\n } else {\n // Internal subflow entries go in the subflow detail section\n if (!subflows.has(sfId)) subflows.set(sfId, []);\n subflows.get(sfId)!.push(entry);\n }\n }\n }\n\n // ── Render a list of entries as numbered text ────────────────────\n // Uses only entry.text (already rendered by the NarrativeRenderer).\n // No type prefix — the renderer output IS the narrative.\n const renderEntries = (entries: NarrativeEntry[], opts?: { inSubflow?: string }): string => {\n let counter = 0;\n const lines: string[] = [];\n\n for (const e of entries) {\n // Skip subflow entry/exit in subflow details (redundant — we're already in the section)\n if (opts?.inSubflow && e.type === \"subflow\") continue;\n\n let text = e.text;\n\n // Strip subflow path prefix from stage names inside subflow details.\n // e.g., \"[sf-system-prompt/ResolvePrompt]\" → \"[ResolvePrompt]\"\n // The section header already identifies the subflow.\n // Uses literal string replacement (not regex) to avoid injection from special characters.\n if (opts?.inSubflow) {\n const prefix = `[${opts.inSubflow}/`;\n const idx = text.indexOf(prefix);\n if (idx !== -1) {\n text = text.slice(0, idx) + \"[\" + text.slice(idx + prefix.length);\n }\n }\n\n const isHeading = e.type === \"stage\" || e.type === \"subflow\" || e.type === \"fork\" || e.type === \"selector\";\n\n if (isHeading) {\n counter++;\n // For subflow markers in root, append the subflow ID for drill-down\n const sfId = (e as { subflowId?: string }).subflowId;\n const idSuffix = e.type === \"subflow\" && sfId ? ` [→ ${sfId}]` : \"\";\n lines.push(`${counter}. ${text}${idSuffix}`);\n } else {\n // Sub-items (steps, conditions, loops, breaks, errors) — indented\n lines.push(` ${text}`);\n }\n }\n\n return lines.join(\"\\n\");\n };\n\n // ── Assemble the full LLM-ready document ────────────────────────\n const sections: string[] = [];\n sections.push(\"## Execution Narrative\\n\");\n sections.push(renderEntries(root));\n\n if (subflows.size > 0) {\n sections.push(\"\\n\\n## Subflow Details\");\n sections.push(\"Use the subflow IDs above to look up details below.\\n\");\n for (const [sfId, entries] of subflows) {\n const name = subflowNames.get(sfId) ?? sfId;\n sections.push(`### ${name} (${sfId})\\n`);\n sections.push(renderEntries(entries, { inSubflow: sfId }));\n sections.push(\"\");\n }\n }\n\n // ── Append the full debug bundle when caller provided snapshot/spec ──\n // Everything below the narrative is for LLM debugging: final state,\n // per-stage commit log (shows EXACTLY what each stage wrote), spec\n // topology, and any recorder snapshots (metrics, tokens, instructions,\n // emit events). Without these the story has no payloads to reason over.\n if (runtimeSnapshot) {\n const snap = runtimeSnapshot as {\n sharedState?: unknown;\n commitLog?: unknown;\n recorders?: unknown;\n subflowResults?: unknown;\n };\n\n if (snap.sharedState !== undefined) {\n sections.push(\"\\n\\n## Final Shared State\");\n sections.push(\"```json\");\n sections.push(safeJsonStringify(snap.sharedState));\n sections.push(\"```\");\n }\n\n if (Array.isArray(snap.commitLog) && snap.commitLog.length > 0) {\n sections.push(\"\\n\\n## Commit Log\");\n sections.push(\n \"Each entry = one stage execution's writes to shared state. \" +\n \"`rsid` is the runtimeStageId (use it to correlate with narrative + executionTree).\\n\",\n );\n sections.push(\"```json\");\n sections.push(safeJsonStringify(snap.commitLog));\n sections.push(\"```\");\n }\n\n if (snap.recorders && typeof snap.recorders === \"object\") {\n sections.push(\"\\n\\n## Recorder Snapshots\");\n sections.push(\n \"Per-recorder data captured DURING the run (metrics, tokens, instructions, emit events).\\n\",\n );\n sections.push(\"```json\");\n sections.push(safeJsonStringify(snap.recorders));\n sections.push(\"```\");\n }\n\n if (snap.subflowResults && typeof snap.subflowResults === \"object\") {\n const keys = Object.keys(snap.subflowResults as Record<string, unknown>);\n if (keys.length > 0) {\n sections.push(\"\\n\\n## Subflow Results\");\n sections.push(\"```json\");\n sections.push(safeJsonStringify(snap.subflowResults));\n sections.push(\"```\");\n }\n }\n }\n\n if (spec) {\n sections.push(\"\\n\\n## Flowchart Spec (topology)\");\n sections.push(\n \"Node + edge metadata for the chart that ran. Useful for 'where in \" +\n \"the graph did step N happen?' questions.\\n\",\n );\n sections.push(\"```json\");\n sections.push(safeJsonStringify(spec));\n sections.push(\"```\");\n }\n\n return sections.join(\"\\n\");\n }, [narrativeEntries, narrative, runtimeSnapshot, spec]);\n\n const handleCopy = useCallback(async () => {\n const text = buildLLMNarrative();\n await navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [buildLLMNarrative]);\n\n if (unstyled) {\n return (\n <div className={className} style={style} data-fp=\"narrative-panel\">\n {hasStructured ? (\n <StoryNarrative entries={narrativeEntries!} revealedEntryCount={revealedEntryCount} unstyled />\n ) : (\n <NarrativeTrace narrative={narrative} revealedCount={revealedCount} unstyled />\n )}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n overflow: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n ...style,\n }}\n data-fp=\"narrative-panel\"\n >\n {/* Intro + Copy button */}\n <div\n style={{\n padding: `${pad - 4}px ${pad}px`,\n fontSize: fs.small,\n color: theme.textMuted,\n borderBottom: `1px solid ${theme.border}`,\n flexShrink: 0,\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span style={{ fontStyle: \"italic\" }}>\n What happened at each stage, what data flowed, what decisions were made, and why.\n </span>\n <button\n onClick={handleCopy}\n title=\"Copy narrative as LLM-ready text (includes subflow details)\"\n style={{\n background: copied ? theme.success : theme.bgSecondary,\n border: `1px solid ${theme.border}`,\n borderRadius: 4,\n padding: \"2px 8px\",\n fontSize: fs.small,\n color: copied ? \"#fff\" : theme.textSecondary,\n cursor: \"pointer\",\n flexShrink: 0,\n marginLeft: 8,\n transition: \"all 0.2s\",\n }}\n >\n {copied ? \"Copied!\" : \"Copy for LLM\"}\n </button>\n </div>\n {hasStructured ? (\n <StoryNarrative\n entries={narrativeEntries!}\n revealedEntryCount={revealedEntryCount}\n size={size}\n style={{ flex: 1 }}\n />\n ) : (\n <NarrativeTrace\n narrative={narrative}\n revealedCount={revealedCount}\n size={size}\n style={{ flex: 1 }}\n />\n )}\n </div>\n );\n}\n","/**\n * StoryNarrative — Rich rendering of structured narrative entries.\n *\n * Recorder-based view: renders CombinedNarrativeRecorder output with\n * progressive reveal synced to snapshot index. Each entry is typed\n * (stage, step, condition, fork, subflow, loop, break, error) and\n * rendered with appropriate icon + indentation.\n *\n * Data source: FlowRecorder (fires AFTER stage execution)\n */\nimport { useMemo, useRef, useEffect } from \"react\";\nimport type { NarrativeEntry, BaseComponentProps } from \"../../types\";\nimport { theme, fontSize, padding } from \"../../theme\";\n\nexport interface StoryNarrativeProps extends BaseComponentProps {\n /** Structured narrative entries from CombinedNarrativeRecorder */\n entries: NarrativeEntry[];\n /** Number of entries to reveal (position-based sync from NarrativePanel) */\n revealedEntryCount: number;\n}\n\nconst ENTRY_ICONS: Record<string, { icon: string; color: string; label: string }> = {\n stage: { icon: \"▸\", color: theme.primary, label: \"Stage\" },\n step: { icon: \"·\", color: theme.textMuted, label: \"Data operation\" },\n condition: { icon: \"◇\", color: theme.warning, label: \"Decision\" },\n fork: { icon: \"⑃\", color: theme.primary, label: \"Parallel\" },\n selector: { icon: \"⑃\", color: theme.primary, label: \"Selector\" },\n subflow: { icon: \"↳\", color: theme.textSecondary, label: \"Subflow\" },\n loop: { icon: \"↻\", color: theme.warning, label: \"Loop\" },\n break: { icon: \"■\", color: theme.error, label: \"Break\" },\n error: { icon: \"✗\", color: theme.error, label: \"Error\" },\n};\n\nexport function StoryNarrative({\n entries,\n revealedEntryCount,\n size = \"default\",\n unstyled = false,\n className,\n style: outerStyle,\n}: StoryNarrativeProps) {\n const fs = fontSize[size];\n const pad = padding[size];\n\n // Position-based reveal: NarrativePanel computes the cut point based on\n // section boundaries (stage entries). This handles loops (same stageId,\n // different iterations) and subflow repeats correctly.\n const revealedCount = revealedEntryCount;\n\n // Filter revealed entries: show root-level entries + subflow Entering/Exiting markers.\n // Subflow internal entries (stage, step, condition inside a subflow) are hidden —\n // they appear in the drill-down view.\n const revealed = useMemo(() => {\n const raw = entries.slice(0, revealedCount);\n return raw.filter((e) => {\n const sfId = (e as { subflowId?: string }).subflowId;\n if (!sfId) return true; // root-level — always show\n if (e.type === \"subflow\") return true; // Entering/Exiting markers — show\n return false; // internal subflow entries — hide (drill-down only)\n });\n }, [entries, revealedCount]);\n // Future count: only count entries that would actually be shown (same filter as revealed)\n const futureCount = useMemo(() => {\n let count = 0;\n for (let i = revealedCount; i < entries.length; i++) {\n const e = entries[i] as { subflowId?: string };\n if (!e.subflowId || entries[i].type === \"subflow\") count++;\n }\n return count;\n }, [entries, revealedCount]);\n\n const latestRef = useRef<HTMLDivElement>(null);\n useEffect(() => {\n latestRef.current?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }, [revealed.length]);\n\n // Compute heading numbers for each revealed entry.\n // Flat sequential counter matching flowchart traversal (DFS visit order):\n // 1. [Stage: Seed] ...\n // 2. [Subflow: SystemPrompt] ...\n // 3. [Subflow: Messages] ...\n // 4. [Stage: ApplyPreparedMessages] ...\n //\n // Counter increments on: stage, subflow entry, condition, first fork in sequence.\n // No counter on: step, subflow exit, loop, break, error, subsequent forks.\n const numberedEntries = useMemo(() => {\n let counter = 0;\n // Track subflow enter/exit: first occurrence of type=subflow per stageId = enter, second = exit.\n const subflowSeen = new Set<string>();\n let prevType = \"\";\n\n return revealed.map((entry) => {\n // Strip legacy \"Stage N: \" prefix from text (default renderer)\n let cleanText = entry.text;\n cleanText = cleanText.replace(/^Stage \\d+:\\s*/, \"\");\n // Detect fork type BEFORE stripping prefix\n const isSelector = entry.type === \"fork\" && entry.text.includes(\"[Selected]\");\n cleanText = cleanText.replace(/^\\[(Selected|Parallel)\\]:\\s*/, \"\");\n\n // ── Subflow: detect enter vs exit by toggle ──\n if (entry.type === \"subflow\") {\n // Use stageId as toggle key (unique per subflow visit).\n // Fall back to text for renderers that don't set stageId.\n const toggleKey = (entry as { stageId?: string }).stageId ?? entry.text;\n const isExit = subflowSeen.has(toggleKey);\n if (!isExit) {\n subflowSeen.add(toggleKey);\n counter++;\n return {\n ...entry,\n heading: `${counter}`,\n headingType: \"Subflow\",\n text: cleanText,\n isHeading: true,\n isSubflow: true,\n };\n }\n // Exit marker — no heading, will be hidden in render\n return { ...entry, heading: null, isHeading: false, isSubflowExit: true };\n }\n\n // ── Stage ──\n if (entry.type === \"stage\") {\n counter++;\n return { ...entry, heading: `${counter}`, headingType: \"Stage\", text: cleanText, isHeading: true };\n }\n\n // ── Condition (decision) — nested under the preceding stage, no separate number ──\n if (entry.type === \"condition\") {\n return { ...entry, heading: null, headingType: \"Decision\", text: cleanText, isHeading: false };\n }\n\n // ── Fork / Selector — first in sequence gets number ──\n if (entry.type === \"fork\" || entry.type === \"selector\") {\n const isForkHeading = prevType !== \"fork\" && prevType !== \"selector\";\n prevType = entry.type;\n if (isForkHeading) {\n counter++;\n const typeLabel = entry.type === \"selector\" || isSelector ? \"Selector\" : \"Fork\";\n return { ...entry, heading: `${counter}`, headingType: typeLabel, text: cleanText, isHeading: true };\n }\n return { ...entry, heading: null, isHeading: false, text: cleanText };\n }\n\n prevType = entry.type;\n // loop, break, step, error — no heading number\n // Loop is a back-edge (not a new node), break is termination signal\n return { ...entry, heading: null, isHeading: false };\n });\n }, [revealed]);\n\n if (unstyled) {\n return (\n <div className={className} style={outerStyle} data-fp=\"story-narrative\" role=\"log\">\n {numberedEntries.map((entry, i) => {\n if ((entry as any).isSubflowExit) return null;\n const ht = (entry as any).headingType;\n return (\n <div key={i} data-fp=\"narrative-entry\" data-type={entry.type}>\n {entry.heading\n ? entry.text.startsWith('[')\n ? `${entry.heading}. ${entry.text}`\n : `${entry.heading}. [${ht}: ${entry.stageName ?? ''}] ${entry.text}`\n : entry.text}\n </div>\n );\n })}\n </div>\n );\n }\n\n return (\n <div\n className={className}\n style={{\n flex: 1,\n overflow: \"auto\",\n padding: pad,\n fontFamily: theme.fontSans,\n ...outerStyle,\n }}\n data-fp=\"story-narrative\"\n role=\"log\"\n aria-label=\"Execution narrative\"\n >\n {numberedEntries.map((entry, i) => {\n // Skip subflow exit markers — entry marker is enough\n if ((entry as any).isSubflowExit) return null;\n\n const meta = ENTRY_ICONS[entry.type] ?? ENTRY_ICONS.step;\n const isHeading = entry.isHeading;\n const isDecision = entry.type === \"condition\";\n const isError = entry.type === \"error\";\n const isBreak = entry.type === \"break\";\n const isSubflow = (entry as any).isSubflow;\n const isLast = i === numberedEntries.length - 1;\n const headingType = (entry as any).headingType as string | undefined;\n\n return (\n <div\n key={i}\n ref={isLast ? latestRef : undefined}\n style={{\n display: \"flex\",\n gap: 8,\n padding: isHeading ? `${pad - 4}px 0` : `2px 0`,\n marginLeft: entry.depth * 16,\n borderBottom: isHeading ? `1px solid ${theme.border}` : undefined,\n marginTop: isHeading && i > 0 ? 8 : 0,\n }}\n >\n <span\n style={{\n color: meta.color,\n fontWeight: 700,\n fontSize: isHeading ? fs.body : fs.small,\n width: 16,\n textAlign: \"center\",\n flexShrink: 0,\n }}\n title={meta.label}\n aria-label={meta.label}\n >\n {meta.icon}\n </span>\n <span\n style={{\n fontSize: isHeading ? fs.body : fs.small,\n fontWeight: isHeading ? 600 : 400,\n color: isError || isBreak\n ? theme.error\n : isDecision\n ? theme.warning\n : isHeading\n ? theme.textPrimary\n : theme.textSecondary,\n lineHeight: 1.6,\n fontFamily: entry.type === \"step\" ? theme.fontMono : theme.fontSans,\n }}\n >\n {entry.heading && headingType ? (\n entry.text.startsWith('[') ? (\n <>\n <strong>{entry.heading}.</strong>\n {' '}{entry.text}\n </>\n ) : (\n <>\n <strong>{entry.heading}. [{headingType}{entry.stageName ? `: ${entry.stageName}` : ''}]</strong>\n {' '}{entry.text}\n </>\n )\n ) : entry.text}\n </span>\n </div>\n );\n })}\n\n {/* Future entries — show count hint only, skip full rendering for performance */}\n {futureCount > 0 && (\n <div style={{\n opacity: 0.3,\n fontSize: fs.small,\n color: theme.textMuted,\n padding: `8px 0`,\n fontStyle: \"italic\",\n }}>\n {futureCount} more {futureCount === 1 ? \"entry\" : \"entries\"} ahead...\n </div>\n )}\n </div>\n );\n}\n","/**\n * SubflowTree — collapsible sidebar listing mounted subflows.\n *\n * Recorder-driven (v6+): derives the tree from a `TraceGraph` produced\n * by `createTraceStructureRecorder`. Filters nodes by\n * `data.isSubflow === true` and lists them as `SubflowTreeEntry[]`\n * keyed by `subflowId`.\n *\n * Limitation (intentional — recorder graph is flat / mount-only):\n * Subflow-within-subflow nesting is NOT represented. The\n * StructureRecorder records the MOUNT of each subflow in the parent\n * chart, not the inner structure of each child chart. Rendering the\n * nested tree requires a separate recorder attached to each child\n * chart instance (deferred — see TODO below).\n *\n * Shared navigation layer — humans click through the tree just like\n * LLMs call getSubflowManifest() / getSubflowSpec().\n *\n * TODO(recorder-driven-nesting): when child charts attach their own\n * `traceStructureRecorder` and surface those graphs via a parent\n * registry, accept `Map<subflowId, TraceGraph>` and recurse to\n * restore the nested rendering the legacy SpecNode-walk supported.\n *\n * All colors come from `--fp-*` CSS variables set by the consumer.\n */\nimport { memo, useState, useCallback, useMemo } from \"react\";\nimport { theme } from \"../../theme\";\nimport type { TraceGraph } from \"./traceStructureRecorder\";\nimport type { BaseComponentProps } from \"../../types\";\n\nexport interface SubflowTreeEntry {\n /** Node name / identifier */\n name: string;\n /** Human-readable description */\n description?: string;\n /** Subflow ID (when this node represents a subflow) */\n subflowId?: string;\n /** Whether this node is a subflow root (has nested structure) */\n isSubflow?: boolean;\n /** Nested children (subflow stages) — always undefined in the\n * current recorder-driven implementation; see file-level TODO. */\n children?: SubflowTreeEntry[];\n}\n\nexport interface SubflowTreeProps extends BaseComponentProps {\n /** Recorder-captured graph from `createTraceStructureRecorder().getGraph()`. */\n graph: TraceGraph;\n /** Currently active stage name (highlights in tree) */\n activeStage?: string | null;\n /** Set of completed stage names */\n doneStages?: Set<string>;\n /** Called when a tree node is clicked */\n onNodeSelect?: (name: string, isSubflow: boolean) => void;\n}\n\n/** Extracts subflow entries from a recorder graph. Insertion-order preserving. */\nexport function graphToSubflowEntries(graph: TraceGraph): SubflowTreeEntry[] {\n if (!graph?.nodes?.length) return [];\n const entries: SubflowTreeEntry[] = [];\n for (const node of graph.nodes) {\n if (!node.data?.isSubflow) continue;\n const entry: SubflowTreeEntry = {\n name: typeof node.data.label === \"string\" ? node.data.label : node.id,\n isSubflow: true,\n };\n if (typeof node.data.description === \"string\") entry.description = node.data.description;\n if (typeof node.data.subflowId === \"string\") entry.subflowId = node.data.subflowId;\n entries.push(entry);\n }\n return entries;\n}\n\n/** Single tree node row */\nconst TreeNode = memo(function TreeNode({\n entry,\n depth,\n activeStage,\n doneStages,\n onNodeSelect,\n}: {\n entry: SubflowTreeEntry;\n depth: number;\n activeStage?: string | null;\n doneStages?: Set<string>;\n onNodeSelect?: (name: string, isSubflow: boolean) => void;\n}) {\n const [expanded, setExpanded] = useState(true);\n const hasChildren = entry.children && entry.children.length > 0;\n const isActive = activeStage === entry.name;\n const isDone = doneStages?.has(entry.name);\n\n const handleClick = useCallback(() => {\n if (hasChildren) {\n setExpanded((prev) => !prev);\n }\n onNodeSelect?.(entry.name, !!entry.isSubflow);\n }, [hasChildren, onNodeSelect, entry.name, entry.isSubflow]);\n\n return (\n <>\n <button\n onClick={handleClick}\n data-fp=\"subflow-tree-node\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n width: \"100%\",\n border: \"none\",\n background: isActive\n ? `color-mix(in srgb, ${theme.primary} 15%, transparent)`\n : \"transparent\",\n cursor: \"pointer\",\n padding: `4px 8px 4px ${8 + depth * 16}px`,\n fontFamily: theme.fontSans,\n fontSize: 12,\n textAlign: \"left\",\n borderRadius: 4,\n transition: \"background 0.15s\",\n }}\n onMouseEnter={(e) => {\n if (!isActive) {\n e.currentTarget.style.background = `color-mix(in srgb, ${theme.textMuted} 10%, transparent)`;\n }\n }}\n onMouseLeave={(e) => {\n if (!isActive) {\n e.currentTarget.style.background = \"transparent\";\n }\n }}\n >\n {/* Expand/collapse chevron for subflows */}\n {hasChildren ? (\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n width: 12,\n textAlign: \"center\",\n flexShrink: 0,\n transition: \"transform 0.15s\",\n transform: expanded ? \"rotate(90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n ▶\n </span>\n ) : (\n <span style={{ width: 12, flexShrink: 0 }} />\n )}\n\n {/* Status dot */}\n <span\n style={{\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n flexShrink: 0,\n background: isActive\n ? theme.primary\n : isDone\n ? theme.success\n : theme.border,\n }}\n />\n\n {/* Label + description */}\n <span style={{ display: \"flex\", flexDirection: \"column\", minWidth: 0 }}>\n <span\n style={{\n color: isActive\n ? theme.primary\n : isDone\n ? theme.textPrimary\n : theme.textSecondary,\n fontWeight: isActive ? 600 : entry.isSubflow ? 500 : 400,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {entry.name}\n {entry.isSubflow && (\n <span style={{ opacity: 0.5, marginLeft: 4, fontSize: 10 }}>⊞</span>\n )}\n </span>\n {entry.description && (\n <span\n style={{\n color: theme.textMuted,\n fontSize: 10,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {entry.description}\n </span>\n )}\n </span>\n </button>\n\n {/* Children */}\n {hasChildren && expanded && (\n <div>\n {entry.children!.map((child, i) => (\n <TreeNode\n key={child.subflowId ?? `${child.name}-${i}`}\n entry={child}\n depth={depth + 1}\n activeStage={activeStage}\n doneStages={doneStages}\n onNodeSelect={onNodeSelect}\n />\n ))}\n </div>\n )}\n </>\n );\n});\n\n/** Section label used for \"Flowchart\" and \"Subflows\" headings. */\nconst SectionLabel = memo(function SectionLabel({ children }: { children: string }) {\n return (\n <div\n style={{\n padding: \"4px 12px 8px\",\n fontSize: 10,\n fontWeight: 600,\n textTransform: \"uppercase\",\n letterSpacing: \"0.05em\",\n color: theme.textMuted,\n }}\n >\n {children}\n </div>\n );\n});\n\nexport const SubflowTree = memo(function SubflowTree({\n graph,\n activeStage,\n doneStages,\n onNodeSelect,\n unstyled = false,\n className,\n style,\n}: SubflowTreeProps) {\n const subflowStages = useMemo(() => graphToSubflowEntries(graph), [graph]);\n\n // Don't render anything if there are no subflows\n if (subflowStages.length === 0) return null;\n\n return (\n <div\n className={className}\n data-fp=\"subflow-tree\"\n style={{\n ...(unstyled\n ? {}\n : {\n fontFamily: theme.fontSans,\n fontSize: 12,\n background: theme.bgPrimary,\n borderRight: `1px solid ${theme.border}`,\n overflowY: \"auto\",\n overflowX: \"hidden\",\n padding: \"8px 0\",\n }),\n ...style,\n }}\n >\n {!unstyled && <SectionLabel>Subflows</SectionLabel>}\n {subflowStages.map((entry, i) => (\n <TreeNode\n key={entry.subflowId ?? `${entry.name}-${i}`}\n entry={entry}\n depth={0}\n activeStage={activeStage}\n doneStages={doneStages}\n onNodeSelect={onNodeSelect}\n />\n ))}\n </div>\n );\n});\n","import { memo } from \"react\";\nimport { theme } from \"../../theme\";\nimport type { BreadcrumbEntry } from \"./useSubflowNavigation\";\n\nexport interface SubflowBreadcrumbProps {\n breadcrumbs: BreadcrumbEntry[];\n onNavigate: (level: number) => void;\n}\n\n/**\n * Breadcrumb bar for subflow drill-down navigation.\n * Shows: Root > SubflowA > SubflowB — clicking any crumb navigates back.\n */\nexport const SubflowBreadcrumb = memo(function SubflowBreadcrumb({\n breadcrumbs,\n onNavigate,\n}: SubflowBreadcrumbProps) {\n if (breadcrumbs.length <= 1) return null;\n\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"6px 12px\",\n background: theme.bgSecondary,\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 12,\n fontFamily: theme.fontSans,\n flexShrink: 0,\n overflowX: \"auto\",\n }}\n >\n {breadcrumbs.map((crumb, i) => {\n const isLast = i === breadcrumbs.length - 1;\n return (\n <span key={`${crumb.label}-${i}`} style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\n {i > 0 && (\n <span style={{ color: theme.textMuted, fontSize: 10 }}>\n ›\n </span>\n )}\n {isLast ? (\n <span style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n <span\n style={{\n color: theme.primary,\n fontWeight: 600,\n }}\n >\n {crumb.label}\n </span>\n {crumb.description && (\n <span\n style={{\n color: theme.textMuted,\n fontWeight: 400,\n fontSize: 11,\n }}\n >\n — {crumb.description}\n </span>\n )}\n </span>\n ) : (\n <button\n onClick={() => onNavigate(i)}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.textSecondary,\n cursor: \"pointer\",\n padding: \"2px 4px\",\n borderRadius: 4,\n fontSize: 12,\n fontFamily: \"inherit\",\n fontWeight: 500,\n transition: \"color 0.15s\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.color = `${theme.primary}`;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.color = `${theme.textSecondary}`;\n }}\n >\n {crumb.label}\n </button>\n )}\n </span>\n );\n })}\n </div>\n );\n});\n","/**\n * TracedFlow — runtime-overlay variant of `<TraceFlow>`.\n *\n * Pairs a build-time `TraceGraph` (from `createTraceStructureRecorder`)\n * with a runtime `RuntimeOverlay` (from `createTraceRuntimeOverlay`)\n * and a scrub index → renders an xyflow chart with per-node coloring\n * (done / active / error), per-edge highlighting (executed paths),\n * loop-edge side-routing, and subflow drill-down.\n *\n * The component is orchestration only. Each responsibility lives in\n * an extracted helper / hook (see `_internal/`):\n *\n * - drill state .................. useSubflowDrill\n * - container resize → fitView ... useChartAutoRefit\n * - graph filtering by drill ..... filterGraphForDrill\n * - breadcrumb path .............. buildSubflowBreadcrumb\n * - slice id normalization ....... normalizeSliceLeafIds\n * - mount status aggregation ..... aggregateMountStatus\n * - node / edge styling .......... toStageNodeWithOverlay + styleEdgeWithOverlay\n * - breadcrumb UI ................ <SubflowBreadcrumbBar>\n *\n * @example\n * ```tsx\n * const trace = useMemo(() => createTraceStructureRecorder(), []);\n * const runtime = useMemo(() => createTraceRuntimeOverlay(), []);\n * // ... attach both to executor, run the chart ...\n * <TracedFlow\n * graph={trace.getGraph()}\n * overlay={runtime.getOverlay()}\n * scrubIndex={sliderValue}\n * onNodeClick={(stageId) => focusStage(stageId)}\n * onSubflowChange={(mountId) => syncShellDrill(mountId)}\n * />\n * ```\n */\n\nimport type * as React from \"react\";\nimport { useCallback, useMemo, useRef, useState } from \"react\";\nimport {\n ReactFlow,\n Background,\n BackgroundVariant,\n MarkerType,\n} from \"@xyflow/react\";\nimport type { Node, Edge, NodeTypes, EdgeTypes, ReactFlowInstance } from \"@xyflow/react\";\nimport type { TraceGraph, TraceNode, TraceEdge } from \"./traceStructureRecorder\";\nimport type { TraceFlowLayout } from \"./TraceFlow\";\nimport { defaultTraceFlowLayout } from \"./TraceFlow\";\nimport { dagreTraceLayout, createDagreTraceLayout } from \"./_internal/dagreTraceLayout\";\nimport type { NodeFootprint, NodeSizeResolver } from \"./_internal/dagreTraceLayout\";\nimport { createSnappedDagreLayout } from \"./_internal/snapLinearSuccessors\";\nimport { withForkCentering } from \"./_internal/centerForkParents\";\nimport type { RuntimeOverlay } from \"./createTraceRuntimeOverlay\";\nimport { sliceOverlay } from \"./createTraceRuntimeOverlay\";\nimport { StageNode } from \"../StageNode\";\nimport type { StageNodeData } from \"../StageNode\";\nimport { rawDefaults } from \"../../theme/tokens\";\nimport type { BaseComponentProps } from \"../../types\";\nimport { filterGraphForDrill, buildSubflowBreadcrumb } from \"./_internal/subflowDrill\";\nimport { aggregateMountStatus } from \"./_internal/overlayProjection\";\nimport { useSubflowDrill } from \"./_internal/useSubflowDrill\";\nimport { useChartAutoRefit } from \"./_internal/useChartAutoRefit\";\nimport { SubflowBreadcrumbBar } from \"./SubflowBreadcrumbBar\";\nimport { GroupContainerNode } from \"../GroupContainerNode\";\nimport { LoopBackEdge } from \"../LoopBackEdge\";\nimport { SmartStepEdge } from \"../SmartStepEdge\";\nimport { applyGroupLayout, wrapInMainChartBox } from \"./_internal/groupLayout\";\nimport { MeasuredNodeSizes } from \"./_internal/MeasuredNodeSizes\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Theming\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface TracedFlowColors {\n /** Default (un-executed) node text + edge stroke. */\n default: string;\n /** Done — visually de-emphasised (lighter). */\n done: string;\n /** Active — current scrub position. */\n active: string;\n /** Error — node with recorded onError. */\n error: string;\n /** Loop back-edge color. */\n loop: string;\n}\n\nconst DEFAULT_COLORS: TracedFlowColors = {\n default: rawDefaults.colors.textMuted,\n done: rawDefaults.colors.success,\n active: rawDefaults.colors.primary,\n error: rawDefaults.colors.error,\n loop: rawDefaults.colors.warning,\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Per-node / per-edge styling (pure)\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Derive overlay state fields for a single node from the current\n * scrub slice. Shared between the default `stageNode` path and the\n * custom-node pass-through path so custom renderers receive the same\n * `active`/`done`/`error`/`dimmed`/`stepNumbers` shape the bundled\n * `<StageNode>` consumes.\n */\n/** Stable empty set so the nodes useMemo doesn't re-run when no co-active set is passed. */\nconst EMPTY_SET: ReadonlySet<string> = new Set<string>();\n\nfunction deriveOverlayFields(\n node: TraceNode,\n doneStageIds: ReadonlySet<string>,\n activeStageId: string | null,\n errorMessage: string | undefined,\n executedOrderIds: readonly string[],\n coActiveStageIds: ReadonlySet<string>,\n): {\n active: boolean;\n done: boolean;\n error: boolean;\n dimmed: boolean;\n errorMessage?: string;\n stepNumbers?: number[];\n} {\n const isDone = doneStageIds.has(node.id);\n // `active` is the SINGLE cursor node OR any node in the co-active set — the\n // latter lets a consumer light a whole parallel cohort (e.g. the lens lighting\n // all branches of a fork) at one cursor. Applies to BOTH stage and custom\n // nodes (custom nodes also OR consumer `data.active` below).\n const isActive = activeStageId === node.id || coActiveStageIds.has(node.id);\n const wasExecuted = isDone || isActive;\n const hasError = !!errorMessage;\n const dimmed = !wasExecuted && executedOrderIds.length > 0;\n\n // Per-stage step number(s) — a loop may visit the same node multiple times.\n let stepNumbers: number[] | undefined;\n if (executedOrderIds.length > 0) {\n const nums: number[] = [];\n for (let i = 0; i < executedOrderIds.length; i++) {\n if (executedOrderIds[i] === node.id) nums.push(i + 1);\n }\n if (nums.length > 0) stepNumbers = nums;\n }\n\n return {\n active: isActive,\n done: isDone,\n error: hasError,\n dimmed,\n ...(errorMessage && { errorMessage }),\n ...(stepNumbers && { stepNumbers }),\n };\n}\n\nfunction toStageNodeWithOverlay(\n node: TraceNode,\n doneStageIds: ReadonlySet<string>,\n activeStageId: string | null,\n errorMessage: string | undefined,\n executedOrderIds: readonly string[],\n coActiveStageIds: ReadonlySet<string>,\n): Node {\n const overlayFields = deriveOverlayFields(\n node,\n doneStageIds,\n activeStageId,\n errorMessage,\n executedOrderIds,\n coActiveStageIds,\n );\n const { dimmed } = overlayFields;\n\n // Custom-node pass-through with overlay enrichment.\n //\n // Behaviour (v0.20+): when a consumer pushes a node with a non-default\n // `type`, we return it with overlay state MERGED INTO `data`\n // (`active`, `done`, `error`, `errorMessage`, `dimmed`, `stepNumbers`).\n // The consumer's custom renderer can read those fields to style itself\n // the same way the bundled `<StageNode>` does, without re-implementing\n // the scrub-slice derivation.\n //\n // Merge semantics: OR-union with consumer `data`. The consumer may\n // ALSO want to mark a node active/done (e.g., agentfootprint-lens marks\n // its User pill active at root cursors — the User pill isn't a real\n // stage so the overlay can't compute it). When EITHER source flags a\n // node active/done/error, the renderer sees it. This composes cleanly:\n // - Pure overlay flow (no consumer override) → overlay values pass through\n // - Consumer override (lens User pill case) → consumer flag wins\n // - Both set → OR (lit either way)\n //\n // `dimmed` is mutually exclusive with `active`/`done` — when a node is\n // active or done at the current cursor it can't simultaneously be\n // \"faded because others have executed.\" We zero dimmed when active or\n // done is true regardless of source.\n if (node.type !== undefined && node.type !== \"stage\") {\n const consumerData = (node.data ?? {}) as Record<string, unknown>;\n const consumerActive = consumerData.active === true;\n const consumerDone = consumerData.done === true;\n const consumerError = consumerData.error === true;\n const finalActive = consumerActive || overlayFields.active;\n const finalDone = consumerDone || overlayFields.done;\n const finalError = consumerError || overlayFields.error;\n const finalDimmed = !finalActive && !finalDone && dimmed;\n return {\n ...node,\n data: {\n ...node.data,\n active: finalActive,\n done: finalDone,\n error: finalError,\n ...(overlayFields.errorMessage !== undefined &&\n consumerData.errorMessage === undefined && {\n errorMessage: overlayFields.errorMessage,\n }),\n ...(finalDimmed && { dimmed: true }),\n ...(overlayFields.stepNumbers && { stepNumbers: overlayFields.stepNumbers }),\n },\n ...(finalDimmed && { style: { ...(node.style ?? {}), opacity: 0.35 } }),\n } as Node;\n }\n\n const stageData: StageNodeData = {\n label: node.data.label,\n isDecider: node.data.isDecider,\n isFork: node.data.isFork,\n isSubflow: node.data.isSubflow,\n ...overlayFields,\n ...(node.data.description !== undefined && { description: node.data.description }),\n ...(node.data.icon !== undefined && { icon: node.data.icon }),\n ...(node.data.subflowId !== undefined && { subflowId: node.data.subflowId }),\n ...(node.data.isLazy === true && { isLazy: true }),\n ...(node.data.emphasis !== undefined && { emphasis: node.data.emphasis }),\n ...(node.data.size !== undefined && { size: node.data.size }),\n } as StageNodeData;\n\n return {\n ...node,\n type: \"stageNode\",\n data: stageData as unknown as Record<string, unknown>,\n ...(dimmed && { style: { opacity: 0.35 } }),\n };\n}\n\nfunction styleEdgeWithOverlay(\n edge: TraceEdge,\n doneStageIds: ReadonlySet<string>,\n activeStageId: string | null,\n colors: TracedFlowColors,\n): Edge {\n const kind = edge.data?.kind ?? \"next\";\n const sourceExecuted = doneStageIds.has(edge.source) || activeStageId === edge.source;\n const targetExecuted = doneStageIds.has(edge.target) || activeStageId === edge.target;\n const traversed = sourceExecuted && targetExecuted;\n const isLeadingEdge = activeStageId === edge.source && !doneStageIds.has(edge.target);\n\n let color: string = colors.default;\n if (kind === \"loop\") color = colors.loop;\n else if (isLeadingEdge) color = colors.active;\n else if (traversed) color = colors.done;\n\n const styled: Edge = {\n ...edge,\n // Loop back-edges use the custom `loopBack` edge — a curve routed along the\n // right margin (clear of the spine). It reads node bounds from the store\n // and anchors on right edges itself, so it needs NO dedicated loop handles\n // on the node (the old approach broke for any node missing them).\n // Every other edge uses `smartStep`: a smoothstep superset that routes a\n // RANK-SKIPPING edge around the node it skips (else identical to smoothstep).\n type: kind === \"loop\" ? \"loopBack\" : \"smartStep\",\n animated: isLeadingEdge,\n style: { stroke: color, strokeWidth: traversed ? 2 : 1.5 },\n markerEnd: { type: MarkerType.ArrowClosed, color, width: 16, height: 16 },\n };\n if (kind === \"loop\") {\n styled.style = { ...styled.style, strokeDasharray: \"4 3\" };\n }\n return styled;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Component\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface TracedFlowProps extends BaseComponentProps {\n /** Build-time graph from `createTraceStructureRecorder().getGraph()`. */\n graph: TraceGraph;\n /** Runtime overlay from `createTraceRuntimeOverlay().getOverlay()`. */\n overlay?: RuntimeOverlay;\n /** Time-travel scrub index. Defaults to the last step (latest state). */\n scrubIndex?: number;\n /** Layout function. Default: BFS tree walk over the recorder graph. */\n layout?: TraceFlowLayout | \"passthrough\";\n /** Color overrides. */\n colors?: Partial<TracedFlowColors>;\n /** Node click handler — receives stage id. */\n onNodeClick?: (stageId: string) => void;\n /**\n * Fires when the chart drills into or out of a subflow (explicit\n * user click on a mount node). Receives the mount stage id (drill\n * in) or `null` (pop back). Container shells use this to keep\n * their data panels in lock-step with the chart's drill state.\n */\n onSubflowChange?: (mountStageId: string | null) => void;\n /**\n * Consumer-supplied xyflow node types. Merged with the built-in\n * `{ stageNode: StageNode }` registry — keys you supply OVERRIDE\n * the default for that node type. Pass `{ stageNode: MyNode }` to\n * replace the default stage renderer entirely, or add new keys\n * for custom node components you push into the graph.\n *\n * v0.20+ — overlay state is injected into custom nodes' `data`\n * fields too (`active`, `done`, `error`, `errorMessage`, `dimmed`,\n * `stepNumbers`), so consumer renderers can style themselves with\n * the same scrub-driven done/active/error semantics the bundled\n * `<StageNode>` uses — without re-implementing the overlay slice\n * derivation. Consumer `data` fields pass through untouched alongside.\n */\n nodeTypes?: NodeTypes;\n /**\n * Consumer-supplied xyflow edge types. Merged with no built-in\n * defaults — pass `{ myEdge: MyEdge }` to register custom edge\n * components for edges you push into the graph with `type: 'myEdge'`.\n */\n edgeTypes?: EdgeTypes;\n /**\n * Extra chart node ids to mark `active` SIMULTANEOUSLY at the current scrub\n * position, on top of the overlay's single active node. Lets a consumer light\n * a whole parallel cohort at one cursor (e.g. the lens lighting every branch\n * of a fork together). Works for BOTH stage and custom nodes. Defaults to\n * none — single-active behaviour is unchanged.\n */\n coActiveStageIds?: ReadonlySet<string>;\n /**\n * Subflow ids to render as GROUP CONTAINER boxes — the subflow's member\n * stages render NESTED inside the box (xyflow `parentId` + `extent`),\n * instead of behind a click-to-zoom DRILL card. Per-subflow choice: any\n * subflow id NOT listed keeps drilling. Default (unset): all drill —\n * existing behavior, nothing changes.\n */\n groupedSubflows?: readonly string[];\n /**\n * Wrap the ENTIRE chart in ONE main-chart container box (the Lens model:\n * the primitive you're viewing is always one box; subflows inside stay\n * drill cards). Pass a config object to enable + label it; omit for no\n * outer box. Composes AFTER drill-filtering, so when you drill into a\n * subflow the box reframes to that subflow's contents.\n */\n mainChartBox?: { label?: string; kind?: string };\n /**\n * Children rendered INSIDE the `<ReactFlow>` element, after the\n * built-in `<Background>`. Use this slot to mount xyflow\n * accessory components like `<Controls />`, `<MiniMap />`, or a\n * custom legend. If unset, only the default Background is rendered.\n */\n children?: React.ReactNode;\n}\n\nconst DEFAULT_NODE_TYPES: NodeTypes = {\n stageNode: StageNode,\n groupContainer: GroupContainerNode,\n};\n\n// Built-in edge types. `loopBack` curves loop-back edges along the right margin\n// (see LoopBackEdge); `smartStep` routes rank-skipping edges around the node\n// they skip (see SmartStepEdge). Always registered; merged UNDER consumer\n// `edgeTypes` (consumer keys win).\nconst DEFAULT_EDGE_TYPES: EdgeTypes = { loopBack: LoopBackEdge, smartStep: SmartStepEdge };\n\nexport function TracedFlow({\n graph,\n overlay,\n scrubIndex,\n layout: layoutProp,\n colors: colorOverrides,\n onNodeClick,\n onSubflowChange,\n groupedSubflows,\n mainChartBox,\n nodeTypes: userNodeTypes,\n edgeTypes: userEdgeTypes,\n coActiveStageIds,\n children,\n className,\n style,\n}: TracedFlowProps) {\n // Dagre is the default (structure-derived spacing); override via `layout`.\n const layout = layoutProp ?? dagreTraceLayout;\n const colors = useMemo<TracedFlowColors>(\n () => ({ ...DEFAULT_COLORS, ...(colorOverrides ?? {}) }),\n [colorOverrides],\n );\n const mergedNodeTypes = useMemo<NodeTypes>(\n () => (userNodeTypes ? { ...DEFAULT_NODE_TYPES, ...userNodeTypes } : DEFAULT_NODE_TYPES),\n [userNodeTypes],\n );\n const mergedEdgeTypes = useMemo<EdgeTypes>(\n () => (userEdgeTypes ? { ...DEFAULT_EDGE_TYPES, ...userEdgeTypes } : DEFAULT_EDGE_TYPES),\n [userEdgeTypes],\n );\n\n // ── Drill state + visibility derivations ──────────────────────────\n const drill = useSubflowDrill(graph, onSubflowChange);\n const groupedSet = useMemo(() => new Set(groupedSubflows ?? []), [groupedSubflows]);\n // Drill-filter the graph, but KEEP members of grouped subflows visible:\n // a grouped subflow renders its members nested in a container box rather\n // than hidden behind a drill card, so it opts out of drill hiding.\n const filteredGraph = useMemo(() => {\n const base = filterGraphForDrill(graph, drill.currentSubflowId);\n if (groupedSet.size === 0) return base;\n const baseIds = new Set(base.nodes.map((n) => n.id));\n const extraNodes = graph.nodes.filter(\n (n) =>\n n.data?.subflowOf !== undefined &&\n groupedSet.has(n.data.subflowOf) &&\n !baseIds.has(n.id),\n );\n if (extraNodes.length === 0) return base;\n const allIds = new Set([...baseIds, ...extraNodes.map((n) => n.id)]);\n const baseEdgeIds = new Set(base.edges.map((e) => e.id));\n const extraEdges = graph.edges.filter(\n (e) => !baseEdgeIds.has(e.id) && allIds.has(e.source) && allIds.has(e.target),\n );\n return { nodes: [...base.nodes, ...extraNodes], edges: [...base.edges, ...extraEdges] };\n }, [graph, drill.currentSubflowId, groupedSet]);\n const breadcrumb = useMemo(\n () => buildSubflowBreadcrumb(graph, drill.currentSubflowId),\n [graph, drill.currentSubflowId],\n );\n // Real rendered node sizes, captured by the <MeasuredNodeSizes> probe once\n // xyflow has measured them — fed into the dagre `nodeSize` resolver below so\n // the layout re-runs with content-exact spacing (measure-then-layout).\n const [measuredSizes, setMeasuredSizes] = useState<Map<string, NodeFootprint> | null>(null);\n\n const positioned = useMemo<TraceGraph>(() => {\n // Default layout = dagre (measured content-exact sizes + tighter pro\n // spacing) → snap pass (kills Brandes–Köpf spine drift on asymmetric\n // graphs). The SAME nodeSize resolver goes to BOTH dagre and snap — else\n // snap reconstructs centers from wrong widths (the identical-resolver\n // invariant). A consumer's custom `layout` owns its own sizing;\n // \"passthrough\" keeps the incoming positions.\n const nodeSize: NodeSizeResolver | undefined = measuredSizes\n ? (n) => measuredSizes.get(n.id)\n : undefined;\n const sizeOpts = nodeSize ? { nodeSize } : {};\n // dagre → snap (spine drift) → fork-centering (off-center fork parents).\n // SAME sizeOpts to every stage (the identical-resolver invariant).\n const dagreBase: TraceFlowLayout = withForkCentering(\n createSnappedDagreLayout(\n createDagreTraceLayout({ ...sizeOpts, rankSep: 52, nodeSep: 36 }),\n sizeOpts,\n ),\n { ...sizeOpts, nodeSep: 36 }, // same nodeSep → clamp preserves dagre's reserved gap\n );\n const realBase: TraceFlowLayout =\n layout === \"passthrough\"\n ? (g: TraceGraph) => g\n : layoutProp === undefined\n ? dagreBase\n : (layout as TraceFlowLayout);\n\n // Per-subflow group boxes (granular; not the main-chart model).\n if (groupedSet.size > 0) {\n const grouped = applyGroupLayout(filteredGraph, {\n groupedSubflowIds: [...groupedSet],\n baseLayout: realBase,\n });\n // Main box can still wrap the grouped result if both are requested.\n return mainChartBox\n ? wrapInMainChartBox(grouped, { baseLayout: (g) => g, ...mainChartBox })\n : grouped;\n }\n\n // Main-chart box: wrap the whole (drill-filtered) chart in ONE box.\n // The base layout positions the contents; the box frames them.\n if (mainChartBox) {\n return wrapInMainChartBox(filteredGraph, { baseLayout: realBase, ...mainChartBox });\n }\n\n return realBase(filteredGraph);\n }, [filteredGraph, layout, layoutProp, groupedSet, mainChartBox, measuredSizes]);\n\n // ── Runtime overlay slice → mount aggregation ────\n // Overlay stage ids are path-qualified (`subflowPath/stageId`, parsed\n // from runtimeStageId) and structure node ids are ALSO path-qualified\n // now (walkSubflowSpecInto), so they match directly — no leaf-stripping.\n // (The former `normalizeSliceLeafIds` step only existed because\n // structure ids used to be bare; it would now MISMATCH by stripping a\n // qualified id down to its leaf.)\n const slice = useMemo(() => {\n const empty = {\n doneStageIds: new Set<string>(),\n activeStageId: null as string | null,\n executedStageIds: new Set<string>(),\n executedOrderIds: [] as string[],\n errors: new Map<string, string>(),\n };\n if (!overlay) return empty;\n const idx = scrubIndex ?? Math.max(0, overlay.executionOrder.length - 1);\n return aggregateMountStatus(sliceOverlay(overlay, idx), graph, drill.currentSubflowId);\n }, [overlay, scrubIndex, graph, drill.currentSubflowId]);\n\n // ── xyflow nodes + edges (re-run per scrub tick) ──────────────────\n const reactFlowNodes = useMemo<Node[]>(\n () =>\n positioned.nodes.map((n) =>\n toStageNodeWithOverlay(\n n,\n slice.doneStageIds,\n slice.activeStageId,\n slice.errors.get(n.id),\n slice.executedOrderIds,\n coActiveStageIds ?? EMPTY_SET,\n ),\n ),\n [positioned.nodes, slice, coActiveStageIds],\n );\n const reactFlowEdges = useMemo<Edge[]>(\n () =>\n positioned.edges.map((e) =>\n styleEdgeWithOverlay(e, slice.doneStageIds, slice.activeStageId, colors),\n ),\n [positioned.edges, slice, colors],\n );\n\n // ── Click handling: drill on subflow mount click, propagate click ─\n const handleNodeClick = useCallback(\n (_: unknown, node: Node) => {\n const data = (node.data ?? {}) as StageNodeData;\n // Grouped subflows render inline (no drill) — only drill the ones\n // still in card mode.\n if (data.isSubflow && data.subflowId && !groupedSet.has(data.subflowId)) {\n drill.drillInto(data.subflowId);\n }\n onNodeClick?.(node.id);\n },\n [drill, onNodeClick, groupedSet],\n );\n\n // ── Container auto-refit (xyflow's fitView is mount-only) ─────────\n const wrapperRef = useRef<HTMLDivElement>(null);\n const [rfInstance, setRfInstance] = useState<ReactFlowInstance | null>(null);\n // refitKey = the drill id: drilling in/out swaps the visible subgraph, so the\n // chart must recenter + rezoom to the new content (otherwise the smaller\n // drilled graph keeps the parent's pan/zoom and sits cramped in a corner).\n useChartAutoRefit(wrapperRef, rfInstance, {\n // Re-fit on drill AND after the measured-size re-layout settles.\n refitKey: `${drill.currentSubflowId ?? \"\"}:${measuredSizes ? \"measured\" : \"estimated\"}`,\n padding: 0.18,\n });\n\n return (\n <div\n ref={wrapperRef}\n className={className}\n style={{\n width: \"100%\",\n height: \"100%\",\n minHeight: 300,\n display: \"flex\",\n flexDirection: \"column\",\n ...style,\n }}\n >\n {breadcrumb.length > 1 && (\n <SubflowBreadcrumbBar\n entries={breadcrumb}\n onNavigate={drill.setCurrentSubflowId}\n />\n )}\n <div style={{ flex: 1, minHeight: 0 }}>\n <ReactFlow\n nodes={reactFlowNodes}\n edges={reactFlowEdges}\n nodeTypes={mergedNodeTypes}\n edgeTypes={mergedEdgeTypes}\n onNodeClick={handleNodeClick}\n onInit={setRfInstance}\n fitView\n fitViewOptions={{ padding: 0.18 }}\n minZoom={0.1}\n proOptions={{ hideAttribution: true }}\n >\n <MeasuredNodeSizes onSizes={setMeasuredSizes} />\n <Background variant={BackgroundVariant.Dots} gap={20} size={1} />\n {children}\n </ReactFlow>\n </div>\n </div>\n );\n}\n","/**\n * dagreTraceLayout — professor-grade `TraceFlowLayout` backed by dagre.\n *\n * Replaces the hand-rolled BFS `defaultTraceFlowLayout` (which used FIXED\n * spacing constants — Y_STEP / X_SPREAD — and documented \"first-wins\"\n * convergence + no overlap detection). Dagre instead derives every\n * position from the STRUCTURE RELATIONS:\n *\n * - **next** (sequential): y-delta = rank depth (longest path), so a\n * convergence node lands at `max(incoming ranks) + 1` — not\n * \"deepest-branch-so-far\".\n * - **fork / selector** (N branches): x-delta = the measured SUBTREE\n * WIDTH of each branch (a wide branch pushes its siblings further; a\n * thin one barely shifts them) — scales cleanly for any N, no collisions.\n * - **merge** (join): centered under the average of its real parents.\n *\n * Compound nesting: dagre is given `parentId` as a compound-parent link,\n * so group-container children (from `applyGroupLayout` / `wrapInMainChartBox`)\n * stay inside their box. Coordinates are returned parent-RELATIVE (xyflow\n * convention), matching what the box transforms expect.\n *\n * Ported from agentfootprint-lens's proven `dagreLayout` (same dagre core),\n * re-shaped to the `TraceFlowLayout` contract: `(TraceGraph) => TraceGraph`.\n * Pure — same graph in, same positions out; no React, no I/O.\n */\n\nimport dagre from \"dagre\";\nimport type { Edge } from \"@xyflow/react\";\nimport type { TraceGraph, TraceNode, TraceEdgeData } from \"../traceStructureRecorder\";\nimport type { TraceFlowLayout } from \"../TraceFlow\";\n\n/** Explicit node footprint (px). */\nexport interface NodeFootprint {\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Consumer-supplied per-node size resolver. Receives the WHOLE node (all\n * recorder semantics: `data.isSubflow`, `data.icon`, `data.subflowId`,\n * `id`, …) and returns a footprint, or `undefined` to leave the node alone\n * (→ falls back to `style.width/height`, then the default footprint).\n *\n * The library imposes NO sizing rules — the consumer decides per node by\n * whatever criteria THEY choose. E.g. make one specific slot a slim bar\n * while another stays a full card; make the LLM-call node large; etc.\n */\nexport type NodeSizeResolver = (node: TraceNode) => NodeFootprint | undefined;\n\n/** Consumer-supplied per-edge layout-weight resolver. Higher weight pulls\n * the two endpoints into a tighter, straighter column (dagre `weight`).\n * Return `undefined` for the default (1). */\nexport type EdgeWeightResolver = (edge: Edge<TraceEdgeData>) => number | undefined;\n\n/** Consumer-supplied per-edge minimum rank-span resolver. `>1` STRETCHES an\n * edge (pushes its target that many ranks down). Note dagre cannot make an\n * edge SHORTER than one rank — `minlen` only increases. Return `undefined`\n * for the default (1). */\nexport type EdgeMinLenResolver = (edge: Edge<TraceEdgeData>) => number | undefined;\n\n/**\n * Consumer-supplied left-to-right ORDER for a node's fork/decider children.\n * Receives the source node id + its child target ids (in spec/edge-insertion\n * order); returns the SAME ids reordered left-to-right (index 0 = leftmost).\n * Ids omitted from the result keep their original relative order after the\n * listed ones. Return the input unchanged (or `undefined` from the resolver)\n * to leave a node alone.\n *\n * Use to place a specific branch on a chosen side — e.g. the looping branch on\n * the right margin where the loop-back curve lives, so the \"iterate\" path reads\n * as one side of the fork. This is a pure VISUAL/LAYOUT decision (it changes\n * which side a branch draws on, never the chart's behavior), so it belongs in\n * the renderer, not the chart spec.\n *\n * Mechanism: dagre seeds its sibling order from edge-insertion order and keeps\n * it as the tie-break for equal-barycenter siblings. We insert each source's\n * edges in the resolved order, so for the common symmetric N-branch decider the\n * result is deterministic. (For graphs where one ordering strictly reduces edge\n * crossings, dagre's crossing-minimizer may still override — best-effort, as\n * documented for any dagre ordering hint.)\n */\nexport type SiblingOrderResolver = (\n sourceId: string,\n childIds: readonly string[],\n) => readonly string[];\n\nexport interface DagreTraceLayoutOptions {\n /** Layout direction. `'TB'` (top-to-bottom) is the default — matches the\n * \"Seed → … → answer\" reading order. */\n readonly direction?: \"TB\" | \"BT\" | \"LR\" | \"RL\";\n /** Vertical spacing between rank layers (px). Surfaced as a knob — the\n * rank-gap delta. Default 80. */\n readonly rankSep?: number;\n /** Horizontal spacing between siblings within a rank (px). The\n * sibling-gap delta dagre adds ON TOP of measured subtree widths.\n * Default 60. */\n readonly nodeSep?: number;\n /** Spacing between edges (px). Default 20. */\n readonly edgeSep?: number;\n /** Fallback node footprint when a node carries no explicit size. dagre\n * needs real dimensions or arrows collapse to a point. */\n readonly nodeWidth?: number;\n readonly nodeHeight?: number;\n /** Per-node size resolver — consumer decides each node's footprint. See\n * `NodeSizeResolver`. Resolution order: resolver → `node.style` → default. */\n readonly nodeSize?: NodeSizeResolver;\n /** Per-edge pull (dagre `weight`). See `EdgeWeightResolver`. */\n readonly edgeWeight?: EdgeWeightResolver;\n /** Per-edge stretch (dagre `minlen`). See `EdgeMinLenResolver`. */\n readonly edgeMinLen?: EdgeMinLenResolver;\n /** Per-node fork/decider child ordering. See `SiblingOrderResolver`. */\n readonly siblingOrder?: SiblingOrderResolver;\n}\n\nexport const DEFAULT_NODE_W = 200;\nexport const DEFAULT_NODE_H = 80;\n\n/**\n * Resolve a node's render size. Order: consumer `nodeSize` resolver (if it\n * returns a footprint) → explicit `style.width/height` (set by the\n * group/main-box transforms) → configured fallback footprint.\n *\n * GROUP-CONTAINER EXCEPTION — style WINS over the resolver. A node flagged\n * `data.isGroupContainer` has been STAMPED with its true box footprint on\n * `style.width/height` by `applyGroupLayout` PASS 2 (or `wrapInMainChartBox`).\n * That footprint is authoritative: it is the size the box actually RENDERS at,\n * so dagre must reserve exactly it or post-container siblings rank inside the\n * box and overlap it. A consumer `nodeSize` resolver that sizes by recorder\n * semantics (e.g. \"any subflow → a 38px slim bar\") would otherwise out-rank\n * the stamp — dagre would be told 38px while the box paints ~794px, and the\n * `route`/`tool-calls`/`final` siblings would land on top of it. So for a\n * group container the resolution order flips to: `style` → resolver → default.\n *\n * Exported so the post-layout `snapLinearSuccessors` pass reconstructs each\n * node's center from the IDENTICAL width dagre placed it at, keeping snapped\n * centers geometry-exact.\n */\nexport function sizeOf(\n node: TraceNode,\n fallbackW: number,\n fallbackH: number,\n resolver?: NodeSizeResolver,\n): { width: number; height: number } {\n const style = (node.style ?? {}) as { width?: unknown; height?: unknown };\n const styleW = typeof style.width === \"number\" ? style.width : undefined;\n const styleH = typeof style.height === \"number\" ? style.height : undefined;\n\n // A stamped group container's footprint is authoritative — style beats the\n // resolver so dagre reserves the box's REAL rendered height (no sibling\n // overlap). Both dimensions must be present to use the stamp; otherwise fall\n // through to the normal order.\n if (node.data?.isGroupContainer && styleW !== undefined && styleH !== undefined) {\n return { width: styleW, height: styleH };\n }\n\n const resolved = resolver?.(node);\n if (resolved) return { width: resolved.width, height: resolved.height };\n return {\n width: styleW ?? fallbackW,\n height: styleH ?? fallbackH,\n };\n}\n\n/**\n * Reorder edges so each source node's forward (non-loop) children are fed to\n * dagre in `siblingOrder`'s left-to-right order. dagre seeds sibling order from\n * edge-insertion order (and keeps it as the equal-barycenter tie-break), so\n * inserting in the resolved order biases each fork's left-to-right layout.\n *\n * Pure. Loop edges are dropped (they never shape layout — the caller skips them\n * anyway). Sources keep first-seen order; within a source, children follow the\n * resolver, and any children the resolver omits keep their original order after\n * the listed ones. Single-child sources are returned untouched.\n */\nfunction reorderSiblingEdges<E extends { source: string; target: string; data?: { kind?: string } }>(\n edges: readonly E[],\n siblingOrder: SiblingOrderResolver,\n): E[] {\n const bySource = new Map<string, E[]>();\n for (const e of edges) {\n if (e.data?.kind === \"loop\") continue;\n const arr = bySource.get(e.source);\n if (arr) arr.push(e);\n else bySource.set(e.source, [e]);\n }\n const out: E[] = [];\n for (const [src, group] of bySource) {\n if (group.length < 2) {\n out.push(...group);\n continue;\n }\n const ordered = siblingOrder(src, group.map((e) => e.target));\n const byTarget = new Map(group.map((e) => [e.target, e]));\n const used = new Set<string>();\n for (const t of ordered) {\n const e = byTarget.get(t);\n if (e && !used.has(t)) {\n out.push(e);\n used.add(t);\n }\n }\n for (const e of group) if (!used.has(e.target)) out.push(e); // resolver omissions\n }\n return out;\n}\n\n/**\n * Lay out a `TraceGraph` with dagre. Returns a NEW graph with each node's\n * `position` set (top-left, parent-relative for nested nodes). Edges pass\n * through unchanged — xyflow routes them once nodes are placed.\n *\n * Loop back-edges (`kind: 'loop'`) are EXCLUDED from the dagre graph: they\n * are visual annotations only (invariant I1) and would otherwise create\n * cycles that distort ranking.\n */\nexport function dagreTraceLayout(\n graph: TraceGraph,\n options: DagreTraceLayoutOptions = {},\n): TraceGraph {\n if (graph.nodes.length === 0) return graph;\n\n const direction = options.direction ?? \"TB\";\n const rankSep = options.rankSep ?? 80;\n const nodeSep = options.nodeSep ?? 60;\n const edgeSep = options.edgeSep ?? 20;\n const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W;\n const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H;\n\n const g = new dagre.graphlib.Graph({ compound: true });\n g.setGraph({ rankdir: direction, ranksep: rankSep, nodesep: nodeSep, edgesep: edgeSep });\n g.setDefaultEdgeLabel(() => ({}));\n\n const sizes = new Map<string, { width: number; height: number }>();\n // Sizes the consumer resolver supplied — applied to the node's `style` so\n // xyflow RENDERS at the same footprint dagre laid out for (layout/paint\n // parity). Style-derived + default sizes are layout-only (the node already\n // renders at them), so we don't override their style.\n const resolvedStyleSizes = new Map<string, NodeFootprint>();\n for (const node of graph.nodes) {\n const resolved = options.nodeSize?.(node);\n const size = sizeOf(node, fallbackW, fallbackH, options.nodeSize);\n sizes.set(node.id, size);\n // Only re-stamp the node's `style` from the resolver when `sizeOf` actually\n // USED the resolver — i.e. the dagre size equals the resolved footprint. A\n // stamped group container ignores the resolver (style wins, see sizeOf), so\n // we must NOT overwrite its authoritative box footprint with the resolver's\n // value (that would shrink the rendered box back to e.g. a 38px slim bar).\n if (resolved && resolved.width === size.width && resolved.height === size.height) {\n resolvedStyleSizes.set(node.id, resolved);\n }\n g.setNode(node.id, { width: size.width, height: size.height });\n if (node.parentId) {\n g.setParent(node.id, node.parentId);\n }\n }\n\n // When a sibling order is requested, feed each fork's child edges to dagre in\n // that order (opt-in; the default path keeps edges byte-identical to before).\n // `reorderSiblingEdges` returns FORWARD edges only (loop edges are dropped —\n // they never shape layout, and the `kind === \"loop\"` skip below is the no-op\n // for that case). The graph's edges are returned UNCHANGED from this function\n // (see the final `return` — loop edges still reach the renderer intact).\n const layoutEdges = options.siblingOrder\n ? reorderSiblingEdges(graph.edges, options.siblingOrder)\n : graph.edges;\n for (const e of layoutEdges) {\n if (e.data?.kind === \"loop\") continue; // visual-only — never shapes layout\n if (g.hasNode(e.source) && g.hasNode(e.target)) {\n // Per-edge pull (weight) + stretch (minlen) — consumer-controlled.\n const label: { weight?: number; minlen?: number } = {};\n const weight = options.edgeWeight?.(e);\n const minlen = options.edgeMinLen?.(e);\n if (typeof weight === \"number\") label.weight = weight;\n if (typeof minlen === \"number\") label.minlen = minlen;\n g.setEdge(e.source, e.target, label);\n }\n }\n\n dagre.layout(g);\n\n // dagre returns CENTER coords; xyflow wants TOP-LEFT. Nested children get\n // coords RELATIVE to their parent's top-left (xyflow convention).\n const positioned: TraceNode[] = graph.nodes.map((node) => {\n const laidOut = g.node(node.id);\n if (!laidOut) return node; // unreached (orphan) — keep original position\n const size = sizes.get(node.id)!;\n let x = laidOut.x - size.width / 2;\n let y = laidOut.y - size.height / 2;\n if (node.parentId) {\n const parent = g.node(node.parentId);\n const parentSize = sizes.get(node.parentId);\n if (parent && parentSize) {\n x -= parent.x - parentSize.width / 2;\n y -= parent.y - parentSize.height / 2;\n }\n }\n // Apply consumer-resolved size to `style` so xyflow RENDERS at the same\n // footprint dagre placed (paint matches layout). Only for resolver-set\n // sizes — style/default-sized nodes already render correctly.\n const styleSize = resolvedStyleSizes.get(node.id);\n if (styleSize) {\n return {\n ...node,\n position: { x, y },\n style: { ...(node.style ?? {}), width: styleSize.width, height: styleSize.height },\n };\n }\n return { ...node, position: { x, y } };\n });\n\n return { nodes: positioned, edges: graph.edges };\n}\n\n/**\n * Build a `TraceFlowLayout` from dagre options. Pass to\n * `<TraceFlow layout={...}>` / `<TracedFlow layout={...}>`, or use it as a\n * `baseLayout` for the group/main-box transforms.\n */\nexport function createDagreTraceLayout(\n options: DagreTraceLayoutOptions = {},\n): TraceFlowLayout {\n return (graph: TraceGraph) => dagreTraceLayout(graph, options);\n}\n","/**\n * snapLinearSuccessors — pure post-dagre alignment pass for the chart SPINE.\n *\n * THE PROBLEM IT FIXES\n * --------------------\n * On a chart like `Context(selector) → [slot, slot] → messageAPI(merge) →\n * callLLM(linear)`, dagre's default balanced x-assignment (Brandes–Köpf\n * `balance()` = median of 4 extreme alignments) drifts a pure linear\n * successor a few px off the spine on an ASYMMETRIC graph (a wide callLLM\n * node + the fork above unbalance the alignment passes). Measured centers:\n * context 915, messageAPI 917, callLLM 921 — callLLM is ~6px off even though\n * it is a single-in / single-out continuation of messageAPI.\n *\n * THE FIX\n * -------\n * A pure `(graph) => graph` pass applied AFTER `dagreTraceLayout`. A node with\n * EXACTLY ONE forward (non-loop) predecessor, whose predecessor has EXACTLY\n * ONE forward (non-loop) successor, and which shares the same `parentId`\n * coordinate space, snaps its CENTER-x onto that predecessor's center-x. The\n * top-left `position.x` is recomputed from the new center using the node's OWN\n * width. `y` is never touched.\n *\n * WHAT IT NEVER MOVES (by construction of the predicate)\n * ------------------------------------------------------\n * - the ROOT — 0 predecessors → predicate (1) fails\n * - a MERGE (messageAPI) — >1 predecessor → predicate (1) fails\n * - FORK / DECISION children — predecessor out-deg>1 → predicate (2) fails\n * - cross-compound hops — differing parentId → predicate (3) fails\n * A fork/merge NODE itself is still snapped onto ITS upstream predecessor when\n * that predecessor is a pure linear hop — correct, it is a continuation of\n * whatever feeds it. Only its CHILDREN are protected.\n *\n * PROPERTIES\n * ----------\n * - PURE: never mutates the input graph; returns a new nodes array (edges by\n * reference, mirroring dagre's own pass-through).\n * - IDEMPOTENT: re-running finds centers already equal → zero-delta writes.\n * - CHAIN-PROPAGATING: nodes are processed in rank (y-asc) order, so a\n * snapped predecessor's corrected x flows down a `a→b→c` chain in one pass.\n * - GEOMETRY-EXACT: widths come from the SAME resolver→style→default order\n * dagre used (`sizeOf`), so reconstructed centers match dagre's placement.\n *\n * Compose it with dagre via `createSnappedDagreLayout`, or call it directly on\n * a `dagreTraceLayout(...)` result. Kept SEPARATE from `dagreTraceLayout` so\n * the base layout's output stays byte-identical for consumers that don't opt\n * in.\n */\n\nimport type { Edge } from \"@xyflow/react\";\nimport type { TraceGraph, TraceNode, TraceEdgeData } from \"../traceStructureRecorder\";\nimport type { TraceFlowLayout } from \"../TraceFlow\";\nimport {\n DEFAULT_NODE_H,\n DEFAULT_NODE_W,\n sizeOf,\n type NodeSizeResolver,\n} from \"./dagreTraceLayout\";\n\n/**\n * Options for the snap pass. These MUST mirror the size-relevant options\n * passed to the `dagreTraceLayout` run that produced the graph, so the pass\n * reconstructs each node's center from the identical width.\n */\nexport interface SnapLinearSuccessorsOptions {\n /** Per-node size resolver — same one passed to dagre. Resolution order:\n * resolver → `node.style` → default. */\n readonly nodeSize?: NodeSizeResolver;\n /** Fallback width when a node carries no resolver/style size. Must match\n * the dagre run's `nodeWidth`. Default 200. */\n readonly nodeWidth?: number;\n /** Fallback height. Must match the dagre run's `nodeHeight`. Default 80.\n * (Height is unused for x-snapping but kept so `sizeOf` resolves the same\n * footprint the resolver may key on.) */\n readonly nodeHeight?: number;\n}\n\n/**\n * Snap pure single-in/single-out linear successors onto their predecessor's\n * center-x. See the file header for the full contract. Pure + idempotent.\n */\nexport function snapLinearSuccessors(\n graph: TraceGraph,\n options: SnapLinearSuccessorsOptions = {},\n): TraceGraph {\n // Empty guard — preserve memo identity, mirror dagre's empty guard.\n if (graph.nodes.length === 0) return graph;\n\n const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W;\n const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H;\n\n // ── id → node map, and a width per node (identical resolution to dagre). ──\n const byId = new Map<string, TraceNode>();\n const width = new Map<string, number>();\n for (const n of graph.nodes) {\n byId.set(n.id, n);\n width.set(n.id, sizeOf(n, fallbackW, fallbackH, options.nodeSize).width);\n }\n\n // ── forward adjacency from edges, EXCLUDING loop back-edges (invariant I1, ──\n // matching dagre's own loop exclusion). Dedupe (source,target) so a doubled\n // edge can't fake a fork; only count edges whose BOTH endpoints are nodes.\n const preds = new Map<string, string[]>();\n const outDegree = new Map<string, number>();\n const seenEdge = new Set<string>();\n for (const e of graph.edges as Edge<TraceEdgeData>[]) {\n if (e.data?.kind === \"loop\") continue;\n if (!byId.has(e.source) || !byId.has(e.target)) continue;\n const key = `${e.source}\u0000${e.target}`;\n if (seenEdge.has(key)) continue;\n seenEdge.add(key);\n const list = preds.get(e.target);\n if (list) list.push(e.source);\n else preds.set(e.target, [e.source]);\n outDegree.set(e.source, (outDegree.get(e.source) ?? 0) + 1);\n }\n\n // ── mutable working x per node (clone — never mutate input). Centers read ──\n // these so a chain `a→b→c` propagates in one pass.\n const workingX = new Map<string, number>();\n for (const n of graph.nodes) workingX.set(n.id, n.position.x);\n const centerX = (id: string) => workingX.get(id)! + width.get(id)! / 2;\n\n // ── rank order = y ascending (TB rank is monotonic in y), ties by current ──\n // x then id → fully deterministic, predecessor finalized before successor.\n const order = [...graph.nodes].sort(\n (a, b) =>\n a.position.y - b.position.y ||\n a.position.x - b.position.x ||\n (a.id < b.id ? -1 : a.id > b.id ? 1 : 0),\n );\n\n for (const n of order) {\n const p = preds.get(n.id);\n if (!p || p.length !== 1) continue; // (1) ROOT (0) or MERGE (>1) → skip\n const pid = p[0]!;\n if ((outDegree.get(pid) ?? 0) !== 1) continue; // (2) pred is FORK/branch → skip\n const P = byId.get(pid)!;\n // (3) same coordinate space — treat both `undefined` as the shared top level.\n if ((n.parentId ?? undefined) !== (P.parentId ?? undefined)) continue;\n // SNAP: center-x of n := center-x of p (p may already be snapped this pass).\n workingX.set(n.id, centerX(pid) - width.get(n.id)! / 2);\n }\n\n // ── emit a new graph; only rebuild nodes whose x actually changed (cheap, ──\n // preserves identity for untouched nodes). Order is preserved (xyflow's\n // parent-before-child invariant). Edges pass through by reference.\n const nodes = graph.nodes.map((n) => {\n const nx = workingX.get(n.id)!;\n return nx === n.position.x ? n : { ...n, position: { x: nx, y: n.position.y } };\n });\n return { nodes, edges: graph.edges };\n}\n\n/**\n * Convenience: run a base `TraceFlowLayout` (typically `createDagreTraceLayout`)\n * then the snap pass, as one composed layout.\n *\n * @example\n * const layout = createSnappedDagreLayout(\n * createDagreTraceLayout({ nodeSize }),\n * { nodeSize }, // SAME size opts so widths match\n * );\n */\nexport function createSnappedDagreLayout(\n base: TraceFlowLayout,\n options: SnapLinearSuccessorsOptions = {},\n): TraceFlowLayout {\n return (graph: TraceGraph) => snapLinearSuccessors(base(graph), options);\n}\n","/**\n * centerForkParents — pure post-dagre pass that centers a FORK/DECISION parent\n * over the geometric span of its direct children.\n *\n * THE PROBLEM IT FIXES\n * --------------------\n * dagre's Brandes–Köpf `balance()` places a node at a balanced BARYCENTER, not\n * the geometric MIDPOINT of its children's span. On asymmetric or even-count\n * fans (e.g. a parent feeding 4 slots of differing widths) the parent sits\n * off-center, so the fan tilts and reads as a staggered bus rather than a clean,\n * symmetric fork. (Centering the parent is the layout half of the fix; a shared\n * fan bend-row is the edge half — see stepRouting.)\n *\n * THE FIX\n * -------\n * A pure `(graph) => graph` pass applied AFTER `dagreTraceLayout` (+ the snap\n * pass). A node with forward (non-loop) out-degree >= 2 that is NOT a merge\n * (in-degree <= 1) has its CENTER-x set to the midpoint of the min/max\n * center-x of its direct children in the SAME compound. `position.x` is\n * recomputed from the node's OWN width; `y` is never touched.\n *\n * WHAT IT NEVER MOVES\n * -------------------\n * - linear nodes (out-degree < 2) — not a fork\n * - MERGE nodes (in-degree > 1) — moving a join distorts its inbound\n * - children in a different compound — cross-box hop, skipped\n * Processed RANK-DESCENDING (y desc) so a nested fork centers over its own\n * (already-centered) children before its parent centers over it.\n *\n * PROPERTIES — mirror snapLinearSuccessors: PURE (new nodes array, edges by\n * reference), IDEMPOTENT (re-running finds centers equal → zero-delta), and\n * GEOMETRY-EXACT (widths via the SAME `sizeOf` resolver→style→default order\n * dagre used — the identical-resolver invariant; group containers resolve to\n * their stamped style footprint, never the resolver).\n */\n\nimport type { Edge } from \"@xyflow/react\";\nimport type { TraceGraph, TraceNode, TraceEdgeData } from \"../traceStructureRecorder\";\nimport type { TraceFlowLayout } from \"../TraceFlow\";\nimport {\n DEFAULT_NODE_H,\n DEFAULT_NODE_W,\n sizeOf,\n type NodeSizeResolver,\n} from \"./dagreTraceLayout\";\n\nexport interface CenterForkParentsOptions {\n /** Per-node size resolver — the SAME one passed to dagre. */\n readonly nodeSize?: NodeSizeResolver;\n /** Fallback width (match the dagre run's `nodeWidth`). Default 200. */\n readonly nodeWidth?: number;\n /** Fallback height (match the dagre run's `nodeHeight`). Default 80. */\n readonly nodeHeight?: number;\n /** Horizontal clearance to preserve from a same-rank neighbor when\n * re-centering (match the dagre run's `nodeSep`). Default 60. */\n readonly nodeSep?: number;\n}\n\nexport function centerForkParents(\n graph: TraceGraph,\n options: CenterForkParentsOptions = {},\n): TraceGraph {\n if (graph.nodes.length === 0) return graph;\n\n const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W;\n const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H;\n\n const byId = new Map<string, TraceNode>();\n const width = new Map<string, number>();\n for (const n of graph.nodes) {\n byId.set(n.id, n);\n width.set(n.id, sizeOf(n, fallbackW, fallbackH, options.nodeSize).width);\n }\n\n // Forward adjacency, EXCLUDING loop back-edges (matching dagre + snap), deduped.\n const childrenOf = new Map<string, string[]>();\n const predsOf = new Map<string, string[]>();\n const outDegree = new Map<string, number>();\n const inDegree = new Map<string, number>();\n const seen = new Set<string>();\n for (const e of graph.edges as Edge<TraceEdgeData>[]) {\n if (e.data?.kind === \"loop\") continue;\n if (!byId.has(e.source) || !byId.has(e.target)) continue;\n const key = `${e.source} ${e.target}`;\n if (seen.has(key)) continue;\n seen.add(key);\n const cl = childrenOf.get(e.source);\n if (cl) cl.push(e.target);\n else childrenOf.set(e.source, [e.target]);\n const pl = predsOf.get(e.target);\n if (pl) pl.push(e.source);\n else predsOf.set(e.target, [e.source]);\n outDegree.set(e.source, (outDegree.get(e.source) ?? 0) + 1);\n inDegree.set(e.target, (inDegree.get(e.target) ?? 0) + 1);\n }\n\n // Working x (clone — never mutate input). Reads propagate within one pass.\n const workingX = new Map<string, number>();\n for (const n of graph.nodes) workingX.set(n.id, n.position.x);\n const centerX = (id: string) => workingX.get(id)! + width.get(id)! / 2;\n\n const nodeSep = options.nodeSep ?? 60;\n // Clamp a desired top-left x for `id` so it can't reduce same-rank,\n // same-compound sibling clearance below the reserved nodeSep gap.\n const clampX = (id: string, desiredX: number): number => {\n const w = width.get(id)!;\n const x0 = workingX.get(id)!;\n const self = byId.get(id)!;\n let minX = -Infinity;\n let maxX = Infinity;\n for (const m of graph.nodes) {\n if (m.id === id || m.parentId !== self.parentId) continue;\n if (Math.abs(m.position.y - self.position.y) > 1) continue; // same rank only\n const mLeft = workingX.get(m.id)!;\n const mRight = mLeft + width.get(m.id)!;\n if (mRight <= x0) minX = Math.max(minX, mRight + nodeSep);\n else if (mLeft >= x0 + w) maxX = Math.min(maxX, mLeft - nodeSep - w);\n }\n return minX <= maxX ? Math.max(minX, Math.min(maxX, desiredX)) : x0;\n };\n\n // Rank-DESCENDING (y desc) so nested forks center before their ancestors.\n const order = [...graph.nodes].sort((a, b) =>\n b.position.y - a.position.y || a.position.x - b.position.x || a.id.localeCompare(b.id),\n );\n for (const n of order) {\n if ((outDegree.get(n.id) ?? 0) < 2) continue; // not a fork/decision\n if ((inDegree.get(n.id) ?? 0) > 1) continue; // a merge — leave it\n const kids = (childrenOf.get(n.id) ?? []).filter(\n (k) => byId.get(k)?.parentId === n.parentId, // same compound only\n );\n if (kids.length < 2) continue;\n const centers = kids.map(centerX);\n const wN = width.get(n.id)!;\n const span = (Math.min(...centers) + Math.max(...centers)) / 2; // fan center\n workingX.set(n.id, clampX(n.id, span - wN / 2));\n\n // Propagate the new center UP the LINEAR trunk feeding this fork: a node that\n // is BOTH a fork parent AND a single-in/single-out continuation must keep its\n // predecessor chain straight, else the edge INTO the fork jogs (a decider fed\n // by one stage is the common case). Walk while single-pred + single-out +\n // NOT a merge + same compound; cycle-guarded; each move clamped.\n // NOTE: the move is clamp-LIMITED — if a trunk node is boxed by same-rank\n // neighbours closer than nodeSep on both sides, clampX leaves it put and the\n // into-fork edge stays slightly jogged (best-effort, never overlaps).\n let curId = n.id;\n const walked = new Set<string>([curId]);\n for (;;) {\n const ps = predsOf.get(curId);\n if (!ps || ps.length !== 1) break; // not a single predecessor\n const p = ps[0];\n if (walked.has(p)) break; // cycle guard (defensive — forward graph is a DAG)\n if ((outDegree.get(p) ?? 0) !== 1) break; // predecessor forks elsewhere → stop\n if ((inDegree.get(p) ?? 0) > 1) break; // predecessor is a MERGE — moving it\n // would jog ITS inbound edges (same reason the main loop leaves merges\n // alone); stop the trunk here.\n if (byId.get(p)?.parentId !== byId.get(curId)?.parentId) break; // cross-compound\n workingX.set(p, clampX(p, centerX(curId) - width.get(p)! / 2));\n walked.add(p);\n curId = p;\n }\n }\n\n const nodes = graph.nodes.map((n) =>\n workingX.get(n.id) === n.position.x\n ? n\n : { ...n, position: { x: workingX.get(n.id)!, y: n.position.y } },\n );\n return { nodes, edges: graph.edges };\n}\n\n/** Compose a base layout (dagre, or snapped-dagre) then the fork-centering pass. */\nexport function withForkCentering(\n base: TraceFlowLayout,\n options: CenterForkParentsOptions = {},\n): TraceFlowLayout {\n return (graph: TraceGraph) => centerForkParents(base(graph), options);\n}\n","/**\n * createTraceRuntimeOverlay — event-driven runtime overlay for `<TracedFlow>`.\n *\n * The runtime twin of `createTraceStructureRecorder` (L7.7). Where the\n * structure recorder accumulates the build-time graph SHAPE from\n * `StructureRecorder` events, this recorder accumulates the runtime\n * EXECUTION STATE (which nodes ran, current active, errors) from\n * `FlowRecorder` events. The two compose into the full time-travel\n * trace UI:\n *\n * StructureRecorder events → TraceGraph (nodes + edges, id-keyed)\n * FlowRecorder events → RuntimeOverlay (per-node state, id-keyed)\n * │\n * ▼\n * <TracedFlow graph={...} overlay={...} scrubIndex={i} />\n *\n * **Universal key**: `runtimeStageId = [subflowPath/]stageId#executionIndex`.\n * Loops re-execute the same stageId with bumping executionIndex — the\n * overlay records each execution as a distinct step in `executionOrder`\n * but updates the SAME node-by-id in `doneStageIds` (because the build-\n * time graph has one node per spec — loops re-visit it).\n *\n * Per L7.7 panel guidance: the consumer pattern mirrors recorder error\n * isolation, exposes a pub-sub `subscribe(listener)` + monotonic\n * `version()` for `useSyncExternalStore` integration, and accumulates\n * pure data with zero React coupling.\n */\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Local type aliases mirroring footprintjs FlowRecorder\n// ─────────────────────────────────────────────────────────────────────────────\n//\n// Same rationale as traceStructureRecorder.ts: explainable-ui has no\n// `footprintjs` dep declared (consumer wires it). We mirror the\n// subset of `FlowRecorder` we consume. If footprintjs changes the\n// interface, this module's types update in lockstep.\n\ninterface TraversalContext {\n readonly runtimeStageId: string;\n readonly iteration?: number;\n readonly runId?: string;\n}\n\ninterface RuntimeStageExecutedEvent {\n readonly stageName: string;\n readonly stageId?: string;\n /** Discriminator for which kind of stage completed. footprintjs v6+\n * fires this event uniformly for every stage kind (proposal #003);\n * consumers route by `stageType` without a chart-spec lookup. */\n readonly stageType: 'linear' | 'decider' | 'fork' | 'selector' | 'subflow-mount';\n readonly traversalContext: TraversalContext;\n}\n\ninterface RuntimeErrorEvent {\n readonly stageName: string;\n readonly stageId?: string;\n readonly message?: string;\n readonly traversalContext?: TraversalContext;\n}\n\ninterface RuntimeRunStartEvent {\n readonly traversalContext?: TraversalContext;\n}\n\ninterface RuntimeRunEndEvent {\n readonly traversalContext?: TraversalContext;\n}\n\n/** Minimal FlowRecorder interface mirror — see top-of-file rationale.\n *\n * As of footprintjs v6 (proposal #003), `onStageExecuted` fires\n * uniformly for ALL stage kinds — linear / decider / fork / selector\n * / subflow-mount. The event payload carries a `stageType` field for\n * consumers that need to route by kind. We no longer need separate\n * `onDecision` / `onFork` / `onSelected` handlers to track \"did this\n * stage run\" — a single `onStageExecuted` handler suffices. */\nexport interface MinimalFlowRecorder {\n readonly id: string;\n onStageExecuted?(event: RuntimeStageExecutedEvent): void;\n onError?(event: RuntimeErrorEvent): void;\n onRunStart?(event: RuntimeRunStartEvent): void;\n onRunEnd?(event: RuntimeRunEndEvent): void;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Runtime overlay shape\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * One entry in the execution timeline. `<TracedFlow>` keys time-travel\n * scrubbing on the index into this array — at index `i`, all entries\n * `0..i-1` are \"done\", entry `i` is \"active\".\n */\nexport interface RuntimeExecutionStep {\n /** `[subflowPath/]stageId#executionIndex` — universal key. */\n readonly runtimeStageId: string;\n /** Base stage id (without `#N`) — matches the `TraceGraph` node id. */\n readonly stageId: string;\n /** Human-readable label (from event.stageName). */\n readonly stageName: string;\n /** When this step recorded, in ms since recorder start. */\n readonly timestampMs: number;\n}\n\nexport interface RuntimeOverlay {\n /** Ordered execution history — drives time-travel scrubbing. */\n readonly executionOrder: readonly RuntimeExecutionStep[];\n /** Per-base-stageId error message (most-recent wins). */\n readonly errors: ReadonlyMap<string, string>;\n /** True after `onRunStart` until `onRunEnd` — useful for \"still running\" indicators. */\n readonly running: boolean;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Handle\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface TraceRuntimeOverlayHandle {\n /** The recorder to attach via `executor.attachFlowRecorder(handle.recorder)`. */\n recorder: MinimalFlowRecorder;\n /** Returns a defensive copy of the current overlay state. */\n getOverlay(): RuntimeOverlay;\n /** Pub-sub: returns unsubscribe. Designed for `useSyncExternalStore`. */\n subscribe(listener: () => void): () => void;\n /** Monotonic version counter — bumps once per overlay-mutating event. */\n version(): number;\n /** Reset for reuse across runs. Does NOT bump version or notify (matches\n * traceStructureRecorder's reset contract). */\n reset(): void;\n}\n\nexport interface CreateTraceRuntimeOverlayOptions {\n id?: string;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Internal helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport { createNotifier } from \"./_internal/notifyChange\";\n\n/**\n * Strip `#executionIndex` suffix to get the base stage id.\n *\n * **WARNING (invariant I3)**: use ONLY for DISPLAY. NEVER for matching\n * commitLog stageIds — those use the full path-prefixed id (e.g.,\n * `'sf-a/sf-b/inner'`) as emitted by the engine. Parsing back to the\n * unqualified inner name loses uniqueness across subflow instances.\n */\nfunction parseStageIdFromRuntimeStageId(runtimeStageId: string): string {\n const hashIdx = runtimeStageId.indexOf(\"#\");\n return hashIdx >= 0 ? runtimeStageId.slice(0, hashIdx) : runtimeStageId;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Factory\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport function createTraceRuntimeOverlay(\n options: CreateTraceRuntimeOverlayOptions = {},\n): TraceRuntimeOverlayHandle {\n const id = options.id ?? \"trace-runtime-overlay\";\n const startTime = performance.now();\n\n let executionOrder: RuntimeExecutionStep[] = [];\n // Defensive dedupe by runtimeStageId — should be moot post-#003\n // since the engine fires `onStageExecuted` exactly once per stage\n // execution, but a future change or a misbehaving recorder upstream\n // could still produce duplicates; keep the set as belt-and-suspenders.\n const recordedRuntimeStageIds = new Set<string>();\n const errors = new Map<string, string>();\n let running = false;\n const notifier = createNotifier(\"traceRuntimeOverlay\");\n const notifyChange = notifier.notify;\n\n function pushStep(runtimeStageId: string, stageId: string, stageName: string): void {\n if (recordedRuntimeStageIds.has(runtimeStageId)) return;\n recordedRuntimeStageIds.add(runtimeStageId);\n executionOrder.push({\n runtimeStageId,\n stageId,\n stageName,\n timestampMs: performance.now() - startTime,\n });\n notifyChange();\n }\n\n const recorder: MinimalFlowRecorder = {\n id,\n onRunStart() {\n running = true;\n notifyChange();\n },\n onRunEnd() {\n running = false;\n notifyChange();\n },\n onStageExecuted(event) {\n // footprintjs v6 (#003) fires this for EVERY stage kind —\n // linear / decider / fork / selector / subflow-mount — so\n // we no longer need separate handlers for the branching events.\n const runtimeStageId = event.traversalContext.runtimeStageId;\n const baseStageId = parseStageIdFromRuntimeStageId(runtimeStageId);\n pushStep(runtimeStageId, baseStageId, event.stageName);\n },\n onError(event) {\n const fallbackId =\n event.stageId ??\n (event.traversalContext\n ? parseStageIdFromRuntimeStageId(event.traversalContext.runtimeStageId)\n : event.stageName);\n errors.set(fallbackId, event.message ?? \"error\");\n notifyChange();\n },\n };\n\n return {\n recorder,\n getOverlay(): RuntimeOverlay {\n return {\n executionOrder: executionOrder.map((s) => ({ ...s })),\n errors: new Map(errors),\n running,\n };\n },\n subscribe: notifier.subscribe,\n version: notifier.version,\n reset(): void {\n executionOrder = [];\n recordedRuntimeStageIds.clear();\n errors.clear();\n running = false;\n // Note: reset does NOT bump version or notify (matches\n // traceStructureRecorder contract — see its `reset()` JSDoc\n // for the consumer-facing recipe).\n },\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Overlay slicing for time-travel\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Snapshot of overlay state AT a specific scrub index. Drives node\n * coloring in `<TracedFlow>`.\n */\nexport interface RuntimeOverlaySlice {\n /** Base stage ids that completed before the active scrub position. */\n readonly doneStageIds: ReadonlySet<string>;\n /** The currently-active stage id (or `null` when scrub is at 0 with no exec yet). */\n readonly activeStageId: string | null;\n /** Union of done + active — convenient for \"executed at all\" checks. */\n readonly executedStageIds: ReadonlySet<string>;\n /** The full ordered list of base stage ids up through the active position —\n * used by renderers that want to number stages by occurrence (e.g.,\n * show \"3rd loop iteration\" badges). */\n readonly executedOrderIds: readonly string[];\n /** Pass-through errors map for the renderer. */\n readonly errors: ReadonlyMap<string, string>;\n}\n\n/**\n * Slice `overlay.executionOrder` at the given index:\n *\n * - `executionOrder[0..index-1]` → \"done\"\n * - `executionOrder[index]` → \"active\"\n * - `index >= executionOrder.length` → all done, no active\n *\n * Returns an empty slice when overlay has no execution history.\n */\nexport function sliceOverlay(\n overlay: RuntimeOverlay,\n index: number,\n): RuntimeOverlaySlice {\n const order = overlay.executionOrder;\n if (order.length === 0) {\n return {\n doneStageIds: new Set(),\n activeStageId: null,\n executedStageIds: new Set(),\n executedOrderIds: [],\n errors: overlay.errors,\n };\n }\n const clampedIndex = Math.max(0, Math.min(index, order.length - 1));\n const doneStageIds = new Set<string>();\n for (let i = 0; i < clampedIndex; i++) {\n doneStageIds.add(order[i]!.stageId);\n }\n const activeStep = order[clampedIndex];\n const activeStageId = activeStep ? activeStep.stageId : null;\n const executedStageIds = new Set(doneStageIds);\n if (activeStageId) executedStageIds.add(activeStageId);\n const executedOrderIds = order.slice(0, clampedIndex + 1).map((s) => s.stageId);\n return {\n doneStageIds,\n activeStageId,\n executedStageIds,\n executedOrderIds,\n errors: overlay.errors,\n };\n}\n","import { memo, useEffect, useRef } from \"react\";\nimport { Handle, Position } from \"@xyflow/react\";\nimport type { NodeProps } from \"@xyflow/react\";\nimport { theme } from \"../../theme\";\n\nconst KEYFRAMES_ID = \"fp-stage-node-keyframes\";\nconst KEYFRAMES_CSS = `\n@media (prefers-reduced-motion: no-preference) {\n @keyframes fp-pulse {\n 0%, 100% { opacity: 0.4; transform: scale(1); }\n 50% { opacity: 0.15; transform: scale(1.06); }\n }\n @keyframes fp-blink {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.3; }\n }\n}\n@media (prefers-reduced-motion: reduce) {\n @keyframes fp-pulse { 0%, 100% { opacity: 0.3; } }\n @keyframes fp-blink { 0%, 100% { opacity: 1; } }\n}\n`;\n\nexport interface StageNodeData {\n label: string;\n active?: boolean;\n done?: boolean;\n error?: boolean;\n linked?: boolean;\n /** Semantic icon hint (e.g., \"llm\", \"tool\", \"rag\", \"start\", \"parse\", \"agent\", \"guard\") */\n icon?: string;\n /** Step numbers in execution order (shown as badges — multiple when revisited via loops) */\n stepNumbers?: number[];\n /** Node was not executed (dim it) */\n dimmed?: boolean;\n /** Node is a subflow root (show nested indicator) */\n isSubflow?: boolean;\n /** Node uses lazy resolution (dashed border + cloud icon when unresolved) */\n isLazy?: boolean;\n /** Node is a decider (renders as diamond shape per flowchart convention) */\n isDecider?: boolean;\n /** Node is a fork (parallel fan-out) */\n isFork?: boolean;\n /** Human-readable description of what this stage does */\n description?: string;\n /** Subflow identifier — set when this node belongs to a subflow */\n subflowId?: string;\n /**\n * Stable stage identifier from the spec (`SpecNode.id`). Renderable as a\n * small monospace caption under the label when `showStageId` is true —\n * useful for teaching the runtimeStageId convention and for debugging\n * which node a recorder event belongs to.\n */\n stageId?: string;\n /**\n * When true, render the `stageId` as a small monospace caption beneath\n * the label. Default false. Drives the \"Show IDs\" toggle in\n * ExplainableShell.\n */\n showStageId?: boolean;\n /**\n * Visual emphasis hint — generic, so the renderer stays domain-agnostic.\n * `hero` = a stage the viewer cares about (accent border + tint + bold);\n * `muted` = mechanism/plumbing (recedes — faded + thin border). The\n * consumer's graph builder sets this from its own semantics (e.g. the\n * agentfootprint lens maps `stageRole` → emphasis). Layers UNDER run status:\n * active/done/error colours still override during a run.\n */\n emphasis?: \"hero\" | \"muted\";\n /**\n * Size tier — scales the card's text + padding to match the footprint the\n * layout allocated (the layout's node-size resolver must scale in lockstep,\n * else the card and its laid-out box disagree). `lg` = a focal stage,\n * `sm` = a minor/plumbing stage, default `md`. Generic — no domain meaning.\n */\n size?: \"sm\" | \"md\" | \"lg\";\n [key: string]: unknown;\n}\n\n// ── Stage icon SVGs ───────────────────────────────────────────────────────\n// Inline SVGs for crisp rendering at any size. Consumers pass a string key\n// via SpecNode.icon; StageNode renders the matching mini-icon.\n\nconst ICON_SIZE = 16;\n\nfunction StageIcon({ type, color }: { type: string; color: string }) {\n const s = ICON_SIZE;\n const props = { width: s, height: s, viewBox: `0 0 ${s} ${s}`, fill: \"none\", style: { flexShrink: 0 } as const };\n\n switch (type) {\n // LLM / AI call — brain/sparkle\n case \"llm\":\n case \"ai\":\n return (\n <svg {...props}>\n <circle cx=\"8\" cy=\"8\" r=\"6\" stroke={color} strokeWidth=\"1.5\" />\n <path d=\"M5.5 8C5.5 6.5 6.5 5 8 5S10.5 6.5 10.5 8\" stroke={color} strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n <circle cx=\"8\" cy=\"9.5\" r=\"1\" fill={color} />\n <line x1=\"8\" y1=\"2\" x2=\"8\" y2=\"3.5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"12.5\" y1=\"4\" x2=\"11.2\" y2=\"5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"3.5\" y1=\"4\" x2=\"4.8\" y2=\"5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n </svg>\n );\n\n // Tool / function call — gear\n case \"tool\":\n case \"function\":\n return (\n <svg {...props}>\n <circle cx=\"8\" cy=\"8\" r=\"3\" stroke={color} strokeWidth=\"1.5\" />\n {[0, 45, 90, 135, 180, 225, 270, 315].map((angle) => {\n const rad = (angle * Math.PI) / 180;\n const x1 = 8 + Math.cos(rad) * 4.5;\n const y1 = 8 + Math.sin(rad) * 4.5;\n const x2 = 8 + Math.cos(rad) * 6;\n const y2 = 8 + Math.sin(rad) * 6;\n return <line key={angle} x1={x1} y1={y1} x2={x2} y2={y2} stroke={color} strokeWidth=\"1.5\" strokeLinecap=\"round\" />;\n })}\n </svg>\n );\n\n // RAG / retrieval — magnifying glass + doc\n case \"rag\":\n case \"search\":\n case \"retrieval\":\n return (\n <svg {...props}>\n <circle cx=\"7\" cy=\"7\" r=\"4\" stroke={color} strokeWidth=\"1.5\" />\n <line x1=\"10\" y1=\"10\" x2=\"13.5\" y2=\"13.5\" stroke={color} strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <line x1=\"5.5\" y1=\"6\" x2=\"8.5\" y2=\"6\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"5.5\" y1=\"8\" x2=\"7.5\" y2=\"8\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n </svg>\n );\n\n // Parse / process — diamond with arrows\n case \"parse\":\n case \"process\":\n case \"transform\":\n return (\n <svg {...props}>\n <rect x=\"4\" y=\"4\" width=\"8\" height=\"8\" rx=\"1.5\" stroke={color} strokeWidth=\"1.5\" transform=\"rotate(45 8 8)\" />\n </svg>\n );\n\n // Start / seed — play triangle\n case \"start\":\n case \"seed\":\n case \"init\":\n return (\n <svg {...props}>\n <path d=\"M5 3.5L12.5 8L5 12.5V3.5Z\" fill={color} opacity=\"0.8\" />\n </svg>\n );\n\n // End / finalize — stop square\n case \"end\":\n case \"finalize\":\n case \"output\":\n return (\n <svg {...props}>\n <rect x=\"4\" y=\"4\" width=\"8\" height=\"8\" rx=\"1.5\" fill={color} opacity=\"0.8\" />\n </svg>\n );\n\n // Agent — person silhouette\n case \"agent\":\n case \"orchestrator\":\n return (\n <svg {...props}>\n <circle cx=\"8\" cy=\"5\" r=\"2.5\" stroke={color} strokeWidth=\"1.5\" />\n <path d=\"M3.5 14C3.5 11 5.5 9 8 9S12.5 11 12.5 14\" stroke={color} strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n );\n\n // Swarm — multi-agent\n case \"swarm\":\n case \"multi-agent\":\n return (\n <svg {...props}>\n <circle cx=\"5\" cy=\"5\" r=\"2\" stroke={color} strokeWidth=\"1.2\" />\n <circle cx=\"11\" cy=\"5\" r=\"2\" stroke={color} strokeWidth=\"1.2\" />\n <circle cx=\"8\" cy=\"11\" r=\"2\" stroke={color} strokeWidth=\"1.2\" />\n <line x1=\"5\" y1=\"7\" x2=\"8\" y2=\"9\" stroke={color} strokeWidth=\"1\" opacity=\"0.5\" />\n <line x1=\"11\" y1=\"7\" x2=\"8\" y2=\"9\" stroke={color} strokeWidth=\"1\" opacity=\"0.5\" />\n </svg>\n );\n\n // Guard / guardrail — shield\n case \"guard\":\n case \"guardrail\":\n case \"validate\":\n return (\n <svg {...props}>\n <path d=\"M8 2L3 5V9C3 11.5 5 13.5 8 14.5C11 13.5 13 11.5 13 9V5L8 2Z\" stroke={color} strokeWidth=\"1.5\" strokeLinejoin=\"round\" />\n <path d=\"M6 8L7.5 9.5L10 6.5\" stroke={color} strokeWidth=\"1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n\n // Stream — wave\n case \"stream\":\n case \"streaming\":\n return (\n <svg {...props}>\n <path d=\"M2 8C4 5 6 11 8 8S12 5 14 8\" stroke={color} strokeWidth=\"1.5\" strokeLinecap=\"round\" fill=\"none\" />\n <path d=\"M2 11C4 8 6 14 8 11S12 8 14 11\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" fill=\"none\" opacity=\"0.5\" />\n </svg>\n );\n\n // Memory / state — database cylinder\n case \"memory\":\n case \"state\":\n case \"db\":\n return (\n <svg {...props}>\n <ellipse cx=\"8\" cy=\"4.5\" rx=\"5\" ry=\"2\" stroke={color} strokeWidth=\"1.3\" />\n <line x1=\"3\" y1=\"4.5\" x2=\"3\" y2=\"11.5\" stroke={color} strokeWidth=\"1.3\" />\n <line x1=\"13\" y1=\"4.5\" x2=\"13\" y2=\"11.5\" stroke={color} strokeWidth=\"1.3\" />\n <ellipse cx=\"8\" cy=\"11.5\" rx=\"5\" ry=\"2\" stroke={color} strokeWidth=\"1.3\" />\n </svg>\n );\n\n // System prompt — document with lines\n case \"system-prompt\":\n case \"prompt\":\n case \"instructions\":\n case \"document\":\n return (\n <svg {...props}>\n <rect x=\"3.5\" y=\"2\" width=\"9\" height=\"12\" rx=\"1.5\" stroke={color} strokeWidth=\"1.3\" fill=\"none\" />\n <line x1=\"5.5\" y1=\"5\" x2=\"10.5\" y2=\"5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"5.5\" y1=\"7.5\" x2=\"10.5\" y2=\"7.5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"5.5\" y1=\"10\" x2=\"8.5\" y2=\"10\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n </svg>\n );\n\n // Messages / conversation — chat bubble\n case \"messages\":\n case \"chat\":\n case \"conversation\":\n return (\n <svg {...props}>\n <rect x=\"2.5\" y=\"3\" width=\"11\" height=\"8\" rx=\"2\" stroke={color} strokeWidth=\"1.3\" fill=\"none\" />\n <path d=\"M5.5 11L5.5 13.5L8.5 11\" stroke={color} strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n <line x1=\"5\" y1=\"6\" x2=\"11\" y2=\"6\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n <line x1=\"5\" y1=\"8.5\" x2=\"9\" y2=\"8.5\" stroke={color} strokeWidth=\"1\" strokeLinecap=\"round\" />\n </svg>\n );\n\n // Loop — circular arrow\n case \"loop\":\n case \"retry\":\n return (\n <svg {...props}>\n <path d=\"M12 8A4 4 0 1 1 8 4\" stroke={color} strokeWidth=\"1.5\" strokeLinecap=\"round\" fill=\"none\" />\n <path d=\"M8 1.5L10.5 4L8 6.5\" stroke={color} strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n </svg>\n );\n\n // Lazy / service — cloud (deferred resolution, loaded on demand)\n case \"lazy\":\n case \"service\":\n case \"cloud\":\n return (\n <svg {...props}>\n <path\n d=\"M4.5 12C2.8 12 1.5 10.7 1.5 9C1.5 7.5 2.5 6.3 3.8 6C4 4 5.8 2.5 8 2.5C9.8 2.5 11.3 3.5 11.9 5C13.9 5.2 15.5 6.8 15.5 8.8C15.5 10.8 13.9 12.5 11.8 12.5H4.5\"\n stroke={color}\n strokeWidth=\"1.3\"\n strokeLinecap=\"round\"\n fill=\"none\"\n />\n </svg>\n );\n\n // Decision — diamond (already handled by isDecider shape)\n case \"decision\":\n case \"router\":\n return (\n <svg {...props}>\n <path d=\"M8 2L14 8L8 14L2 8Z\" stroke={color} strokeWidth=\"1.5\" fill=\"none\" />\n <circle cx=\"8\" cy=\"8\" r=\"1.5\" fill={color} />\n </svg>\n );\n\n default:\n return null;\n }\n}\n\n/**\n * Custom ReactFlow node for pipeline stages.\n * All colors and fonts come from `--fp-*` CSS variables (via theme).\n * Shows execution state via color, icon, step badge, and pulse animation.\n */\nexport const StageNode = memo(function StageNode({\n data,\n}: NodeProps & { data: StageNodeData }) {\n const { label, active, done, error, linked, icon, stepNumbers, dimmed, isSubflow, isLazy, isDecider, isFork, description, stageId, showStageId } = data;\n\n // Lazy nodes show cloud icon by default (unless another icon is specified)\n const effectiveIcon = icon || (isLazy ? \"lazy\" : undefined);\n // Lazy + unresolved = dashed border\n const isLazyUnresolved = isLazy && !done && !active;\n\n // Inject keyframes once into document head\n const injectedRef = useRef(false);\n useEffect(() => {\n if (injectedRef.current) return;\n if (typeof document !== \"undefined\" && !document.getElementById(KEYFRAMES_ID)) {\n const styleEl = document.createElement(\"style\");\n styleEl.id = KEYFRAMES_ID;\n styleEl.textContent = KEYFRAMES_CSS;\n document.head.appendChild(styleEl);\n }\n injectedRef.current = true;\n }, []);\n\n const isOnPath = active || done;\n\n // Emphasis (importance hierarchy). Generic flags — no domain knowledge.\n const isHero = data.emphasis === \"hero\";\n const isMuted = data.emphasis === \"muted\";\n // Card text/padding scale — kept in step with the layout's footprint resolver.\n const sizeScale = data.size === \"lg\" ? 1.3 : data.size === \"sm\" ? 0.85 : 1;\n\n // RESTING (not-yet-run) appearance carries the importance hierarchy: heroes\n // get an accent border + faint accent tint + accent glow. Run status\n // (active/done/error) overrides these during execution.\n const restingBg = isHero\n ? `color-mix(in srgb, ${theme.primary} 12%, ${theme.bgSecondary})`\n : theme.bgSecondary;\n const restingBorder = isHero ? theme.primary : theme.border;\n const restingShadow = isHero\n ? `0 0 10px color-mix(in srgb, ${theme.primary} 22%, transparent)`\n : `0 2px 8px rgba(0,0,0,0.15)`;\n\n const bg = active\n ? theme.primary\n : done\n ? theme.success\n : error\n ? theme.error\n : restingBg;\n\n const borderColor = active\n ? theme.primary\n : done\n ? theme.success\n : error\n ? theme.error\n : restingBorder;\n\n const shadow = active\n ? `0 0 22px color-mix(in srgb, ${theme.primary} 55%, transparent)`\n : done\n ? `0 0 8px color-mix(in srgb, ${theme.success} 20%, transparent)`\n : error\n ? `0 0 12px color-mix(in srgb, ${theme.error} 30%, transparent)`\n : restingShadow;\n\n // Colored states use white for contrast; default uses consumer's text color.\n const textColor =\n active || done || error ? \"#fff\" : theme.textPrimary;\n\n return (\n <>\n <Handle type=\"target\" position={Position.Top} style={{ opacity: 0 }} />\n {/* Centering wrapper. React Flow sizes the node WRAPPER to the layout's\n allocated width (which may be WIDER than the card — e.g. uniform-width\n columns, or a NodeSizeResolver footprint stamped by the layout). The\n card below is content-sized; without this wrapper it sits at the\n wrapper's LEFT edge, so its visual center drifts left of the box\n center the layout placed it at (the wider the box, the worse the\n drift). `width:100%` + center-justify makes the card's visual center\n coincide with the node-box center, so layout centering == paint\n centering. Mirrors SlotPillNode / GroupContainerNode, which already\n fill their wrapper width. */}\n <div style={{ width: \"100%\", display: \"flex\", justifyContent: \"center\" }}>\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n // Plumbing recedes. Layers with the run-overlay `dimmed` (not-yet-run)\n // — a muted AND not-run node is faintest, which is correct.\n opacity: isMuted ? 0.5 : undefined,\n }}\n >\n {/* Step number badges — multiple when revisited via loops */}\n {stepNumbers && stepNumbers.length > 0 && isOnPath && (\n <div\n style={{\n position: \"absolute\",\n top: -10,\n left: -10,\n display: \"flex\",\n gap: 3,\n zIndex: 10,\n }}\n >\n {stepNumbers.map((num, i) => {\n const isLatest = i === stepNumbers.length - 1;\n const badgeBg = isLatest && active ? theme.primary : theme.success;\n const glow = isLatest && active\n ? `color-mix(in srgb, ${theme.primary} 50%, transparent)`\n : `color-mix(in srgb, ${theme.success} 40%, transparent)`;\n return (\n <div\n key={num}\n style={{\n width: 22,\n height: 22,\n borderRadius: \"50%\",\n background: badgeBg,\n color: \"#fff\",\n fontSize: 11,\n fontWeight: 700,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxShadow: `0 0 8px ${glow}`,\n }}\n >\n {num}\n </div>\n );\n })}\n </div>\n )}\n\n {/* Linked pulse ring */}\n {linked && (\n <div\n style={{\n position: \"absolute\",\n inset: -6,\n borderRadius: isDecider ? 0 : `calc(${theme.radius} + 4px)`,\n clipPath: isDecider ? \"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)\" : undefined,\n border: `2px solid ${theme.primary}`,\n opacity: 0.4,\n animation: \"fp-pulse 2s ease-in-out infinite\",\n }}\n />\n )}\n\n {/* Active node pulse ring */}\n {active && (\n <div\n style={{\n position: \"absolute\",\n inset: -6,\n borderRadius: isDecider ? 0 : `calc(${theme.radius} + 4px)`,\n clipPath: isDecider ? \"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)\" : undefined,\n border: `2px solid ${theme.primary}`,\n opacity: 0.3,\n animation: \"fp-pulse 1.5s ease-out infinite\",\n }}\n />\n )}\n\n {/* \"NOW\" badge — marks the step the cursor is on (the live step),\n mirroring the monitor mockup. Sits top-right so it never collides\n with the top-left step-number badge. */}\n {active && (\n <div\n style={{\n position: \"absolute\",\n top: -9,\n right: -8,\n zIndex: 11,\n background: theme.warning,\n color: \"#1a1a1a\",\n fontSize: 9,\n fontWeight: 800,\n letterSpacing: 0.6,\n padding: \"2px 6px\",\n borderRadius: 10,\n boxShadow: `0 0 10px color-mix(in srgb, ${theme.warning} 60%, transparent)`,\n }}\n >\n NOW\n </div>\n )}\n\n {/* Diamond for decider nodes — proper diamond via clip-path */}\n {isDecider ? (\n <div style={{ position: \"relative\", width: 120, height: 72 }}>\n {/* Diamond shape layer */}\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background: bg,\n clipPath: \"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)\",\n border: \"none\",\n boxShadow: shadow,\n transition: \"all 0.3s ease\",\n }}\n />\n {/* Border layer — slightly larger diamond behind */}\n <div\n style={{\n position: \"absolute\",\n inset: -2,\n clipPath: \"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)\",\n background: borderColor,\n zIndex: -1,\n ...(isLazyUnresolved ? {\n background: \"transparent\",\n // Dashed border via SVG for clip-path (CSS border doesn't work with clip-path)\n } : {}),\n }}\n />\n {/* Content — centered on top of diamond */}\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 1,\n fontFamily: theme.fontSans,\n zIndex: 1,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\n {effectiveIcon && <StageIcon type={effectiveIcon} color={textColor} />}\n {!effectiveIcon && (\n <span style={{ fontSize: 9, color: textColor }}>◇</span>\n )}\n <span\n style={{\n fontSize: 11,\n fontWeight: 600,\n color: textColor,\n whiteSpace: \"nowrap\",\n }}\n >\n {label}\n </span>\n </div>\n {description && (\n <span\n style={{\n fontSize: 8,\n fontWeight: 400,\n color: textColor,\n opacity: 0.7,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n maxWidth: 100,\n }}\n >\n {description}\n </span>\n )}\n {showStageId && stageId && (\n <span\n style={{\n fontSize: 8,\n fontFamily: \"ui-monospace, monospace\",\n color: textColor,\n opacity: 0.55,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n maxWidth: 100,\n }}\n title={`stageId: ${stageId}`}\n >\n {stageId}\n </span>\n )}\n </div>\n </div>\n ) : (\n /* Standard rectangular node */\n <div\n style={{\n background: bg,\n border: `${isHero ? \"2.5px\" : isMuted ? \"1px\" : \"2px\"} ${isLazyUnresolved ? \"dashed\" : \"solid\"} ${borderColor}`,\n borderRadius: theme.radius,\n padding: description\n ? `${Math.round(6 * sizeScale)}px ${Math.round(12 * sizeScale)}px`\n : `${Math.round(7 * sizeScale)}px ${Math.round(14 * sizeScale)}px`,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: description ? 2 : 0,\n boxShadow: shadow,\n transition: \"all 0.3s ease\",\n fontFamily: theme.fontSans,\n minWidth: 100,\n justifyContent: \"center\",\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n {/* Semantic icon (lazy nodes default to cloud icon) */}\n {effectiveIcon && <StageIcon type={effectiveIcon} color={textColor} />}\n\n {/* State icon */}\n {done && !effectiveIcon && (\n <span style={{ fontSize: 10, color: textColor }}>✓</span>\n )}\n {active && !effectiveIcon && (\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: \"#fff\",\n animation: \"fp-blink 1s ease-in-out infinite\",\n flexShrink: 0,\n }}\n />\n )}\n {error && !effectiveIcon && (\n <span style={{ fontSize: 10, color: textColor }}>✗</span>\n )}\n\n <span\n style={{\n fontSize: Math.round(13 * sizeScale),\n fontWeight: isHero ? 700 : 500,\n color: textColor,\n whiteSpace: \"nowrap\",\n }}\n >\n {label}\n </span>\n {/* Subflow indicator — nested boxes icon */}\n {isSubflow && (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 16,\n height: 16,\n borderRadius: 3,\n border: `1.5px solid ${textColor}`,\n position: \"relative\",\n opacity: 0.7,\n flexShrink: 0,\n }}\n >\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: 2,\n border: `1px solid ${textColor}`,\n }}\n />\n </span>\n )}\n </div>\n {/* Description subtitle */}\n {description && (\n <span\n style={{\n fontSize: 10,\n fontWeight: 400,\n color: textColor,\n opacity: 0.7,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n maxWidth: 160,\n }}\n >\n {description}\n </span>\n )}\n {/* Stage ID caption — toggled by `showStageId`. Teaches the\n runtimeStageId convention; recorders key their data by\n this ID so consumers can render any recorder's per-stage\n output by lookup. */}\n {showStageId && stageId && (\n <span\n style={{\n fontSize: 9,\n fontFamily: \"ui-monospace, monospace\",\n color: textColor,\n opacity: 0.55,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n maxWidth: 160,\n }}\n title={`stageId: ${stageId}`}\n >\n {stageId}\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n <Handle type=\"source\" position={Position.Bottom} style={{ opacity: 0 }} />\n </>\n );\n});\n","/**\n * Pure helpers for subflow drill-down on a `TraceGraph`.\n *\n * Filtering and breadcrumb computation are derived from the\n * `TraceNodeData.subflowOf` field that the structure recorder sets\n * at `onSubflowMounted` time. Both functions are pure (no I/O, no\n * React) so they can be unit-tested in isolation and reused by any\n * renderer.\n */\n\nimport type { TraceGraph } from \"../traceStructureRecorder\";\n\n/**\n * Filter the trace graph by drill-down scope.\n *\n * - `currentSubflowId === null` → show top-level (nodes with no\n * `subflowOf`). Subflow internals are hidden; their mount node\n * stays visible as a single clickable card.\n * - `currentSubflowId === 'X'` → show only nodes where\n * `subflowOf === 'X'` (the drilled-in subflow's internals).\n *\n * Edges follow the same filter — only edges where both endpoints\n * are in the visible set survive. When nothing would be filtered\n * out, returns the original graph reference (preserves upstream\n * memoization).\n */\nexport function filterGraphForDrill(\n graph: TraceGraph,\n currentSubflowId: string | null,\n): TraceGraph {\n if (graph.nodes.length === 0) return graph;\n const matchesScope = (subflowOf: string | undefined): boolean =>\n currentSubflowId === null ? subflowOf === undefined : subflowOf === currentSubflowId;\n const visibleIds = new Set<string>();\n for (const n of graph.nodes) {\n if (matchesScope(n.data?.subflowOf)) visibleIds.add(n.id);\n }\n if (visibleIds.size === graph.nodes.length) return graph;\n return {\n nodes: graph.nodes.filter((n) => visibleIds.has(n.id)),\n edges: graph.edges.filter((e) => visibleIds.has(e.source) && visibleIds.has(e.target)),\n };\n}\n\n/** Entry in the breadcrumb path. `subflowId === null` is the root. */\nexport interface BreadcrumbEntry {\n subflowId: string | null;\n label: string;\n}\n\n/**\n * Build the breadcrumb path for the current drill level.\n *\n * Always starts with the root `{ subflowId: null, label: 'Chart' }`.\n * When drilled into a subflow, appends one entry with the mount\n * node's display label (falling back to the subflow id). Multi-level\n * drill chains are NOT supported by the current chart UX (drill is\n * always from root or sibling — clicking a deeper subflow's mount\n * replaces the current scope), so the path has at most 2 entries.\n */\nexport function buildSubflowBreadcrumb(\n graph: TraceGraph,\n currentSubflowId: string | null,\n): BreadcrumbEntry[] {\n const out: BreadcrumbEntry[] = [{ subflowId: null, label: \"Chart\" }];\n if (currentSubflowId !== null) {\n const mount = graph.nodes.find((n) => n.data?.subflowId === currentSubflowId);\n out.push({\n subflowId: currentSubflowId,\n label: mount?.data?.label ?? currentSubflowId,\n });\n }\n return out;\n}\n","/**\n * Pure helper for projecting a raw `RuntimeOverlaySlice` into the\n * shape `<TracedFlow>` needs for per-node coloring:\n *\n * `aggregateMountStatus` — when execution is INSIDE a subflow, light\n * up the mount node in the parent view as done/active based on its\n * internals' statuses.\n *\n * Pure (no I/O, no React).\n *\n * Note: there is NO id-normalization step. Both the overlay slice and\n * the structure graph use path-QUALIFIED stage ids (`subflowPath/stageId`,\n * mirroring runtimeStageId), so they match directly. (A former\n * `normalizeSliceLeafIds` step existed only while structure ids were\n * bare; once `walkSubflowSpecInto` started qualifying inner ids, leaf-\n * stripping became a mismatch and was removed.)\n */\n\nimport type { TraceGraph } from \"../traceStructureRecorder\";\n\nexport interface OverlaySlice {\n doneStageIds: ReadonlySet<string>;\n activeStageId: string | null;\n executedStageIds: ReadonlySet<string>;\n executedOrderIds: readonly string[];\n errors: ReadonlyMap<string, string>;\n}\n\n/**\n * Aggregate subflow internals' status onto their mount nodes.\n *\n * - Mount is DONE when EVERY internal stage is done.\n * - Mount is ACTIVE only when an internal stage is CURRENTLY active\n * (not merely past-done), and only when viewing the TOP-LEVEL chart\n * (`currentSubflowId === null`). When drilled INTO a subflow, the\n * active highlight stays on the actual subflow stage, not the mount.\n * (Promoting on past-done internals let a looping subflow steal\n * \"active\" from the real live top-level node — see the inline note.)\n *\n * Pre-condition: slice has already been leaf-normalized so its\n * stage ids match `graph.nodes[].id`.\n */\nexport function aggregateMountStatus(\n slice: OverlaySlice,\n graph: TraceGraph,\n currentSubflowId: string | null,\n): OverlaySlice {\n if (graph.nodes.length === 0) return slice;\n const mounts = graph.nodes.filter((n) => n.data?.isSubflow && n.data?.subflowId);\n if (mounts.length === 0) return slice;\n const doneIds = new Set(slice.doneStageIds);\n let activeId = slice.activeStageId;\n for (const mount of mounts) {\n const sfId = mount.data!.subflowId as string;\n const members = graph.nodes.filter((n) => n.data?.subflowOf === sfId);\n if (members.length === 0) continue;\n const anyActive = members.some((m) => m.id === slice.activeStageId);\n const allDone = members.every((m) => slice.doneStageIds.has(m.id));\n if (allDone) doneIds.add(mount.id);\n // Promote \"active\" to the mount ONLY when the live node is genuinely INSIDE\n // this subflow (anyActive). Previously a mount with merely PAST-done members\n // (`anyDone`) also stole active — and once subflow internals are materialised\n // (for drill), a looping subflow's earlier-iteration done members made the\n // mount steal \"active\" from the real top-level live node (e.g. the tool\n // call), so that node's NOW highlight disappeared. The mount's own done-ness\n // still comes from its own commit + the allDone branch above.\n else if (anyActive && currentSubflowId === null) {\n activeId = mount.id;\n }\n }\n return { ...slice, doneStageIds: doneIds, activeStageId: activeId };\n}\n","/**\n * useSubflowDrill — drill state for the chart's view scope.\n *\n * - Owns `currentSubflowId: string | null` (null = top-level)\n * - Exposes `drillInto(subflowId)` and `drillUp()` for navigation\n * - Notifies the host via `onSubflowChange(mountStageId | null)`\n * whenever the drill state changes — host wires this to its own\n * drill-stack so data panels follow\n *\n * Drill changes are EXPLICIT — there's no auto-drill on scrub. The\n * mount node's status reflects \"execution is inside\" via\n * `aggregateMountStatus` (see overlayProjection.ts).\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { TraceGraph } from \"../traceStructureRecorder\";\n\nexport interface SubflowDrillHandle {\n /** Current drill scope. `null` = top-level. */\n currentSubflowId: string | null;\n /** Navigate INTO the given subflow (by `subflowId`). */\n drillInto: (subflowId: string) => void;\n /** Pop back up to the parent / top-level. */\n drillUp: () => void;\n /** Direct setter for breadcrumb navigation (any target including `null`). */\n setCurrentSubflowId: (id: string | null) => void;\n}\n\nexport function useSubflowDrill(\n graph: TraceGraph,\n onSubflowChange?: (mountStageId: string | null) => void,\n): SubflowDrillHandle {\n const [currentSubflowId, setCurrentSubflowId] = useState<string | null>(null);\n\n // Reset drill state when the graph IDENTITY changes (e.g., the\n // user switched to a different sample in the playground sidebar).\n // Without this, the drill state from sample A persists into\n // sample B's rendering — `currentSubflowId='payment'` survives the\n // chart swap, but sample B has no 'payment' subflow, so the filter\n // returns no visible nodes (blank chart).\n //\n // Also reset when the currently-drilled subflow no longer exists\n // in the new graph (defensive — graph mutations could remove a\n // subflow without changing the wrapper reference).\n const lastGraphRef = useRef<TraceGraph | null>(null);\n if (lastGraphRef.current !== graph) {\n lastGraphRef.current = graph;\n if (\n currentSubflowId !== null &&\n !graph.nodes.some((n) => n.data?.subflowId === currentSubflowId)\n ) {\n // Schedule reset for next render (can't setState during render).\n queueMicrotask(() => setCurrentSubflowId(null));\n }\n }\n\n // Notify the host when drill changes. Resolve the mount stage id\n // from the graph (the parent-chart node whose `subflowId` matches).\n const lastNotifiedRef = useRef<string | null | undefined>(undefined);\n useEffect(() => {\n if (lastNotifiedRef.current === currentSubflowId) return;\n lastNotifiedRef.current = currentSubflowId;\n if (currentSubflowId === null) {\n onSubflowChange?.(null);\n } else {\n const mount = graph.nodes.find((n) => n.data?.subflowId === currentSubflowId);\n if (mount) onSubflowChange?.(mount.id);\n }\n }, [currentSubflowId, graph, onSubflowChange]);\n\n const drillInto = useCallback((subflowId: string) => {\n setCurrentSubflowId(subflowId);\n }, []);\n const drillUp = useCallback(() => {\n setCurrentSubflowId(null);\n }, []);\n\n return { currentSubflowId, drillInto, drillUp, setCurrentSubflowId };\n}\n","/**\n * useChartAutoRefit — keep an xyflow chart fitted to its container.\n *\n * xyflow's `fitView` prop only runs on mount; it does NOT re-fit\n * when the container resizes. This hook closes that gap by:\n *\n * 1. Observing the wrapper element via `ResizeObserver` →\n * `instance.fitView({ duration, padding })` on the next animation\n * frame (so the new container size is measured first).\n * 2. Also listening to `window resize` events — `ExplainableShell`\n * dispatches synthetic resize events when its detail panels\n * toggle (those size changes may be animated and not yet\n * measurable by ResizeObserver on the first tick).\n *\n * Without this hook the chart shrinks once on Details-open and\n * never grows back when Details closes.\n *\n * It ALSO re-fits when the VISIBLE GRAPH changes (e.g. drilling into /\n * out of a subflow). xyflow only auto-fits on mount, so after a drill the\n * new, smaller subgraph keeps the parent chart's pan/zoom — leaving it\n * cramped in one corner with empty space around it. Pass a `refitKey`\n * (the drill id) so the chart recenters + rezooms to the drilled content.\n */\n\nimport { useEffect } from \"react\";\nimport type { RefObject } from \"react\";\nimport type { ReactFlowInstance } from \"@xyflow/react\";\n\nexport function useChartAutoRefit(\n wrapperRef: RefObject<HTMLElement | null>,\n rfInstance: ReactFlowInstance | null,\n options: { duration?: number; padding?: number; refitKey?: unknown } = {},\n): void {\n const duration = options.duration ?? 200;\n const padding = options.padding ?? 0.1;\n const refitKey = options.refitKey;\n\n useEffect(() => {\n const el = wrapperRef.current;\n if (!el || !rfInstance) return;\n let raf = 0;\n const refit = () => {\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n rfInstance.fitView({ duration, padding });\n });\n };\n const ro = new ResizeObserver(refit);\n ro.observe(el);\n window.addEventListener(\"resize\", refit);\n return () => {\n ro.disconnect();\n window.removeEventListener(\"resize\", refit);\n cancelAnimationFrame(raf);\n };\n }, [rfInstance, wrapperRef, duration, padding]);\n\n // Re-fit when the visible graph changes (drill in/out). Two rAFs: the first\n // lets React commit the new node set, the second lets xyflow measure the new\n // nodes' dimensions before fitView reads them — otherwise fitView centers on\n // stale/zero-size bounds and the drilled chart still lands off-center.\n useEffect(() => {\n if (!rfInstance) return;\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => {\n rfInstance.fitView({ duration, padding });\n });\n });\n return () => {\n cancelAnimationFrame(raf1);\n cancelAnimationFrame(raf2);\n };\n }, [rfInstance, refitKey, duration, padding]);\n}\n","/**\n * SubflowBreadcrumbBar — clickable trail of subflow drill levels.\n *\n * Chart › Outer Subflow › Inner Subflow\n *\n * The last entry renders disabled (you're already here). Earlier\n * entries are clickable — fire `onNavigate(subflowId)` (null = root).\n *\n * Pure presentation: takes the precomputed `entries` array (built by\n * `buildSubflowBreadcrumb` in `_internal/subflowDrill.ts`). No drill\n * state lives here.\n */\n\nimport type { BreadcrumbEntry } from \"./_internal/subflowDrill\";\nimport { rawDefaults } from \"../../theme/tokens\";\n\nexport interface SubflowBreadcrumbBarProps {\n entries: BreadcrumbEntry[];\n onNavigate: (subflowId: string | null) => void;\n}\n\nexport function SubflowBreadcrumbBar({ entries, onNavigate }: SubflowBreadcrumbBarProps) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n padding: \"6px 12px\",\n fontSize: 11,\n background: rawDefaults.colors.bgSecondary,\n borderBottom: `1px solid ${rawDefaults.colors.border}`,\n flexShrink: 0,\n }}\n aria-label=\"Subflow breadcrumb\"\n >\n {entries.map((entry, i) => {\n const isLast = i === entries.length - 1;\n return (\n <span\n key={entry.subflowId ?? \"__top__\"}\n style={{ display: \"inline-flex\", alignItems: \"center\", gap: 6 }}\n >\n <button\n type=\"button\"\n onClick={() => onNavigate(entry.subflowId)}\n disabled={isLast}\n style={{\n background: \"transparent\",\n border: \"none\",\n padding: 0,\n fontSize: 11,\n fontWeight: isLast ? 600 : 500,\n color: isLast ? rawDefaults.colors.textPrimary : rawDefaults.colors.primary,\n cursor: isLast ? \"default\" : \"pointer\",\n textDecoration: isLast ? \"none\" : \"underline\",\n fontFamily: \"inherit\",\n }}\n >\n {entry.label}\n </button>\n {!isLast && <span style={{ color: rawDefaults.colors.textMuted }}>›</span>}\n </span>\n );\n })}\n </div>\n );\n}\n","/**\n * GroupContainerNode — xyflow renderer for a subflow rendered as a GROUP\n * box (the `parentId` + `extent:'parent'` sub-flow pattern). Produced by\n * `applyGroupLayout` (it retypes a subflow mount to `groupContainer` and\n * sizes it via `style.width/height`); the subflow's member stages render\n * NESTED inside, as their own xyflow nodes positioned over this box.\n *\n * This box is therefore mostly chrome: a titled, bordered frame the member\n * nodes sit inside. It carries top/bottom handles so the parent-chain edges\n * (e.g. `context → this`, `this → message-api`) still connect to it.\n *\n * Overlay-aware: when the subflow's internals are active/done (aggregated\n * onto the mount by `aggregateMountStatus`), the frame highlights — same\n * done/active semantics the bundled `StageNode` uses.\n */\n\nimport { Handle, Position } from \"@xyflow/react\";\nimport type { NodeProps } from \"@xyflow/react\";\nimport { rawDefaults } from \"../../theme/tokens\";\n\nconst C = rawDefaults.colors;\n\nexport interface GroupContainerNodeData {\n label: string;\n isGroupContainer?: boolean;\n active?: boolean;\n done?: boolean;\n error?: boolean;\n dimmed?: boolean;\n description?: string;\n icon?: string;\n [key: string]: unknown;\n}\n\nexport function GroupContainerNode({ data }: NodeProps) {\n const d = data as GroupContainerNodeData;\n const borderColor = d.error\n ? C.error\n : d.active\n ? C.primary\n : d.done\n ? C.success\n : C.border;\n\n return (\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n boxSizing: \"border-box\",\n border: `1.5px ${d.active || d.done || d.error ? \"solid\" : \"dashed\"} ${borderColor}`,\n borderRadius: 12,\n // Translucent so the dotted background + nested children read clearly.\n background: \"rgba(148, 163, 184, 0.06)\",\n opacity: d.dimmed ? 0.4 : 1,\n position: \"relative\",\n }}\n >\n {/* Title header strip. */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n padding: \"8px 12px\",\n fontSize: 12,\n fontWeight: 600,\n color: C.textMuted,\n letterSpacing: 0.2,\n }}\n >\n {d.icon ? <span aria-hidden>{d.icon}</span> : null}\n <span>{d.label}</span>\n </div>\n\n {/* Edge handles — top target, bottom source (top→bottom flow). */}\n <Handle type=\"target\" position={Position.Top} style={{ opacity: 0 }} />\n <Handle type=\"source\" position={Position.Bottom} style={{ opacity: 0 }} />\n </div>\n );\n}\n","/**\n * LoopBackEdge — xyflow custom edge for `loopTo` back-edges, routed as a\n * CURVE along the chart's right margin instead of straight down the spine.\n *\n * WHY a custom edge (not handle-based side-routing): the prior approach asked\n * every node type to declare dedicated `loop-source` / `loop-target` handles;\n * any node missing them (custom consumer nodes, group boxes, slot pills)\n * silently fell back to the default top/bottom handles and the loop collapsed\n * back onto the spine. This component sidesteps handles entirely: it reads the\n * source/target node bounds straight from the xyflow store, anchors on their\n * RIGHT edges, and bows out to a shared lane clear of every content node. It\n * therefore works for ANY node type with zero per-node wiring — register it\n * once and every loop curves.\n *\n * The math lives in `_internal/loopRouting` (pure, unit-tested); this is the\n * thin React adapter. `style` (stroke color + dash) and `markerEnd` (arrow)\n * flow through from the renderer's edge styler unchanged.\n */\n\nimport { BaseEdge, useStore } from \"@xyflow/react\";\nimport type { CSSProperties } from \"react\";\nimport type { EdgeProps, InternalNode, ReactFlowState } from \"@xyflow/react\";\nimport { LOOP_LANE_GAP, loopBackPath, loopLaneX } from \"../FlowchartView/_internal/loopRouting\";\nimport { GROUP_CONTAINER_NODE_TYPE } from \"../FlowchartView/_internal/groupLayout\";\n\n/** A loop-back spans the whole chart height down the right margin, so a SOLID\n * line at full weight reads as a wall. We soften it — dashed + slightly muted —\n * so it registers as a \"control returns to the top\" path, not a hard edge.\n * The renderer's color/state still flows through `style`; we only ADD the dash\n * and CAP the opacity (never brighter than `softCap`, but free to dim further\n * when the edge is out of the current scrub scope). */\nconst LOOP_DASH = \"5 5\";\nconst LOOP_STROKE_OPACITY_CAP = 0.55; // muted — the long return shouldn't dominate\nconst LOOP_STROKE_WIDTH = 1.5; // thinner than a spine edge (default ~2)\nexport function softenLoopStyle(style: CSSProperties | undefined): CSSProperties {\n // Use SVG-native stroke props (strokeOpacity / strokeWidth) — they render on\n // the <path> reliably, unlike `opacity` which react-flow's BaseEdge does not\n // forward to the stroke. strokeOpacity is CAPPED (never bolder than the cap)\n // but may go lower when the renderer dims an out-of-scope edge.\n const passedStrokeOpacity =\n typeof style?.strokeOpacity === \"number\" ? style.strokeOpacity : 1;\n return {\n ...style,\n strokeDasharray: style?.strokeDasharray ?? LOOP_DASH,\n strokeOpacity: Math.min(passedStrokeOpacity, LOOP_STROKE_OPACITY_CAP),\n strokeWidth: LOOP_STROKE_WIDTH,\n };\n}\n\n/** Slightly larger corner radius than a normal step edge — a gentler, rounder\n * arc reinforces the \"soft return\" read. */\nconst LOOP_CORNER_RADIUS = 28;\n\n/** Absolute x of a node's right edge. */\nfunction rightEdge(node: InternalNode): number {\n return node.internals.positionAbsolute.x + (node.measured.width ?? 0);\n}\n\n/** Absolute y of a node's vertical center. */\nfunction centerY(node: InternalNode): number {\n return node.internals.positionAbsolute.y + (node.measured.height ?? 0) / 2;\n}\n\nexport function LoopBackEdge({ id, source, target, markerEnd, style }: EdgeProps) {\n // Derive the full SVG path inside the store selector and return it as a\n // STRING — primitive equality means the edge only re-renders when its\n // geometry actually changes (no per-tick churn, no render loop).\n const path = useStore((s: ReactFlowState) => {\n const src = s.nodeLookup.get(source);\n const tgt = s.nodeLookup.get(target);\n if (!src || !tgt) return \"\";\n\n // Lane sits right of every CONTENT node. Group containers (the frame box\n // itself) are excluded — the box spans the whole chart, so counting it\n // would always push the lane outside its own border.\n const contentRights: number[] = [];\n for (const n of s.nodeLookup.values()) {\n if (n.type === GROUP_CONTAINER_NODE_TYPE) continue;\n contentRights.push(rightEdge(n));\n }\n // Add the endpoints explicitly: when source or target IS a group container\n // (a loop into/out of a box), the loop above skipped it, so include its\n // right edge here so the lane still clears the endpoint. For ordinary\n // (content) endpoints this is a harmless duplicate — loopLaneX takes a max.\n const laneX = loopLaneX([...contentRights, rightEdge(src), rightEdge(tgt)], LOOP_LANE_GAP);\n\n return loopBackPath(\n { right: rightEdge(src), centerY: centerY(src) },\n { right: rightEdge(tgt), centerY: centerY(tgt) },\n laneX,\n LOOP_CORNER_RADIUS,\n );\n });\n\n if (!path) return null;\n return (\n <BaseEdge\n id={id}\n path={path}\n markerEnd={markerEnd}\n style={softenLoopStyle(style)}\n aria-label=\"Loop back\"\n />\n );\n}\n","/**\n * loopRouting — pure geometry for the right-margin loop-back curve.\n *\n * A `loopTo` back-edge (e.g. ReAct's `Route → Context`) must NOT be drawn\n * straight down the chart spine — it overlaps every node it passes. Instead\n * it is routed as a CURVE that exits the source node's RIGHT edge, bows out to\n * a vertical \"lane\" clear of every content node, and re-enters the target\n * node's RIGHT edge. The lane is shared by all loops so they stack tidily on\n * the right margin.\n *\n * This module is the pure core (no React, no DOM): the `LoopBackEdge`\n * component gathers node bounds from the xyflow store and calls these; the\n * `wrapInMainChartBox` layout reserves `LOOP_LANE_GAP` of right-margin width\n * so the curve renders INSIDE the chart's frame. Keeping the math here makes\n * it unit-testable and keeps the edge component a thin adapter.\n */\n\n/**\n * Horizontal gap (px) between the rightmost content node and the loop lane —\n * how far right of everything the curve bows. Shared by `LoopBackEdge` (which\n * draws to the lane) and `wrapInMainChartBox` (which reserves room for it), so\n * the curve always lands inside the frame.\n */\nexport const LOOP_LANE_GAP = 56;\n\n/** A loop endpoint: a node's right edge x and vertical center y (flow coords). */\nexport interface LoopEndpoint {\n /** Absolute x of the node's RIGHT edge (position.x + width). */\n readonly right: number;\n /** Absolute y of the node's vertical center. */\n readonly centerY: number;\n}\n\n/**\n * The x of the vertical lane the loop curve bows out to: just right of the\n * widest content node, so the curve clears every node it arcs past. Pass the\n * right-edge x of every content node (the box container itself is excluded by\n * the caller — it would otherwise always be the widest and push the lane\n * outside its own frame). Empty input → `gap` (degenerate but safe).\n */\nexport function loopLaneX(contentRights: readonly number[], gap: number = LOOP_LANE_GAP): number {\n // Empty-input fallback: `max` stays -Infinity until the loop assigns it, so\n // `!Number.isFinite` catches the no-nodes case and degrades the lane to `gap`.\n let max = -Infinity;\n for (const r of contentRights) if (r > max) max = r;\n if (!Number.isFinite(max)) max = 0;\n return max + gap;\n}\n\n/**\n * SVG path for one right-margin loop-back curve. A cubic bezier whose BOTH\n * route HUGS the lane: it leaves the source heading right, runs straight UP (or\n * down) the lane — which sits right of EVERY node — and only turns in toward the\n * target at the target's own row (the target is the chart's first node, alone at\n * the top, so the turn-in clears everything). Corners are rounded for a curved\n * feel. A pure inward-bowing bezier was abandoned because it cuts back toward\n * the target's x BEFORE the top, slicing across whatever node is rightmost in\n * the rows it passes (e.g. the tools slot).\n *\n * `radius` is the corner rounding (clamped to fit the available run/rise).\n */\nexport function loopBackPath(\n source: LoopEndpoint,\n target: LoopEndpoint,\n laneX: number,\n radius = 22,\n): string {\n const { right: sx, centerY: sy } = source;\n const { right: tx, centerY: ty } = target;\n // Corner radius can't exceed half the vertical run, nor the horizontal gap to\n // the lane on either side.\n const r = Math.max(\n 0,\n Math.min(radius, Math.abs(sy - ty) / 2, laneX - sx, laneX - tx),\n );\n const up = ty <= sy; // target above source (the normal ReAct loop)\n const vy1 = up ? sy - r : sy + r; // first corner's far-y (leaving source row)\n const vy2 = up ? ty + r : ty - r; // second corner's near-y (entering target row)\n // out to the lane → round → straight up/down the lane → round → in to target.\n return [\n `M ${sx},${sy}`,\n `L ${laneX - r},${sy}`,\n `Q ${laneX},${sy} ${laneX},${vy1}`,\n `L ${laneX},${vy2}`,\n `Q ${laneX},${ty} ${laneX - r},${ty}`,\n `L ${tx},${ty}`,\n ].join(\" \");\n}\n","/**\n * groupLayout — xyflow NATIVE container boxes for the trace chart.\n *\n * Two box mechanisms live here, plus the existing drill (elsewhere):\n *\n * - **Drill** (`subflowDrill.ts` + `useSubflowDrill`): a subflow shows as\n * ONE mount card; clicking it zooms in. The DEFAULT for every subflow.\n * - **Main-chart box** (`wrapInMainChartBox`): wrap the WHOLE chart in ONE\n * container box. This is the Lens model — the primitive you're viewing\n * (LLMCall / Agent) is always one box; every subflow inside it stays a\n * drill card. A `nodeTypes` registry then styles each inner card\n * (system-prompt / messages / tools / LLM). USE THIS for Lens.\n * - **Per-subflow group** (`applyGroupLayout`): box individual subflows\n * (mount → container, members nested inside). A more granular tool kept\n * for consumers that want specific subflows inlined as boxes rather than\n * drilled. NOT what the Lens main-chart model uses.\n *\n * All are pure `(graph, opts) => graph` (no React, no I/O) and compose with\n * `<TracedFlow>` before nodes reach `<ReactFlow>`. explainable-ui stays\n * policy-free: it offers the mechanisms; the consumer (Lens) picks.\n *\n * Pure: `(graph, opts) => graph`. No React, no I/O. Composed by `<TracedFlow>`\n * before the nodes reach `<ReactFlow>`.\n *\n * What it does, given `groupedSubflowIds`:\n * 1. For each grouped subflow that is actually present (a mount node whose\n * `subflowId` is listed AND has ≥1 member where `subflowOf === id`):\n * - lay the OUTER graph out with `baseLayout` (members excluded; the\n * mount stays as the box anchor);\n * - lay the subflow's MEMBERS out with `baseLayout` in isolation, then\n * normalise them to the box's local coordinate space;\n * - size the container box to fit the members (+ header + padding);\n * - convert the mount node to `type: 'groupContainer'` with a `style`\n * width/height, and nest each member via `parentId` + `extent`.\n * 2. Subflows NOT listed are left untouched (they continue to drill).\n *\n * Node ORDER invariant (xyflow requirement): a parent node MUST appear\n * before its children in the array. We emit all outer nodes (containers\n * included) first, then all nested members — so every container precedes\n * its members.\n */\n\nimport type { TraceGraph, TraceNode } from \"../traceStructureRecorder\";\nimport type { TraceFlowLayout } from \"../TraceFlow\";\nimport { LOOP_LANE_GAP } from \"./loopRouting\";\n\n/** xyflow node type used for the container box. Consumers register a\n * renderer for this key (explainable-ui ships a default `GroupContainerNode`). */\nexport const GROUP_CONTAINER_NODE_TYPE = \"groupContainer\";\n\nexport interface GroupLayoutOptions {\n /** Subflow ids (the mount's `subflowId`) to render as group boxes. */\n readonly groupedSubflowIds: readonly string[];\n /** Layout for both the outer graph and each subflow's interior. */\n readonly baseLayout: TraceFlowLayout;\n /** Inner padding inside the container box, in px. Default 16. */\n readonly padding?: number;\n /** Header strip height (room for the box title), in px. Default 44. */\n readonly headerHeight?: number;\n /** Assumed node footprint for box sizing (the layout sets positions, not\n * sizes). Defaults match the bundled `StageNode` footprint. */\n readonly nodeWidth?: number;\n readonly nodeHeight?: number;\n}\n\nconst DEFAULT_PADDING = 16;\nconst DEFAULT_HEADER = 44;\nconst DEFAULT_NODE_W = 200;\nconst DEFAULT_NODE_H = 80;\n\n/**\n * Resolve a node's rendered FOOTPRINT for box-sizing math.\n *\n * A node's true extent is `position + footprint`, not its top-left corner.\n * For a `groupContainer` produced by a prior pass the footprint lives on\n * `style.width/height` (e.g. a boxed subflow ~1756px wide); for a plain\n * stage card it is the configured default. Composing nested boxes therefore\n * REQUIRES reading this — otherwise a wide container is measured as a point\n * and the outer box is sized far too small to contain it.\n *\n * Mirrors `dagreTraceLayout.sizeOf` (`style.width/height` → default) so the\n * box transforms and the dagre layout agree on every node's footprint.\n */\nfunction footprintOf(\n node: TraceNode,\n fallbackW: number,\n fallbackH: number,\n): { width: number; height: number } {\n const style = (node.style ?? {}) as { width?: unknown; height?: unknown };\n const w = typeof style.width === \"number\" ? style.width : fallbackW;\n const h = typeof style.height === \"number\" ? style.height : fallbackH;\n return { width: w, height: h };\n}\n\n/**\n * Apply group-container nesting to a positioned-or-unpositioned graph.\n * Returns a NEW graph (input is not mutated). Edges pass through unchanged\n * — xyflow resolves them by node id regardless of nesting, so an edge that\n * pointed at a now-container mount still connects to the box, and\n * member↔member edges render inside it.\n */\nexport function applyGroupLayout(graph: TraceGraph, opts: GroupLayoutOptions): TraceGraph {\n const padding = opts.padding ?? DEFAULT_PADDING;\n const headerHeight = opts.headerHeight ?? DEFAULT_HEADER;\n const nodeW = opts.nodeWidth ?? DEFAULT_NODE_W;\n const nodeH = opts.nodeHeight ?? DEFAULT_NODE_H;\n const baseLayout = opts.baseLayout;\n\n // Which requested subflows are genuinely groupable: a mount node carrying\n // that subflowId AND at least one member tagged subflowOf === id.\n const requested = new Set(opts.groupedSubflowIds);\n const membersBySubflow = new Map<string, TraceNode[]>();\n for (const n of graph.nodes) {\n const of = n.data?.subflowOf;\n if (of !== undefined && requested.has(of)) {\n const arr = membersBySubflow.get(of) ?? [];\n arr.push(n);\n membersBySubflow.set(of, arr);\n }\n }\n const mountBySubflow = new Map<string, TraceNode>();\n for (const n of graph.nodes) {\n const sfId = n.data?.subflowId;\n if (n.data?.isSubflow && sfId !== undefined && requested.has(sfId) && membersBySubflow.has(sfId)) {\n mountBySubflow.set(sfId, n);\n }\n }\n // Only group subflows that have BOTH a mount and members.\n const activeGroups = new Set<string>();\n for (const sfId of mountBySubflow.keys()) activeGroups.add(sfId);\n\n // Nothing to do — return input unchanged (preserves upstream memoization).\n if (activeGroups.size === 0) {\n return graph;\n }\n\n // Member ids across all active groups (excluded from the outer layout).\n const memberIds = new Set<string>();\n for (const sfId of activeGroups) {\n for (const m of membersBySubflow.get(sfId) ?? []) memberIds.add(m.id);\n }\n\n // ── PASS 1 — lay out each group's MEMBERS and size its box FIRST. We must\n // know each container's true footprint BEFORE the outer layout runs, or\n // dagre would place the outer siblings (Route, ToolCalls, …) around the\n // mount's default 200px point and they'd collide once the box balloons.\n // (Inside-out reflow: size the inner box, then place the outer graph\n // around it at its real size.) ──\n const containerNodes: TraceNode[] = [];\n const nestedMembers: TraceNode[] = [];\n /** Per-group: box size + the normalisation origin needed when nesting. */\n const groupBox = new Map<\n string,\n { width: number; height: number; minX: number; minY: number; members: TraceNode[] }\n >();\n\n for (const sfId of activeGroups) {\n const members = membersBySubflow.get(sfId)!;\n const innerOnlyEdges = graph.edges.filter((e) => {\n const s = members.some((m) => m.id === e.source);\n const t = members.some((m) => m.id === e.target);\n return s && t;\n });\n const innerPositioned = baseLayout({ nodes: members, edges: innerOnlyEdges });\n\n // Normalise member positions to the box's local space (min → 0). Measure\n // each member's full FOOTPRINT (position + width/height), not just its\n // top-left corner — a member may itself be a sized container (nested\n // composition), and corner-only math would undersize this box around it.\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const m of innerPositioned.nodes) {\n const p = m.position;\n const { width, height } = footprintOf(m, nodeW, nodeH);\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x + width > maxX) maxX = p.x + width;\n if (p.y + height > maxY) maxY = p.y + height;\n }\n if (!Number.isFinite(minX)) {\n minX = 0;\n minY = 0;\n maxX = 0;\n maxY = 0;\n }\n\n // maxX/maxY already include each member's footprint, so the inner extent\n // is just the spanned distance (no extra nodeW/nodeH to add).\n const boxWidth = maxX - minX + padding * 2;\n const boxHeight = maxY - minY + headerHeight + padding * 2;\n groupBox.set(sfId, { width: boxWidth, height: boxHeight, minX, minY, members: innerPositioned.nodes });\n }\n\n // ── PASS 2 — lay out the OUTER graph with each mount STAMPED at its real\n // box size, so dagre reserves the correct footprint and outer siblings\n // are placed clear of the box (no overlap). ──\n const outerNodes = graph.nodes\n .filter((n) => !memberIds.has(n.id))\n .map((n) => {\n const box = n.data?.subflowId ? groupBox.get(n.data.subflowId) : undefined;\n // Stamp the box's footprint onto the mount so the dagre baseLayout\n // (which reads style.width/height via sizeOf) places siblings around it.\n // ALSO flag `data.isGroupContainer` so `sizeOf` treats this stamped\n // footprint as AUTHORITATIVE — i.e. style WINS over any consumer\n // `nodeSize` resolver. Without the flag, a resolver that sizes by\n // recorder semantics (e.g. \"any subflow → a 38px slim bar\") out-ranks\n // the stamp: dagre reserves 38px while the box renders ~794px, so the\n // post-container siblings (route / tool-calls / final) rank inside the\n // box and overlap it. The flag makes dagre reserve the box's TRUE height.\n return box\n ? {\n ...n,\n style: { ...(n.style ?? {}), width: box.width, height: box.height },\n data: { ...n.data, isGroupContainer: true },\n }\n : n;\n });\n const outerEdges = graph.edges.filter(\n (e) => !memberIds.has(e.source) && !memberIds.has(e.target),\n );\n const outerPositioned = baseLayout({ nodes: outerNodes, edges: outerEdges });\n const outerPosById = new Map(outerPositioned.nodes.map((n) => [n.id, n.position]));\n\n // ── Emit containers (at their outer position) + nest their members. ──\n for (const sfId of activeGroups) {\n const mount = mountBySubflow.get(sfId)!;\n const box = groupBox.get(sfId)!;\n const { width: boxWidth, height: boxHeight, minX, minY } = box;\n\n // Container = the mount node, retyped + sized, keeping its outer position.\n const mountPos = outerPosById.get(mount.id) ?? mount.position ?? { x: 0, y: 0 };\n containerNodes.push({\n ...mount,\n type: GROUP_CONTAINER_NODE_TYPE,\n position: mountPos,\n style: { ...(mount.style ?? {}), width: boxWidth, height: boxHeight },\n data: { ...mount.data, isGroupContainer: true },\n });\n\n // Members nested under the container, positioned in local space below\n // the header strip.\n for (const m of box.members) {\n const relX = m.position.x - minX + padding;\n const relY = m.position.y - minY + headerHeight + padding;\n nestedMembers.push({\n ...(m as TraceNode),\n parentId: mount.id,\n extent: \"parent\",\n position: { x: relX, y: relY },\n });\n }\n }\n\n // ── Reassemble: outer nodes (with containers swapped in) FIRST, then\n // nested members — guarantees every parent precedes its children. ──\n const containerById = new Map(containerNodes.map((c) => [c.id, c]));\n const outerOut: TraceNode[] = outerPositioned.nodes.map(\n (n) => containerById.get(n.id) ?? n,\n );\n\n return {\n nodes: [...outerOut, ...nestedMembers],\n edges: graph.edges,\n };\n}\n\n/**\n * Convenience: wrap a base layout into a `TraceFlowLayout` that applies\n * group containers. Pass to `<TraceFlow layout={...}>` / `<TracedFlow>`.\n */\nexport function createGroupedLayout(opts: GroupLayoutOptions): TraceFlowLayout {\n return (graph: TraceGraph) => applyGroupLayout(graph, opts);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Main-chart box — wrap the ENTIRE (drill-filtered) chart in ONE container\n// ─────────────────────────────────────────────────────────────────────────────\n//\n// The Lens model: the chart you're looking at (an LLMCall / Agent primitive)\n// is ALWAYS one box; every subflow INSIDE it is a drill card (click → zoom).\n// This is distinct from `applyGroupLayout` (which boxes individual subflows).\n// Here there's no per-subflow mount — the whole graph is the box's contents,\n// so we synthesise ONE container node and nest every top-level node under it.\n//\n// Composition contract: feed this the ALREADY drill-filtered graph (top-level\n// nodes only; subflow internals hidden behind their drill cards). Nodes that\n// already carry a `parentId` are left parented as-is (only parentId-less\n// top-level nodes get re-parented to the main box), so this composes safely\n// even if some upstream nesting exists.\n\n/** Default id for the synthesised main-chart container node. */\nexport const MAIN_CHART_BOX_ID = \"__main_chart__\";\n\nexport interface MainChartBoxOptions {\n /** Layout applied to the chart's contents before wrapping. */\n readonly baseLayout: TraceFlowLayout;\n /** Container node id. Default `__main_chart__`. */\n readonly id?: string;\n /** Box title (rendered in the container header). */\n readonly label?: string;\n /** Optional taxonomy hint surfaced on `data` (e.g. 'LLMCall' | 'Agent'). */\n readonly kind?: string;\n readonly padding?: number;\n readonly headerHeight?: number;\n readonly nodeWidth?: number;\n readonly nodeHeight?: number;\n}\n\n/**\n * Wrap an entire graph in a single main-chart container box. Pure\n * `(graph, opts) => graph`; input not mutated. Empty graph → returned\n * unchanged (nothing to wrap).\n */\nexport function wrapInMainChartBox(graph: TraceGraph, opts: MainChartBoxOptions): TraceGraph {\n if (graph.nodes.length === 0) return graph;\n\n const padding = opts.padding ?? DEFAULT_PADDING;\n const headerHeight = opts.headerHeight ?? DEFAULT_HEADER;\n const nodeW = opts.nodeWidth ?? DEFAULT_NODE_W;\n const nodeH = opts.nodeHeight ?? DEFAULT_NODE_H;\n const mainId = opts.id ?? MAIN_CHART_BOX_ID;\n\n const positioned = opts.baseLayout(graph);\n\n // Only top-level nodes (no existing parentId) get re-parented to the box;\n // already-nested nodes keep their parent (their relative position is\n // unaffected by re-parenting their ancestor — xyflow positions are\n // parent-relative).\n const topLevel = positioned.nodes.filter((n) => n.parentId === undefined);\n\n // Bounding box of the top-level nodes → container size. We measure each\n // node's full FOOTPRINT (position + width/height), not just its top-left\n // corner — a top-level node may itself be a wide group container (from a\n // prior `applyGroupLayout` pass) carrying a large `style.width`. Reading\n // only the corner would size the box as if that container were a 200px\n // node, so it would overflow the outer box (the nesting bug).\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const n of topLevel) {\n const p = n.position;\n const { width, height } = footprintOf(n, nodeW, nodeH);\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x + width > maxX) maxX = p.x + width;\n if (p.y + height > maxY) maxY = p.y + height;\n }\n if (!Number.isFinite(minX)) {\n minX = 0;\n minY = 0;\n maxX = 0;\n maxY = 0;\n }\n\n // maxX/maxY already include the widest/tallest node's footprint, so the\n // box size is just the spanned extent + padding (+ header for the title).\n // When the chart has a loop-back edge, `LoopBackEdge` bows out to a lane\n // `LOOP_LANE_GAP` right of the widest content node — reserve that width so\n // the curve renders INSIDE the frame instead of spilling past its right border.\n const hasLoopEdge = graph.edges.some((e) => e.data?.kind === \"loop\");\n const loopReserve = hasLoopEdge ? LOOP_LANE_GAP : 0;\n const boxWidth = maxX - minX + padding * 2 + loopReserve;\n const boxHeight = maxY - minY + headerHeight + padding * 2;\n\n const container: TraceNode = {\n id: mainId,\n type: GROUP_CONTAINER_NODE_TYPE,\n position: { x: 0, y: 0 },\n style: { width: boxWidth, height: boxHeight },\n data: {\n label: opts.label ?? \"Chart\",\n isDecider: false,\n isFork: false,\n isStreaming: false,\n isSubflow: false,\n isGroupContainer: true,\n isMainChart: true,\n ...(opts.kind !== undefined && { kind: opts.kind }),\n prevIds: [],\n nextIds: [],\n },\n } as TraceNode;\n\n const topLevelIds = new Set(topLevel.map((n) => n.id));\n const reparented: TraceNode[] = positioned.nodes.map((n) => {\n if (!topLevelIds.has(n.id)) return n; // already nested — leave as-is\n return {\n ...n,\n parentId: mainId,\n extent: \"parent\",\n position: {\n x: n.position.x - minX + padding,\n y: n.position.y - minY + headerHeight + padding,\n },\n };\n });\n\n // Container FIRST (xyflow parent-before-child invariant).\n return { nodes: [container, ...reparented], edges: graph.edges };\n}\n\n/**\n * Convenience: a `TraceFlowLayout` that wraps the whole chart in one\n * main-chart box. Pass to `<TraceFlow layout={...}>` / `<TracedFlow>`.\n */\nexport function createMainChartBoxLayout(opts: MainChartBoxOptions): TraceFlowLayout {\n return (graph: TraceGraph) => wrapInMainChartBox(graph, opts);\n}\n","/**\n * SmartStepEdge — a smooth-step edge that routes a RANK-SKIPPING (staggered)\n * edge AROUND the node(s) it skips, instead of bending through them.\n *\n * It is a drop-in superset of the built-in `smoothstep` edge: for an ordinary\n * adjacent edge it produces the IDENTICAL path (default midpoint bend); only\n * when the edge skips a rank — a node sits vertically between its endpoints —\n * does it move the bend into the gap below that node (see `stepRouting`).\n *\n * WHY a custom edge (not a layout tweak): which edges skip a rank depends on the\n * final laid-out geometry, which only the renderer knows. Like `LoopBackEdge`,\n * this reads node bounds straight from the xyflow store, so it works for ANY\n * staggered merge in ANY chart with zero per-node or per-chart wiring — register\n * it once as the default step edge and every staggered edge routes cleanly.\n *\n * The decision math lives in `_internal/stepRouting` (pure, unit-tested); this\n * is the thin React adapter. `style` + `markerEnd` flow through unchanged.\n */\n\nimport { BaseEdge, getSmoothStepPath, useStore } from \"@xyflow/react\";\nimport type { EdgeProps, ReactFlowState } from \"@xyflow/react\";\nimport { Position } from \"@xyflow/react\";\nimport {\n staggeredBendY,\n forkFanBendY,\n resolveStepBendY,\n type VerticalBounds,\n} from \"../FlowchartView/_internal/stepRouting\";\nimport { GROUP_CONTAINER_NODE_TYPE } from \"../FlowchartView/_internal/groupLayout\";\nimport type { TraceEdgeData } from \"../FlowchartView/traceStructureRecorder\";\n\nexport function SmartStepEdge({\n id,\n source,\n target,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n markerEnd,\n style,\n}: EdgeProps) {\n // The bend y for a staggered edge, or null for an ordinary adjacent edge.\n // Derived in the store selector and returned as a NUMBER/null — primitive\n // equality means the edge only re-renders when its routing actually changes.\n const bendY = useStore((s: ReactFlowState) => {\n const src = s.nodeLookup.get(source);\n const tgt = s.nodeLookup.get(target);\n if (!src || !tgt) return null;\n const sourceBottom = src.internals.positionAbsolute.y + (src.measured.height ?? 0);\n const targetTop = tgt.internals.positionAbsolute.y;\n\n // FORK FAN: if this source feeds >= 2 children (excluding loop back-edges),\n // every edge leaving it shares ONE bend row above the nearest child, so the\n // fan reads as a clean comb instead of N staggered diagonals. Derived from\n // the source's geometry → all siblings return the same primitive.\n const childTops: number[] = [];\n for (const e of s.edges) {\n if (e.source !== source) continue;\n if ((e.data as TraceEdgeData | undefined)?.kind === \"loop\") continue;\n const c = s.nodeLookup.get(e.target);\n if (c && c.type !== GROUP_CONTAINER_NODE_TYPE) {\n childTops.push(c.internals.positionAbsolute.y);\n }\n }\n const fan = forkFanBendY(sourceBottom, childTops);\n\n // Rank-skip clearance: route around any node this edge SKIPS.\n const others: VerticalBounds[] = [];\n for (const n of s.nodeLookup.values()) {\n if (n.id === source || n.id === target) continue;\n if (n.type === GROUP_CONTAINER_NODE_TYPE) continue; // the frame box spans everything\n const top = n.internals.positionAbsolute.y;\n others.push({ top, bottom: top + (n.measured.height ?? 0) });\n }\n const staggered = staggeredBendY(sourceBottom, targetTop, others);\n\n // Shared fan row for forks, EXCEPT a fork branch that also skips a rank —\n // there the rank-skip bend wins so the long drop stays below the skipped node.\n return resolveStepBendY(fan, staggered);\n });\n\n const [path] = getSmoothStepPath({\n sourceX,\n sourceY,\n sourcePosition: sourcePosition ?? Position.Bottom,\n targetX,\n targetY,\n targetPosition: targetPosition ?? Position.Top,\n // Override the bend only for a staggered edge; otherwise let getSmoothStepPath\n // use its default centerY (== the built-in `smoothstep` path, byte-for-byte).\n ...(bendY !== null ? { centerY: bendY } : {}),\n });\n\n return <BaseEdge id={id} path={path} markerEnd={markerEnd} style={style} />;\n}\n","/**\n * stepRouting — pure geometry for the \"smart\" step edge that routes a\n * RANK-SKIPPING (staggered) edge AROUND the node(s) it skips.\n *\n * The problem: a normal smooth-step edge bends at the vertical MIDPOINT between\n * its endpoints. When an edge skips a rank (e.g. the agent merge-tree's\n * `tools → call-llm`, which bypasses `message-api`), that midpoint falls right\n * on the skipped node's row, so the horizontal segment cuts straight through it\n * — it reads as if the edge connects to the skipped node.\n *\n * The fix: place the bend in the GAP just below the lowest skipped node and\n * above the target, so the horizontal run clears every skipped node. Because the\n * bend sits below ALL skipped nodes, vertical clearance alone guarantees the\n * horizontal run never overlaps them. (The vertical run stays at the source's x;\n * for fork-join staggered merges the skipped input is laterally offset from the\n * trunk, so that run is already clear — the case this targets.)\n *\n * This module is the pure core (no React/DOM); `SmartStepEdge` is the thin\n * adapter that reads node bounds from the xyflow store and calls this. Keeping\n * the math here makes it unit-testable, mirroring `loopRouting`.\n */\n\n/** A node's vertical extent in flow coordinates (top edge .. bottom edge). */\nexport interface VerticalBounds {\n readonly top: number;\n readonly bottom: number;\n}\n\n/**\n * The y at which a step edge should bend to clear every rank it SKIPS, or `null`\n * when it skips nothing (caller then uses the default midpoint bend == ordinary\n * smooth-step).\n *\n * A node counts as \"skipped\" when its vertical CENTER lies strictly between the\n * source's bottom and the target's top. The bend is placed midway between the\n * lowest skipped node's bottom and the target's top, clamped to stay\n * `minGapFromTarget` above the target so a rounded corner still fits.\n */\nexport function staggeredBendY(\n sourceBottom: number,\n targetTop: number,\n others: readonly VerticalBounds[],\n minGapFromTarget = 8,\n): number | null {\n let lowestSkippedBottom = -Infinity;\n for (const n of others) {\n const cy = (n.top + n.bottom) / 2;\n if (cy > sourceBottom && cy < targetTop && n.bottom > lowestSkippedBottom) {\n lowestSkippedBottom = n.bottom;\n }\n }\n if (lowestSkippedBottom === -Infinity) return null; // nothing skipped → default bend\n return Math.min((lowestSkippedBottom + targetTop) / 2, targetTop - minGapFromTarget);\n}\n\n/**\n * The shared bend-y for a FORK FAN. When one source feeds N children (out-degree\n * >= 2), every edge leaving it bends at the SAME row — midway between the\n * source's bottom and the NEAREST child's top — so the fan reads as one clean\n * comb instead of N independently-bent diagonals (the staggered-staircase look).\n *\n * Because the value derives only from the SOURCE's geometry + its children\n * (identical for every sibling edge), each edge's store selector returns the\n * same primitive → React Flow re-renders the whole fan as a unit. Returns\n * `null` for a non-fork (< 2 children); the caller then uses the staggered /\n * default-midpoint bend.\n */\nexport function forkFanBendY(\n sourceBottom: number,\n childTops: readonly number[],\n minGapFromTarget = 8,\n): number | null {\n if (childTops.length < 2) return null;\n const nearestTop = Math.min(...childTops);\n // Midway to the nearest child, but kept a corner-radius above it.\n return Math.min((sourceBottom + nearestTop) / 2, nearestTop - minGapFromTarget);\n}\n\n/**\n * Precedence when both a fork-fan bend and a rank-skip bend could apply to one\n * edge. The shared fan row gives forks a clean comb, BUT a fork branch that\n * ALSO skips a rank must keep its rank-skip bend — that bend sits BELOW the\n * skipped node, so the branch's long drop can't cut through it (the fan row is\n * high, near the source, and would not clear it). So: rank-skip WINS when\n * present, else the fan bend, else null (caller uses the default midpoint).\n */\nexport function resolveStepBendY(\n forkBend: number | null,\n staggeredBend: number | null,\n): number | null {\n return staggeredBend ?? forkBend;\n}\n","import { useEffect } from \"react\";\nimport { useNodesInitialized, useStore } from \"@xyflow/react\";\nimport type { ReactFlowState } from \"@xyflow/react\";\nimport { extractMeasuredFootprints, sameFootprints } from \"./measuredFootprints\";\n\n/**\n * MeasuredNodeSizes — the \"measure, then lay out\" probe (xyflow's recommended\n * pattern for layout libraries like dagre).\n *\n * Dagre needs each node's dimensions BEFORE it can place them, but the real\n * size of a content-sized card isn't known until React has rendered it. So:\n *\n * 1. First pass — the chart lays out with estimated sizes (the dagre\n * default footprint) and renders. Nodes appear, slightly loose.\n * 2. xyflow MEASURES every node; their footprints land on the internal nodes.\n * 3. This probe reads each node's real measured `{width,height}` and calls\n * `onSizes(map)`. Feed that map into the dagre `nodeSize` resolver and the\n * layout re-runs with content-EXACT sizes — no fixed-width-column gaps,\n * tighter and aligned, for any node content (long label, icon, badge,\n * a brand-new node type) with zero spacing constants to tune.\n *\n * WHERE THE SIZES LIVE, AND HOW WE SUBSCRIBE (xyflow v12):\n * The measured footprint is on the INTERNAL node in the store's `nodeLookup`,\n * NOT on the user nodes from `getNodes()` (those read `measured: {0,0}`). And\n * `nodeLookup` is a single Map xyflow mutates IN PLACE — its reference never\n * changes — so `useStore(s => s.nodeLookup)` would be Object.is-equal forever\n * and the effect would fire only once, on the initial `nodesInitialized` flip,\n * never on a later resize (async font/icon load, dynamic label). Instead we\n * select the DERIVED footprint map and dedupe with `sameFootprints`: the\n * selected value is stable across ticks that change no footprint, and changes\n * exactly when some node re-measures — so the relayout re-runs when, and only\n * when, the sizes actually move. (Reading `getNodes()` here was a silent no-op:\n * every footprint came back 0×0, `onSizes` was never called, and the layout was\n * stuck on estimated sizes forever.)\n *\n * Render this as a child of `<ReactFlow>` (the hooks need its context).\n * It renders nothing.\n */\nexport interface MeasuredNodeSizesProps {\n /** Called with `id -> {width,height}` once all nodes are measured (and again\n * whenever a footprint changes). */\n readonly onSizes: (sizes: Map<string, import(\"./dagreTraceLayout\").NodeFootprint>) => void;\n /** Include hidden nodes in the readiness check (default false). */\n readonly includeHiddenNodes?: boolean;\n}\n\nexport function MeasuredNodeSizes({\n onSizes,\n includeHiddenNodes = false,\n}: MeasuredNodeSizesProps): null {\n const initialized = useNodesInitialized({ includeHiddenNodes });\n // Subscribe to the DERIVED, deduped footprint map (see header for why not the\n // raw nodeLookup). `sameFootprints` keeps the reference stable until a real\n // re-measure, so the effect below re-runs precisely on size changes.\n const sizes = useStore(\n (s: ReactFlowState) => extractMeasuredFootprints(s.nodeLookup),\n sameFootprints,\n );\n\n useEffect(() => {\n // Gate on `initialized` so we never relayout from a half-measured first\n // paint (some nodes 0×0): wait until every node has a real footprint, then\n // (and on every subsequent footprint change) feed content-exact sizes in.\n if (!initialized || sizes.size === 0) return;\n onSizes(sizes);\n }, [initialized, sizes, onSizes]);\n\n return null;\n}\n","/**\n * measuredFootprints — pure core of the \"measure, then lay out\" probe.\n *\n * Given the entries of xyflow's `nodeLookup` store (`[id, internalNode]`),\n * collect each node's REAL measured footprint into an `id -> {width,height}`\n * map for the dagre `nodeSize` resolver.\n *\n * WHY THIS IS THE SOURCE (xyflow v12): the measured footprint lives on the\n * INTERNAL node in `nodeLookup` — NOT on the user nodes from `getNodes()`,\n * which report `measured: {0,0}` until you read the internal copy. The probe\n * used to read `getNodes()`, so every footprint came back 0×0, the sizes map\n * was always empty, and the layout silently stayed on estimated sizes forever\n * (cards laid out on a fallback column width → off-center forks/deciders). This\n * pure helper takes the lookup-shaped entries so the unit test pins the\n * contract: read the `.measured` field, and DROP unmeasured (0×0) nodes so a\n * half-measured first paint never feeds a degenerate size into the layout.\n *\n * Footprints are ROUNDED to whole pixels. The measured size is re-stamped onto\n * each node's `style.width` by the dagre pass, so the measure→stamp→re-measure\n * cycle must reach a fixed point; rounding kills sub-pixel jitter (border-box /\n * transform rounding) that would otherwise let the layout oscillate. Integer px\n * is plenty for spacing.\n *\n * Pure (no React/DOM) so it is unit-testable; `MeasuredNodeSizes` is the thin\n * hook adapter that subscribes to the store and calls this. Mirrors the\n * pure-core/thin-adapter split used by `stepRouting` / `loopRouting`.\n */\nimport type { NodeFootprint } from \"./dagreTraceLayout\";\n\n/** The shape this helper needs from an xyflow internal node. */\nexport interface MeasuredLike {\n readonly measured?: { readonly width?: number; readonly height?: number };\n}\n\n/**\n * Collect `id -> {width,height}` from `nodeLookup`-shaped entries, keeping only\n * nodes with a real positive measured footprint (0×0 / missing → skipped).\n * Footprints are rounded to whole pixels (fixed-point stability — see header).\n */\nexport function extractMeasuredFootprints(\n entries: Iterable<readonly [string, MeasuredLike]>,\n): Map<string, NodeFootprint> {\n const sizes = new Map<string, NodeFootprint>();\n for (const [id, node] of entries) {\n const width = node.measured?.width;\n const height = node.measured?.height;\n if (typeof width === \"number\" && typeof height === \"number\" && width > 0 && height > 0) {\n sizes.set(id, { width: Math.round(width), height: Math.round(height) });\n }\n }\n return sizes;\n}\n\n/**\n * Footprint-map equality — true iff both maps hold the same ids with the same\n * (rounded) footprints. Used as the xyflow `useStore` equality fn so the probe\n * subscribes to a value that is STABLE across store ticks that don't change any\n * footprint, yet changes when a node actually re-measures. (Selecting the\n * `nodeLookup` Map itself never works: xyflow mutates it IN PLACE — same\n * reference forever — so an Object.is subscription would only ever fire on the\n * one-time `nodesInitialized` flip, never on a later resize.)\n */\nexport function sameFootprints(\n a: Map<string, NodeFootprint>,\n b: Map<string, NodeFootprint>,\n): boolean {\n if (a === b) return true;\n if (a.size !== b.size) return false;\n for (const [id, s] of a) {\n const t = b.get(id);\n if (!t || t.width !== s.width || t.height !== s.height) return false;\n }\n return true;\n}\n","/**\n * InspectorPanel — Node-specific debug view.\n *\n * Two tabs:\n * - State: scope values at the selected step (time-travel synced)\n * - Data Trace: backward causal chain from the selected node\n *\n * Like Chrome DevTools' Scope + Call Stack panels when paused at a breakpoint.\n */\nimport { memo, useState } from \"react\";\nimport { theme } from \"../../theme\";\nimport type { StageSnapshot } from \"../../types\";\nimport { MemoryPanel } from \"../MemoryPanel\";\nimport { DataTracePanel, type CausalFrame } from \"../DataTracePanel/DataTracePanel\";\n\nexport interface InspectorPanelProps {\n snapshots: StageSnapshot[];\n selectedIndex: number;\n /** Causal chain frames for the selected node (empty = no trace available). */\n dataTraceFrames: CausalFrame[];\n /** Currently selected runtimeStageId. */\n selectedStageId?: string;\n /** Navigate to a stage when clicking a Data Trace frame. */\n onNavigateToStage?: (runtimeStageId: string) => void;\n}\n\ntype InspectorTab = \"state\" | \"trace\";\n\nexport const InspectorPanel = memo(function InspectorPanel({\n snapshots,\n selectedIndex,\n dataTraceFrames,\n selectedStageId,\n onNavigateToStage,\n}: InspectorPanelProps) {\n const [tab, setTab] = useState<InspectorTab>(\"state\");\n const currentSnapshot = snapshots[selectedIndex];\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n overflow: \"hidden\",\n }}\n >\n {/* Tab bar */}\n <div\n style={{\n display: \"flex\",\n borderBottom: `1px solid ${theme.border}`,\n flexShrink: 0,\n }}\n >\n <TabButton\n active={tab === \"state\"}\n onClick={() => setTab(\"state\")}\n label=\"State\"\n />\n <TabButton\n active={tab === \"trace\"}\n onClick={() => setTab(\"trace\")}\n label=\"Data Trace\"\n badge={dataTraceFrames.length > 0 ? String(dataTraceFrames.length) : undefined}\n />\n </div>\n\n {/* Tab content */}\n <div style={{ flex: 1, overflow: \"auto\" }}>\n {tab === \"state\" && (\n <MemoryPanel\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n />\n )}\n {tab === \"trace\" && (\n <DataTracePanel\n frames={dataTraceFrames}\n selectedStageId={selectedStageId}\n onFrameClick={onNavigateToStage}\n fromStageName={currentSnapshot?.stageName}\n />\n )}\n </div>\n </div>\n );\n});\n\nfunction TabButton({\n active,\n onClick,\n label,\n badge,\n}: {\n active: boolean;\n onClick: () => void;\n label: string;\n badge?: string;\n}) {\n return (\n <button\n onClick={onClick}\n style={{\n padding: \"8px 14px\",\n border: \"none\",\n borderBottom: active\n ? \"2px solid var(--fp-accent, #6366f1)\"\n : \"2px solid transparent\",\n background: \"transparent\",\n color: active ? \"var(--fp-accent, #6366f1)\" : theme.textMuted,\n fontWeight: active ? 600 : 400,\n fontSize: 12,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n }}\n >\n {label}\n {badge && (\n <span\n style={{\n fontSize: 10,\n background: active\n ? \"var(--fp-accent, #6366f1)\"\n : theme.textMuted,\n color: \"#fff\",\n borderRadius: 8,\n padding: \"1px 5px\",\n fontWeight: 600,\n }}\n >\n {badge}\n </span>\n )}\n </button>\n );\n}\n","/**\n * DataTracePanel — Backward causal chain visualization.\n *\n * Shows the data dependency chain from the selected stage backward:\n * \"Format read processed from Process, which read input from Seed.\"\n *\n * Like Chrome DevTools' Call Stack — click a frame to navigate there.\n *\n * Uses causalChain() from footprintjs/trace internally. The commitLog\n * and keysRead data come from props (collected during traversal).\n */\nimport { memo, useMemo } from \"react\";\nimport { theme } from \"../../theme\";\nimport type { StageSnapshot } from \"../../types\";\n\n// ── Types for causal chain data ────────────────────────────────────\n\n/** A node in the causal DAG (matches footprintjs CausalNode shape). */\nexport interface CausalFrame {\n runtimeStageId: string;\n stageId: string;\n stageName: string;\n keysWritten: string[];\n linkedBy: string;\n depth: number;\n}\n\nexport interface DataTracePanelProps {\n /** Flattened causal chain frames (BFS order from causalChain + flattenCausalDAG). */\n frames: CausalFrame[];\n /** Currently selected stage's runtimeStageId. */\n selectedStageId?: string;\n /** Callback when a frame is clicked — navigate time-travel to that stage. */\n onFrameClick?: (runtimeStageId: string) => void;\n /** Optional: stage name for the \"tracing from\" header. */\n fromStageName?: string;\n}\n\n/**\n * Render the backward causal chain as a stack trace.\n * Each frame shows: stage name, what it wrote, linked by which key.\n * Click a frame to navigate the time-travel slider.\n */\nexport const DataTracePanel = memo(function DataTracePanel({\n frames,\n selectedStageId,\n onFrameClick,\n fromStageName,\n}: DataTracePanelProps) {\n if (frames.length === 0) {\n return (\n <div style={{ padding: \"14px 14px 12px\", fontSize: 13, lineHeight: 1.55 }}>\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.5px\",\n fontWeight: 600,\n marginBottom: 6,\n }}\n >\n Backward causal chain\n </div>\n <div style={{ color: theme.textSecondary, marginBottom: 10 }}>\n Trace any value back to the stage that created it — and everything upstream that\n influenced it.\n </div>\n <div style={{ color: theme.textMuted, fontSize: 12 }}>\n Select a stage above to see its dependency chain.\n </div>\n </div>\n );\n }\n\n return (\n <div style={{ padding: \"8px 0\", fontSize: 13 }}>\n {fromStageName && (\n <div style={{ padding: \"4px 12px 8px\" }}>\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.5px\",\n fontWeight: 600,\n }}\n >\n Data trace from {fromStageName}\n </div>\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n fontStyle: \"italic\",\n marginTop: 3,\n }}\n >\n Every value here was derived from the stages below.\n </div>\n </div>\n )}\n {frames.map((frame, i) => (\n <DataTraceFrame\n key={frame.runtimeStageId}\n frame={frame}\n isFirst={i === 0}\n isLast={i === frames.length - 1}\n isSelected={frame.runtimeStageId === selectedStageId}\n onClick={onFrameClick}\n />\n ))}\n </div>\n );\n});\n\nconst DataTraceFrame = memo(function DataTraceFrame({\n frame,\n isFirst,\n isLast,\n isSelected,\n onClick,\n}: {\n frame: CausalFrame;\n isFirst: boolean;\n isLast: boolean;\n isSelected: boolean;\n onClick?: (id: string) => void;\n}) {\n return (\n <button\n onClick={() => onClick?.(frame.runtimeStageId)}\n style={{\n display: \"block\",\n width: \"100%\",\n textAlign: \"left\",\n border: \"none\",\n background: isSelected\n ? \"var(--fp-accent-bg, rgba(99,102,241,0.12))\"\n : \"transparent\",\n padding: \"6px 12px 6px 16px\",\n cursor: onClick ? \"pointer\" : \"default\",\n borderLeft: isSelected\n ? \"3px solid var(--fp-accent, #6366f1)\"\n : \"3px solid transparent\",\n color: \"inherit\",\n fontSize: 13,\n }}\n >\n {/* Stage name + depth indicator */}\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n {/* Connector line */}\n {!isFirst && (\n <span style={{ color: theme.textMuted, fontSize: 11 }}>\n ↑\n </span>\n )}\n <span\n style={{\n fontWeight: isFirst ? 600 : 400,\n color: isFirst\n ? \"var(--fp-accent, #6366f1)\"\n : theme.textPrimary,\n }}\n >\n {frame.stageName}\n </span>\n {isLast && !isFirst && (\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n fontStyle: \"italic\",\n }}\n >\n (origin)\n </span>\n )}\n </div>\n\n {/* What this stage wrote */}\n {frame.keysWritten.length > 0 && (\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n paddingLeft: isFirst ? 0 : 18,\n marginTop: 2,\n }}\n >\n wrote:{\" \"}\n <span style={{ color: theme.textSecondary }}>\n {frame.keysWritten.join(\", \")}\n </span>\n </div>\n )}\n\n {/* Linked by which key */}\n {frame.linkedBy && (\n <div\n style={{\n fontSize: 11,\n color: \"var(--fp-accent, #6366f1)\",\n paddingLeft: 18,\n marginTop: 1,\n }}\n >\n ← via {frame.linkedBy}\n </div>\n )}\n </button>\n );\n});\n","/**\n * InsightPanel — Recorder outputs renamed as \"Insights\".\n *\n * Two modes:\n * - Tabs: one insight at a time (full height) — when flowchart is visible\n * - Grid: all insights visible (2x2) — when flowchart is collapsed\n *\n * Each insight maps to a recorder's toSnapshot() output.\n * User-facing names: Story, Performance, Quality, Cost.\n */\nimport { memo, useState } from \"react\";\nimport { theme } from \"../../theme\";\n\nexport interface InsightConfig {\n /** Unique ID (matches recorder id). */\n id: string;\n /** User-facing name (Story, Performance, Quality, Cost). */\n name: string;\n /** Aggregate summary for collapsed header (e.g., \"1.2ms 3R 3W\"). */\n summary?: string;\n /** Render the insight content. */\n render: () => React.ReactNode;\n}\n\nexport interface InsightPanelProps {\n insights: InsightConfig[];\n /** Which insight is expanded by default (by id). */\n expandedId?: string;\n /** Display mode: tabs (one at a time) or grid (all visible). */\n mode: \"tabs\" | \"grid\";\n}\n\nexport const InsightPanel = memo(function InsightPanel({\n insights,\n expandedId,\n mode,\n}: InsightPanelProps) {\n if (insights.length === 0) {\n return (\n <div style={{ padding: 12, color: theme.textMuted, fontSize: 13 }}>\n No insights available. Attach recorders to see data.\n </div>\n );\n }\n\n if (mode === \"grid\") {\n return <InsightGrid insights={insights} />;\n }\n\n return <InsightTabs insights={insights} defaultId={expandedId} />;\n});\n\n// ── Tabs mode (one at a time, full height) ─────────────────────────\n\nconst InsightTabs = memo(function InsightTabs({\n insights,\n defaultId,\n}: {\n insights: InsightConfig[];\n defaultId?: string;\n}) {\n const [activeId, setActiveId] = useState(defaultId ?? insights[0]?.id);\n const active = insights.find((i) => i.id === activeId) ?? insights[0];\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n overflow: \"hidden\",\n }}\n >\n {/* Tab bar */}\n <div\n style={{\n display: \"flex\",\n borderBottom: `1px solid ${theme.border}`,\n flexShrink: 0,\n overflowX: \"auto\",\n }}\n >\n {insights.map((insight) => (\n <button\n key={insight.id}\n onClick={() => setActiveId(insight.id)}\n style={{\n padding: \"8px 12px\",\n border: \"none\",\n borderBottom:\n activeId === insight.id\n ? \"2px solid var(--fp-accent, #6366f1)\"\n : \"2px solid transparent\",\n background: \"transparent\",\n color:\n activeId === insight.id\n ? \"var(--fp-accent, #6366f1)\"\n : theme.textMuted,\n fontWeight: activeId === insight.id ? 600 : 400,\n fontSize: 12,\n cursor: \"pointer\",\n whiteSpace: \"nowrap\",\n }}\n >\n {insight.name}\n </button>\n ))}\n </div>\n\n {/* Active content */}\n <div style={{ flex: 1, overflow: \"auto\" }}>\n {active?.render()}\n </div>\n </div>\n );\n});\n\n// ── Grid mode (all visible, 2x2) ──────────────────────────────────\n\nconst InsightGrid = memo(function InsightGrid({\n insights,\n}: {\n insights: InsightConfig[];\n}) {\n const cols = insights.length <= 2 ? 1 : 2;\n\n return (\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: `repeat(${cols}, 1fr)`,\n height: \"100%\",\n overflow: \"auto\",\n gap: 1,\n background: theme.border,\n }}\n >\n {insights.map((insight) => (\n <div\n key={insight.id}\n style={{\n background: \"var(--fp-bg, #1a1b26)\",\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n }}\n >\n {/* Grid cell header */}\n <div\n style={{\n padding: \"6px 10px\",\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n textTransform: \"uppercase\",\n letterSpacing: \"0.5px\",\n borderBottom: `1px solid ${theme.border}`,\n flexShrink: 0,\n }}\n >\n {insight.name}\n {insight.summary && (\n <span\n style={{\n marginLeft: 8,\n fontWeight: 400,\n fontSize: 10,\n color: theme.textMuted,\n }}\n >\n {insight.summary}\n </span>\n )}\n </div>\n {/* Grid cell content */}\n <div style={{ flex: 1, overflow: \"auto\" }}>\n {insight.render()}\n </div>\n </div>\n ))}\n </div>\n );\n});\n","/**\n * CompactTimeline — Collapsed = dot line, expanded = Gantt chart.\n *\n * Collapsed: single row of colored dots showing execution progress.\n * Expanded: delegates to GanttTimeline for full duration bars.\n */\nimport { memo, useState } from \"react\";\nimport { theme } from \"../../theme\";\nimport type { StageSnapshot } from \"../../types\";\nimport { GanttTimeline } from \"../GanttTimeline\";\n\nexport interface CompactTimelineProps {\n snapshots: StageSnapshot[];\n selectedIndex: number;\n /** Start expanded or collapsed. Default: collapsed. */\n defaultExpanded?: boolean;\n}\n\nexport const CompactTimeline = memo(function CompactTimeline({\n snapshots,\n selectedIndex,\n defaultExpanded = false,\n}: CompactTimelineProps) {\n const [expanded, setExpanded] = useState(defaultExpanded);\n\n if (snapshots.length === 0) return null;\n\n return (\n <div style={{ borderTop: `1px solid ${theme.border}` }}>\n {/* Toggle header */}\n <button\n onClick={() => setExpanded((e) => !e)}\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"6px 12px\",\n border: \"none\",\n background: \"transparent\",\n cursor: \"pointer\",\n fontSize: 11,\n color: theme.textMuted,\n fontWeight: 600,\n textTransform: \"uppercase\",\n letterSpacing: \"0.5px\",\n }}\n >\n <span style={{ fontSize: 10 }}>{expanded ? \"▼\" : \"▸\"}</span>\n Timeline\n <span style={{ fontWeight: 400, fontSize: 10 }}>\n {snapshots.length} stages\n </span>\n\n {/* Compact dot line (visible when collapsed) */}\n {!expanded && (\n <div\n style={{\n flex: 1,\n display: \"flex\",\n alignItems: \"center\",\n gap: 2,\n marginLeft: 8,\n }}\n >\n {snapshots.map((snap, i) => (\n <div\n key={i}\n style={{\n width: i === selectedIndex ? 8 : 5,\n height: i === selectedIndex ? 8 : 5,\n borderRadius: \"50%\",\n background:\n i < selectedIndex\n ? \"var(--fp-success, #22c55e)\"\n : i === selectedIndex\n ? \"var(--fp-accent, #6366f1)\"\n : theme.textMuted + \"40\",\n transition: \"all 0.15s\",\n flexShrink: 0,\n }}\n title={snap.stageName}\n />\n ))}\n {/* Connecting line */}\n <div\n style={{\n flex: 1,\n height: 1,\n background: theme.textMuted + \"30\",\n marginLeft: -2,\n marginRight: 4,\n }}\n />\n </div>\n )}\n </button>\n\n {/* Expanded: full Gantt */}\n {expanded && (\n <div style={{ padding: \"0 12px 8px\" }}>\n <GanttTimeline\n snapshots={snapshots}\n selectedIndex={selectedIndex}\n />\n </div>\n )}\n </div>\n );\n});\n","/**\n * TraceViewer — drop-in component that renders an `agentfootprint.exportTrace()`\n * JSON as a fully interactive Behind-the-Scenes view.\n *\n * The pattern:\n * 1. Producer side calls `agentfootprint.exportTrace(runner)` to capture\n * a portable JSON `AgentfootprintTrace` (schemaVersion 1).\n * 2. The JSON is shipped anywhere — file, HTTP, clipboard, database.\n * 3. Consumer side passes it to `<TraceViewer trace={...} />` and gets\n * the full BTS view: flowchart topology, narrative timeline, snapshot\n * memory state, recorder data — without re-executing anything.\n *\n * Accepts EITHER a parsed object OR a raw JSON string. Validates\n * `schemaVersion === 1` and surfaces parse / validation errors via the\n * optional `onError` callback. When the trace is invalid, renders the\n * `fallback` prop (or nothing if not provided).\n *\n * @example\n * ```tsx\n * import { TraceViewer } from 'footprint-explainable-ui';\n *\n * function MyDebugPage({ trace }: { trace: unknown }) {\n * return <TraceViewer trace={trace} />;\n * }\n * ```\n *\n * @example Paste-from-clipboard pattern (the playground viewer)\n * ```tsx\n * const [raw, setRaw] = useState('');\n * <textarea value={raw} onChange={(e) => setRaw(e.target.value)} />\n * <TraceViewer\n * trace={raw}\n * onError={(err) => setStatus(err)}\n * fallback={<div>Paste a trace JSON to begin.</div>}\n * />\n * ```\n *\n * The component is a thin shell over `toVisualizationSnapshots` +\n * `<ExplainableShell />` — exactly the composition consumers would write\n * by hand. Source is short on purpose; read it as the reference.\n */\nimport * as React from 'react';\nimport { useMemo } from 'react';\nimport { ExplainableShell, type ExplainableShellProps, type ShellTab } from '../ExplainableShell';\nimport { toVisualizationSnapshots } from '../../adapters/fromRuntimeSnapshot';\n\n/**\n * Schema-versioned trace shape produced by `agentfootprint.exportTrace`.\n * Pinned to `schemaVersion: 1`; future shape changes will bump the version\n * and TraceViewer will gain a multi-version dispatch table.\n */\nexport interface AgentfootprintTrace {\n readonly schemaVersion: 1;\n readonly exportedAt?: string;\n readonly redacted?: boolean;\n readonly snapshot?: unknown;\n readonly narrativeEntries?: unknown[];\n readonly spec?: unknown;\n}\n\n/**\n * Result of parsing + validating raw input. Internal — exposed via\n * `onError` so consumers can show their own error UI.\n */\nexport type TraceParseError =\n | { kind: 'invalid-json'; message: string }\n | { kind: 'not-object'; message: string }\n | { kind: 'missing-version'; message: string }\n | { kind: 'unsupported-version'; message: string; version: number };\n\nexport interface TraceViewerProps\n extends Pick<\n ExplainableShellProps,\n 'tabs' | 'defaultTab' | 'hideTabs' | 'size' | 'panelLabels' | 'recorderViews' | 'renderFlowchart'\n > {\n /**\n * Trace to render. Accepts a parsed `AgentfootprintTrace` object or a\n * raw JSON string (the component parses + validates it). `null` /\n * `undefined` / empty-string render the `fallback`.\n */\n readonly trace?: AgentfootprintTrace | string | null;\n /**\n * Called on parse / validation errors. If you need to show your own\n * error UI, capture the error here and render alongside.\n */\n readonly onError?: (error: TraceParseError) => void;\n /** Element rendered when no valid trace is available. */\n readonly fallback?: React.ReactNode;\n}\n\nfunction parseTrace(input: TraceViewerProps['trace']): {\n ok: true;\n trace: AgentfootprintTrace;\n} | { ok: false; error: TraceParseError } {\n if (input == null) {\n return {\n ok: false,\n error: { kind: 'invalid-json', message: 'No trace provided.' },\n };\n }\n\n let candidate: unknown = input;\n if (typeof input === 'string') {\n if (!input.trim()) {\n return { ok: false, error: { kind: 'invalid-json', message: 'Empty input.' } };\n }\n try {\n candidate = JSON.parse(input);\n } catch (err) {\n return {\n ok: false,\n error: { kind: 'invalid-json', message: (err as Error).message },\n };\n }\n }\n\n if (!candidate || typeof candidate !== 'object') {\n return {\n ok: false,\n error: { kind: 'not-object', message: 'Trace must be a JSON object.' },\n };\n }\n\n const t = candidate as AgentfootprintTrace;\n if (typeof t.schemaVersion !== 'number') {\n return {\n ok: false,\n error: {\n kind: 'missing-version',\n message: 'Trace is missing required field `schemaVersion`. Did you pass an exportTrace() output?',\n },\n };\n }\n if (t.schemaVersion !== 1) {\n return {\n ok: false,\n error: {\n kind: 'unsupported-version',\n message: `Unsupported schemaVersion ${t.schemaVersion}. This TraceViewer renders schemaVersion 1.`,\n version: t.schemaVersion as number,\n },\n };\n }\n\n return { ok: true, trace: t };\n}\n\nconst DEFAULT_TABS: ShellTab[] = ['explainable'];\n\nexport function TraceViewer({\n trace,\n onError,\n fallback,\n tabs = DEFAULT_TABS,\n defaultTab = 'narrative',\n hideTabs,\n size,\n panelLabels,\n recorderViews,\n renderFlowchart,\n}: TraceViewerProps): React.ReactElement | null {\n const parsed = useMemo(() => parseTrace(trace), [trace]);\n\n // Surface errors via callback; render is determined by the validity below.\n React.useEffect(() => {\n if (!parsed.ok && onError) onError(parsed.error);\n }, [parsed, onError]);\n\n const snapshots = useMemo(() => {\n if (!parsed.ok || !parsed.trace.snapshot) return [];\n try {\n return toVisualizationSnapshots(\n parsed.trace.snapshot as Parameters<typeof toVisualizationSnapshots>[0],\n (parsed.trace.narrativeEntries as Parameters<typeof toVisualizationSnapshots>[1]) ?? undefined,\n );\n } catch {\n return [];\n }\n }, [parsed]);\n\n if (!parsed.ok || snapshots.length === 0) {\n return (fallback ?? null) as React.ReactElement | null;\n }\n\n return (\n <ExplainableShell\n snapshots={snapshots}\n spec={parsed.trace.spec as ExplainableShellProps['spec']}\n narrativeEntries={parsed.trace.narrativeEntries as ExplainableShellProps['narrativeEntries']}\n tabs={tabs}\n defaultTab={defaultTab}\n hideTabs={hideTabs}\n size={size}\n panelLabels={panelLabels}\n recorderViews={recorderViews}\n renderFlowchart={renderFlowchart}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAA0C;;;ACuBnC,SAAS,gBAAgB,QAA6C;AAC3E,QAAM,OAA+B,CAAC;AACtC,MAAI,OAAO,QAAQ;AACjB,UAAM,IAAI,OAAO;AACjB,QAAI,EAAE,QAAS,MAAK,oBAAoB,IAAI,EAAE;AAC9C,QAAI,EAAE,QAAS,MAAK,oBAAoB,IAAI,EAAE;AAC9C,QAAI,EAAE,MAAO,MAAK,kBAAkB,IAAI,EAAE;AAC1C,QAAI,EAAE,QAAS,MAAK,oBAAoB,IAAI,EAAE;AAC9C,QAAI,EAAE,UAAW,MAAK,iBAAiB,IAAI,EAAE;AAC7C,QAAI,EAAE,YAAa,MAAK,mBAAmB,IAAI,EAAE;AACjD,QAAI,EAAE,WAAY,MAAK,kBAAkB,IAAI,EAAE;AAC/C,QAAI,EAAE,YAAa,MAAK,mBAAmB,IAAI,EAAE;AACjD,QAAI,EAAE,cAAe,MAAK,qBAAqB,IAAI,EAAE;AACrD,QAAI,EAAE,UAAW,MAAK,iBAAiB,IAAI,EAAE;AAC7C,QAAI,EAAE,OAAQ,MAAK,aAAa,IAAI,EAAE;AAAA,EACxC;AACA,MAAI,OAAO,OAAQ,MAAK,aAAa,IAAI,OAAO;AAChD,MAAI,OAAO,YAAY,KAAM,MAAK,gBAAgB,IAAI,OAAO,WAAW;AACxE,MAAI,OAAO,YAAY,KAAM,MAAK,gBAAgB,IAAI,OAAO,WAAW;AACxE,SAAO;AACT;AAGO,IAAM,cAAc;AAAA,EACzB,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,EACR,YAAY;AAAA,IACV,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAGO,IAAM,gBAER;AAAA,EACH,QAAQ;AAAA,IACN,SAAS,2BAA2B,YAAY,OAAO,OAAO;AAAA,IAC9D,SAAS,2BAA2B,YAAY,OAAO,OAAO;AAAA,IAC9D,OAAO,yBAAyB,YAAY,OAAO,KAAK;AAAA,IACxD,SAAS,2BAA2B,YAAY,OAAO,OAAO;AAAA,IAC9D,WAAW,wBAAwB,YAAY,OAAO,SAAS;AAAA,IAC/D,aAAa,0BAA0B,YAAY,OAAO,WAAW;AAAA,IACrE,YAAY,yBAAyB,YAAY,OAAO,UAAU;AAAA,IAClE,aAAa,0BAA0B,YAAY,OAAO,WAAW;AAAA,IACrE,eAAe,4BAA4B,YAAY,OAAO,aAAa;AAAA,IAC3E,WAAW,wBAAwB,YAAY,OAAO,SAAS;AAAA,IAC/D,QAAQ,oBAAoB,YAAY,OAAO,MAAM;AAAA,EACvD;AAAA,EACA,QAAQ,oBAAoB,YAAY,MAAM;AAAA,EAC9C,YAAY;AAAA,IACV,MAAM,uBAAuB,YAAY,WAAW,IAAI;AAAA,IACxD,MAAM,uBAAuB,YAAY,WAAW,IAAI;AAAA,EAC1D;AACF;;;ADnDM;AAlCN,IAAM,mBAAe,4BAA2B,CAAC,CAAC;AAE3C,SAAS,oBAAiC;AAC/C,aAAO,yBAAW,YAAY;AAChC;AAyBO,SAAS,eAAe,EAAE,SAAS,CAAC,GAAG,SAAS,GAAwB;AAC7E,QAAM,UAAU,gBAAgB,MAAM;AAEtC,SACE,4CAAC,aAAa,UAAb,EAAsB,OAAO,QAC5B;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,EAAE,GAAI,SAAiC,SAAS,WAAW;AAAA,MAClE,WAAU;AAAA,MAET;AAAA;AAAA,EACH,GACF;AAEJ;;;AExCO,SAAS,EAAE,SAAiB,UAA0B;AAC3D,SAAO,OAAO,OAAO,KAAK,QAAQ;AACpC;AAGO,IAAM,QAAQ;AAAA,EACnB,SAAS,EAAE,sBAAsB,SAAS;AAAA,EAC1C,SAAS,EAAE,sBAAsB,SAAS;AAAA,EAC1C,OAAO,EAAE,oBAAoB,SAAS;AAAA,EACtC,SAAS,EAAE,sBAAsB,SAAS;AAAA,EAC1C,WAAW,EAAE,mBAAmB,SAAS;AAAA,EACzC,aAAa,EAAE,qBAAqB,SAAS;AAAA,EAC7C,YAAY,EAAE,oBAAoB,SAAS;AAAA,EAC3C,aAAa,EAAE,qBAAqB,SAAS;AAAA,EAC7C,eAAe,EAAE,uBAAuB,SAAS;AAAA,EACjD,WAAW,EAAE,mBAAmB,SAAS;AAAA,EACzC,QAAQ,EAAE,eAAe,SAAS;AAAA,EAClC,QAAQ,EAAE,eAAe,KAAK;AAAA,EAC9B,UAAU,EAAE,kBAAkB,6CAA6C;AAAA,EAC3E,UAAU,EAAE,kBAAkB,0CAA0C;AAC1E;AAGO,IAAM,WAAyE;AAAA,EACpF,SAAS,EAAE,OAAO,IAAI,MAAM,IAAI,OAAO,EAAE;AAAA,EACzC,SAAS,EAAE,OAAO,IAAI,MAAM,IAAI,OAAO,GAAG;AAAA,EAC1C,UAAU,EAAE,OAAO,IAAI,MAAM,IAAI,OAAO,GAAG;AAC7C;AAGO,IAAM,UAAgC;AAAA,EAC3C,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AACZ;;;ACrCO,IAAM,WAAwB;AAAA,EACnC,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,EACR,YAAY;AAAA,IACV,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAGO,IAAM,WAAwB;AAAA,EACnC,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,EACR,YAAY;AAAA,IACV,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAGO,IAAM,YAAyB;AAAA,EACpC,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,EACR,YAAY;AAAA,IACV,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAGO,IAAM,YAAyB;AAAA,EACpC,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,EACR,YAAY;AAAA,IACV,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAGO,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC1EA,IAAAA,gBAAoC;AAc7B,SAAS,kBAAkB,SAA8C;AAC9E,QAAM,cAAc,SAAS,SAAS;AACtC,QAAM,aAAa,SAAS,QAAQ;AAEpC,QAAM,CAAC,QAAQ,SAAS,QAAI;AAAA,IAC1B,MAAM,SAAS,gBAAgB,UAAU,SAAS,SAAS,YAAY,MAAM;AAAA,EAC/E;AAEA,+BAAU,MAAM;AACd,UAAM,MAAM,SAAS,YAAY;AACjC,UAAM,MAAM,IAAI,iBAAiB,MAAM;AACrC,gBAAU,SAAS,gBAAgB,UAAU,SAAS,GAAG,CAAC;AAAA,IAC5D,CAAC;AACD,QAAI,QAAQ,SAAS,iBAAiB;AAAA,MACpC,YAAY;AAAA,MACZ,iBAAiB,CAAC,OAAO;AAAA,IAC3B,CAAC;AACD,WAAO,MAAM,IAAI,WAAW;AAAA,EAC9B,GAAG,CAAC,SAAS,QAAQ,CAAC;AAEtB,SAAO,SAAS,aAAa;AAC/B;;;ACzDA,IAAAC,gBAAgC;AAoG1B,IAAAC,sBAAA;AAxEC,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAAyB;AAEvB,QAAM,eAAW,sBAA2B,IAAI;AAEhD,QAAM,EAAE,QAAQ,QAAQ,QAAI,uBAAQ,MAAM;AACxC,QAAI,MAAM;AACR,aAAO,EAAE,QAAQ,MAAM,SAAS,oBAAI,IAAY,EAAE;AAAA,IACpD;AACA,QAAI,CAAC,aAAa,UAAU,WAAW,GAAG;AACxC,aAAO,EAAE,QAAQ,CAAC,GAAG,SAAS,oBAAI,IAAY,EAAE;AAAA,IAClD;AAEA,UAAM,UAAU,KAAK,IAAI,eAAe,UAAU,SAAS,CAAC;AAC5D,QAAI;AACJ,UAAM,QAAQ,SAAS;AAEvB,QAAI,SAAS,MAAM,cAAc,aAAa,MAAM,SAAS,SAAS;AAEpE,eAAS,EAAE,GAAG,MAAM,YAAY;AAChC,eAAS,IAAI,MAAM,QAAQ,GAAG,KAAK,SAAS,KAAK;AAC/C,eAAO,OAAO,QAAQ,UAAU,CAAC,GAAG,MAAM;AAAA,MAC5C;AAAA,IACF,OAAO;AAEL,eAAS,CAAC;AACV,eAAS,IAAI,GAAG,KAAK,SAAS,KAAK;AACjC,eAAO,OAAO,QAAQ,UAAU,CAAC,GAAG,MAAM;AAAA,MAC5C;AAAA,IACF;AAGA,aAAS,UAAU,EAAE,WAAW,OAAO,SAAS,aAAa,OAAO;AAEpE,UAAM,KAAK,oBAAI,IAAY;AAC3B,QAAI,gBAAgB,UAAU,GAAG;AAE/B,UAAI;AACJ,UAAI,SAAS,MAAM,cAAc,aAAa,MAAM,UAAU,UAAU,GAAG;AACzE,eAAO,MAAM;AAAA,MACf,OAAO;AACL,eAAO,CAAC;AACR,iBAAS,IAAI,GAAG,IAAI,SAAS,KAAK;AAChC,iBAAO,OAAO,MAAM,UAAU,CAAC,GAAG,MAAM;AAAA,QAC1C;AAAA,MACF;AACA,YAAM,UAAU,UAAU,OAAO,GAAG,UAAU,CAAC;AAC/C,iBAAW,KAAK,OAAO,KAAK,OAAO,GAAG;AACpC,YAAI,EAAE,KAAK,MAAO,IAAG,IAAI,CAAC;AAAA,MAC5B;AAAA,IACF,WAAW,gBAAgB,YAAY,KAAK,UAAU,CAAC,GAAG;AACxD,iBAAW,KAAK,OAAO,KAAK,UAAU,CAAC,EAAE,MAAM,EAAG,IAAG,IAAI,CAAC;AAAA,IAC5D;AAEA,WAAO,EAAE,QAAQ,QAAQ,SAAS,GAAG;AAAA,EACvC,GAAG,CAAC,MAAM,WAAW,eAAe,YAAY,CAAC;AAEjD,QAAM,UAAU,OAAO,QAAQ,MAAM;AACrC,QAAM,KAAK,SAAS,IAAI;AACxB,QAAM,MAAM,QAAQ,IAAI;AAExB,MAAI,UAAU;AACZ,WACE,8CAAC,SAAI,WAAsB,OAAc,WAAQ,oBAAmB,MAAK,UAAS,cAAW,gBAC3F;AAAA,mDAAC,SAAI,WAAQ,gBAAe,0BAAY;AAAA,MACxC,6CAAC,SAAI,WAAQ,eACX,uDAAC,UAAM,eAAK,UAAU,QAAQ,MAAM,CAAC,GAAE,GACzC;AAAA,OACF;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY,MAAM;AAAA,QAClB,GAAG;AAAA,MACL;AAAA,MACA,WAAQ;AAAA,MACR,MAAK;AAAA,MACL,cAAW;AAAA,MAEX;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,UAAU,GAAG;AAAA,cACb,YAAY;AAAA,cACZ,OAAO,MAAM;AAAA,cACb,eAAe;AAAA,cACf,eAAe;AAAA,YACjB;AAAA,YACD;AAAA;AAAA,QAED;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,WAAW;AAAA,cACX,YAAY,MAAM;AAAA,cAClB,QAAQ,aAAa,MAAM,MAAM;AAAA,cACjC,cAAc,MAAM;AAAA,cACpB,SAAS,GAAG,GAAG,MAAM,MAAM,CAAC;AAAA,cAC5B,YAAY,MAAM;AAAA,cAClB,UAAU,GAAG;AAAA,cACb,YAAY;AAAA,YACd;AAAA,YAEA;AAAA,2DAAC,UAAK,OAAO,EAAE,OAAO,MAAM,UAAU,GAAI,eAAI;AAAA,cAC7C,QAAQ,WAAW,KAClB;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,aAAa;AAAA,oBACb,OAAO,MAAM;AAAA,oBACb,WAAW;AAAA,kBACb;AAAA,kBAEC;AAAA;AAAA,cACH;AAAA,cAED,QAAQ,IAAI,CAAC,CAAC,KAAK,KAAK,GAAG,MAAM;AAChC,sBAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,sBAAM,SAAS,MAAM,QAAQ,SAAS;AACtC,uBACE;AAAA,kBAAC;AAAA;AAAA,oBAEC,OAAO;AAAA,sBACL,aAAa;AAAA,sBACb,YAAY,QACR,sBAAsB,MAAM,OAAO,uBACnC;AAAA,sBACJ,cAAc;AAAA,sBACd,YAAY;AAAA,sBACZ,aAAa;AAAA,sBACb,cAAc;AAAA,oBAChB;AAAA,oBAEA;AAAA,oEAAC,UAAK,OAAO,EAAE,OAAO,MAAM,QAAQ,GAAG;AAAA;AAAA,wBAAO;AAAA,wBAAI;AAAA,yBAAM;AAAA,sBACxD,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,UAAU,GAAG,gBAAE;AAAA,sBAC3C,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,QAAQ,GACjC,sBAAY,KAAK,GACpB;AAAA,sBACC,aACC;AAAA,wBAAC;AAAA;AAAA,0BACC,OAAO;AAAA,4BACL,OAAO,MAAM;AAAA,4BACb,UAAU,GAAG;AAAA,4BACb,YAAY;AAAA,4BACZ,SAAS;AAAA,0BACX;AAAA,0BACD;AAAA;AAAA,4BACG,OAAO;AAAA,4BAAM;AAAA;AAAA;AAAA,sBACjB;AAAA,sBAED,CAAC,UAAU,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,UAAU,GAAG,eAAC;AAAA;AAAA;AAAA,kBA7BjD;AAAA,gBA8BP;AAAA,cAEJ,CAAC;AAAA,cACD,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,UAAU,GAAI,eAAI;AAAA;AAAA;AAAA,QAChD;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,YAAY,OAAwB;AAC3C,MAAI,OAAO,UAAU,SAAU,QAAO,IAAI,KAAK;AAC/C,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO,KAAK,UAAU,KAAK;AAC5E,SAAO,OAAO,KAAK;AACrB;;;AC5MA,IAAAC,gBAAwB;AA6Cd,IAAAC,sBAAA;AA5BH,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAAsB;AACpB,QAAM,cAAU,uBAAQ,MAAM;AAC5B,QAAI,WAAW;AACb,aAAO,CAAC,EAAE,OAAO,UAAU,MAAM,WAAW,WAAW,KAAK,CAAC;AAAA,IAC/D;AACA,UAAM,MAAM,iBAAiB,UAAU,SAAS;AAChD,WAAO,UAAU,MAAM,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,OAAO;AAAA,MAChD,OAAO,EAAE;AAAA,MACT,MAAM,EAAE;AAAA,MACR,WAAW,MAAM;AAAA,IACnB,EAAE;AAAA,EACJ,GAAG,CAAC,WAAW,eAAe,SAAS,CAAC;AAExC,QAAM,KAAK,SAAS,IAAI;AACxB,QAAM,MAAM,QAAQ,IAAI;AAExB,MAAI,UAAU;AACZ,WACE,6CAAC,SAAI,WAAsB,OAAc,WAAQ,iBAC9C,kBAAQ,IAAI,CAAC,OAAO,MACnB,8CAAC,SAAY,WAAQ,mBAAkB,gBAAc,MAAM,WACzD;AAAA,mDAAC,YAAQ,gBAAM,OAAM;AAAA,MACrB,6CAAC,OAAG,gBAAM,MAAK;AAAA,SAFP,CAGV,CACD,GACH;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO,EAAE,SAAS,KAAK,YAAY,MAAM,UAAU,GAAG,MAAM;AAAA,MAC5D,WAAQ;AAAA,MAER;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,UAAU,GAAG;AAAA,cACb,YAAY;AAAA,cACZ,OAAO,MAAM;AAAA,cACb,eAAe;AAAA,cACf,eAAe;AAAA,YACjB;AAAA,YACD;AAAA;AAAA,QAED;AAAA,QACA,6CAAC,SAAI,OAAO,EAAE,WAAW,GAAG,SAAS,QAAQ,eAAe,SAAS,GAClE,kBAAQ,IAAI,CAAC,OAAO,MACnB;AAAA,UAAC;AAAA;AAAA,YAEC,OAAO;AAAA,cACL,SAAS;AAAA,cACT,KAAK;AAAA,cACL,SAAS,GAAG,GAAG;AAAA,cACf,cACE,IAAI,QAAQ,SAAS,IAAI,aAAa,MAAM,MAAM,KAAK;AAAA,YAC3D;AAAA,YAGA;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,SAAS;AAAA,oBACT,eAAe;AAAA,oBACf,YAAY;AAAA,oBACZ,OAAO;AAAA,oBACP,YAAY;AAAA,oBACZ,YAAY;AAAA,kBACd;AAAA,kBAEA;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,OAAO;AAAA,0BACP,QAAQ;AAAA,0BACR,cAAc;AAAA,0BACd,YAAY,MAAM,YAAY,MAAM,UAAU,MAAM;AAAA,0BACpD,YAAY;AAAA,wBACd;AAAA;AAAA,oBACF;AAAA,oBACC,IAAI,QAAQ,SAAS,KACpB;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,OAAO;AAAA,0BACP,MAAM;AAAA,0BACN,YAAY,MAAM;AAAA,0BAClB,WAAW;AAAA,wBACb;AAAA;AAAA,oBACF;AAAA;AAAA;AAAA,cAEJ;AAAA,cAGA,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,GACjC;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,UAAU,GAAG;AAAA,sBACb,YAAY;AAAA,sBACZ,OAAO,MAAM,YAAY,MAAM,UAAU,MAAM;AAAA,oBACjD;AAAA,oBAEC,gBAAM;AAAA;AAAA,gBACT;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,UAAU,GAAG;AAAA,sBACb,YAAY;AAAA,sBACZ,OAAO,MAAM,YAAY,MAAM,cAAc,MAAM;AAAA,sBACnD,WAAW;AAAA,oBACb;AAAA,oBAEC,gBAAM;AAAA;AAAA,gBACT;AAAA,iBACF;AAAA;AAAA;AAAA,UA9DK;AAAA,QA+DP,CACD,GACH;AAAA;AAAA;AAAA,EACF;AAEJ;;;AC9IA,IAAAC,gBAAkE;AAkGxD,IAAAC,sBAAA;AArEV,SAAS,YAAY,OAAmC;AACtD,QAAM,SAA2B,CAAC;AAClC,MAAI,UAAiC;AAErC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,UAAU,KAAK,UAAU;AAC/B,UAAM,SAAS,QAAQ,WAAW,OAAO,KAAK,MAAM,KAAK,IAAI;AAE7D,QAAI,CAAC,UAAU,CAAC,SAAS;AACvB,gBAAU,EAAE,QAAQ,MAAM,WAAW,GAAG,OAAO,CAAC,EAAE;AAClD,aAAO,KAAK,OAAO;AAAA,IACrB,OAAO;AACL,cAAQ,MAAM,KAAK,EAAE,MAAM,SAAS,KAAK,EAAE,CAAC;AAAA,IAC9C;AAAA,EACF;AAEA,SAAO;AACT;AAMO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA,mBAAmB;AAAA,EACnB;AAAA,EACA,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,WAAW,iBAAiB,OAAO,UAAU,MAAM,GAAG,aAAa,IAAI;AAC7E,QAAM,SAAS,iBAAiB,OAAO,UAAU,MAAM,aAAa,IAAI,CAAC;AAEzE,QAAM,qBAAiB,uBAAQ,MAAM,YAAY,QAAQ,GAAG,CAAC,QAAQ,CAAC;AACtE,QAAM,mBAAe,uBAAQ,MAAM,YAAY,MAAM,GAAG,CAAC,MAAM,CAAC;AAEhE,QAAM,CAAC,cAAc,eAAe,QAAI,wBAAsB,MAAM;AAClE,QAAI,CAAC,iBAAkB,QAAO,oBAAI,IAAI;AACtC,WAAO,IAAI,IAAI,YAAY,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,EAC/D,CAAC;AAED,QAAM,gBAAY,sBAAuB,IAAI;AAE7C,+BAAU,MAAM;AACd,cAAU,SAAS,eAAe,EAAE,UAAU,UAAU,OAAO,UAAU,CAAC;AAAA,EAC5E,GAAG,CAAC,eAAe,MAAM,CAAC;AAE1B,QAAM,aAAS,2BAAY,CAAC,QAAgB;AAC1C,oBAAgB,CAAC,SAAS;AACxB,YAAM,OAAO,IAAI,IAAI,IAAI;AACzB,UAAI,KAAK,IAAI,GAAG,EAAG,MAAK,OAAO,GAAG;AAAA,UAC7B,MAAK,IAAI,GAAG;AACjB,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,eAAe,SAAS;AACxC,QAAM,KAAK,SAAS,IAAI;AACxB,QAAM,MAAM,QAAQ,IAAI;AAGxB,MAAI,UAAU;AACZ,WACE,8CAAC,SAAI,WAAsB,OAAc,WAAQ,mBAC9C;AAAA,qBAAe,IAAI,CAAC,OAAO,OAC1B,8CAAC,SAA0B,WAAQ,mBAAkB,eAAa,OAAO,SACvE;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAQ;AAAA,YACR,oBAAkB,MAAM,MAAM,SAAS;AAAA,YACvC,kBAAgB,aAAa,IAAI,MAAM,SAAS;AAAA,YAChD,MAAM,MAAM,MAAM,SAAS,IAAI,WAAW;AAAA,YAC1C,UAAU,MAAM,MAAM,SAAS,IAAI,IAAI;AAAA,YACvC,iBAAe,MAAM,MAAM,SAAS,IAAI,CAAC,aAAa,IAAI,MAAM,SAAS,IAAI;AAAA,YAC7E,cAAY,SAAS,KAAK,CAAC,KAAK,MAAM,MAAM,MAAM,SAAS,OAAO,UAAU,cAAc,EAAE;AAAA,YAC5F,SAAS,MAAM;AACb,kBAAI,MAAM,MAAM,SAAS,EAAG,QAAO,MAAM,SAAS;AAClD,6BAAe,MAAM,SAAS;AAAA,YAChC;AAAA,YACA,WAAW,CAAC,MAA2B;AACrC,kBAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,kBAAE,eAAe;AACjB,oBAAI,MAAM,MAAM,SAAS,EAAG,QAAO,MAAM,SAAS;AAClD,+BAAe,MAAM,SAAS;AAAA,cAChC;AAAA,YACF;AAAA,YAEC,gBAAM;AAAA;AAAA,QACT;AAAA,QACC,CAAC,aAAa,IAAI,MAAM,SAAS,KAChC,MAAM,MAAM,IAAI,CAAC,SACf,6CAAC,SAAmB,WAAQ,kBACzB,eAAK,QADE,KAAK,GAEf,CACD;AAAA,WA5BK,MAAM,SA6BhB,CACD;AAAA,MACA,aAAa,SAAS,KACrB,8CAAC,SAAI,WAAQ,yBACV;AAAA,qBAAa;AAAA,QAAO;AAAA,QAAO,aAAa,WAAW,IAAI,UAAU;AAAA,QAAS;AAAA,SAC7E;AAAA,OAEJ;AAAA,EAEJ;AAGA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS;AAAA,QACT,YAAY,MAAM;AAAA,QAClB,GAAG;AAAA,MACL;AAAA,MACA,WAAQ;AAAA,MAEP;AAAA,uBAAe,IAAI,CAAC,OAAO,OAAO;AACjC,gBAAM,WAAW,OAAO;AACxB,gBAAM,cAAc,aAAa,IAAI,MAAM,SAAS;AACpD,gBAAM,WAAW,MAAM,MAAM,SAAS;AAEtC,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,KAAK,WAAW,YAAY;AAAA,cAC5B,OAAO,EAAE,cAAc,EAAE;AAAA,cACzB,WAAQ;AAAA,cAGR;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAM,WAAW,WAAW;AAAA,oBAC5B,UAAU,WAAW,IAAI;AAAA,oBACzB,iBAAe,WAAW,CAAC,cAAc;AAAA,oBACzC,cAAY,SAAS,KAAK,CAAC,KAAK,MAAM,MAAM,MAAM,SAAS,WAAW,cAAc,aAAa;AAAA,oBACjG,SAAS,MAAM;AACb,0BAAI,SAAU,QAAO,MAAM,SAAS;AACpC,qCAAe,MAAM,SAAS;AAAA,oBAChC;AAAA,oBACA,WAAW,CAAC,MAA2B;AACrC,0BAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,0BAAE,eAAe;AACjB,4BAAI,SAAU,QAAO,MAAM,SAAS;AACpC,uCAAe,MAAM,SAAS;AAAA,sBAChC;AAAA,oBACF;AAAA,oBACA,OAAO;AAAA,sBACL,UAAU,GAAG;AAAA,sBACb,YAAY;AAAA,sBACZ,OAAO,WAAW,MAAM,cAAc,MAAM;AAAA,sBAC5C,SAAS,OAAO,MAAM,CAAC;AAAA,sBACvB,cAAc;AAAA,sBACd,YAAY,WAAW,MAAM,aAAa;AAAA,sBAC1C,YAAY,WACR,aAAa,MAAM,OAAO,KAC1B,aAAa,MAAM,OAAO;AAAA,sBAC9B,QAAQ,WAAW,YAAY;AAAA,sBAC/B,YAAY;AAAA,sBACZ,SAAS;AAAA,sBACT,YAAY;AAAA,sBACZ,KAAK;AAAA,sBACL,YAAY;AAAA,sBACZ,YAAY;AAAA,oBACd;AAAA,oBAEC;AAAA,kCACC;AAAA,wBAAC;AAAA;AAAA,0BACC,OAAO;AAAA,4BACL,UAAU,GAAG,QAAQ;AAAA,4BACrB,OAAO,MAAM;AAAA,4BACb,YAAY;AAAA,4BACZ,WAAW,cAAc,mBAAmB;AAAA,4BAC5C,SAAS;AAAA,4BACT,OAAO;AAAA,4BACP,YAAY;AAAA,0BACd;AAAA,0BACD;AAAA;AAAA,sBAED;AAAA,sBAED,CAAC,YAAY,6CAAC,UAAK,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,GAAG;AAAA,sBACzD,6CAAC,UAAM,gBAAM,QAAO;AAAA;AAAA;AAAA,gBACtB;AAAA,gBAGC,CAAC,eACA,MAAM,MAAM,IAAI,CAAC,SACf;AAAA,kBAAC;AAAA;AAAA,oBAEC,OAAO;AAAA,sBACL,UAAU,GAAG;AAAA,sBACb,YAAY;AAAA,sBACZ,OAAO,WAAW,MAAM,gBAAgB,MAAM;AAAA,sBAC9C,SAAS,OAAO,MAAM,CAAC,UAAU,MAAM,EAAE;AAAA,sBACzC,SAAS,WAAW,MAAM;AAAA,sBAC1B,YAAY;AAAA,oBACd;AAAA,oBACA,WAAQ;AAAA,oBAEP,eAAK;AAAA;AAAA,kBAXD,KAAK;AAAA,gBAYZ,CACD;AAAA;AAAA;AAAA,YA7EE,MAAM;AAAA,UA8Eb;AAAA,QAEJ,CAAC;AAAA,QAGA,aAAa,SAAS,KACrB,8CAAC,SAAI,OAAO;AAAA,UACV,SAAS;AAAA,UACT,UAAU,GAAG;AAAA,UACb,OAAO,MAAM;AAAA,UACb,SAAS,OAAO,GAAG;AAAA,UACnB,WAAW;AAAA,QACb,GACG;AAAA,uBAAa;AAAA,UAAO;AAAA,UAAO,aAAa,WAAW,IAAI,UAAU;AAAA,UAAS;AAAA,WAC7E;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;AC9PA,IAAAC,gBAAqD;AAwEzC,IAAAC,sBAAA;AApDL,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,iBAAiB;AACnB,GAAuB;AACrB,QAAM,CAAC,UAAU,WAAW,QAAI,wBAAS,KAAK;AAC9C,QAAM,mBAAe,sBAA8B,IAAI;AACvD,QAAM,yBAAqB,sBAA8B,IAAI;AAE7D,QAAM,oBAAgB;AAAA,IACpB,MAAM,KAAK,IAAI,GAAG,UAAU,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,CAAC;AAAA,IACnE,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,KAAK,SAAS,IAAI;AACxB,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,aAAa,SAAS,YAAY,KAAK,SAAS,aAAa,MAAM;AACzE,QAAM,UAAU,SAAS,YAAY,KAAK;AAC1C,QAAM,YAAY,SAAS,YAAY,KAAK;AAE5C,QAAM,cAAc,iBAAiB,KAAK,UAAU,SAAS;AAC7D,QAAM,UAAU,YAAY,CAAC;AAG7B,+BAAU,MAAM;AACd,QAAI,CAAC,WAAW,aAAa,WAAW,mBAAmB,SAAS;AAClE,mBAAa,QAAQ,eAAe;AAAA,QAClC,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,eAAe,OAAO,CAAC;AAE3B,MAAI,UAAU;AACZ,WACE,6CAAC,SAAI,WAAsB,OAAc,WAAQ,kBAAiB,MAAK,WAAU,cAAW,sBACzF,oBAAU,IAAI,CAAC,MAAM,QACpB;AAAA,MAAC;AAAA;AAAA,QAEC,WAAQ;AAAA,QACR,iBAAe,QAAQ;AAAA,QACvB,gBAAc,OAAO;AAAA,QACrB,MAAK;AAAA,QACL,iBAAe,QAAQ;AAAA,QACvB,cAAY,GAAG,KAAK,UAAU,KAAK,KAAK,UAAU;AAAA,QAClD,SAAS,MAAM,WAAW,GAAG;AAAA,QAE7B;AAAA,uDAAC,UAAK,WAAQ,eAAe,eAAK,YAAW;AAAA,UAC7C,8CAAC,UAAK,WAAQ,kBAAkB;AAAA,iBAAK;AAAA,YAAW;AAAA,aAAE;AAAA;AAAA;AAAA,MAV7C,GAAG,KAAK,SAAS,IAAI,GAAG;AAAA,IAW/B,CACD,GACH;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO,EAAE,SAAS,KAAK,YAAY,MAAM,UAAU,GAAG,MAAM;AAAA,MAC5D,WAAQ;AAAA,MAGR;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,gBAAgB;AAAA,YAClB;AAAA,YAEA;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,UAAU,GAAG;AAAA,oBACb,YAAY;AAAA,oBACZ,OAAO,MAAM;AAAA,oBACb,eAAe;AAAA,oBACf,eAAe;AAAA,kBACjB;AAAA,kBAEC,mBAAS,YAAY,aAAa;AAAA;AAAA,cACrC;AAAA,cACC,eACC;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;AAAA,kBACpC,OAAO;AAAA,oBACL,YAAY;AAAA,oBACZ,QAAQ,aAAa,MAAM,MAAM;AAAA,oBACjC,cAAc;AAAA,oBACd,OAAO,MAAM;AAAA,oBACb,UAAU,GAAG;AAAA,oBACb,SAAS;AAAA,oBACT,QAAQ;AAAA,oBACR,YAAY,MAAM;AAAA,kBACpB;AAAA,kBAEC,qBACG,aACA,GAAG,UAAU,SAAS,cAAc;AAAA;AAAA,cAC1C;AAAA;AAAA;AAAA,QAEJ;AAAA,QAGA;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL,cAAW;AAAA,YACX,OAAO;AAAA,cACL,WAAW;AAAA,cACX,SAAS;AAAA,cACT,eAAe;AAAA,cACf,KAAK;AAAA,cACL,GAAI,UACA,CAAC,IACD;AAAA,gBACE,WAAW,kBAAkB,YAAY;AAAA,gBACzC,WAAW;AAAA,gBACX,gBAAgB;AAAA,cAClB;AAAA,YACN;AAAA,YAEC,oBAAU,IAAI,CAAC,MAAM,QAAQ;AAC5B,oBAAM,UAAW,KAAK,UAAU,gBAAiB;AACjD,oBAAM,WAAW,KAAK,IAAK,KAAK,aAAa,gBAAiB,KAAK,CAAC;AACpE,oBAAM,aAAa,QAAQ;AAC3B,oBAAM,YAAY,OAAO;AAEzB,qBACE;AAAA,gBAAC;AAAA;AAAA,kBAEC,KAAK,aAAa,eAAe;AAAA,kBACjC,MAAK;AAAA,kBACL,iBAAe;AAAA,kBACf,cAAY,GAAG,KAAK,UAAU,KAAK,KAAK,UAAU;AAAA,kBAClD,SAAS,MAAM,WAAW,GAAG;AAAA,kBAC7B,OAAO;AAAA,oBACL,SAAS;AAAA,oBACT,YAAY;AAAA,oBACZ,KAAK,SAAS,YAAY,IAAI;AAAA,oBAC9B,QAAQ,WAAW,YAAY;AAAA,oBAC/B,SAAS,YAAY,IAAI;AAAA,oBACzB,YAAY;AAAA,oBACZ,QAAQ;AAAA,oBACR,YAAY;AAAA,kBACd;AAAA,kBAEA;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO,KAAK;AAAA,wBACZ,OAAO;AAAA,0BACL,OAAO;AAAA,0BACP,UAAU,GAAG;AAAA,0BACb,OAAO,aAAa,MAAM,UAAU,MAAM;AAAA,0BAC1C,YAAY,aAAa,MAAM;AAAA,0BAC/B,WAAW;AAAA,0BACX,YAAY;AAAA,0BACZ,UAAU;AAAA,0BACV,cAAc;AAAA,0BACd,YAAY;AAAA,wBACd;AAAA,wBAEC,eAAK;AAAA;AAAA,oBACR;AAAA,oBACA;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,MAAM;AAAA,0BACN,QAAQ,SAAS,YAAY,IAAI;AAAA,0BACjC,UAAU;AAAA,0BACV,YAAY,MAAM;AAAA,0BAClB,cAAc;AAAA,wBAChB;AAAA,wBAEC,uBACC;AAAA,0BAAC;AAAA;AAAA,4BACC,OAAO;AAAA,8BACL,UAAU;AAAA,8BACV,MAAM,GAAG,OAAO;AAAA,8BAChB,KAAK;AAAA,8BACL,OAAO,GAAG,QAAQ;AAAA,8BAClB,QAAQ;AAAA,8BACR,cAAc;AAAA,8BACd,YAAY,aAAa,MAAM,UAAU,MAAM;AAAA,8BAC/C,YAAY;AAAA,4BACd;AAAA;AAAA,wBACF;AAAA;AAAA,oBAEJ;AAAA,oBACA;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,UAAU,GAAG;AAAA,0BACb,OAAO,MAAM;AAAA,0BACb,YAAY,MAAM;AAAA,0BAClB,OAAO;AAAA,0BACP,YAAY;AAAA,wBACd;AAAA,wBAEC;AAAA,+BAAK;AAAA,0BAAW;AAAA;AAAA;AAAA,oBACnB;AAAA;AAAA;AAAA,gBAnEK,GAAG,KAAK,SAAS,IAAI,GAAG;AAAA,cAoE/B;AAAA,YAEJ,CAAC;AAAA;AAAA,QACH;AAAA,QAGA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,WAAW;AAAA,cACX,YAAY,cAAc,SAAS,YAAY,IAAI;AAAA,cACnD,aAAa,WAAW,SAAS,YAAY,IAAI;AAAA,cACjD,SAAS;AAAA,cACT,gBAAgB;AAAA,cAChB,UAAU,GAAG,QAAQ;AAAA,cACrB,OAAO,MAAM;AAAA,cACb,YAAY,MAAM;AAAA,YACpB;AAAA,YAEA;AAAA,2DAAC,UAAK,iBAAG;AAAA,cACR,SAAS,aACR,8CAAC,UAAO;AAAA,iCAAgB,GAAG,QAAQ,CAAC;AAAA,gBAAE;AAAA,iBAAE;AAAA,cAE1C,8CAAC,UAAM;AAAA,8BAAc,QAAQ,CAAC;AAAA,gBAAE;AAAA,iBAAE;AAAA;AAAA;AAAA,QACpC;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACvPA,IAAAC,gBAAyB;AAsCnB,IAAAC,sBAAA;AAhBC,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAAuB;AACrB,QAAM,CAAC,eAAe,gBAAgB,QAAI,wBAAS,CAAC;AACpD,QAAM,KAAK,SAAS,IAAI;AACxB,QAAM,MAAM,QAAQ,IAAI;AAExB,MAAI,UAAU,WAAW,GAAG;AAC1B,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO;AAAA,UACL,SAAS,MAAM;AAAA,UACf,WAAW;AAAA,UACX,OAAO,WAAW,SAAY,MAAM;AAAA,UACpC,UAAU,GAAG;AAAA,UACb,GAAG;AAAA,QACL;AAAA,QACA,WAAQ;AAAA,QACT;AAAA;AAAA,IAED;AAAA,EAEJ;AAEA,MAAI,UAAU;AACZ,WACE,8CAAC,SAAI,WAAsB,OAAc,WAAQ,kBAC/C;AAAA,mDAAC,QAAI,iBAAM;AAAA,MACV,gBACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK,UAAU,SAAS;AAAA,UACxB,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,iBAAiB,SAAS,EAAE,OAAO,KAAK,CAAC;AAAA;AAAA,MAC5D;AAAA,MAEF;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,UAAQ;AAAA;AAAA,MACV;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,UAAQ;AAAA;AAAA,MACV;AAAA,MACC,aACC;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,UAAU;AAAA,UACV,UAAQ;AAAA;AAAA,MACV;AAAA,OAEJ;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,YAAY,MAAM;AAAA,QAClB,YAAY,MAAM;AAAA,QAClB,UAAU;AAAA,QACV,GAAG;AAAA,MACL;AAAA,MACA,WAAQ;AAAA,MAGR;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,SAAS,GAAG,GAAG,MAAM,MAAM,CAAC;AAAA,cAC5B,cAAc,aAAa,MAAM,MAAM;AAAA,cACvC,YAAY,MAAM;AAAA,cAClB,YAAY;AAAA,YACd;AAAA,YAEA;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,SAAS;AAAA,oBACT,YAAY;AAAA,oBACZ,KAAK;AAAA,oBACL,cAAc,eAAe,IAAI;AAAA,kBACnC;AAAA,kBAEA;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,UAAU,GAAG,OAAO;AAAA,0BACpB,YAAY;AAAA,0BACZ,OAAO,MAAM;AAAA,wBACf;AAAA,wBAEC;AAAA;AAAA,oBACH;AAAA,oBACA;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,UAAU,GAAG;AAAA,0BACb,OAAO,MAAM;AAAA,0BACb,YAAY,MAAM;AAAA,wBACpB;AAAA,wBAEC;AAAA,0CAAgB;AAAA,0BAAE;AAAA,0BAAE,UAAU;AAAA;AAAA;AAAA,oBACjC;AAAA;AAAA;AAAA,cACF;AAAA,cAEC,gBACC,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GAC1D;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAM;AAAA,oBACN,UAAU,kBAAkB;AAAA,oBAC5B,SAAS,MAAM,iBAAiB,CAAC,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC;AAAA;AAAA,gBAC3D;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAK;AAAA,oBACL,KAAK,UAAU,SAAS;AAAA,oBACxB,OAAO;AAAA,oBACP,UAAU,CAAC,MAAM,iBAAiB,SAAS,EAAE,OAAO,KAAK,CAAC;AAAA,oBAC1D,OAAO;AAAA,sBACL,MAAM;AAAA,sBACN,QAAQ;AAAA,sBACR,aAAa,MAAM;AAAA,sBACnB,QAAQ;AAAA,oBACV;AAAA;AAAA,gBACF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAM;AAAA,oBACN,UAAU,kBAAkB,UAAU,SAAS;AAAA,oBAC/C,SAAS,MACP,iBAAiB,CAAC,MAAM,KAAK,IAAI,UAAU,SAAS,GAAG,IAAI,CAAC,CAAC;AAAA;AAAA,gBAEjE;AAAA,iBACF;AAAA;AAAA;AAAA,QAEJ;AAAA,QAGA,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,OAAO,GACtC;AAAA;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA;AAAA,UACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,QAAQ;AAAA,gBACR,YAAY,MAAM;AAAA,gBAClB,QAAQ,KAAK,GAAG;AAAA,cAClB;AAAA;AAAA,UACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA;AAAA,UACF;AAAA,WACF;AAAA,QAGC,aACC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,WAAW,aAAa,MAAM,MAAM;AAAA,cACpC,YAAY,MAAM;AAAA,cAClB,YAAY;AAAA,YACd;AAAA,YAEA;AAAA,cAAC;AAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA,UAAU;AAAA,gBACV;AAAA;AAAA,YACF;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO;AAAA,QACL,YAAY,MAAM;AAAA,QAClB,QAAQ,aAAa,MAAM,MAAM;AAAA,QACjC,OAAO,WAAW,MAAM,YAAY,MAAM;AAAA,QAC1C,cAAc;AAAA,QACd,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,QAAQ,WAAW,gBAAgB;AAAA,QACnC,SAAS,WAAW,MAAM;AAAA,QAC1B,UAAU;AAAA,QACV,YAAY;AAAA,MACd;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;;;ACrPA,IAAAC,gBAAwB;AA8FZ,IAAAC,sBAAA;AAlEZ,SAAS,YACP,MACA,MACa;AACb,QAAM,UAAuB,CAAC;AAC9B,QAAM,UAAU,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK,QAAQ,CAAC,CAAC,GAAG,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC;AAE1E,aAAW,OAAO,SAAS;AACzB,UAAM,SAAS,QAAQ,QAAQ,OAAO;AACtC,UAAM,SAAS,OAAO;AACtB,UAAM,SAAS,OAAO,GAAG;AACzB,UAAM,SAAS,KAAK,GAAG;AAEvB,QAAI,CAAC,UAAU,QAAQ;AACrB,cAAQ,KAAK,EAAE,KAAK,MAAM,SAAS,UAAU,OAAO,CAAC;AAAA,IACvD,WAAW,UAAU,CAAC,QAAQ;AAC5B,cAAQ,KAAK,EAAE,KAAK,MAAM,WAAW,UAAU,OAAO,CAAC;AAAA,IACzD,WAAW,KAAK,UAAU,MAAM,MAAM,KAAK,UAAU,MAAM,GAAG;AAC5D,cAAQ,KAAK,EAAE,KAAK,MAAM,WAAW,UAAU,QAAQ,UAAU,OAAO,CAAC;AAAA,IAC3E,OAAO;AACL,cAAQ,KAAK,EAAE,KAAK,MAAM,aAAa,UAAU,OAAO,CAAC;AAAA,IAC3D;AAAA,EACF;AAEA,QAAM,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,EAAE;AAC/D,UAAQ,KAAK,CAAC,GAAG,MAAM,MAAM,EAAE,IAAI,IAAI,MAAM,EAAE,IAAI,CAAC;AACpD,SAAO;AACT;AAEA,SAAS,IAAIC,IAAoB;AAC/B,MAAI,OAAOA,OAAM,SAAU,QAAO,IAAIA,EAAC;AACvC,MAAI,OAAOA,OAAM,YAAYA,OAAM,KAAM,QAAO,KAAK,UAAUA,IAAG,MAAM,CAAC;AACzE,SAAO,OAAOA,EAAC;AACjB;AAEA,IAAM,aAAkF;AAAA,EACtF,OAAO,EAAE,IAAI,sBAAsB,MAAM,OAAO,sBAAsB,IAAI,MAAM,SAAS,MAAM,IAAI;AAAA,EACnG,SAAS,EAAE,IAAI,sBAAsB,MAAM,KAAK,sBAAsB,IAAI,MAAM,OAAO,MAAM,IAAI;AAAA,EACjG,SAAS,EAAE,IAAI,sBAAsB,MAAM,OAAO,sBAAsB,IAAI,MAAM,SAAS,MAAM,IAAI;AAAA,EACrG,WAAW,EAAE,IAAI,eAAe,IAAI,IAAI,MAAM,IAAI;AACpD;AAMO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAAmB;AACjB,QAAM,cAAU,uBAAQ,MAAM,YAAY,UAAU,OAAO,GAAG,CAAC,UAAU,OAAO,CAAC;AACjF,QAAM,UAAU,gBAAgB,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,IAAI;AAEhF,QAAM,KAAK,SAAS,IAAI;AACxB,QAAM,MAAM,QAAQ,IAAI;AAExB,MAAI,UAAU;AACZ,WACE,6CAAC,SAAI,WAAsB,OAAc,WAAQ,cAC9C,kBAAQ,IAAI,CAAC,MACZ,8CAAC,SAAgB,WAAQ,cAAa,aAAW,EAAE,MACjD;AAAA,mDAAC,UAAK,WAAQ,YAAY,YAAE,KAAI;AAAA,MAC/B,EAAE,SAAS,aACV,8EACE;AAAA,qDAAC,UAAK,WAAQ,YAAY,cAAI,EAAE,QAAQ,GAAE;AAAA,QAC1C,6CAAC,UAAK,WAAQ,YAAY,cAAI,EAAE,QAAQ,GAAE;AAAA,SAC5C;AAAA,OAEA,EAAE,SAAS,WAAW,EAAE,SAAS,gBACjC,6CAAC,UAAK,WAAQ,cAAc,cAAI,EAAE,QAAQ,GAAE;AAAA,MAE7C,EAAE,SAAS,aACV,6CAAC,UAAK,WAAQ,cAAc,cAAI,EAAE,QAAQ,GAAE;AAAA,SAZtC,EAAE,GAcZ,CACD,GACH;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO,EAAE,SAAS,KAAK,YAAY,MAAM,UAAU,GAAG,MAAM;AAAA,MAC5D,WAAQ;AAAA,MAEP;AAAA,gBAAQ,WAAW,KAClB,6CAAC,SAAI,OAAO,EAAE,UAAU,GAAG,MAAM,OAAO,MAAM,WAAW,WAAW,SAAS,GAAG,wBAEhF;AAAA,QAED,QAAQ,IAAI,CAAC,UAAU;AACtB,gBAAM,KAAK,WAAW,MAAM,IAAI;AAChC,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,YAAY;AAAA,gBACZ,KAAK;AAAA,gBACL,SAAS,OAAO,MAAM,CAAC;AAAA,gBACvB,cAAc;AAAA,gBACd,cAAc;AAAA,gBACd,YAAY,GAAG;AAAA,gBACf,UAAU,GAAG;AAAA,gBACb,YAAY;AAAA,cACd;AAAA,cACA,WAAQ;AAAA,cAER;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,OAAO;AAAA,sBACP,YAAY;AAAA,sBACZ,YAAY;AAAA,sBACZ,OAAO,GAAG,MAAM,MAAM;AAAA,sBACtB,WAAW;AAAA,oBACb;AAAA,oBAEC,aAAG;AAAA;AAAA,gBACN;AAAA,gBACA,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,SAAS,YAAY,KAAK,YAAY,EAAE,GACjE,gBAAM,KACT;AAAA,gBACA,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,UAAU,GAAG,eAAC;AAAA,gBACzC,MAAM,SAAS,YACd,8CAAC,UACC;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,OAAO,MAAM;AAAA,wBACb,gBAAgB;AAAA,wBAChB,SAAS;AAAA,sBACX;AAAA,sBAEC,cAAI,MAAM,QAAQ;AAAA;AAAA,kBACrB;AAAA,kBACA,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,WAAW,QAAQ,QAAQ,GAAG,oBAAM;AAAA,kBAChE,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,QAAQ,GAAI,cAAI,MAAM,QAAQ,GAAE;AAAA,mBAC9D,IAEA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,OACE,MAAM,SAAS,UACX,MAAM,UACN,MAAM,SAAS,YACb,MAAM,QACN,MAAM;AAAA,oBAChB;AAAA,oBAEC,cAAI,MAAM,SAAS,YAAY,MAAM,WAAW,MAAM,QAAQ;AAAA;AAAA,gBACjE;AAAA;AAAA;AAAA,YAvDG,MAAM;AAAA,UAyDb;AAAA,QAEJ,CAAC;AAAA;AAAA;AAAA,EACH;AAEJ;;;ACpKM,IAAAC,sBAAA;AAdC,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,OAAO,CAAC;AAAA,EACR,cAAc;AAAA,EACd,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,KAAK,SAAS,IAAI;AACxB,QAAM,MAAM,QAAQ,IAAI;AAExB,MAAI,UAAU;AACZ,WACE,8CAAC,SAAI,WAAsB,OAAc,WAAQ,gBAC/C;AAAA,mDAAC,SAAI,WAAQ,eACX,uDAAC,SAAK,iBAAO,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,WAAU,GACzD;AAAA,MACC,CAAC,eACA,6CAAC,SAAI,WAAQ,kBACV,eAAK,IAAI,CAAC,MAAM,MACf,6CAAC,SAAY,WAAQ,gBAAe,cAAY,KAAK,WAAW,OAAO,GACpE,kBADO,CAEV,CACD,GACH;AAAA,OAEJ;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,eAAe;AAAA,QACf,UAAU;AAAA,QACV,GAAG;AAAA,MACL;AAAA,MACA,WAAQ;AAAA,MAEP;AAAA,gBACC,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,QAAQ,SAAS,IAAI,GACpD;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,UAAU,GAAG;AAAA,gBACb,YAAY;AAAA,gBACZ,OAAO,MAAM;AAAA,gBACb,eAAe;AAAA,gBACf,eAAe;AAAA,gBACf,cAAc;AAAA,cAChB;AAAA,cAEC,mBAAS,YAAY,WAAW;AAAA;AAAA,UACnC;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,UAAU,GAAG;AAAA,gBACb,YAAY,MAAM;AAAA,gBAClB,OAAO,MAAM;AAAA,gBACb,YAAY,MAAM;AAAA,gBAClB,SAAS;AAAA,gBACT,cAAc,MAAM;AAAA,gBACpB,UAAU;AAAA,gBACV,QAAQ;AAAA,cACV;AAAA,cAEC,eAAK,UAAU,MAAM,MAAM,CAAC;AAAA;AAAA,UAC/B;AAAA,WACF;AAAA,QAGD,CAAC,eACA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,WAAW,aAAa,MAAM,MAAM;AAAA,cACpC,SAAS;AAAA,cACT,UAAU;AAAA,cACV,WAAW;AAAA,cACX,YAAY;AAAA,YACd;AAAA,YAEA;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,UAAU,GAAG;AAAA,oBACb,YAAY;AAAA,oBACZ,OAAO,MAAM;AAAA,oBACb,eAAe;AAAA,oBACf,eAAe;AAAA,oBACf,cAAc;AAAA,kBAChB;AAAA,kBACD;AAAA;AAAA,cAED;AAAA,cACC,KAAK,WAAW,KACf,6CAAC,SAAI,OAAO,EAAE,UAAU,GAAG,MAAM,OAAO,MAAM,WAAW,WAAW,SAAS,GAAG,+BAEhF;AAAA,cAED,KAAK,IAAI,CAAC,MAAM,MACf;AAAA,gBAAC;AAAA;AAAA,kBAEC,OAAO;AAAA,oBACL,UAAU,GAAG;AAAA,oBACb,YAAY,MAAM;AAAA,oBAClB,OAAO,KAAK,WAAW,OAAO,IAAI,MAAM,QAAQ,MAAM;AAAA,oBACtD,SAAS;AAAA,oBACT,cAAc,aAAa,MAAM,WAAW;AAAA,oBAC5C,YAAY;AAAA,oBACZ,WAAW;AAAA,kBACb;AAAA,kBAEC;AAAA;AAAA,gBAXI;AAAA,cAYP,CACD;AAAA;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;ACrIA,IAAAC,gBAA+C;AA8FzC,IAAAC,sBAAA;AAvDN,SAAS,eACP,MACA,MACgB;AAChB,QAAM,UAA0B,CAAC;AACjC,QAAM,UAAU,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK,QAAQ,CAAC,CAAC,GAAG,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC;AAE1E,aAAW,OAAO,SAAS;AACzB,UAAM,SAAS,QAAQ,QAAQ,OAAO;AACtC,UAAM,SAAS,OAAO;AACtB,UAAM,SAAS,OAAO,GAAG;AACzB,UAAM,SAAS,KAAK,GAAG;AAEvB,QAAI,CAAC,UAAU,QAAQ;AACrB,cAAQ,KAAK,EAAE,KAAK,MAAM,SAAS,UAAU,OAAO,CAAC;AAAA,IACvD,WAAW,UAAU,CAAC,QAAQ;AAC5B,cAAQ,KAAK,EAAE,KAAK,MAAM,WAAW,UAAU,OAAO,CAAC;AAAA,IACzD,WAAW,KAAK,UAAU,MAAM,MAAM,KAAK,UAAU,MAAM,GAAG;AAC5D,cAAQ,KAAK,EAAE,KAAK,MAAM,WAAW,UAAU,QAAQ,UAAU,OAAO,CAAC;AAAA,IAC3E;AAAA,EACF;AAEA,QAAM,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,EAAE;AACjD,UAAQ,KAAK,CAAC,GAAG,MAAM,MAAM,EAAE,IAAI,IAAI,MAAM,EAAE,IAAI,CAAC;AACpD,SAAO;AACT;AAEA,SAASC,KAAIC,IAAoB;AAC/B,MAAI,OAAOA,OAAM,SAAU,QAAO,IAAIA,EAAC;AACvC,MAAI,OAAOA,OAAM,YAAYA,OAAM,KAAM,QAAO,KAAK,UAAUA,IAAG,MAAM,CAAC;AACzE,SAAO,OAAOA,EAAC;AACjB;AAEA,IAAM,cAAuF;AAAA,EAC3F,OAAS,EAAE,IAAI,wBAAyB,IAAI,WAAW,OAAO,MAAM;AAAA,EACpE,SAAS,EAAE,IAAI,yBAAyB,IAAI,WAAW,OAAO,MAAM;AAAA,EACpE,SAAS,EAAE,IAAI,wBAAyB,IAAI,WAAW,OAAO,MAAM;AACtE;AAMA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,GAAG,GAE9D;AAAA,kDAAC,SACC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU,GAAG,QAAQ;AAAA,YACrB,YAAY;AAAA,YACZ,OAAO,MAAM;AAAA,UACf;AAAA,UAEC,mBAAS;AAAA;AAAA,MACZ;AAAA,MACC,SAAS,eACR;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU,GAAG;AAAA,YACb,OAAO,MAAM;AAAA,YACb,WAAW;AAAA,YACX,YAAY;AAAA,UACd;AAAA,UAEC,mBAAS;AAAA;AAAA,MACZ;AAAA,OAEJ;AAAA,IAGC,SAAS,UACR,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GAC1D;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,YACE,SAAS,WAAW,SAChB,MAAM,UACN,SAAS,WAAW,WAClB,MAAM,UACN,SAAS,WAAW,UAClB,MAAM,QACN,MAAM;AAAA,UAClB;AAAA;AAAA,MACF;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU,GAAG;AAAA,YACb,OAAO,MAAM;AAAA,YACb,eAAe;AAAA,YACf,eAAe;AAAA,UACjB;AAAA,UAEC,mBAAS;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IAID,SAAS,aACR,8CAAC,SACC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU,GAAG;AAAA,YACb,YAAY;AAAA,YACZ,OAAO,MAAM;AAAA,YACb,eAAe;AAAA,YACf,eAAe;AAAA,YACf,cAAc;AAAA,UAChB;AAAA,UACD;AAAA;AAAA,MAED;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU,GAAG;AAAA,YACb,YAAY;AAAA,YACZ,OAAO,MAAM;AAAA,YACb,YAAY,MAAM;AAAA,YAClB,QAAQ,aAAa,MAAM,MAAM;AAAA,YACjC,cAAc,MAAM;AAAA,YACpB,SAAS;AAAA,UACX;AAAA,UAEC,mBAAS;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IAID,SAAS,aAAa,KACrB;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU,GAAG;AAAA,UACb,OAAO,MAAM;AAAA,QACf;AAAA,QACD;AAAA;AAAA,UACe,SAAS,aAAa,IAAI,OAAO,SAAS;AAAA,UAAW;AAAA;AAAA;AAAA,IACrE;AAAA,KAEJ;AAEJ;AAWA,SAAS,gBACP,YACA,SACa;AACb,QAAM,YAAY,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACxD,QAAM,OAAoB,CAAC;AAG3B,aAAW,UAAU,SAAS;AAC5B,SAAK,KAAK,EAAE,MAAM,UAAU,OAAO,CAAC;AAAA,EACtC;AAGA,QAAM,gBAAgB,OAAO,KAAK,UAAU,EACzC,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,EAC/B,KAAK;AACR,aAAW,OAAO,eAAe;AAC/B,SAAK,KAAK,EAAE,MAAM,aAAa,KAAK,OAAO,WAAW,GAAG,EAAE,CAAC;AAAA,EAC9D;AAEA,SAAO;AACT;AAEA,SAAS,QAAQ;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,WAAO,uBAAQ,MAAM,gBAAgB,YAAY,OAAO,GAAG,CAAC,YAAY,OAAO,CAAC;AACtF,QAAM,YAAY,OAAO,KAAK,UAAU,EAAE;AAE1C,SACE,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,GAAG,GAE9D;AAAA,kDAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GAC1D;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU,GAAG,QAAQ;AAAA,YACrB,YAAY;AAAA,YACZ,OAAO,MAAM;AAAA,YACb,YAAY,MAAM;AAAA,UACpB;AAAA,UAEC,mBAAS;AAAA;AAAA,MACZ;AAAA,MACC,SAAS,aAAa,KACrB;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU,GAAG;AAAA,YACb,OAAO,MAAM;AAAA,YACb,YAAY,MAAM;AAAA,UACpB;AAAA,UAEC;AAAA,qBAAS;AAAA,YAAW;AAAA;AAAA;AAAA,MACvB;AAAA,OAEJ;AAAA,IAGA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU,GAAG;AAAA,UACb,YAAY;AAAA,UACZ,OAAO,MAAM;AAAA,UACb,eAAe;AAAA,UACf,eAAe;AAAA,QACjB;AAAA,QACD;AAAA;AAAA,UAEC,8CAAC,UAAK,OAAO,EAAE,YAAY,KAAK,YAAY,EAAE,GAAG;AAAA;AAAA,YAC7C;AAAA,YAAU;AAAA,YAAK,cAAc,IAAI,MAAM;AAAA,YACxC,QAAQ,SAAS,KAAK,KAAK,QAAQ,MAAM;AAAA,YAAW;AAAA,aACvD;AAAA;AAAA;AAAA,IACF;AAAA,IAGC,KAAK,WAAW,IACf;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU,GAAG;AAAA,UACb,OAAO,MAAM;AAAA,UACb,WAAW;AAAA,UACX,YAAY,MAAM;AAAA,UAClB,SAAS,GAAG,GAAG;AAAA,UACf,YAAY,MAAM;AAAA,UAClB,cAAc,MAAM;AAAA,QACtB;AAAA,QACD;AAAA;AAAA,IAED,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,YAAY,MAAM;AAAA,UAClB,UAAU,GAAG;AAAA,UACb,YAAY,MAAM;AAAA,UAClB,QAAQ,aAAa,MAAM,MAAM;AAAA,UACjC,cAAc,MAAM;AAAA,UACpB,UAAU;AAAA,QACZ;AAAA,QAEC,eAAK,IAAI,CAAC,QAAQ;AACjB,cAAI,IAAI,SAAS,UAAU;AACzB,kBAAM,EAAE,OAAO,IAAI;AACnB,kBAAM,QAAQ,YAAY,OAAO,IAAI;AACrC,mBACE;AAAA,cAAC;AAAA;AAAA,gBAEC,OAAO;AAAA,kBACL,SAAS;AAAA,kBACT,YAAY;AAAA,kBACZ,KAAK;AAAA,kBACL,SAAS,OAAO,GAAG;AAAA,kBACnB,cAAc,aAAa,MAAM,MAAM;AAAA,kBACvC,YAAY,MAAM;AAAA,gBACpB;AAAA,gBACA,WAAQ;AAAA,gBACR,aAAW,OAAO;AAAA,gBAElB;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,UAAU,GAAG;AAAA,wBACb,YAAY;AAAA,wBACZ,OAAO,MAAM;AAAA,wBACb,OAAO;AAAA,wBACP,YAAY;AAAA,wBACZ,WAAW;AAAA,wBACX,YAAY;AAAA,sBACd;AAAA,sBAEC,gBAAM;AAAA;AAAA,kBACT;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,OAAO,MAAM;AAAA,wBACb,YAAY;AAAA,wBACZ,YAAY;AAAA,wBACZ,YAAY;AAAA,sBACd;AAAA,sBAEC,iBAAO;AAAA;AAAA,kBACV;AAAA,kBACA,6CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,IAAI,GACjD,iBAAO,SAAS,YACf,8EACE;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,OAAO,MAAM;AAAA,0BACb,gBAAgB;AAAA,0BAChB,SAAS;AAAA,wBACX;AAAA,wBAEC,UAAAD,KAAI,OAAO,QAAQ;AAAA;AAAA,oBACtB;AAAA,oBACA,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,WAAW,QAAQ,QAAQ,GAAG,oBAAM;AAAA,oBAChE,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,QAAQ,GAAI,UAAAA,KAAI,OAAO,QAAQ,GAAE;AAAA,qBAC/D,IACE,OAAO,SAAS,UAClB,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,QAAQ,GAAI,UAAAA,KAAI,OAAO,QAAQ,GAAE,IAE7D,6CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,OAAO,gBAAgB,eAAe,GAC/D,UAAAA,KAAI,OAAO,QAAQ,GACtB,GAEJ;AAAA;AAAA;AAAA,cAzDK,OAAO;AAAA,YA0Dd;AAAA,UAEJ;AAGA,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,YAAY;AAAA,gBACZ,KAAK;AAAA,gBACL,SAAS,OAAO,GAAG;AAAA,gBACnB,cAAc,aAAa,MAAM,MAAM;AAAA,gBACvC,SAAS;AAAA,cACX;AAAA,cACA,WAAQ;AAAA,cAER;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,OAAO;AAAA,sBACP,YAAY;AAAA,sBACZ,YAAY;AAAA,oBACd;AAAA;AAAA,gBACF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,OAAO,MAAM;AAAA,sBACb,YAAY;AAAA,sBACZ,YAAY;AAAA,sBACZ,YAAY;AAAA,oBACd;AAAA,oBAEC,cAAI;AAAA;AAAA,gBACP;AAAA,gBACA,6CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,KAAK,OAAO,MAAM,UAAU,GACzE,UAAAA,KAAI,IAAI,KAAK,GAChB;AAAA;AAAA;AAAA,YA9BK,IAAI;AAAA,UA+BX;AAAA,QAEJ,CAAC;AAAA;AAAA,IACH;AAAA,KAEJ;AAEJ;AAMA,SAAS,mBAAmB,EAAE,SAAS,GAAgC;AACrE,SACE,8CAAC,SAAI,WAAQ,uBACX;AAAA,iDAAC,SAAI,WAAQ,eAAe,mBAAS,YAAW;AAAA,IAC/C,SAAS,eACR,6CAAC,SAAI,WAAQ,qBAAqB,mBAAS,aAAY;AAAA,IAExD,SAAS,UAAU,6CAAC,SAAI,WAAQ,gBAAgB,mBAAS,QAAO;AAAA,IAChE,SAAS,aACR,6CAAC,SAAI,WAAQ,mBAAmB,mBAAS,WAAU;AAAA,KAEvD;AAEJ;AAEA,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,WAAO,uBAAQ,MAAM,gBAAgB,YAAY,OAAO,GAAG,CAAC,YAAY,OAAO,CAAC;AACtF,SACE,8CAAC,SAAI,WAAQ,oBACX;AAAA,iDAAC,SAAI,WAAQ,eAAe,mBAAS,YAAW;AAAA,IAC/C,KAAK,IAAI,CAAC,QAAQ;AACjB,UAAI,IAAI,SAAS,UAAU;AACzB,cAAM,IAAI,IAAI;AACd,eACE,8CAAC,SAAgB,WAAQ,iBAAgB,aAAW,EAAE,MACpD;AAAA,uDAAC,UAAK,WAAQ,cAAc,YAAE,KAAI;AAAA,UACjC,EAAE,SAAS,aACV,8EACE;AAAA,yDAAC,UAAK,WAAQ,cAAc,UAAAA,KAAI,EAAE,QAAQ,GAAE;AAAA,YAC5C,6CAAC,UAAK,WAAQ,cAAc,UAAAA,KAAI,EAAE,QAAQ,GAAE;AAAA,aAC9C;AAAA,UAED,EAAE,SAAS,WACV,6CAAC,UAAK,WAAQ,gBAAgB,UAAAA,KAAI,EAAE,QAAQ,GAAE;AAAA,UAE/C,EAAE,SAAS,aACV,6CAAC,UAAK,WAAQ,gBAAgB,UAAAA,KAAI,EAAE,QAAQ,GAAE;AAAA,aAZxC,EAAE,GAcZ;AAAA,MAEJ;AACA,aACE,8CAAC,SAAkB,WAAQ,oBACzB;AAAA,qDAAC,UAAK,WAAQ,iBAAiB,cAAI,KAAI;AAAA,QACvC,6CAAC,UAAK,WAAQ,mBAAmB,UAAAA,KAAI,IAAI,KAAK,GAAE;AAAA,WAFxC,IAAI,GAGd;AAAA,IAEJ,CAAC;AAAA,KACH;AAEJ;AAUA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,MAAI,UAAU;AACZ,WACE,6CAAC,YAAO,WAAQ,eAAc,aAAW,YAAY,SAAS,UAC3D,yBAAe,WAAW,QAAQ,UACrC;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,cAAc;AAAA,QACd,QAAQ,aAAa,MAAM,MAAM;AAAA,QACjC,UAAU;AAAA,QACV,YAAY;AAAA,MACd;AAAA,MACA,WAAQ;AAAA,MAEN,WAAC,UAAU,KAAK,EAAY,IAAI,CAAC,MACjC;AAAA,QAAC;AAAA;AAAA,UAEC,SAAS,MAAM,aAAa,WAAW;AAAA,UACvC,OAAO;AAAA,YACL,SAAS;AAAA,YACT,UAAU,GAAG;AAAA,YACb,YAAY,MAAM,aAAa,MAAM;AAAA,YACrC,eAAe;AAAA,YACf,eAAe;AAAA,YACf,OAAO,MAAM,aAAa,MAAM,cAAc,MAAM;AAAA,YACpD,YAAY,MAAM,aAAa,MAAM,aAAa;AAAA,YAClD,QAAQ;AAAA,YACR,QAAQ,MAAM,aAAa,YAAY;AAAA,UACzC;AAAA,UAEC,gBAAM,WAAW,WAAW;AAAA;AAAA,QAdxB;AAAA,MAeP,CACD;AAAA;AAAA,EACH;AAEJ;AAMO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,aAAa;AAAA,EACb;AAAA,EACA,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,CAAC,cAAc,eAAe,QAAI,wBAA0B,kBAAkB,QAAQ;AAG5F,QAAM,aAAa,kBAAkB;AAErC,QAAM,mBAAe,2BAAY,MAAM;AACrC,UAAM,OAAwB,eAAe,WAAW,QAAQ;AAChE,oBAAgB,IAAI;AACpB,mBAAe,IAAI;AAAA,EACrB,GAAG,CAAC,YAAY,YAAY,CAAC;AAE7B,QAAM,WAAW,UAAU,aAAa;AACxC,QAAM,aAAa,gBAAgB,IAAI,UAAU,gBAAgB,CAAC,GAAG,UAAU,OAAO;AACtF,QAAM,aAAa,UAAU,UAAU,CAAC;AAExC,QAAM,cAAU;AAAA,IACd,MAAM,eAAe,YAAY,UAAU;AAAA,IAC3C,CAAC,YAAY,UAAU;AAAA,EACzB;AAEA,QAAM,KAAK,SAAS,IAAI;AACxB,QAAM,MAAM,QAAQ,IAAI;AAExB,MAAI,CAAC,UAAU;AACb,WACE,6CAAC,SAAI,WAAsB,OAAc,WAAQ,sBAC/C,uDAAC,SAAI,OAAO,WAAW,CAAC,IAAI,EAAE,OAAO,MAAM,WAAW,UAAU,GAAG,MAAM,WAAW,UAAU,SAAS,IAAI,GAAG,+BAE9G,GACF;AAAA,EAEJ;AAEA,MAAI,UAAU;AACZ,WACE,8CAAC,SAAI,WAAsB,OAAc,WAAQ,sBAAqB,aAAW,YAC9E;AAAA,oBACC,6CAAC,cAAW,YAAwB,UAAU,cAAc,IAAQ,UAAQ,MAAC;AAAA,MAE9E,eAAe,WACd,6CAAC,sBAAmB,UAAoB,IAExC,6CAAC,mBAAgB,UAAoB,SAAkB,YAAwB;AAAA,OAEnF;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY,MAAM;AAAA,QAClB,UAAU;AAAA,QACV,GAAG;AAAA,MACL;AAAA,MACA,WAAQ;AAAA,MACR,aAAW;AAAA,MAEV;AAAA,sBACC,6CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,gBAAgB,YAAY,cAAc,GAAG,GAC1E,uDAAC,cAAW,YAAwB,UAAU,cAAc,IAAQ,UAAU,OAAO,GACvF;AAAA,QAED,eAAe,WACd,6CAAC,cAAW,UAAoB,IAAQ,KAAU,IAElD,6CAAC,WAAQ,UAAoB,SAAkB,YAAwB,IAAQ,KAAU;AAAA;AAAA;AAAA,EAE7F;AAEJ;;;AC5nBA,IAAAE,iBAAyD;AAoFnD,IAAAC,uBAAA;AArEC,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAC5C,QAAM,cAAU,uBAA6C,IAAI;AACjE,QAAM,QAAQ,UAAU;AACxB,QAAM,UAAU,gBAAgB;AAChC,QAAM,UAAU,gBAAgB,QAAQ;AAGxC,gCAAU,MAAM;AACd,QAAI,CAAC,WAAW,CAAC,aAAc;AAC/B,QAAI,iBAAiB,QAAQ,GAAG;AAC9B,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,UAAM,WAAW,UAAU,aAAa,GAAG,cAAc;AACzD,UAAM,WAAW,UAAU,OAAO,CAAC,GAAG,SAAS,IAAI,KAAK,YAAY,CAAC,KAAK;AAC1E,UAAM,WAAW,WAAW;AAC5B,UAAM,SAAS;AACf,UAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,IAAI,WAAW,QAAQ,GAAI,CAAC;AAE7D,YAAQ,UAAU,WAAW,MAAM;AACjC,oBAAc,gBAAgB,CAAC;AAAA,IACjC,GAAG,KAAK;AAER,WAAO,MAAM;AACX,UAAI,QAAQ,QAAS,cAAa,QAAQ,OAAO;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,SAAS,eAAe,WAAW,OAAO,eAAe,YAAY,CAAC;AAE1E,QAAM,iBAAa,4BAAY,MAAM;AACnC,QAAI,SAAS;AACX,iBAAW,KAAK;AAAA,IAClB,OAAO;AACL,UAAI,iBAAiB,QAAQ,EAAG,eAAc,CAAC;AAC/C,iBAAW,IAAI;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,SAAS,eAAe,OAAO,aAAa,CAAC;AAEjD,QAAM,oBAAgB;AAAA,IACpB,CAAC,MAA2B;AAC1B,UAAI,EAAE,QAAQ,eAAe,WAAW,CAAC,SAAS;AAChD,UAAE,eAAe;AACjB,mBAAW,KAAK;AAChB,sBAAc,gBAAgB,CAAC;AAAA,MACjC,WAAW,EAAE,QAAQ,gBAAgB,WAAW,CAAC,SAAS;AACxD,UAAE,eAAe;AACjB,mBAAW,KAAK;AAChB,sBAAc,gBAAgB,CAAC;AAAA,MACjC,WAAW,EAAE,QAAQ,OAAO,cAAc;AACxC,UAAE,eAAe;AACjB,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,CAAC,SAAS,SAAS,SAAS,eAAe,eAAe,cAAc,UAAU;AAAA,EACpF;AAEA,QAAM,KAAK,SAAS,IAAI;AAExB,MAAI,UAAU;AACZ,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAQ;AAAA,QACR,MAAK;AAAA,QACL,cAAW;AAAA,QACX,UAAU;AAAA,QACV,WAAW;AAAA,QAEX;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,WAAQ;AAAA,cACR,UAAU,CAAC,WAAW;AAAA,cACtB,SAAS,MAAM;AAAE,2BAAW,KAAK;AAAG,8BAAc,gBAAgB,CAAC;AAAA,cAAG;AAAA,cACtE,cAAW;AAAA,cACZ;AAAA;AAAA,UAED;AAAA,UACC,gBACC,8CAAC,YAAO,WAAQ,WAAU,SAAS,YAAY,cAAY,UAAU,UAAU,QAC5E,oBAAU,UAAU,QACvB;AAAA,UAEF;AAAA,YAAC;AAAA;AAAA,cACC,WAAQ;AAAA,cACR,UAAU,CAAC,WAAW;AAAA,cACtB,SAAS,MAAM;AAAE,2BAAW,KAAK;AAAG,8BAAc,gBAAgB,CAAC;AAAA,cAAG;AAAA,cACtE,cAAW;AAAA,cACZ;AAAA;AAAA,UAED;AAAA,UACA,8CAAC,SAAI,WAAQ,YACV,oBAAU,IAAI,CAAC,MAAM,MACpB;AAAA,YAAC;AAAA;AAAA,cAEC,WAAQ;AAAA,cACR,eAAa,MAAM;AAAA,cACnB,aAAW,IAAI;AAAA,cACf,SAAS,MAAM;AAAE,2BAAW,KAAK;AAAG,8BAAc,CAAC;AAAA,cAAG;AAAA,cACtD,OAAO,KAAK;AAAA;AAAA,YALP;AAAA,UAMP,CACD,GACH;AAAA;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,QAAM,WAAW,CAAC,cAA4C;AAAA,IAC5D,YAAY,MAAM;AAAA,IAClB,QAAQ,aAAa,MAAM,MAAM;AAAA,IACjC,OAAO,WAAW,MAAM,YAAY,MAAM;AAAA,IAC1C,cAAc;AAAA,IACd,SAAS;AAAA,IACT,UAAU,GAAG;AAAA,IACb,YAAY;AAAA,IACZ,QAAQ,WAAW,gBAAgB;AAAA,IACnC,SAAS,WAAW,MAAM;AAAA,IAC1B,YAAY;AAAA,EACd;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY,MAAM;AAAA,QAClB,cAAc,aAAa,MAAM,MAAM;AAAA,QACvC,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,YAAY;AAAA,QACZ,GAAG;AAAA,MACL;AAAA,MACA,WAAQ;AAAA,MACR,MAAK;AAAA,MACL,cAAW;AAAA,MACX,UAAU;AAAA,MACV,WAAW;AAAA,MAEX;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,SAAS,CAAC,WAAW,OAAO;AAAA,YACnC,UAAU,CAAC,WAAW;AAAA,YACtB,SAAS,MAAM;AAAE,yBAAW,KAAK;AAAG,4BAAc,gBAAgB,CAAC;AAAA,YAAG;AAAA,YACtE,cAAW;AAAA,YACZ;AAAA;AAAA,QAED;AAAA,QAEC,gBACC;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,OAAO;AAAA,cACL,YAAY,UAAU,MAAM,UAAU,MAAM;AAAA,cAC5C,QAAQ,aAAa,MAAM,MAAM;AAAA,cACjC,OAAO,UAAU,UAAU,MAAM;AAAA,cACjC,cAAc;AAAA,cACd,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,gBAAgB;AAAA,cAChB,QAAQ;AAAA,cACR,UAAU;AAAA,cACV,YAAY;AAAA,YACd;AAAA,YACA,OAAO,UAAU,UAAU;AAAA,YAC3B,cAAY,UAAU,UAAU;AAAA,YAE/B,oBAAU,WAAW;AAAA;AAAA,QACxB;AAAA,QAGF;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,SAAS,CAAC,WAAW,OAAO;AAAA,YACnC,UAAU,CAAC,WAAW;AAAA,YACtB,SAAS,MAAM;AAAE,yBAAW,KAAK;AAAG,4BAAc,gBAAgB,CAAC;AAAA,YAAG;AAAA,YACtE,cAAW;AAAA,YACZ;AAAA;AAAA,QAED;AAAA,QAGA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,MAAM;AAAA,cACN,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,KAAK;AAAA,cACL,SAAS;AAAA,YACX;AAAA,YAEC,oBAAU,IAAI,CAAC,MAAM,MAAM;AAC1B,oBAAM,WAAW,MAAM;AACvB,oBAAM,SAAS,IAAI;AACnB,qBACE;AAAA,gBAAC;AAAA;AAAA,kBAEC,SAAS,MAAM;AAAE,+BAAW,KAAK;AAAG,kCAAc,CAAC;AAAA,kBAAG;AAAA,kBACtD,OAAO,KAAK;AAAA,kBACZ,OAAO;AAAA,oBACL,MAAM;AAAA,oBACN,QAAQ,WAAW,KAAK;AAAA,oBACxB,cAAc;AAAA,oBACd,QAAQ;AAAA,oBACR,QAAQ;AAAA,oBACR,YAAY,WACR,MAAM,UACN,SACE,MAAM,UACN,MAAM;AAAA,oBACZ,SAAS,UAAU,WAAW,IAAI;AAAA,oBAClC,YAAY;AAAA,kBACd;AAAA;AAAA,gBAhBK;AAAA,cAiBP;AAAA,YAEJ,CAAC;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACtOA,IAAAC,iBAAwE;;;ACejE,SAAS,qBAAqB,SAAoE;AACvG,QAAM,SAAS,oBAAI,IAAkD;AACrE,MAAI;AAEJ,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,KAAK,QAAQ,CAAC,EAAE;AACtB,QAAI,IAAI;AACN,YAAM,WAAW,OAAO,IAAI,EAAE;AAC9B,UAAI,CAAC,UAAU;AACb,eAAO,IAAI,IAAI,EAAE,UAAU,GAAG,QAAQ,IAAI,EAAE,CAAC;AAAA,MAC/C,OAAO;AACL,iBAAS,SAAS,IAAI;AAAA,MACxB;AACA,eAAS;AAAA,IACX,WAAW,QAAQ;AAEjB,aAAO,IAAI,MAAM,EAAG,SAAS,IAAI;AAAA,IACnC;AAAA,EACF;AAEA,SAAO;AACT;AAoBO,SAAS,0BACd,kBACA,WACA,eACA,YACQ;AACR,MAAI,CAAC,iBAAiB,UAAU,UAAU,WAAW,EAAG,QAAO;AAE/D,MAAI,YAAY;AAEd,QAAI,YAAY;AAChB,aAAS,KAAK,GAAG,MAAM,iBAAiB,KAAK,UAAU,QAAQ,MAAM;AACnE,YAAM,WAAW,UAAU,EAAE,EAAE;AAC/B,UAAI,CAAC,SAAU;AACf,YAAM,QAAQ,WAAW,IAAI,QAAQ;AACrC,UAAI,SAAS,MAAM,SAAS,WAAW;AACrC,oBAAY,MAAM;AAAA,MACpB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAGA,MAAI,WAAW;AACf,WAAS,KAAK,GAAG,MAAM,iBAAiB,KAAK,UAAU,QAAQ,MAAM;AACnE,UAAM,WAAW,UAAU,EAAE,EAAE;AAC/B,QAAI,CAAC,SAAU;AAEf,QAAI,QAAQ;AACZ,aAAS,IAAI,UAAU,IAAI,iBAAiB,QAAQ,KAAK;AACvD,UAAI,iBAAiB,CAAC,EAAE,mBAAmB,UAAU;AACnD,gBAAQ;AACR,mBAAW;AACX;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,MAAO;AAEZ,WAAO,WAAW,iBAAiB,QAAQ;AACzC,YAAM,MAAM,iBAAiB,QAAQ,EAAE;AACvC,UAAI,OAAO,QAAQ,SAAU;AAC7B;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAiBO,SAAS,wBACd,SACA,WACA,aACkB;AAElB,QAAM,SAAS,YAAY;AAC3B,QAAM,WAAW,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,WAAW,MAAM,CAAC;AACtE,MAAI,SAAS,SAAS,EAAG,QAAO;AAGhC,QAAM,OAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,cAAc,SAAS;AAC5D,MAAI,KAAK,SAAS,EAAG,QAAO;AAG5B,QAAM,SAA2B,CAAC;AAClC,QAAM,aAAa,eAAe;AAClC,MAAI,SAAS;AACb,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,SAAS,aAAa,MAAM,cAAc,WAAW,MAAM,cAAc,YAAY;AAAE,eAAS;AAAM;AAAA,IAAU;AAC1H,QAAI,UAAU,MAAM,SAAS,aAAa,MAAM,cAAc,UAAU,MAAM,cAAc,WAAY;AACxG,QAAI,OAAQ,QAAO,KAAK,KAAK;AAAA,EAC/B;AACA,SAAO;AACT;;;AClFA,IAAM,oBAAoB;AAI1B,IAAM,cAAc,oBAAI,IAAI,CAAC,aAAa,eAAe,WAAW,CAAC;AAarE,SAAS,gBAAgB,OAAyB;AAChD,SACE,UAAU,QACV,OAAO,UAAU,aACf,MAAkC,mBAAmB,QACpD,MAAkC,kBAAkB;AAE3D;AAEA,SAAS,cAAc,OAAkD;AACvE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AA0BO,SAAS,gBAAgB,MAAe,OAAyB;AACtE,MAAI,gBAAgB,KAAK,EAAG,QAAO;AACnC,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,MAAI,gBAAgB,IAAI,KAAK,CAAC,cAAc,IAAI,GAAG;AAGjD,WAAO,CAAC;AAAA,EACV;AACA,QAAM,MAA+B,EAAE,GAAI,KAAiC;AAC5E,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,YAAY,IAAI,GAAG,EAAG;AAC1B,QAAI,GAAG,IAAI,gBAAgB,IAAI,GAAG,GAAG,KAAK;AAAA,EAC5C;AACA,SAAO;AACT;AAGA,SAAS,QAAQ,MAAe,MAAyB;AACvD,MAAI,MAAe;AACnB,aAAW,OAAO,MAAM;AACtB,QAAI,CAAC,cAAc,GAAG,KAAK,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO;AACvD,UAAO,IAAgC,GAAG;AAAA,EAC5C;AACA,SAAO;AACT;AAQA,SAAS,QAAQ,QAAiC,MAAgB,OAAsB;AACtF,MAAI,KAAK,KAAK,CAAC,MAAM,YAAY,IAAI,CAAC,CAAC,EAAG;AAC1C,MAAI,MAA+B;AACnC,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,KAAK;AACxC,UAAM,MAAM,IAAI,KAAK,CAAC,CAAE;AACxB,UAAM,OAAgC,MAAM,QAAQ,GAAG,IAClD,IAAI,MAAM,IACX,cAAc,GAAG,KAAK,CAAC,gBAAgB,GAAG,IACxC,EAAE,GAAG,IAAI,IACT,CAAC;AACP,QAAI,KAAK,CAAC,CAAE,IAAI;AAChB,UAAM;AAAA,EACR;AACA,QAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AACjC,MAAI,UAAU,QAAW;AACvB,WAAO,IAAI,IAAI;AAAA,EACjB,OAAO;AACL,QAAI,IAAI,IAAI;AAAA,EACd;AACF;AAgBA,SAAS,kBAAkB,QAAiC,QAAgC;AAC1F,QAAM,QAAQ,MAAM,QAAQ,OAAO,KAAK,IAAI,OAAO,QAAQ;AAC3D,MAAI,OAAO;AACT,eAAW,MAAM,OAAO;AACtB,UAAI,CAAC,MAAM,OAAO,GAAG,SAAS,SAAU;AACxC,YAAM,OAAO,GAAG,KAAK,MAAM,iBAAiB;AAC5C,UAAI,GAAG,SAAS,SAAS;AACvB,gBAAQ,QAAQ,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,GAAG,QAAQ,OAAO,SAAS,IAAI,CAAC,CAAC;AAAA,MAC7F,WAAW,GAAG,SAAS,UAAU;AAC/B,cAAM,OAAO,QAAQ,OAAO,WAAW,IAAI;AAC3C,cAAM,UAAU,QAAQ,QAAQ,IAAI;AACpC,gBAAQ,QAAQ,MAAM,MAAM,QAAQ,OAAO,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,IAAI,IAAI;AAAA,MACpG,WAAW,GAAG,SAAS,UAAU;AAC/B,gBAAQ,QAAQ,MAAM,MAAS;AAAA,MACjC,OAAO;AAEL,gBAAQ,QAAQ,MAAM,QAAQ,OAAO,WAAW,IAAI,CAAC;AAAA,MACvD;AAAA,IACF;AACA;AAAA,EACF;AACA,MAAI,cAAc,OAAO,SAAS,GAAG;AACnC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,SAAS,EAAG,SAAQ,QAAQ,CAAC,GAAG,GAAG,KAAK;AAAA,EAC3F;AACA,MAAI,cAAc,OAAO,OAAO,GAAG;AACjC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,OAAO,GAAG;AACzD,cAAQ,QAAQ,CAAC,GAAG,GAAG,gBAAgB,OAAO,GAAG,GAAG,KAAK,CAAC;AAAA,IAC5D;AAAA,EACF;AACF;AASA,SAAS,eAAe,WAAmE;AACzF,QAAM,QAAQ,oBAAI,IAAgC;AAClD,MAAI,CAAC,MAAM,QAAQ,SAAS,EAAG,QAAO;AACtC,aAAW,SAAS,WAAW;AAC7B,QAAI,CAAC,cAAc,KAAK,EAAG;AAC3B,UAAM,SAAS;AACf,QAAI,OAAO,OAAO,mBAAmB,YAAY,OAAO,eAAe,WAAW,EAAG;AACrF,QAAI,CAAC,cAAc,OAAO,SAAS,KAAK,CAAC,cAAc,OAAO,OAAO,KAAK,CAAC,MAAM,QAAQ,OAAO,KAAK,GAAG;AACtG;AAAA,IACF;AACA,UAAM,OAAO,MAAM,IAAI,OAAO,cAAc;AAC5C,QAAI,KAAM,MAAK,KAAK,MAAM;AAAA,QACrB,OAAM,IAAI,OAAO,gBAAgB,CAAC,MAAM,CAAC;AAAA,EAChD;AACA,SAAO;AACT;AAqBO,SAAS,yBACd,SACA,kBACiB;AACjB,QAAM,oBAAoB,kBAAkB,SACxC,uBAAuB,gBAAgB,IACvC,oBAAI,IAAsB;AAG9B,QAAM,eAAe,oBAAoB,QAAQ,SAAS;AAK1D,QAAM,cAAc,eAAe,QAAQ,SAAS;AAEpD,QAAM,YAA6B,CAAC;AACpC,cAAY,QAAQ,eAAe,WAAW,QAAQ,aAAa,GAAG,QAAQ,gBAAgB,CAAC,GAAG,mBAAmB,cAAc,WAAW;AAC9I,SAAO;AACT;AAeA,SAAS,oBAAoB,WAAqD;AAChF,QAAM,UAAU,oBAAI,IAAoB;AACxC,MAAI,CAAC,UAAW,QAAO;AACvB,aAAW,OAAO,WAAW;AAC3B,QAAI,IAAI,SAAS,aAAa,CAAC,IAAI,QAAQ,OAAO,IAAI,SAAS,SAAU;AACzE,UAAM,OAAO,IAAI;AAKjB,QAAI,KAAK,OAAO;AACd,iBAAW,QAAQ,OAAO,OAAO,KAAK,KAAK,GAAG;AAC5C,cAAM,OAAO,MAAM;AACnB,cAAM,IAAI,MAAM;AAChB,YAAI,CAAC,QAAQ,OAAO,MAAM,YAAY,KAAK,EAAG;AAC9C,gBAAQ,IAAI,MAAM,KAAK,OAAO,QAAQ,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC;AAAA,MAC5D;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ;AACf,iBAAW,CAAC,WAAW,OAAO,KAAK,OAAO,QAAQ,KAAK,MAAM,GAAG;AAC9D,YAAI,OAAO,QAAQ,kBAAkB,YAAY,QAAQ,gBAAgB,GAAG;AAC1E,kBAAQ,IAAI,WAAW,KAAK,MAAM,QAAQ,aAAa,CAAC;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,uBAAuB,SAAkD;AAChF,QAAM,MAAM,oBAAI,IAAsB;AACtC,MAAI;AAEJ,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,WAAW;AACnB,yBAAmB,MAAM;AAAA,IAC3B;AAEA,QAAI,kBAAkB;AACpB,UAAI,CAAC,IAAI,IAAI,gBAAgB,GAAG;AAC9B,YAAI,IAAI,kBAAkB,CAAC,CAAC;AAAA,MAC9B;AACA,YAAM,SAAS,KAAK,OAAO,MAAM,KAAK;AACtC,UAAI,IAAI,gBAAgB,EAAG,KAAK,GAAG,MAAM,GAAG,MAAM,IAAI,EAAE;AAAA,IAC1D;AAAA,EACF;AAGA,SAAO;AACT;AAEA,SAAS,YACP,MACA,KACA,aACA,gBAAwB,GACxB,gBACA,mBAA4C,CAAC,GAC7C,oBAA2C,oBAAI,IAAI,GACnD,eAAoC,oBAAI,IAAI,GAC5C,cAA+C,oBAAI,IAAI,GAC/C;AAER,QAAM,YAAY,KAAK,QAAQ,KAAK;AACpC,QAAM,cACH,YAAY,aAAa,IAAI,SAAS,IAAI,YAC1C,OAAO,KAAK,SAAS,eAAe,WAAW,KAAK,QAAQ,aAAa;AAE5E,QAAM,UAAU;AAGhB,QAAM,UAAU,KAAK,MAAM,KAAK,QAAQ;AACxC,QAAM,cAAc,KAAK,QAAQ,KAAK,MAAM;AAO5C,QAAM,aAAa,kBAAkB,IAAI,OAAO,KAAK,kBAAkB,IAAI,WAAW;AACtF,MAAI;AACJ,MAAI,YAAY;AACd,gBAAY,WAAW,KAAK,IAAI;AAAA,EAClC,OAAO;AACL,UAAM,QAAkB,CAAC,GAAG,WAAW,YAAY;AACnD,QAAI,KAAK,YAAa,OAAM,KAAK,KAAK,WAAW;AACjD,QAAI,KAAK,aAAa;AACpB,YAAM,OAAO,OAAO,KAAK,KAAK,WAAW;AACzC,UAAI,KAAK,SAAS,EAAG,OAAM,KAAK,UAAU,KAAK,KAAK,IAAI,CAAC,EAAE;AAAA,IAC7D;AACA,gBAAY,MAAM,KAAK,IAAI;AAAA,EAC7B;AAOA,QAAM,SAAS,EAAE,GAAG,iBAAiB;AACrC,QAAM,UAAU,KAAK,iBAAiB,YAAY,IAAI,KAAK,cAAc,IAAI;AAC7E,MAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,eAAW,UAAU,QAAS,mBAAkB,QAAQ,MAAM;AAAA,EAChE,WAAW,KAAK,aAAa;AAC3B,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,WAAW,GAAG;AAC3D,UAAI,YAAY,IAAI,GAAG,EAAG;AAC1B,UAAI,UAAU,QAAW;AACvB,eAAO,OAAO,GAAG;AAAA,MACnB,OAAO;AACL,eAAO,GAAG,IAAI,gBAAgB,OAAO,GAAG,GAAG,KAAK;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAOA,QAAM,YACH,KAAK,iBAAiB,iBAAiB,KAAK,cAAc,IAAI,WAC/D,iBAAiB,KAAK,aAAa,OAAO;AAE5C,MAAI,KAAK;AAAA,IACP,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,gBAAgB,KAAK,kBAAkB;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,YAAY,IAAI;AAAA,IAC3D,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI;AAAA,IACrD,GAAI,WAAW,EAAE,eAAe,SAAS,IAAI;AAAA,EAC/C,CAAC;AAED,MAAI,SAAS,UAAU;AAGvB,MAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAC7C,QAAI,cAAc;AAClB,eAAW,SAAS,KAAK,UAAU;AACjC,YAAM,WAAW,YAAY,OAAO,KAAK,aAAa,QAAQ,gBAAgB,QAAQ,mBAAmB,cAAc,WAAW;AAClI,oBAAc,KAAK,IAAI,aAAa,QAAQ;AAAA,IAC9C;AACA,aAAS;AAAA,EACX;AAGA,MAAI,KAAK,MAAM;AACb,aAAS,YAAY,KAAK,MAAM,KAAK,aAAa,QAAQ,gBAAgB,QAAQ,mBAAmB,cAAc,WAAW;AAAA,EAChI;AAEA,SAAO;AACT;AAWO,SAAS,yBACd,eACA,kBACiB;AACjB,MAAI,CAAC,iBAAiB,OAAO,kBAAkB,SAAU,QAAO,CAAC;AACjE,QAAM,KAAK;AAQX,MAAI,CAAC,GAAG,aAAa,cAAe,QAAO,CAAC;AAE5C,QAAM,UAA2B;AAAA,IAC/B,aAAa,GAAG,YAAY,iBAAiB,CAAC;AAAA,IAC9C,eAAe,GAAG,YAAY;AAAA,IAC9B,WAAW,GAAG,YAAY,WAAW,CAAC;AAAA,EACxC;AAEA,QAAM,YAAY,yBAAyB,SAAS,gBAAgB;AAKpE,QAAM,SAAS,GAAG,YAAY,GAAG,GAAG,SAAS,MAAM;AACnD,MAAI,QAAQ;AACV,eAAW,QAAQ,WAAW;AAC5B,UAAI,KAAK,UAAU,WAAW,MAAM,GAAG;AACrC,aAAK,YAAY,KAAK,UAAU,MAAM,OAAO,MAAM;AAAA,MACrD;AACA,UAAI,KAAK,WAAW,WAAW,MAAM,GAAG;AACtC,aAAK,aAAa,KAAK,WAAW,MAAM,OAAO,MAAM;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMO,SAAS,gBACd,QASiB;AACjB,MAAI,QAAQ;AACZ,SAAO,OAAO,IAAI,CAAC,MAAM;AACvB,UAAM,WAAW,EAAE,cAAc;AACjC,UAAM,OAAsB;AAAA,MAC1B,WAAW,EAAE;AAAA,MACb,YAAY,EAAE,SAAS,EAAE;AAAA,MACzB,QAAQ,EAAE,UAAU,CAAC;AAAA,MACrB,WAAW,EAAE,aAAa,GAAG,EAAE,SAAS,EAAE,IAAI;AAAA,MAC9C,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,GAAI,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,IAAI;AAAA,MACrD,GAAI,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,IAAI;AAAA,IACjD;AACA,aAAS;AACT,WAAO;AAAA,EACT,CAAC;AACH;;;AC/fM,IAAAC,uBAAA;AAfC,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,aAAa,gBAAgB,IAC/B,UAAU,gBAAgB,CAAC,GAAG,UAAU,OACxC;AACJ,QAAM,aAAa,UAAU,aAAa,GAAG,UAAU,CAAC;AAExD,MAAI,UAAU;AACZ,WACE,+CAAC,SAAI,WAAsB,OAAc,WAAQ,gBAC/C;AAAA,oDAAC,mBAAgB,WAAsB,eAA8B,UAAQ,MAAC;AAAA,MAC9E,8CAAC,aAAU,UAAU,YAAY,SAAS,YAAY,UAAQ,MAAC;AAAA,OACjE;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,UAAU;AAAA,QACV,SAAS;AAAA,QACT,eAAe;AAAA,QACf,GAAG;AAAA,MACL;AAAA,MACA,WAAQ;AAAA,MAER;AAAA,sDAAC,mBAAgB,WAAsB,eAA8B,MAAY;AAAA,QACjF,8CAAC,SAAI,OAAO,EAAE,WAAW,aAAa,MAAM,MAAM,GAAG,GACnD,wDAAC,aAAU,UAAU,YAAY,SAAS,YAAY,eAAa,MAAC,MAAY,GAClF;AAAA;AAAA;AAAA,EACF;AAEJ;;;AC/CA,IAAAC,iBAA+C;;;ACD/C,IAAAC,iBAA2C;AAoJ/B,IAAAC,uBAAA;AAzIZ,IAAM,cAA8E;AAAA,EAClF,OAAW,EAAE,MAAM,UAAK,OAAO,MAAM,SAAe,OAAO,QAAQ;AAAA,EACnE,MAAW,EAAE,MAAM,QAAK,OAAO,MAAM,WAAgB,OAAO,iBAAiB;AAAA,EAC7E,WAAW,EAAE,MAAM,UAAK,OAAO,MAAM,SAAgB,OAAO,WAAW;AAAA,EACvE,MAAW,EAAE,MAAM,UAAK,OAAO,MAAM,SAAe,OAAO,WAAW;AAAA,EACtE,UAAW,EAAE,MAAM,UAAK,OAAO,MAAM,SAAe,OAAO,WAAW;AAAA,EACtE,SAAW,EAAE,MAAM,UAAK,OAAO,MAAM,eAAgB,OAAO,UAAU;AAAA,EACtE,MAAW,EAAE,MAAM,UAAK,OAAO,MAAM,SAAgB,OAAO,OAAO;AAAA,EACnE,OAAW,EAAE,MAAM,UAAK,OAAO,MAAM,OAAgB,OAAO,QAAQ;AAAA,EACpE,OAAW,EAAE,MAAM,UAAK,OAAO,MAAM,OAAgB,OAAO,QAAQ;AACtE;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA,OAAO;AACT,GAAwB;AACtB,QAAM,KAAK,SAAS,IAAI;AACxB,QAAM,MAAM,QAAQ,IAAI;AAKxB,QAAM,gBAAgB;AAKtB,QAAM,eAAW,wBAAQ,MAAM;AAC7B,UAAM,MAAM,QAAQ,MAAM,GAAG,aAAa;AAC1C,WAAO,IAAI,OAAO,CAAC,MAAM;AACvB,YAAM,OAAQ,EAA6B;AAC3C,UAAI,CAAC,KAAM,QAAO;AAClB,UAAI,EAAE,SAAS,UAAW,QAAO;AACjC,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,SAAS,aAAa,CAAC;AAE3B,QAAM,kBAAc,wBAAQ,MAAM;AAChC,QAAI,QAAQ;AACZ,aAAS,IAAI,eAAe,IAAI,QAAQ,QAAQ,KAAK;AACnD,YAAM,IAAI,QAAQ,CAAC;AACnB,UAAI,CAAC,EAAE,aAAa,QAAQ,CAAC,EAAE,SAAS,UAAW;AAAA,IACrD;AACA,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,aAAa,CAAC;AAE3B,QAAM,gBAAY,uBAAuB,IAAI;AAC7C,gCAAU,MAAM;AACd,cAAU,SAAS,eAAe,EAAE,UAAU,UAAU,OAAO,UAAU,CAAC;AAAA,EAC5E,GAAG,CAAC,SAAS,MAAM,CAAC;AAWpB,QAAM,sBAAkB,wBAAQ,MAAM;AACpC,QAAI,UAAU;AAEd,UAAM,cAAc,oBAAI,IAAY;AACpC,QAAI,WAAW;AAEf,WAAO,SAAS,IAAI,CAAC,UAAU;AAE7B,UAAI,YAAY,MAAM;AACtB,kBAAY,UAAU,QAAQ,kBAAkB,EAAE;AAElD,YAAM,aAAa,MAAM,SAAS,UAAU,MAAM,KAAK,SAAS,YAAY;AAC5E,kBAAY,UAAU,QAAQ,gCAAgC,EAAE;AAGhE,UAAI,MAAM,SAAS,WAAW;AAG5B,cAAM,YAAa,MAA+B,WAAW,MAAM;AACnE,cAAM,SAAS,YAAY,IAAI,SAAS;AACxC,YAAI,CAAC,QAAQ;AACX,sBAAY,IAAI,SAAS;AACzB;AACA,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,SAAS,GAAG,OAAO;AAAA,YACnB,aAAa;AAAA,YACb,MAAM;AAAA,YACN,WAAW;AAAA,YACX,WAAW;AAAA,UACb;AAAA,QACF;AAEA,eAAO,EAAE,GAAG,OAAO,SAAS,MAAM,WAAW,OAAO,eAAe,KAAK;AAAA,MAC1E;AAGA,UAAI,MAAM,SAAS,SAAS;AAC1B;AACA,eAAO,EAAE,GAAG,OAAO,SAAS,GAAG,OAAO,IAAI,aAAa,SAAS,MAAM,WAAW,WAAW,KAAK;AAAA,MACnG;AAGA,UAAI,MAAM,SAAS,aAAa;AAC9B,eAAO,EAAE,GAAG,OAAO,SAAS,MAAM,aAAa,YAAY,MAAM,WAAW,WAAW,MAAM;AAAA,MAC/F;AAGA,UAAI,MAAM,SAAS,UAAU,MAAM,SAAS,YAAY;AACtD,cAAM,gBAAgB,aAAa,UAAU,aAAa;AAC1D,mBAAW,MAAM;AACjB,YAAI,eAAe;AACjB;AACA,gBAAM,YAAY,MAAM,SAAS,cAAc,aAAa,aAAa;AACzE,iBAAO,EAAE,GAAG,OAAO,SAAS,GAAG,OAAO,IAAI,aAAa,WAAW,MAAM,WAAW,WAAW,KAAK;AAAA,QACrG;AACA,eAAO,EAAE,GAAG,OAAO,SAAS,MAAM,WAAW,OAAO,MAAM,UAAU;AAAA,MACtE;AAEA,iBAAW,MAAM;AAGjB,aAAO,EAAE,GAAG,OAAO,SAAS,MAAM,WAAW,MAAM;AAAA,IACrD,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,CAAC;AAEb,MAAI,UAAU;AACZ,WACE,8CAAC,SAAI,WAAsB,OAAO,YAAY,WAAQ,mBAAkB,MAAK,OAC1E,0BAAgB,IAAI,CAAC,OAAO,MAAM;AACjC,UAAK,MAAc,cAAe,QAAO;AACzC,YAAM,KAAM,MAAc;AAC1B,aACE,8CAAC,SAAY,WAAQ,mBAAkB,aAAW,MAAM,MACrD,gBAAM,UACH,MAAM,KAAK,WAAW,GAAG,IACvB,GAAG,MAAM,OAAO,KAAK,MAAM,IAAI,KAC/B,GAAG,MAAM,OAAO,MAAM,EAAE,KAAK,MAAM,aAAa,EAAE,KAAK,MAAM,IAAI,KACnE,MAAM,QALF,CAMV;AAAA,IAEJ,CAAC,GACH;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS;AAAA,QACT,YAAY,MAAM;AAAA,QAClB,GAAG;AAAA,MACL;AAAA,MACA,WAAQ;AAAA,MACR,MAAK;AAAA,MACL,cAAW;AAAA,MAEV;AAAA,wBAAgB,IAAI,CAAC,OAAO,MAAM;AAEjC,cAAK,MAAc,cAAe,QAAO;AAEzC,gBAAM,OAAO,YAAY,MAAM,IAAI,KAAK,YAAY;AACpD,gBAAM,YAAY,MAAM;AACxB,gBAAM,aAAa,MAAM,SAAS;AAClC,gBAAM,UAAU,MAAM,SAAS;AAC/B,gBAAM,UAAU,MAAM,SAAS;AAC/B,gBAAM,YAAa,MAAc;AACjC,gBAAM,SAAS,MAAM,gBAAgB,SAAS;AAC9C,gBAAM,cAAe,MAAc;AAEnC,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,KAAK,SAAS,YAAY;AAAA,cAC1B,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,KAAK;AAAA,gBACL,SAAS,YAAY,GAAG,MAAM,CAAC,SAAS;AAAA,gBACxC,YAAY,MAAM,QAAQ;AAAA,gBAC1B,cAAc,YAAY,aAAa,MAAM,MAAM,KAAK;AAAA,gBACxD,WAAW,aAAa,IAAI,IAAI,IAAI;AAAA,cACtC;AAAA,cAEA;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,OAAO,KAAK;AAAA,sBACZ,YAAY;AAAA,sBACZ,UAAU,YAAY,GAAG,OAAO,GAAG;AAAA,sBACnC,OAAO;AAAA,sBACP,WAAW;AAAA,sBACX,YAAY;AAAA,oBACd;AAAA,oBACA,OAAO,KAAK;AAAA,oBACZ,cAAY,KAAK;AAAA,oBAEhB,eAAK;AAAA;AAAA,gBACR;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,UAAU,YAAY,GAAG,OAAO,GAAG;AAAA,sBACnC,YAAY,YAAY,MAAM;AAAA,sBAC9B,OAAO,WAAW,UACd,MAAM,QACN,aACE,MAAM,UACN,YACE,MAAM,cACN,MAAM;AAAA,sBACd,YAAY;AAAA,sBACZ,YAAY,MAAM,SAAS,SAAS,MAAM,WAAW,MAAM;AAAA,oBAC7D;AAAA,oBAEC,gBAAM,WAAW,cAChB,MAAM,KAAK,WAAW,GAAG,IACvB,gFACE;AAAA,qEAAC,YAAQ;AAAA,8BAAM;AAAA,wBAAQ;AAAA,yBAAC;AAAA,sBACvB;AAAA,sBAAK,MAAM;AAAA,uBACd,IAEA,gFACE;AAAA,qEAAC,YAAQ;AAAA,8BAAM;AAAA,wBAAQ;AAAA,wBAAI;AAAA,wBAAa,MAAM,YAAY,KAAK,MAAM,SAAS,KAAK;AAAA,wBAAG;AAAA,yBAAC;AAAA,sBACtF;AAAA,sBAAK,MAAM;AAAA,uBACd,IAEA,MAAM;AAAA;AAAA,gBACZ;AAAA;AAAA;AAAA,YArDK;AAAA,UAsDP;AAAA,QAEJ,CAAC;AAAA,QAGA,cAAc,KACb,+CAAC,SAAI,OAAO;AAAA,UACV,SAAS;AAAA,UACT,UAAU,GAAG;AAAA,UACb,OAAO,MAAM;AAAA,UACb,SAAS;AAAA,UACT,WAAW;AAAA,QACb,GACG;AAAA;AAAA,UAAY;AAAA,UAAO,gBAAgB,IAAI,UAAU;AAAA,UAAU;AAAA,WAC9D;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;ADqCU,IAAAC,uBAAA;AA7RV,SAAS,kBAAkB,OAAwB;AACjD,QAAM,OAAO,oBAAI,QAAgB;AACjC,QAAM,YAAY;AAClB,MAAI;AACF,QAAI,OAAO,KAAK;AAAA,MACd;AAAA,MACA,CAAC,MAAMC,OAAM;AACX,YAAI,OAAOA,OAAM,YAAYA,OAAM,MAAM;AACvC,cAAI,KAAK,IAAIA,EAAW,EAAG,QAAO;AAClC,eAAK,IAAIA,EAAW;AAAA,QACtB;AACA,eAAOA;AAAA,MACT;AAAA,MACA;AAAA,IACF;AACA,QAAI,QAAQ,KAAK,SAAS,WAAW;AACnC,aAAO,KAAK,MAAM,GAAG,SAAS,IAAI;AAAA,oBAAuB,SAAS;AAAA,IACpE;AACA,WAAO,QAAQ;AAAA,EACjB,SAAS,KAAK;AACZ,WAAO,qBAAqB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EAC9E;AACF;AA2BO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,KAAK,SAAS,IAAI;AACxB,QAAM,MAAM,QAAQ,IAAI;AAKxB,QAAM,gBAAY,wBAAkB,MAAM;AACxC,UAAM,QAAkB,CAAC;AACzB,eAAW,QAAQ,WAAW;AAC5B,YAAM,cAAc,KAAK,aAAa,IAAI,MAAM,IAAI,EAAE,OAAO,OAAO;AACpE,YAAM,KAAK,GAAG,UAAU;AAAA,IAC1B;AACA,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,CAAC;AAGd,QAAM,oBAAgB,wBAAQ,MAAM;AAClC,QAAI,UAAU,WAAW,KAAK,UAAU,WAAW,EAAG,QAAO,UAAU;AACvE,UAAM,kBAA4B,CAAC;AACnC,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,YAAM,UAAU,UAAU,CAAC,EAAE,UAAU;AACvC,UAAI,QAAQ,WAAW,QAAQ,KAAK,CAAC,QAAQ,MAAM,wBAAwB,GAAG;AAC5E,wBAAgB,KAAK,CAAC;AAAA,MACxB;AAAA,IACF;AACA,QAAI,gBAAgB,WAAW,GAAG;AAChC,YAAM,SAAS,gBAAgB,KAAK,UAAU;AAC9C,aAAO,KAAK,IAAI,GAAG,KAAK,KAAK,UAAU,SAAS,KAAK,CAAC;AAAA,IACxD;AACA,UAAM,eAAe,KAAK,IAAI,gBAAgB,GAAG,gBAAgB,MAAM;AACvE,UAAM,SAAS,eAAe,gBAAgB,SAC1C,gBAAgB,YAAY,IAC5B,UAAU;AACd,WAAO,KAAK,IAAI,GAAG,MAAM;AAAA,EAC3B,GAAG,CAAC,UAAU,QAAQ,eAAe,SAAS,CAAC;AAI/C,QAAM,iBAAa;AAAA,IACjB,MAAM,kBAAkB,SAAS,qBAAqB,gBAAgB,IAAI;AAAA,IAC1E,CAAC,gBAAgB;AAAA,EACnB;AAGA,QAAM,yBAAqB;AAAA,IACzB,MAAM,kBAAkB,SAAS,0BAA0B,kBAAkB,WAAW,eAAe,UAAU,IAAI;AAAA,IACrH,CAAC,kBAAkB,WAAW,eAAe,UAAU;AAAA,EACzD;AAEA,QAAM,gBAAgB,oBAAoB,iBAAiB,SAAS;AAGpE,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAE1C,QAAM,wBAAoB,4BAAY,MAAM;AAC1C,QAAI,CAAC,kBAAkB,QAAQ;AAC7B,aAAO,UAAU,KAAK,IAAI;AAAA,IAC5B;AAKA,UAAM,OAAyB,CAAC;AAChC,UAAM,WAAW,oBAAI,IAA8B;AACnD,UAAM,eAAe,oBAAI,IAAoB;AAE7C,eAAW,SAAS,kBAAkB;AACpC,YAAM,OAAO,MAAM;AACnB,UAAI,CAAC,MAAM;AACT,aAAK,KAAK,KAAK;AAAA,MACjB,OAAO;AAGL,YAAI,MAAM,SAAS,WAAW;AAC5B,gBAAM,SAAS,MAAM,cAAc;AACnC,cAAI,CAAC,QAAQ;AACX,iBAAK,KAAK,KAAK;AAAA,UACjB;AAEA,cAAI,MAAM,aAAa,CAAC,QAAQ;AAC9B,yBAAa,IAAI,MAAM,MAAM,SAAS;AAAA,UACxC;AAAA,QACF,OAAO;AAEL,cAAI,CAAC,SAAS,IAAI,IAAI,EAAG,UAAS,IAAI,MAAM,CAAC,CAAC;AAC9C,mBAAS,IAAI,IAAI,EAAG,KAAK,KAAK;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AAKA,UAAM,gBAAgB,CAAC,SAA2B,SAA0C;AAC1F,UAAI,UAAU;AACd,YAAM,QAAkB,CAAC;AAEzB,iBAAW,KAAK,SAAS;AAEvB,YAAI,MAAM,aAAa,EAAE,SAAS,UAAW;AAE7C,YAAI,OAAO,EAAE;AAMb,YAAI,MAAM,WAAW;AACnB,gBAAM,SAAS,IAAI,KAAK,SAAS;AACjC,gBAAM,MAAM,KAAK,QAAQ,MAAM;AAC/B,cAAI,QAAQ,IAAI;AACd,mBAAO,KAAK,MAAM,GAAG,GAAG,IAAI,MAAM,KAAK,MAAM,MAAM,OAAO,MAAM;AAAA,UAClE;AAAA,QACF;AAEA,cAAM,YAAY,EAAE,SAAS,WAAW,EAAE,SAAS,aAAa,EAAE,SAAS,UAAU,EAAE,SAAS;AAEhG,YAAI,WAAW;AACb;AAEA,gBAAM,OAAQ,EAA6B;AAC3C,gBAAM,WAAW,EAAE,SAAS,aAAa,OAAO,YAAO,IAAI,MAAM;AACjE,gBAAM,KAAK,GAAG,OAAO,KAAK,IAAI,GAAG,QAAQ,EAAE;AAAA,QAC7C,OAAO;AAEL,gBAAM,KAAK,KAAK,IAAI,EAAE;AAAA,QACxB;AAAA,MACF;AAEA,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB;AAGA,UAAM,WAAqB,CAAC;AAC5B,aAAS,KAAK,0BAA0B;AACxC,aAAS,KAAK,cAAc,IAAI,CAAC;AAEjC,QAAI,SAAS,OAAO,GAAG;AACrB,eAAS,KAAK,wBAAwB;AACtC,eAAS,KAAK,uDAAuD;AACrE,iBAAW,CAAC,MAAM,OAAO,KAAK,UAAU;AACtC,cAAM,OAAO,aAAa,IAAI,IAAI,KAAK;AACvC,iBAAS,KAAK,OAAO,IAAI,KAAK,IAAI;AAAA,CAAK;AACvC,iBAAS,KAAK,cAAc,SAAS,EAAE,WAAW,KAAK,CAAC,CAAC;AACzD,iBAAS,KAAK,EAAE;AAAA,MAClB;AAAA,IACF;AAOA,QAAI,iBAAiB;AACnB,YAAM,OAAO;AAOb,UAAI,KAAK,gBAAgB,QAAW;AAClC,iBAAS,KAAK,2BAA2B;AACzC,iBAAS,KAAK,SAAS;AACvB,iBAAS,KAAK,kBAAkB,KAAK,WAAW,CAAC;AACjD,iBAAS,KAAK,KAAK;AAAA,MACrB;AAEA,UAAI,MAAM,QAAQ,KAAK,SAAS,KAAK,KAAK,UAAU,SAAS,GAAG;AAC9D,iBAAS,KAAK,mBAAmB;AACjC,iBAAS;AAAA,UACP;AAAA,QAEF;AACA,iBAAS,KAAK,SAAS;AACvB,iBAAS,KAAK,kBAAkB,KAAK,SAAS,CAAC;AAC/C,iBAAS,KAAK,KAAK;AAAA,MACrB;AAEA,UAAI,KAAK,aAAa,OAAO,KAAK,cAAc,UAAU;AACxD,iBAAS,KAAK,2BAA2B;AACzC,iBAAS;AAAA,UACP;AAAA,QACF;AACA,iBAAS,KAAK,SAAS;AACvB,iBAAS,KAAK,kBAAkB,KAAK,SAAS,CAAC;AAC/C,iBAAS,KAAK,KAAK;AAAA,MACrB;AAEA,UAAI,KAAK,kBAAkB,OAAO,KAAK,mBAAmB,UAAU;AAClE,cAAM,OAAO,OAAO,KAAK,KAAK,cAAyC;AACvE,YAAI,KAAK,SAAS,GAAG;AACnB,mBAAS,KAAK,wBAAwB;AACtC,mBAAS,KAAK,SAAS;AACvB,mBAAS,KAAK,kBAAkB,KAAK,cAAc,CAAC;AACpD,mBAAS,KAAK,KAAK;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM;AACR,eAAS,KAAK,kCAAkC;AAChD,eAAS;AAAA,QACP;AAAA,MAEF;AACA,eAAS,KAAK,SAAS;AACvB,eAAS,KAAK,kBAAkB,IAAI,CAAC;AACrC,eAAS,KAAK,KAAK;AAAA,IACrB;AAEA,WAAO,SAAS,KAAK,IAAI;AAAA,EAC3B,GAAG,CAAC,kBAAkB,WAAW,iBAAiB,IAAI,CAAC;AAEvD,QAAM,iBAAa,4BAAY,YAAY;AACzC,UAAM,OAAO,kBAAkB;AAC/B,UAAM,UAAU,UAAU,UAAU,IAAI;AACxC,cAAU,IAAI;AACd,eAAW,MAAM,UAAU,KAAK,GAAG,GAAI;AAAA,EACzC,GAAG,CAAC,iBAAiB,CAAC;AAEtB,MAAI,UAAU;AACZ,WACE,8CAAC,SAAI,WAAsB,OAAc,WAAQ,mBAC9C,0BACC,8CAAC,kBAAe,SAAS,kBAAmB,oBAAwC,UAAQ,MAAC,IAE7F,8CAAC,kBAAe,WAAsB,eAA8B,UAAQ,MAAC,GAEjF;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,UAAU;AAAA,QACV,SAAS;AAAA,QACT,eAAe;AAAA,QACf,GAAG;AAAA,MACL;AAAA,MACA,WAAQ;AAAA,MAGR;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,SAAS,GAAG,MAAM,CAAC,MAAM,GAAG;AAAA,cAC5B,UAAU,GAAG;AAAA,cACb,OAAO,MAAM;AAAA,cACb,cAAc,aAAa,MAAM,MAAM;AAAA,cACvC,YAAY;AAAA,cACZ,SAAS;AAAA,cACT,gBAAgB;AAAA,cAChB,YAAY;AAAA,YACd;AAAA,YAEA;AAAA,4DAAC,UAAK,OAAO,EAAE,WAAW,SAAS,GAAG,+FAEtC;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS;AAAA,kBACT,OAAM;AAAA,kBACN,OAAO;AAAA,oBACL,YAAY,SAAS,MAAM,UAAU,MAAM;AAAA,oBAC3C,QAAQ,aAAa,MAAM,MAAM;AAAA,oBACjC,cAAc;AAAA,oBACd,SAAS;AAAA,oBACT,UAAU,GAAG;AAAA,oBACb,OAAO,SAAS,SAAS,MAAM;AAAA,oBAC/B,QAAQ;AAAA,oBACR,YAAY;AAAA,oBACZ,YAAY;AAAA,oBACZ,YAAY;AAAA,kBACd;AAAA,kBAEC,mBAAS,YAAY;AAAA;AAAA,cACxB;AAAA;AAAA;AAAA,QACF;AAAA,QACC,gBACC;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT;AAAA,YACA;AAAA,YACA,OAAO,EAAE,MAAM,EAAE;AAAA;AAAA,QACnB,IAEA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA,OAAO,EAAE,MAAM,EAAE;AAAA;AAAA,QACnB;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;AEnWA,IAAAC,iBAAqD;AA0EjD,IAAAC,uBAAA;AA3CG,SAAS,sBAAsB,OAAuC;AAC3E,MAAI,CAAC,OAAO,OAAO,OAAQ,QAAO,CAAC;AACnC,QAAM,UAA8B,CAAC;AACrC,aAAW,QAAQ,MAAM,OAAO;AAC9B,QAAI,CAAC,KAAK,MAAM,UAAW;AAC3B,UAAM,QAA0B;AAAA,MAC9B,MAAM,OAAO,KAAK,KAAK,UAAU,WAAW,KAAK,KAAK,QAAQ,KAAK;AAAA,MACnE,WAAW;AAAA,IACb;AACA,QAAI,OAAO,KAAK,KAAK,gBAAgB,SAAU,OAAM,cAAc,KAAK,KAAK;AAC7E,QAAI,OAAO,KAAK,KAAK,cAAc,SAAU,OAAM,YAAY,KAAK,KAAK;AACzE,YAAQ,KAAK,KAAK;AAAA,EACpB;AACA,SAAO;AACT;AAGA,IAAM,eAAW,qBAAK,SAASC,UAAS;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,IAAI;AAC7C,QAAM,cAAc,MAAM,YAAY,MAAM,SAAS,SAAS;AAC9D,QAAM,WAAW,gBAAgB,MAAM;AACvC,QAAM,SAAS,YAAY,IAAI,MAAM,IAAI;AAEzC,QAAM,kBAAc,4BAAY,MAAM;AACpC,QAAI,aAAa;AACf,kBAAY,CAAC,SAAS,CAAC,IAAI;AAAA,IAC7B;AACA,mBAAe,MAAM,MAAM,CAAC,CAAC,MAAM,SAAS;AAAA,EAC9C,GAAG,CAAC,aAAa,cAAc,MAAM,MAAM,MAAM,SAAS,CAAC;AAE3D,SACE,gFACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAQ;AAAA,QACR,OAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,KAAK;AAAA,UACL,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,YAAY,WACR,sBAAsB,MAAM,OAAO,uBACnC;AAAA,UACJ,QAAQ;AAAA,UACR,SAAS,eAAe,IAAI,QAAQ,EAAE;AAAA,UACtC,YAAY,MAAM;AAAA,UAClB,UAAU;AAAA,UACV,WAAW;AAAA,UACX,cAAc;AAAA,UACd,YAAY;AAAA,QACd;AAAA,QACA,cAAc,CAAC,MAAM;AACnB,cAAI,CAAC,UAAU;AACb,cAAE,cAAc,MAAM,aAAa,sBAAsB,MAAM,SAAS;AAAA,UAC1E;AAAA,QACF;AAAA,QACA,cAAc,CAAC,MAAM;AACnB,cAAI,CAAC,UAAU;AACb,cAAE,cAAc,MAAM,aAAa;AAAA,UACrC;AAAA,QACF;AAAA,QAGC;AAAA,wBACC;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,OAAO,MAAM;AAAA,gBACb,OAAO;AAAA,gBACP,WAAW;AAAA,gBACX,YAAY;AAAA,gBACZ,YAAY;AAAA,gBACZ,WAAW,WAAW,kBAAkB;AAAA,gBACxC,SAAS;AAAA,cACX;AAAA,cACD;AAAA;AAAA,UAED,IAEA,8CAAC,UAAK,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,GAAG;AAAA,UAI7C;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,OAAO;AAAA,gBACP,QAAQ;AAAA,gBACR,cAAc;AAAA,gBACd,YAAY;AAAA,gBACZ,YAAY,WACR,MAAM,UACN,SACE,MAAM,UACN,MAAM;AAAA,cACd;AAAA;AAAA,UACF;AAAA,UAGA,+CAAC,UAAK,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,UAAU,EAAE,GACnE;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,OAAO,WACH,MAAM,UACN,SACE,MAAM,cACN,MAAM;AAAA,kBACZ,YAAY,WAAW,MAAM,MAAM,YAAY,MAAM;AAAA,kBACrD,YAAY;AAAA,kBACZ,UAAU;AAAA,kBACV,cAAc;AAAA,gBAChB;AAAA,gBAEC;AAAA,wBAAM;AAAA,kBACN,MAAM,aACL,8CAAC,UAAK,OAAO,EAAE,SAAS,KAAK,YAAY,GAAG,UAAU,GAAG,GAAG,oBAAC;AAAA;AAAA;AAAA,YAEjE;AAAA,YACC,MAAM,eACL;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,OAAO,MAAM;AAAA,kBACb,UAAU;AAAA,kBACV,YAAY;AAAA,kBACZ,UAAU;AAAA,kBACV,cAAc;AAAA,gBAChB;AAAA,gBAEC,gBAAM;AAAA;AAAA,YACT;AAAA,aAEJ;AAAA;AAAA;AAAA,IACF;AAAA,IAGC,eAAe,YACd,8CAAC,SACE,gBAAM,SAAU,IAAI,CAAC,OAAO,MAC3B;AAAA,MAACA;AAAA,MAAA;AAAA,QAEC,OAAO;AAAA,QACP,OAAO,QAAQ;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA;AAAA,MALK,MAAM,aAAa,GAAG,MAAM,IAAI,IAAI,CAAC;AAAA,IAM5C,CACD,GACH;AAAA,KAEJ;AAEJ,CAAC;AAGD,IAAM,mBAAe,qBAAK,SAASC,cAAa,EAAE,SAAS,GAAyB;AAClF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,eAAe;AAAA,QACf,OAAO,MAAM;AAAA,MACf;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ,CAAC;AAEM,IAAM,kBAAc,qBAAK,SAASC,aAAY;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,oBAAgB,wBAAQ,MAAM,sBAAsB,KAAK,GAAG,CAAC,KAAK,CAAC;AAGzE,MAAI,cAAc,WAAW,EAAG,QAAO;AAEvC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAQ;AAAA,MACR,OAAO;AAAA,QACL,GAAI,WACA,CAAC,IACD;AAAA,UACE,YAAY,MAAM;AAAA,UAClB,UAAU;AAAA,UACV,YAAY,MAAM;AAAA,UAClB,aAAa,aAAa,MAAM,MAAM;AAAA,UACtC,WAAW;AAAA,UACX,WAAW;AAAA,UACX,SAAS;AAAA,QACX;AAAA,QACJ,GAAG;AAAA,MACL;AAAA,MAEC;AAAA,SAAC,YAAY,8CAAC,gBAAa,sBAAQ;AAAA,QACnC,cAAc,IAAI,CAAC,OAAO,MACzB;AAAA,UAAC;AAAA;AAAA,YAEC;AAAA,YACA,OAAO;AAAA,YACP;AAAA,YACA;AAAA,YACA;AAAA;AAAA,UALK,MAAM,aAAa,GAAG,MAAM,IAAI,IAAI,CAAC;AAAA,QAM5C,CACD;AAAA;AAAA;AAAA,EACH;AAEJ,CAAC;;;AC7RD,IAAAC,iBAAqB;AAuCP,IAAAC,uBAAA;AA1BP,IAAM,wBAAoB,qBAAK,SAASC,mBAAkB;AAAA,EAC/D;AAAA,EACA;AACF,GAA2B;AACzB,MAAI,YAAY,UAAU,EAAG,QAAO;AAEpC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,SAAS;AAAA,QACT,YAAY,MAAM;AAAA,QAClB,cAAc,aAAa,MAAM,MAAM;AAAA,QACvC,UAAU;AAAA,QACV,YAAY,MAAM;AAAA,QAClB,YAAY;AAAA,QACZ,WAAW;AAAA,MACb;AAAA,MAEC,sBAAY,IAAI,CAAC,OAAO,MAAM;AAC7B,cAAM,SAAS,MAAM,YAAY,SAAS;AAC1C,eACE,+CAAC,UAAiC,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GACtF;AAAA,cAAI,KACH,8CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,WAAW,UAAU,GAAG,GAAG,oBAEvD;AAAA,UAED,SACC,+CAAC,UAAK,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GAC3D;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,OAAO,MAAM;AAAA,kBACb,YAAY;AAAA,gBACd;AAAA,gBAEC,gBAAM;AAAA;AAAA,YACT;AAAA,YACC,MAAM,eACL;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,OAAO,MAAM;AAAA,kBACb,YAAY;AAAA,kBACZ,UAAU;AAAA,gBACZ;AAAA,gBACD;AAAA;AAAA,kBACI,MAAM;AAAA;AAAA;AAAA,YACX;AAAA,aAEJ,IAEA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS,MAAM,WAAW,CAAC;AAAA,cAC3B,OAAO;AAAA,gBACL,YAAY;AAAA,gBACZ,QAAQ;AAAA,gBACR,OAAO,MAAM;AAAA,gBACb,QAAQ;AAAA,gBACR,SAAS;AAAA,gBACT,cAAc;AAAA,gBACd,UAAU;AAAA,gBACV,YAAY;AAAA,gBACZ,YAAY;AAAA,gBACZ,YAAY;AAAA,cACd;AAAA,cACA,cAAc,CAAC,MAAM;AACnB,kBAAE,cAAc,MAAM,QAAQ,GAAG,MAAM,OAAO;AAAA,cAChD;AAAA,cACA,cAAc,CAAC,MAAM;AACnB,kBAAE,cAAc,MAAM,QAAQ,GAAG,MAAM,aAAa;AAAA,cACtD;AAAA,cAEC,gBAAM;AAAA;AAAA,UACT;AAAA,aAnDO,GAAG,MAAM,KAAK,IAAI,CAAC,EAqD9B;AAAA,MAEJ,CAAC;AAAA;AAAA,EACH;AAEJ,CAAC;;;AC1DD,IAAAC,iBAAuD;AACvD,IAAAA,iBAKO;;;ACjBP,mBAAkB;AAwFX,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AAsBvB,SAAS,OACd,MACA,WACA,WACA,UACmC;AACnC,QAAM,QAAS,KAAK,SAAS,CAAC;AAC9B,QAAM,SAAS,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAC/D,QAAM,SAAS,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;AAMjE,MAAI,KAAK,MAAM,oBAAoB,WAAW,UAAa,WAAW,QAAW;AAC/E,WAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAAA,EACzC;AAEA,QAAM,WAAW,WAAW,IAAI;AAChC,MAAI,SAAU,QAAO,EAAE,OAAO,SAAS,OAAO,QAAQ,SAAS,OAAO;AACtE,SAAO;AAAA,IACL,OAAO,UAAU;AAAA,IACjB,QAAQ,UAAU;AAAA,EACpB;AACF;AAaA,SAAS,oBACP,OACA,cACK;AACL,QAAM,WAAW,oBAAI,IAAiB;AACtC,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,MAAM,SAAS,OAAQ;AAC7B,UAAM,MAAM,SAAS,IAAI,EAAE,MAAM;AACjC,QAAI,IAAK,KAAI,KAAK,CAAC;AAAA,QACd,UAAS,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;AAAA,EACjC;AACA,QAAM,MAAW,CAAC;AAClB,aAAW,CAAC,KAAK,KAAK,KAAK,UAAU;AACnC,QAAI,MAAM,SAAS,GAAG;AACpB,UAAI,KAAK,GAAG,KAAK;AACjB;AAAA,IACF;AACA,UAAM,UAAU,aAAa,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AAC5D,UAAM,WAAW,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;AACxD,UAAM,OAAO,oBAAI,IAAY;AAC7B,eAAW,KAAK,SAAS;AACvB,YAAM,IAAI,SAAS,IAAI,CAAC;AACxB,UAAI,KAAK,CAAC,KAAK,IAAI,CAAC,GAAG;AACrB,YAAI,KAAK,CAAC;AACV,aAAK,IAAI,CAAC;AAAA,MACZ;AAAA,IACF;AACA,eAAW,KAAK,MAAO,KAAI,CAAC,KAAK,IAAI,EAAE,MAAM,EAAG,KAAI,KAAK,CAAC;AAAA,EAC5D;AACA,SAAO;AACT;AAWO,SAAS,iBACd,OACA,UAAmC,CAAC,GACxB;AACZ,MAAI,MAAM,MAAM,WAAW,EAAG,QAAO;AAErC,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,YAAY,QAAQ,cAAc;AAExC,QAAM,IAAI,IAAI,aAAAC,QAAM,SAAS,MAAM,EAAE,UAAU,KAAK,CAAC;AACrD,IAAE,SAAS,EAAE,SAAS,WAAW,SAAS,SAAS,SAAS,SAAS,SAAS,QAAQ,CAAC;AACvF,IAAE,oBAAoB,OAAO,CAAC,EAAE;AAEhC,QAAM,QAAQ,oBAAI,IAA+C;AAKjE,QAAM,qBAAqB,oBAAI,IAA2B;AAC1D,aAAW,QAAQ,MAAM,OAAO;AAC9B,UAAM,WAAW,QAAQ,WAAW,IAAI;AACxC,UAAM,OAAO,OAAO,MAAM,WAAW,WAAW,QAAQ,QAAQ;AAChE,UAAM,IAAI,KAAK,IAAI,IAAI;AAMvB,QAAI,YAAY,SAAS,UAAU,KAAK,SAAS,SAAS,WAAW,KAAK,QAAQ;AAChF,yBAAmB,IAAI,KAAK,IAAI,QAAQ;AAAA,IAC1C;AACA,MAAE,QAAQ,KAAK,IAAI,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,CAAC;AAC7D,QAAI,KAAK,UAAU;AACjB,QAAE,UAAU,KAAK,IAAI,KAAK,QAAQ;AAAA,IACpC;AAAA,EACF;AAQA,QAAM,cAAc,QAAQ,eACxB,oBAAoB,MAAM,OAAO,QAAQ,YAAY,IACrD,MAAM;AACV,aAAW,KAAK,aAAa;AAC3B,QAAI,EAAE,MAAM,SAAS,OAAQ;AAC7B,QAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG;AAE9C,YAAM,QAA8C,CAAC;AACrD,YAAM,SAAS,QAAQ,aAAa,CAAC;AACrC,YAAM,SAAS,QAAQ,aAAa,CAAC;AACrC,UAAI,OAAO,WAAW,SAAU,OAAM,SAAS;AAC/C,UAAI,OAAO,WAAW,SAAU,OAAM,SAAS;AAC/C,QAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,IACrC;AAAA,EACF;AAEA,eAAAA,QAAM,OAAO,CAAC;AAId,QAAM,aAA0B,MAAM,MAAM,IAAI,CAAC,SAAS;AACxD,UAAM,UAAU,EAAE,KAAK,KAAK,EAAE;AAC9B,QAAI,CAAC,QAAS,QAAO;AACrB,UAAM,OAAO,MAAM,IAAI,KAAK,EAAE;AAC9B,QAAI,IAAI,QAAQ,IAAI,KAAK,QAAQ;AACjC,QAAI,IAAI,QAAQ,IAAI,KAAK,SAAS;AAClC,QAAI,KAAK,UAAU;AACjB,YAAM,SAAS,EAAE,KAAK,KAAK,QAAQ;AACnC,YAAM,aAAa,MAAM,IAAI,KAAK,QAAQ;AAC1C,UAAI,UAAU,YAAY;AACxB,aAAK,OAAO,IAAI,WAAW,QAAQ;AACnC,aAAK,OAAO,IAAI,WAAW,SAAS;AAAA,MACtC;AAAA,IACF;AAIA,UAAM,YAAY,mBAAmB,IAAI,KAAK,EAAE;AAChD,QAAI,WAAW;AACb,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,EAAE,GAAG,EAAE;AAAA,QACjB,OAAO,EAAE,GAAI,KAAK,SAAS,CAAC,GAAI,OAAO,UAAU,OAAO,QAAQ,UAAU,OAAO;AAAA,MACnF;AAAA,IACF;AACA,WAAO,EAAE,GAAG,MAAM,UAAU,EAAE,GAAG,EAAE,EAAE;AAAA,EACvC,CAAC;AAED,SAAO,EAAE,OAAO,YAAY,OAAO,MAAM,MAAM;AACjD;AAOO,SAAS,uBACd,UAAmC,CAAC,GACnB;AACjB,SAAO,CAAC,UAAsB,iBAAiB,OAAO,OAAO;AAC/D;;;AClPO,SAAS,qBACd,OACA,UAAuC,CAAC,GAC5B;AAEZ,MAAI,MAAM,MAAM,WAAW,EAAG,QAAO;AAErC,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,YAAY,QAAQ,cAAc;AAGxC,QAAM,OAAO,oBAAI,IAAuB;AACxC,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,KAAK,MAAM,OAAO;AAC3B,SAAK,IAAI,EAAE,IAAI,CAAC;AAChB,UAAM,IAAI,EAAE,IAAI,OAAO,GAAG,WAAW,WAAW,QAAQ,QAAQ,EAAE,KAAK;AAAA,EACzE;AAKA,QAAM,QAAQ,oBAAI,IAAsB;AACxC,QAAM,YAAY,oBAAI,IAAoB;AAC1C,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,KAAK,MAAM,OAAgC;AACpD,QAAI,EAAE,MAAM,SAAS,OAAQ;AAC7B,QAAI,CAAC,KAAK,IAAI,EAAE,MAAM,KAAK,CAAC,KAAK,IAAI,EAAE,MAAM,EAAG;AAChD,UAAM,MAAM,GAAG,EAAE,MAAM,KAAI,EAAE,MAAM;AACnC,QAAI,SAAS,IAAI,GAAG,EAAG;AACvB,aAAS,IAAI,GAAG;AAChB,UAAM,OAAO,MAAM,IAAI,EAAE,MAAM;AAC/B,QAAI,KAAM,MAAK,KAAK,EAAE,MAAM;AAAA,QACvB,OAAM,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;AACnC,cAAU,IAAI,EAAE,SAAS,UAAU,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;AAAA,EAC5D;AAIA,QAAM,WAAW,oBAAI,IAAoB;AACzC,aAAW,KAAK,MAAM,MAAO,UAAS,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC;AAC5D,QAAM,UAAU,CAAC,OAAe,SAAS,IAAI,EAAE,IAAK,MAAM,IAAI,EAAE,IAAK;AAIrE,QAAM,QAAQ,CAAC,GAAG,MAAM,KAAK,EAAE;AAAA,IAC7B,CAAC,GAAG,MACF,EAAE,SAAS,IAAI,EAAE,SAAS,KAC1B,EAAE,SAAS,IAAI,EAAE,SAAS,MACzB,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI;AAAA,EAC1C;AAEA,aAAW,KAAK,OAAO;AACrB,UAAM,IAAI,MAAM,IAAI,EAAE,EAAE;AACxB,QAAI,CAAC,KAAK,EAAE,WAAW,EAAG;AAC1B,UAAM,MAAM,EAAE,CAAC;AACf,SAAK,UAAU,IAAI,GAAG,KAAK,OAAO,EAAG;AACrC,UAAM,IAAI,KAAK,IAAI,GAAG;AAEtB,SAAK,EAAE,YAAY,aAAgB,EAAE,YAAY,QAAY;AAE7D,aAAS,IAAI,EAAE,IAAI,QAAQ,GAAG,IAAI,MAAM,IAAI,EAAE,EAAE,IAAK,CAAC;AAAA,EACxD;AAKA,QAAM,QAAQ,MAAM,MAAM,IAAI,CAAC,MAAM;AACnC,UAAM,KAAK,SAAS,IAAI,EAAE,EAAE;AAC5B,WAAO,OAAO,EAAE,SAAS,IAAI,IAAI,EAAE,GAAG,GAAG,UAAU,EAAE,GAAG,IAAI,GAAG,EAAE,SAAS,EAAE,EAAE;AAAA,EAChF,CAAC;AACD,SAAO,EAAE,OAAO,OAAO,MAAM,MAAM;AACrC;AAYO,SAAS,yBACd,MACA,UAAuC,CAAC,GACvB;AACjB,SAAO,CAAC,UAAsB,qBAAqB,KAAK,KAAK,GAAG,OAAO;AACzE;;;AC9GO,SAAS,kBACd,OACA,UAAoC,CAAC,GACzB;AACZ,MAAI,MAAM,MAAM,WAAW,EAAG,QAAO;AAErC,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,YAAY,QAAQ,cAAc;AAExC,QAAM,OAAO,oBAAI,IAAuB;AACxC,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,KAAK,MAAM,OAAO;AAC3B,SAAK,IAAI,EAAE,IAAI,CAAC;AAChB,UAAM,IAAI,EAAE,IAAI,OAAO,GAAG,WAAW,WAAW,QAAQ,QAAQ,EAAE,KAAK;AAAA,EACzE;AAGA,QAAM,aAAa,oBAAI,IAAsB;AAC7C,QAAM,UAAU,oBAAI,IAAsB;AAC1C,QAAM,YAAY,oBAAI,IAAoB;AAC1C,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,KAAK,MAAM,OAAgC;AACpD,QAAI,EAAE,MAAM,SAAS,OAAQ;AAC7B,QAAI,CAAC,KAAK,IAAI,EAAE,MAAM,KAAK,CAAC,KAAK,IAAI,EAAE,MAAM,EAAG;AAChD,UAAM,MAAM,GAAG,EAAE,MAAM,IAAI,EAAE,MAAM;AACnC,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,UAAM,KAAK,WAAW,IAAI,EAAE,MAAM;AAClC,QAAI,GAAI,IAAG,KAAK,EAAE,MAAM;AAAA,QACnB,YAAW,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;AACxC,UAAM,KAAK,QAAQ,IAAI,EAAE,MAAM;AAC/B,QAAI,GAAI,IAAG,KAAK,EAAE,MAAM;AAAA,QACnB,SAAQ,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;AACrC,cAAU,IAAI,EAAE,SAAS,UAAU,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;AAC1D,aAAS,IAAI,EAAE,SAAS,SAAS,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;AAAA,EAC1D;AAGA,QAAM,WAAW,oBAAI,IAAoB;AACzC,aAAW,KAAK,MAAM,MAAO,UAAS,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC;AAC5D,QAAM,UAAU,CAAC,OAAe,SAAS,IAAI,EAAE,IAAK,MAAM,IAAI,EAAE,IAAK;AAErE,QAAM,UAAU,QAAQ,WAAW;AAGnC,QAAM,SAAS,CAAC,IAAY,aAA6B;AACvD,UAAM,IAAI,MAAM,IAAI,EAAE;AACtB,UAAM,KAAK,SAAS,IAAI,EAAE;AAC1B,UAAM,OAAO,KAAK,IAAI,EAAE;AACxB,QAAI,OAAO;AACX,QAAI,OAAO;AACX,eAAW,KAAK,MAAM,OAAO;AAC3B,UAAI,EAAE,OAAO,MAAM,EAAE,aAAa,KAAK,SAAU;AACjD,UAAI,KAAK,IAAI,EAAE,SAAS,IAAI,KAAK,SAAS,CAAC,IAAI,EAAG;AAClD,YAAM,QAAQ,SAAS,IAAI,EAAE,EAAE;AAC/B,YAAM,SAAS,QAAQ,MAAM,IAAI,EAAE,EAAE;AACrC,UAAI,UAAU,GAAI,QAAO,KAAK,IAAI,MAAM,SAAS,OAAO;AAAA,eAC/C,SAAS,KAAK,EAAG,QAAO,KAAK,IAAI,MAAM,QAAQ,UAAU,CAAC;AAAA,IACrE;AACA,WAAO,QAAQ,OAAO,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,QAAQ,CAAC,IAAI;AAAA,EACnE;AAGA,QAAM,QAAQ,CAAC,GAAG,MAAM,KAAK,EAAE;AAAA,IAAK,CAAC,GAAG,MACtC,EAAE,SAAS,IAAI,EAAE,SAAS,KAAK,EAAE,SAAS,IAAI,EAAE,SAAS,KAAK,EAAE,GAAG,cAAc,EAAE,EAAE;AAAA,EACvF;AACA,aAAW,KAAK,OAAO;AACrB,SAAK,UAAU,IAAI,EAAE,EAAE,KAAK,KAAK,EAAG;AACpC,SAAK,SAAS,IAAI,EAAE,EAAE,KAAK,KAAK,EAAG;AACnC,UAAM,QAAQ,WAAW,IAAI,EAAE,EAAE,KAAK,CAAC,GAAG;AAAA,MACxC,CAAC,MAAM,KAAK,IAAI,CAAC,GAAG,aAAa,EAAE;AAAA;AAAA,IACrC;AACA,QAAI,KAAK,SAAS,EAAG;AACrB,UAAM,UAAU,KAAK,IAAI,OAAO;AAChC,UAAM,KAAK,MAAM,IAAI,EAAE,EAAE;AACzB,UAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,IAAI,KAAK,IAAI,GAAG,OAAO,KAAK;AAC7D,aAAS,IAAI,EAAE,IAAI,OAAO,EAAE,IAAI,OAAO,KAAK,CAAC,CAAC;AAU9C,QAAI,QAAQ,EAAE;AACd,UAAM,SAAS,oBAAI,IAAY,CAAC,KAAK,CAAC;AACtC,eAAS;AACP,YAAM,KAAK,QAAQ,IAAI,KAAK;AAC5B,UAAI,CAAC,MAAM,GAAG,WAAW,EAAG;AAC5B,YAAM,IAAI,GAAG,CAAC;AACd,UAAI,OAAO,IAAI,CAAC,EAAG;AACnB,WAAK,UAAU,IAAI,CAAC,KAAK,OAAO,EAAG;AACnC,WAAK,SAAS,IAAI,CAAC,KAAK,KAAK,EAAG;AAGhC,UAAI,KAAK,IAAI,CAAC,GAAG,aAAa,KAAK,IAAI,KAAK,GAAG,SAAU;AACzD,eAAS,IAAI,GAAG,OAAO,GAAG,QAAQ,KAAK,IAAI,MAAM,IAAI,CAAC,IAAK,CAAC,CAAC;AAC7D,aAAO,IAAI,CAAC;AACZ,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM,MAAM;AAAA,IAAI,CAAC,MAC7B,SAAS,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,IAC9B,IACA,EAAE,GAAG,GAAG,UAAU,EAAE,GAAG,SAAS,IAAI,EAAE,EAAE,GAAI,GAAG,EAAE,SAAS,EAAE,EAAE;AAAA,EACpE;AACA,SAAO,EAAE,OAAO,OAAO,MAAM,MAAM;AACrC;AAGO,SAAS,kBACd,MACA,UAAoC,CAAC,GACpB;AACjB,SAAO,CAAC,UAAsB,kBAAkB,KAAK,KAAK,GAAG,OAAO;AACtE;;;AC8FO,SAAS,aACd,SACA,OACqB;AACrB,QAAM,QAAQ,QAAQ;AACtB,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,MACL,cAAc,oBAAI,IAAI;AAAA,MACtB,eAAe;AAAA,MACf,kBAAkB,oBAAI,IAAI;AAAA,MAC1B,kBAAkB,CAAC;AAAA,MACnB,QAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AACA,QAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,MAAM,SAAS,CAAC,CAAC;AAClE,QAAM,eAAe,oBAAI,IAAY;AACrC,WAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACrC,iBAAa,IAAI,MAAM,CAAC,EAAG,OAAO;AAAA,EACpC;AACA,QAAM,aAAa,MAAM,YAAY;AACrC,QAAM,gBAAgB,aAAa,WAAW,UAAU;AACxD,QAAM,mBAAmB,IAAI,IAAI,YAAY;AAC7C,MAAI,cAAe,kBAAiB,IAAI,aAAa;AACrD,QAAM,mBAAmB,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO;AAC9E,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,QAAQ;AAAA,EAClB;AACF;;;AC9SA,IAAAC,iBAAwC;AACxC,IAAAA,iBAAiC;AA6FzB,IAAAC,uBAAA;AAzFR,IAAM,eAAe;AACrB,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6EtB,IAAM,YAAY;AAElB,SAAS,UAAU,EAAE,MAAM,MAAM,GAAoC;AACnE,QAAM,IAAI;AACV,QAAM,QAAQ,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,OAAO,CAAC,IAAI,CAAC,IAAI,MAAM,QAAQ,OAAO,EAAE,YAAY,EAAE,EAAW;AAE/G,UAAQ,MAAM;AAAA;AAAA,IAEZ,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,YAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,QAAQ,OAAO,aAAY,OAAM;AAAA,QAC7D,8CAAC,UAAK,GAAE,4CAA2C,QAAQ,OAAO,aAAY,OAAM,eAAc,SAAQ;AAAA,QAC1G,8CAAC,YAAO,IAAG,KAAI,IAAG,OAAM,GAAE,KAAI,MAAM,OAAO;AAAA,QAC3C,8CAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,OAAM,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ;AAAA,QACzF,8CAAC,UAAK,IAAG,QAAO,IAAG,KAAI,IAAG,QAAO,IAAG,KAAI,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ;AAAA,QAC7F,8CAAC,UAAK,IAAG,OAAM,IAAG,KAAI,IAAG,OAAM,IAAG,KAAI,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ;AAAA,SAC7F;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,YAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,QAAQ,OAAO,aAAY,OAAM;AAAA,QAC5D,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,KAAK,KAAK,GAAG,EAAE,IAAI,CAAC,UAAU;AACnD,gBAAM,MAAO,QAAQ,KAAK,KAAM;AAChC,gBAAM,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI;AAC/B,gBAAM,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI;AAC/B,gBAAM,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI;AAC/B,gBAAM,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI;AAC/B,iBAAO,8CAAC,UAAiB,IAAQ,IAAQ,IAAQ,IAAQ,QAAQ,OAAO,aAAY,OAAM,eAAc,WAAtF,KAA8F;AAAA,QAClH,CAAC;AAAA,SACH;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,YAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,QAAQ,OAAO,aAAY,OAAM;AAAA,QAC7D,8CAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,QAAO,IAAG,QAAO,QAAQ,OAAO,aAAY,OAAM,eAAc,SAAQ;AAAA,QACjG,8CAAC,UAAK,IAAG,OAAM,IAAG,KAAI,IAAG,OAAM,IAAG,KAAI,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ;AAAA,QAC3F,8CAAC,UAAK,IAAG,OAAM,IAAG,KAAI,IAAG,OAAM,IAAG,KAAI,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ;AAAA,SAC7F;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aACE,8CAAC,SAAK,GAAG,OACP,wDAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,KAAI,QAAO,KAAI,IAAG,OAAM,QAAQ,OAAO,aAAY,OAAM,WAAU,kBAAiB,GAC9G;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aACE,8CAAC,SAAK,GAAG,OACP,wDAAC,UAAK,GAAE,6BAA4B,MAAM,OAAO,SAAQ,OAAM,GACjE;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aACE,8CAAC,SAAK,GAAG,OACP,wDAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,KAAI,QAAO,KAAI,IAAG,OAAM,MAAM,OAAO,SAAQ,OAAM,GAC7E;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,YAAO,IAAG,KAAI,IAAG,KAAI,GAAE,OAAM,QAAQ,OAAO,aAAY,OAAM;AAAA,QAC/D,8CAAC,UAAK,GAAE,4CAA2C,QAAQ,OAAO,aAAY,OAAM,eAAc,SAAQ;AAAA,SAC5G;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,YAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,QAAQ,OAAO,aAAY,OAAM;AAAA,QAC7D,8CAAC,YAAO,IAAG,MAAK,IAAG,KAAI,GAAE,KAAI,QAAQ,OAAO,aAAY,OAAM;AAAA,QAC9D,8CAAC,YAAO,IAAG,KAAI,IAAG,MAAK,GAAE,KAAI,QAAQ,OAAO,aAAY,OAAM;AAAA,QAC9D,8CAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,QAAQ,OAAO,aAAY,KAAI,SAAQ,OAAM;AAAA,QAC/E,8CAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,QAAQ,OAAO,aAAY,KAAI,SAAQ,OAAM;AAAA,SAClF;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,UAAK,GAAE,+DAA8D,QAAQ,OAAO,aAAY,OAAM,gBAAe,SAAQ;AAAA,QAC9H,8CAAC,UAAK,GAAE,uBAAsB,QAAQ,OAAO,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ;AAAA,SAC9G;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,UAAK,GAAE,+BAA8B,QAAQ,OAAO,aAAY,OAAM,eAAc,SAAQ,MAAK,QAAO;AAAA,QACzG,8CAAC,UAAK,GAAE,kCAAiC,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ,MAAK,QAAO,SAAQ,OAAM;AAAA,SAC1H;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,aAAQ,IAAG,KAAI,IAAG,OAAM,IAAG,KAAI,IAAG,KAAI,QAAQ,OAAO,aAAY,OAAM;AAAA,QACxE,8CAAC,UAAK,IAAG,KAAI,IAAG,OAAM,IAAG,KAAI,IAAG,QAAO,QAAQ,OAAO,aAAY,OAAM;AAAA,QACxE,8CAAC,UAAK,IAAG,MAAK,IAAG,OAAM,IAAG,MAAK,IAAG,QAAO,QAAQ,OAAO,aAAY,OAAM;AAAA,QAC1E,8CAAC,aAAQ,IAAG,KAAI,IAAG,QAAO,IAAG,KAAI,IAAG,KAAI,QAAQ,OAAO,aAAY,OAAM;AAAA,SAC3E;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,UAAK,GAAE,OAAM,GAAE,KAAI,OAAM,KAAI,QAAO,MAAK,IAAG,OAAM,QAAQ,OAAO,aAAY,OAAM,MAAK,QAAO;AAAA,QAChG,8CAAC,UAAK,IAAG,OAAM,IAAG,KAAI,IAAG,QAAO,IAAG,KAAI,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ;AAAA,QAC5F,8CAAC,UAAK,IAAG,OAAM,IAAG,OAAM,IAAG,QAAO,IAAG,OAAM,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ;AAAA,QAChG,8CAAC,UAAK,IAAG,OAAM,IAAG,MAAK,IAAG,OAAM,IAAG,MAAK,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ;AAAA,SAC/F;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,UAAK,GAAE,OAAM,GAAE,KAAI,OAAM,MAAK,QAAO,KAAI,IAAG,KAAI,QAAQ,OAAO,aAAY,OAAM,MAAK,QAAO;AAAA,QAC9F,8CAAC,UAAK,GAAE,2BAA0B,QAAQ,OAAO,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,MAAK,QAAO;AAAA,QAC5H,8CAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,KAAI,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ;AAAA,QACxF,8CAAC,UAAK,IAAG,KAAI,IAAG,OAAM,IAAG,KAAI,IAAG,OAAM,QAAQ,OAAO,aAAY,KAAI,eAAc,SAAQ;AAAA,SAC7F;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,UAAK,GAAE,uBAAsB,QAAQ,OAAO,aAAY,OAAM,eAAc,SAAQ,MAAK,QAAO;AAAA,QACjG,8CAAC,UAAK,GAAE,uBAAsB,QAAQ,OAAO,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,MAAK,QAAO;AAAA,SAC1H;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aACE,8CAAC,SAAK,GAAG,OACP;AAAA,QAAC;AAAA;AAAA,UACC,GAAE;AAAA,UACF,QAAQ;AAAA,UACR,aAAY;AAAA,UACZ,eAAc;AAAA,UACd,MAAK;AAAA;AAAA,MACP,GACF;AAAA;AAAA,IAIJ,KAAK;AAAA,IACL,KAAK;AACH,aACE,+CAAC,SAAK,GAAG,OACP;AAAA,sDAAC,UAAK,GAAE,uBAAsB,QAAQ,OAAO,aAAY,OAAM,MAAK,QAAO;AAAA,QAC3E,8CAAC,YAAO,IAAG,KAAI,IAAG,KAAI,GAAE,OAAM,MAAM,OAAO;AAAA,SAC7C;AAAA,IAGJ;AACE,aAAO;AAAA,EACX;AACF;AAOO,IAAM,gBAAY,qBAAK,SAASC,WAAU;AAAA,EAC/C;AACF,GAAwC;AACtC,QAAM,EAAE,OAAO,QAAQ,MAAM,OAAO,QAAQ,MAAM,aAAa,QAAQ,WAAW,QAAQ,WAAW,QAAQ,aAAa,SAAS,YAAY,IAAI;AAGnJ,QAAM,gBAAgB,SAAS,SAAS,SAAS;AAEjD,QAAM,mBAAmB,UAAU,CAAC,QAAQ,CAAC;AAG7C,QAAM,kBAAc,uBAAO,KAAK;AAChC,gCAAU,MAAM;AACd,QAAI,YAAY,QAAS;AACzB,QAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,YAAY,GAAG;AAC7E,YAAM,UAAU,SAAS,cAAc,OAAO;AAC9C,cAAQ,KAAK;AACb,cAAQ,cAAc;AACtB,eAAS,KAAK,YAAY,OAAO;AAAA,IACnC;AACA,gBAAY,UAAU;AAAA,EACxB,GAAG,CAAC,CAAC;AAEL,QAAM,WAAW,UAAU;AAG3B,QAAM,SAAS,KAAK,aAAa;AACjC,QAAM,UAAU,KAAK,aAAa;AAElC,QAAM,YAAY,KAAK,SAAS,OAAO,MAAM,KAAK,SAAS,OAAO,OAAO;AAKzE,QAAM,YAAY,SACd,sBAAsB,MAAM,OAAO,SAAS,MAAM,WAAW,MAC7D,MAAM;AACV,QAAM,gBAAgB,SAAS,MAAM,UAAU,MAAM;AACrD,QAAM,gBAAgB,SAClB,+BAA+B,MAAM,OAAO,uBAC5C;AAEJ,QAAM,KAAK,SACP,MAAM,UACN,OACE,MAAM,UACN,QACE,MAAM,QACN;AAER,QAAM,cAAc,SAChB,MAAM,UACN,OACE,MAAM,UACN,QACE,MAAM,QACN;AAER,QAAM,SAAS,SACX,+BAA+B,MAAM,OAAO,uBAC5C,OACE,8BAA8B,MAAM,OAAO,uBAC3C,QACE,+BAA+B,MAAM,KAAK,uBAC1C;AAGR,QAAM,YACJ,UAAU,QAAQ,QAAQ,SAAS,MAAM;AAE3C,SACE,gFACE;AAAA,kDAAC,yBAAO,MAAK,UAAS,UAAU,wBAAS,KAAK,OAAO,EAAE,SAAS,EAAE,GAAG;AAAA,IAWrE,8CAAC,SAAI,OAAO,EAAE,OAAO,QAAQ,SAAS,QAAQ,gBAAgB,SAAS,GACrE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,KAAK;AAAA;AAAA;AAAA,UAGL,SAAS,UAAU,MAAM;AAAA,QAC3B;AAAA,QAGC;AAAA,yBAAe,YAAY,SAAS,KAAK,YACxC;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,KAAK;AAAA,gBACL,MAAM;AAAA,gBACN,SAAS;AAAA,gBACT,KAAK;AAAA,gBACL,QAAQ;AAAA,cACV;AAAA,cAEC,sBAAY,IAAI,CAAC,KAAK,MAAM;AAC3B,sBAAM,WAAW,MAAM,YAAY,SAAS;AAC5C,sBAAM,UAAU,YAAY,SAAS,MAAM,UAAU,MAAM;AAC3D,sBAAM,OAAO,YAAY,SACrB,sBAAsB,MAAM,OAAO,uBACnC,sBAAsB,MAAM,OAAO;AACvC,uBACE;AAAA,kBAAC;AAAA;AAAA,oBAEC,OAAO;AAAA,sBACL,OAAO;AAAA,sBACP,QAAQ;AAAA,sBACR,cAAc;AAAA,sBACd,YAAY;AAAA,sBACZ,OAAO;AAAA,sBACP,UAAU;AAAA,sBACV,YAAY;AAAA,sBACZ,SAAS;AAAA,sBACT,YAAY;AAAA,sBACZ,gBAAgB;AAAA,sBAChB,WAAW,WAAW,IAAI;AAAA,oBAC5B;AAAA,oBAEC;AAAA;AAAA,kBAfI;AAAA,gBAgBP;AAAA,cAEJ,CAAC;AAAA;AAAA,UACH;AAAA,UAID,UACC;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,OAAO;AAAA,gBACP,cAAc,YAAY,IAAI,QAAQ,MAAM,MAAM;AAAA,gBAClD,UAAU,YAAY,gDAAgD;AAAA,gBACtE,QAAQ,aAAa,MAAM,OAAO;AAAA,gBAClC,SAAS;AAAA,gBACT,WAAW;AAAA,cACb;AAAA;AAAA,UACF;AAAA,UAID,UACC;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,OAAO;AAAA,gBACP,cAAc,YAAY,IAAI,QAAQ,MAAM,MAAM;AAAA,gBAClD,UAAU,YAAY,gDAAgD;AAAA,gBACtE,QAAQ,aAAa,MAAM,OAAO;AAAA,gBAClC,SAAS;AAAA,gBACT,WAAW;AAAA,cACb;AAAA;AAAA,UACF;AAAA,UAMD,UACC;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,KAAK;AAAA,gBACL,OAAO;AAAA,gBACP,QAAQ;AAAA,gBACR,YAAY,MAAM;AAAA,gBAClB,OAAO;AAAA,gBACP,UAAU;AAAA,gBACV,YAAY;AAAA,gBACZ,eAAe;AAAA,gBACf,SAAS;AAAA,gBACT,cAAc;AAAA,gBACd,WAAW,+BAA+B,MAAM,OAAO;AAAA,cACzD;AAAA,cACD;AAAA;AAAA,UAED;AAAA,UAID,YACC,+CAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,KAAK,QAAQ,GAAG,GAEzD;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,OAAO;AAAA,kBACP,YAAY;AAAA,kBACZ,UAAU;AAAA,kBACV,QAAQ;AAAA,kBACR,WAAW;AAAA,kBACX,YAAY;AAAA,gBACd;AAAA;AAAA,YACF;AAAA,YAEA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,OAAO;AAAA,kBACP,UAAU;AAAA,kBACV,YAAY;AAAA,kBACZ,QAAQ;AAAA,kBACR,GAAI,mBAAmB;AAAA,oBACrB,YAAY;AAAA;AAAA,kBAEd,IAAI,CAAC;AAAA,gBACP;AAAA;AAAA,YACF;AAAA,YAEA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,OAAO;AAAA,kBACP,SAAS;AAAA,kBACT,eAAe;AAAA,kBACf,YAAY;AAAA,kBACZ,gBAAgB;AAAA,kBAChB,KAAK;AAAA,kBACL,YAAY,MAAM;AAAA,kBAClB,QAAQ;AAAA,gBACV;AAAA,gBAEA;AAAA,iEAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GACzD;AAAA,qCAAiB,8CAAC,aAAU,MAAM,eAAe,OAAO,WAAW;AAAA,oBACnE,CAAC,iBACA,8CAAC,UAAK,OAAO,EAAE,UAAU,GAAG,OAAO,UAAU,GAAG,oBAAQ;AAAA,oBAE1D;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,UAAU;AAAA,0BACV,YAAY;AAAA,0BACZ,OAAO;AAAA,0BACP,YAAY;AAAA,wBACd;AAAA,wBAEC;AAAA;AAAA,oBACH;AAAA,qBACF;AAAA,kBACC,eACC;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,UAAU;AAAA,wBACV,YAAY;AAAA,wBACZ,OAAO;AAAA,wBACP,SAAS;AAAA,wBACT,YAAY;AAAA,wBACZ,UAAU;AAAA,wBACV,cAAc;AAAA,wBACd,UAAU;AAAA,sBACZ;AAAA,sBAEC;AAAA;AAAA,kBACH;AAAA,kBAED,eAAe,WACd;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,UAAU;AAAA,wBACV,YAAY;AAAA,wBACZ,OAAO;AAAA,wBACP,SAAS;AAAA,wBACT,YAAY;AAAA,wBACZ,UAAU;AAAA,wBACV,cAAc;AAAA,wBACd,UAAU;AAAA,sBACZ;AAAA,sBACA,OAAO,YAAY,OAAO;AAAA,sBAEzB;AAAA;AAAA,kBACH;AAAA;AAAA;AAAA,YAEJ;AAAA,aACF;AAAA;AAAA,YAGA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,YAAY;AAAA,kBACZ,QAAQ,GAAG,SAAS,UAAU,UAAU,QAAQ,KAAK,IAAI,mBAAmB,WAAW,OAAO,IAAI,WAAW;AAAA,kBAC7G,cAAc,MAAM;AAAA,kBACpB,SAAS,cACL,GAAG,KAAK,MAAM,IAAI,SAAS,CAAC,MAAM,KAAK,MAAM,KAAK,SAAS,CAAC,OAC5D,GAAG,KAAK,MAAM,IAAI,SAAS,CAAC,MAAM,KAAK,MAAM,KAAK,SAAS,CAAC;AAAA,kBAChE,SAAS;AAAA,kBACT,eAAe;AAAA,kBACf,YAAY;AAAA,kBACZ,KAAK,cAAc,IAAI;AAAA,kBACvB,WAAW;AAAA,kBACX,YAAY;AAAA,kBACZ,YAAY,MAAM;AAAA,kBAClB,UAAU;AAAA,kBACV,gBAAgB;AAAA,gBAClB;AAAA,gBAEA;AAAA,iEAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GAEzD;AAAA,qCAAiB,8CAAC,aAAU,MAAM,eAAe,OAAO,WAAW;AAAA,oBAGnE,QAAQ,CAAC,iBACR,8CAAC,UAAK,OAAO,EAAE,UAAU,IAAI,OAAO,UAAU,GAAG,oBAAQ;AAAA,oBAE1D,UAAU,CAAC,iBACV;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,OAAO;AAAA,0BACP,QAAQ;AAAA,0BACR,cAAc;AAAA,0BACd,YAAY;AAAA,0BACZ,WAAW;AAAA,0BACX,YAAY;AAAA,wBACd;AAAA;AAAA,oBACF;AAAA,oBAED,SAAS,CAAC,iBACT,8CAAC,UAAK,OAAO,EAAE,UAAU,IAAI,OAAO,UAAU,GAAG,oBAAQ;AAAA,oBAG3D;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,UAAU,KAAK,MAAM,KAAK,SAAS;AAAA,0BACnC,YAAY,SAAS,MAAM;AAAA,0BAC3B,OAAO;AAAA,0BACP,YAAY;AAAA,wBACd;AAAA,wBAEC;AAAA;AAAA,oBACH;AAAA,oBAEC,aACC;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,0BACL,SAAS;AAAA,0BACT,YAAY;AAAA,0BACZ,gBAAgB;AAAA,0BAChB,OAAO;AAAA,0BACP,QAAQ;AAAA,0BACR,cAAc;AAAA,0BACd,QAAQ,eAAe,SAAS;AAAA,0BAChC,UAAU;AAAA,0BACV,SAAS;AAAA,0BACT,YAAY;AAAA,wBACd;AAAA,wBAEA;AAAA,0BAAC;AAAA;AAAA,4BACC,OAAO;AAAA,8BACL,OAAO;AAAA,8BACP,QAAQ;AAAA,8BACR,cAAc;AAAA,8BACd,QAAQ,aAAa,SAAS;AAAA,4BAChC;AAAA;AAAA,wBACF;AAAA;AAAA,oBACF;AAAA,qBAEJ;AAAA,kBAEC,eACC;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,UAAU;AAAA,wBACV,YAAY;AAAA,wBACZ,OAAO;AAAA,wBACP,SAAS;AAAA,wBACT,YAAY;AAAA,wBACZ,UAAU;AAAA,wBACV,cAAc;AAAA,wBACd,UAAU;AAAA,sBACZ;AAAA,sBAEC;AAAA;AAAA,kBACH;AAAA,kBAMD,eAAe,WACd;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,UAAU;AAAA,wBACV,YAAY;AAAA,wBACZ,OAAO;AAAA,wBACP,SAAS;AAAA,wBACT,YAAY;AAAA,wBACZ,UAAU;AAAA,wBACV,cAAc;AAAA,wBACd,UAAU;AAAA,sBACZ;AAAA,sBACA,OAAO,YAAY,OAAO;AAAA,sBAEzB;AAAA;AAAA,kBACH;AAAA;AAAA;AAAA,YAEJ;AAAA;AAAA;AAAA;AAAA,IAEJ,GACF;AAAA,IACA,8CAAC,yBAAO,MAAK,UAAS,UAAU,wBAAS,QAAQ,OAAO,EAAE,SAAS,EAAE,GAAG;AAAA,KAC1E;AAEJ,CAAC;;;ACxqBM,SAAS,oBACd,OACA,kBACY;AACZ,MAAI,MAAM,MAAM,WAAW,EAAG,QAAO;AACrC,QAAM,eAAe,CAAC,cACpB,qBAAqB,OAAO,cAAc,SAAY,cAAc;AACtE,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,KAAK,MAAM,OAAO;AAC3B,QAAI,aAAa,EAAE,MAAM,SAAS,EAAG,YAAW,IAAI,EAAE,EAAE;AAAA,EAC1D;AACA,MAAI,WAAW,SAAS,MAAM,MAAM,OAAQ,QAAO;AACnD,SAAO;AAAA,IACL,OAAO,MAAM,MAAM,OAAO,CAAC,MAAM,WAAW,IAAI,EAAE,EAAE,CAAC;AAAA,IACrD,OAAO,MAAM,MAAM,OAAO,CAAC,MAAM,WAAW,IAAI,EAAE,MAAM,KAAK,WAAW,IAAI,EAAE,MAAM,CAAC;AAAA,EACvF;AACF;AAkBO,SAAS,uBACd,OACA,kBACmB;AACnB,QAAM,MAAyB,CAAC,EAAE,WAAW,MAAM,OAAO,QAAQ,CAAC;AACnE,MAAI,qBAAqB,MAAM;AAC7B,UAAM,QAAQ,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,cAAc,gBAAgB;AAC5E,QAAI,KAAK;AAAA,MACP,WAAW;AAAA,MACX,OAAO,OAAO,MAAM,SAAS;AAAA,IAC/B,CAAC;AAAA,EACH;AACA,SAAO;AACT;;;AC/BO,SAAS,qBACd,OACA,OACA,kBACc;AACd,MAAI,MAAM,MAAM,WAAW,EAAG,QAAO;AACrC,QAAM,SAAS,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,aAAa,EAAE,MAAM,SAAS;AAC/E,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,UAAU,IAAI,IAAI,MAAM,YAAY;AAC1C,MAAI,WAAW,MAAM;AACrB,aAAW,SAAS,QAAQ;AAC1B,UAAM,OAAO,MAAM,KAAM;AACzB,UAAM,UAAU,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,cAAc,IAAI;AACpE,QAAI,QAAQ,WAAW,EAAG;AAC1B,UAAM,YAAY,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,aAAa;AAClE,UAAM,UAAU,QAAQ,MAAM,CAAC,MAAM,MAAM,aAAa,IAAI,EAAE,EAAE,CAAC;AACjE,QAAI,QAAS,SAAQ,IAAI,MAAM,EAAE;AAAA,aAQxB,aAAa,qBAAqB,MAAM;AAC/C,iBAAW,MAAM;AAAA,IACnB;AAAA,EACF;AACA,SAAO,EAAE,GAAG,OAAO,cAAc,SAAS,eAAe,SAAS;AACpE;;;ACzDA,IAAAC,iBAAyD;AAclD,SAAS,gBACd,OACA,iBACoB;AACpB,QAAM,CAAC,kBAAkB,mBAAmB,QAAI,yBAAwB,IAAI;AAY5E,QAAM,mBAAe,uBAA0B,IAAI;AACnD,MAAI,aAAa,YAAY,OAAO;AAClC,iBAAa,UAAU;AACvB,QACE,qBAAqB,QACrB,CAAC,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,cAAc,gBAAgB,GAC/D;AAEA,qBAAe,MAAM,oBAAoB,IAAI,CAAC;AAAA,IAChD;AAAA,EACF;AAIA,QAAM,sBAAkB,uBAAkC,MAAS;AACnE,gCAAU,MAAM;AACd,QAAI,gBAAgB,YAAY,iBAAkB;AAClD,oBAAgB,UAAU;AAC1B,QAAI,qBAAqB,MAAM;AAC7B,wBAAkB,IAAI;AAAA,IACxB,OAAO;AACL,YAAM,QAAQ,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,cAAc,gBAAgB;AAC5E,UAAI,MAAO,mBAAkB,MAAM,EAAE;AAAA,IACvC;AAAA,EACF,GAAG,CAAC,kBAAkB,OAAO,eAAe,CAAC;AAE7C,QAAM,gBAAY,4BAAY,CAAC,cAAsB;AACnD,wBAAoB,SAAS;AAAA,EAC/B,GAAG,CAAC,CAAC;AACL,QAAM,cAAU,4BAAY,MAAM;AAChC,wBAAoB,IAAI;AAAA,EAC1B,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,kBAAkB,WAAW,SAAS,oBAAoB;AACrE;;;ACtDA,IAAAC,iBAA0B;AAInB,SAAS,kBACd,YACA,YACA,UAAuE,CAAC,GAClE;AACN,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAMC,WAAU,QAAQ,WAAW;AACnC,QAAM,WAAW,QAAQ;AAEzB,gCAAU,MAAM;AACd,UAAM,KAAK,WAAW;AACtB,QAAI,CAAC,MAAM,CAAC,WAAY;AACxB,QAAI,MAAM;AACV,UAAM,QAAQ,MAAM;AAClB,2BAAqB,GAAG;AACxB,YAAM,sBAAsB,MAAM;AAChC,mBAAW,QAAQ,EAAE,UAAU,SAAAA,SAAQ,CAAC;AAAA,MAC1C,CAAC;AAAA,IACH;AACA,UAAM,KAAK,IAAI,eAAe,KAAK;AACnC,OAAG,QAAQ,EAAE;AACb,WAAO,iBAAiB,UAAU,KAAK;AACvC,WAAO,MAAM;AACX,SAAG,WAAW;AACd,aAAO,oBAAoB,UAAU,KAAK;AAC1C,2BAAqB,GAAG;AAAA,IAC1B;AAAA,EACF,GAAG,CAAC,YAAY,YAAY,UAAUA,QAAO,CAAC;AAM9C,gCAAU,MAAM;AACd,QAAI,CAAC,WAAY;AACjB,QAAI,OAAO;AACX,UAAM,OAAO,sBAAsB,MAAM;AACvC,aAAO,sBAAsB,MAAM;AACjC,mBAAW,QAAQ,EAAE,UAAU,SAAAA,SAAQ,CAAC;AAAA,MAC1C,CAAC;AAAA,IACH,CAAC;AACD,WAAO,MAAM;AACX,2BAAqB,IAAI;AACzB,2BAAqB,IAAI;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,YAAY,UAAU,UAAUA,QAAO,CAAC;AAC9C;;;ACnCU,IAAAC,uBAAA;AAlBH,SAAS,qBAAqB,EAAE,SAAS,WAAW,GAA8B;AACvF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,SAAS;AAAA,QACT,UAAU;AAAA,QACV,YAAY,YAAY,OAAO;AAAA,QAC/B,cAAc,aAAa,YAAY,OAAO,MAAM;AAAA,QACpD,YAAY;AAAA,MACd;AAAA,MACA,cAAW;AAAA,MAEV,kBAAQ,IAAI,CAAC,OAAO,MAAM;AACzB,cAAM,SAAS,MAAM,QAAQ,SAAS;AACtC,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,OAAO,EAAE,SAAS,eAAe,YAAY,UAAU,KAAK,EAAE;AAAA,YAE9D;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS,MAAM,WAAW,MAAM,SAAS;AAAA,kBACzC,UAAU;AAAA,kBACV,OAAO;AAAA,oBACL,YAAY;AAAA,oBACZ,QAAQ;AAAA,oBACR,SAAS;AAAA,oBACT,UAAU;AAAA,oBACV,YAAY,SAAS,MAAM;AAAA,oBAC3B,OAAO,SAAS,YAAY,OAAO,cAAc,YAAY,OAAO;AAAA,oBACpE,QAAQ,SAAS,YAAY;AAAA,oBAC7B,gBAAgB,SAAS,SAAS;AAAA,oBAClC,YAAY;AAAA,kBACd;AAAA,kBAEC,gBAAM;AAAA;AAAA,cACT;AAAA,cACC,CAAC,UAAU,8CAAC,UAAK,OAAO,EAAE,OAAO,YAAY,OAAO,UAAU,GAAG,oBAAC;AAAA;AAAA;AAAA,UArB9D,MAAM,aAAa;AAAA,QAsB1B;AAAA,MAEJ,CAAC;AAAA;AAAA,EACH;AAEJ;;;ACnDA,IAAAC,iBAAiC;AA2C3B,IAAAC,uBAAA;AAvCN,IAAM,IAAI,YAAY;AAcf,SAAS,mBAAmB,EAAE,KAAK,GAAc;AACtD,QAAM,IAAI;AACV,QAAM,cAAc,EAAE,QAClB,EAAE,QACF,EAAE,SACA,EAAE,UACF,EAAE,OACA,EAAE,UACF,EAAE;AAEV,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,QAAQ,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,UAAU,QAAQ,IAAI,WAAW;AAAA,QAClF,cAAc;AAAA;AAAA,QAEd,YAAY;AAAA,QACZ,SAAS,EAAE,SAAS,MAAM;AAAA,QAC1B,UAAU;AAAA,MACZ;AAAA,MAGA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,KAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,OAAO,EAAE;AAAA,cACT,eAAe;AAAA,YACjB;AAAA,YAEC;AAAA,gBAAE,OAAO,8CAAC,UAAK,eAAW,MAAE,YAAE,MAAK,IAAU;AAAA,cAC9C,8CAAC,UAAM,YAAE,OAAM;AAAA;AAAA;AAAA,QACjB;AAAA,QAGA,8CAAC,yBAAO,MAAK,UAAS,UAAU,wBAAS,KAAK,OAAO,EAAE,SAAS,EAAE,GAAG;AAAA,QACrE,8CAAC,yBAAO,MAAK,UAAS,UAAU,wBAAS,QAAQ,OAAO,EAAE,SAAS,EAAE,GAAG;AAAA;AAAA;AAAA,EAC1E;AAEJ;;;AC7DA,IAAAC,iBAAmC;;;ACI5B,IAAM,gBAAgB;AAiBtB,SAAS,UAAU,eAAkC,MAAc,eAAuB;AAG/F,MAAI,MAAM;AACV,aAAW,KAAK,cAAe,KAAI,IAAI,IAAK,OAAM;AAClD,MAAI,CAAC,OAAO,SAAS,GAAG,EAAG,OAAM;AACjC,SAAO,MAAM;AACf;AAcO,SAAS,aACd,QACA,QACA,OACA,SAAS,IACD;AACR,QAAM,EAAE,OAAO,IAAI,SAAS,GAAG,IAAI;AACnC,QAAM,EAAE,OAAO,IAAI,SAAS,GAAG,IAAI;AAGnC,QAAM,IAAI,KAAK;AAAA,IACb;AAAA,IACA,KAAK,IAAI,QAAQ,KAAK,IAAI,KAAK,EAAE,IAAI,GAAG,QAAQ,IAAI,QAAQ,EAAE;AAAA,EAChE;AACA,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,KAAK,KAAK,IAAI,KAAK;AAC/B,QAAM,MAAM,KAAK,KAAK,IAAI,KAAK;AAE/B,SAAO;AAAA,IACL,KAAK,EAAE,IAAI,EAAE;AAAA,IACb,KAAK,QAAQ,CAAC,IAAI,EAAE;AAAA,IACpB,KAAK,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG;AAAA,IAChC,KAAK,KAAK,IAAI,GAAG;AAAA,IACjB,KAAK,KAAK,IAAI,EAAE,IAAI,QAAQ,CAAC,IAAI,EAAE;AAAA,IACnC,KAAK,EAAE,IAAI,EAAE;AAAA,EACf,EAAE,KAAK,GAAG;AACZ;;;ACvCO,IAAM,4BAA4B;AAiBzC,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AACvB,IAAMC,kBAAiB;AACvB,IAAMC,kBAAiB;AAevB,SAAS,YACP,MACA,WACA,WACmC;AACnC,QAAM,QAAS,KAAK,SAAS,CAAC;AAC9B,QAAM,IAAI,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAC1D,QAAM,IAAI,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;AAC5D,SAAO,EAAE,OAAO,GAAG,QAAQ,EAAE;AAC/B;AASO,SAAS,iBAAiB,OAAmB,MAAsC;AACxF,QAAMC,WAAU,KAAK,WAAW;AAChC,QAAM,eAAe,KAAK,gBAAgB;AAC1C,QAAM,QAAQ,KAAK,aAAaF;AAChC,QAAM,QAAQ,KAAK,cAAcC;AACjC,QAAM,aAAa,KAAK;AAIxB,QAAM,YAAY,IAAI,IAAI,KAAK,iBAAiB;AAChD,QAAM,mBAAmB,oBAAI,IAAyB;AACtD,aAAW,KAAK,MAAM,OAAO;AAC3B,UAAM,KAAK,EAAE,MAAM;AACnB,QAAI,OAAO,UAAa,UAAU,IAAI,EAAE,GAAG;AACzC,YAAM,MAAM,iBAAiB,IAAI,EAAE,KAAK,CAAC;AACzC,UAAI,KAAK,CAAC;AACV,uBAAiB,IAAI,IAAI,GAAG;AAAA,IAC9B;AAAA,EACF;AACA,QAAM,iBAAiB,oBAAI,IAAuB;AAClD,aAAW,KAAK,MAAM,OAAO;AAC3B,UAAM,OAAO,EAAE,MAAM;AACrB,QAAI,EAAE,MAAM,aAAa,SAAS,UAAa,UAAU,IAAI,IAAI,KAAK,iBAAiB,IAAI,IAAI,GAAG;AAChG,qBAAe,IAAI,MAAM,CAAC;AAAA,IAC5B;AAAA,EACF;AAEA,QAAM,eAAe,oBAAI,IAAY;AACrC,aAAW,QAAQ,eAAe,KAAK,EAAG,cAAa,IAAI,IAAI;AAG/D,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO;AAAA,EACT;AAGA,QAAM,YAAY,oBAAI,IAAY;AAClC,aAAW,QAAQ,cAAc;AAC/B,eAAW,KAAK,iBAAiB,IAAI,IAAI,KAAK,CAAC,EAAG,WAAU,IAAI,EAAE,EAAE;AAAA,EACtE;AAQA,QAAM,iBAA8B,CAAC;AACrC,QAAM,gBAA6B,CAAC;AAEpC,QAAM,WAAW,oBAAI,IAGnB;AAEF,aAAW,QAAQ,cAAc;AAC/B,UAAM,UAAU,iBAAiB,IAAI,IAAI;AACzC,UAAM,iBAAiB,MAAM,MAAM,OAAO,CAAC,MAAM;AAC/C,YAAM,IAAI,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM;AAC/C,YAAM,IAAI,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM;AAC/C,aAAO,KAAK;AAAA,IACd,CAAC;AACD,UAAM,kBAAkB,WAAW,EAAE,OAAO,SAAS,OAAO,eAAe,CAAC;AAM5E,QAAI,OAAO;AACX,QAAI,OAAO;AACX,QAAI,OAAO;AACX,QAAI,OAAO;AACX,eAAW,KAAK,gBAAgB,OAAO;AACrC,YAAM,IAAI,EAAE;AACZ,YAAM,EAAE,OAAO,OAAO,IAAI,YAAY,GAAG,OAAO,KAAK;AACrD,UAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,UAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,UAAI,EAAE,IAAI,QAAQ,KAAM,QAAO,EAAE,IAAI;AACrC,UAAI,EAAE,IAAI,SAAS,KAAM,QAAO,EAAE,IAAI;AAAA,IACxC;AACA,QAAI,CAAC,OAAO,SAAS,IAAI,GAAG;AAC1B,aAAO;AACP,aAAO;AACP,aAAO;AACP,aAAO;AAAA,IACT;AAIA,UAAM,WAAW,OAAO,OAAOC,WAAU;AACzC,UAAM,YAAY,OAAO,OAAO,eAAeA,WAAU;AACzD,aAAS,IAAI,MAAM,EAAE,OAAO,UAAU,QAAQ,WAAW,MAAM,MAAM,SAAS,gBAAgB,MAAM,CAAC;AAAA,EACvG;AAKA,QAAM,aAAa,MAAM,MACtB,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC,EAClC,IAAI,CAAC,MAAM;AACV,UAAM,MAAM,EAAE,MAAM,YAAY,SAAS,IAAI,EAAE,KAAK,SAAS,IAAI;AAUjE,WAAO,MACH;AAAA,MACE,GAAG;AAAA,MACH,OAAO,EAAE,GAAI,EAAE,SAAS,CAAC,GAAI,OAAO,IAAI,OAAO,QAAQ,IAAI,OAAO;AAAA,MAClE,MAAM,EAAE,GAAG,EAAE,MAAM,kBAAkB,KAAK;AAAA,IAC5C,IACA;AAAA,EACN,CAAC;AACH,QAAM,aAAa,MAAM,MAAM;AAAA,IAC7B,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,MAAM,KAAK,CAAC,UAAU,IAAI,EAAE,MAAM;AAAA,EAC5D;AACA,QAAM,kBAAkB,WAAW,EAAE,OAAO,YAAY,OAAO,WAAW,CAAC;AAC3E,QAAM,eAAe,IAAI,IAAI,gBAAgB,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AAGjF,aAAW,QAAQ,cAAc;AAC/B,UAAM,QAAQ,eAAe,IAAI,IAAI;AACrC,UAAM,MAAM,SAAS,IAAI,IAAI;AAC7B,UAAM,EAAE,OAAO,UAAU,QAAQ,WAAW,MAAM,KAAK,IAAI;AAG3D,UAAM,WAAW,aAAa,IAAI,MAAM,EAAE,KAAK,MAAM,YAAY,EAAE,GAAG,GAAG,GAAG,EAAE;AAC9E,mBAAe,KAAK;AAAA,MAClB,GAAG;AAAA,MACH,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO,EAAE,GAAI,MAAM,SAAS,CAAC,GAAI,OAAO,UAAU,QAAQ,UAAU;AAAA,MACpE,MAAM,EAAE,GAAG,MAAM,MAAM,kBAAkB,KAAK;AAAA,IAChD,CAAC;AAID,eAAW,KAAK,IAAI,SAAS;AAC3B,YAAM,OAAO,EAAE,SAAS,IAAI,OAAOA;AACnC,YAAM,OAAO,EAAE,SAAS,IAAI,OAAO,eAAeA;AAClD,oBAAc,KAAK;AAAA,QACjB,GAAI;AAAA,QACJ,UAAU,MAAM;AAAA,QAChB,QAAQ;AAAA,QACR,UAAU,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,EACF;AAIA,QAAM,gBAAgB,IAAI,IAAI,eAAe,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAClE,QAAM,WAAwB,gBAAgB,MAAM;AAAA,IAClD,CAAC,MAAM,cAAc,IAAI,EAAE,EAAE,KAAK;AAAA,EACpC;AAEA,SAAO;AAAA,IACL,OAAO,CAAC,GAAG,UAAU,GAAG,aAAa;AAAA,IACrC,OAAO,MAAM;AAAA,EACf;AACF;AA2BO,IAAM,oBAAoB;AAsB1B,SAAS,mBAAmB,OAAmB,MAAuC;AAC3F,MAAI,MAAM,MAAM,WAAW,EAAG,QAAO;AAErC,QAAMC,WAAU,KAAK,WAAW;AAChC,QAAM,eAAe,KAAK,gBAAgB;AAC1C,QAAM,QAAQ,KAAK,aAAaC;AAChC,QAAM,QAAQ,KAAK,cAAcC;AACjC,QAAM,SAAS,KAAK,MAAM;AAE1B,QAAM,aAAa,KAAK,WAAW,KAAK;AAMxC,QAAM,WAAW,WAAW,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,MAAS;AAQxE,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,aAAW,KAAK,UAAU;AACxB,UAAM,IAAI,EAAE;AACZ,UAAM,EAAE,OAAO,OAAO,IAAI,YAAY,GAAG,OAAO,KAAK;AACrD,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,QAAQ,KAAM,QAAO,EAAE,IAAI;AACrC,QAAI,EAAE,IAAI,SAAS,KAAM,QAAO,EAAE,IAAI;AAAA,EACxC;AACA,MAAI,CAAC,OAAO,SAAS,IAAI,GAAG;AAC1B,WAAO;AACP,WAAO;AACP,WAAO;AACP,WAAO;AAAA,EACT;AAOA,QAAM,cAAc,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,SAAS,MAAM;AACnE,QAAM,cAAc,cAAc,gBAAgB;AAClD,QAAM,WAAW,OAAO,OAAOF,WAAU,IAAI;AAC7C,QAAM,YAAY,OAAO,OAAO,eAAeA,WAAU;AAEzD,QAAM,YAAuB;AAAA,IAC3B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,UAAU,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACvB,OAAO,EAAE,OAAO,UAAU,QAAQ,UAAU;AAAA,IAC5C,MAAM;AAAA,MACJ,OAAO,KAAK,SAAS;AAAA,MACrB,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,WAAW;AAAA,MACX,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,GAAI,KAAK,SAAS,UAAa,EAAE,MAAM,KAAK,KAAK;AAAA,MACjD,SAAS,CAAC;AAAA,MACV,SAAS,CAAC;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,cAAc,IAAI,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACrD,QAAM,aAA0B,WAAW,MAAM,IAAI,CAAC,MAAM;AAC1D,QAAI,CAAC,YAAY,IAAI,EAAE,EAAE,EAAG,QAAO;AACnC,WAAO;AAAA,MACL,GAAG;AAAA,MACH,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,UAAU;AAAA,QACR,GAAG,EAAE,SAAS,IAAI,OAAOA;AAAA,QACzB,GAAG,EAAE,SAAS,IAAI,OAAO,eAAeA;AAAA,MAC1C;AAAA,IACF;AAAA,EACF,CAAC;AAGD,SAAO,EAAE,OAAO,CAAC,WAAW,GAAG,UAAU,GAAG,OAAO,MAAM,MAAM;AACjE;;;AFlTI,IAAAG,uBAAA;AAjEJ,IAAM,YAAY;AAClB,IAAM,0BAA0B;AAChC,IAAM,oBAAoB;AACnB,SAAS,gBAAgB,OAAiD;AAK/E,QAAM,sBACJ,OAAO,OAAO,kBAAkB,WAAW,MAAM,gBAAgB;AACnE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,iBAAiB,OAAO,mBAAmB;AAAA,IAC3C,eAAe,KAAK,IAAI,qBAAqB,uBAAuB;AAAA,IACpE,aAAa;AAAA,EACf;AACF;AAIA,IAAM,qBAAqB;AAG3B,SAAS,UAAU,MAA4B;AAC7C,SAAO,KAAK,UAAU,iBAAiB,KAAK,KAAK,SAAS,SAAS;AACrE;AAGA,SAAS,QAAQ,MAA4B;AAC3C,SAAO,KAAK,UAAU,iBAAiB,KAAK,KAAK,SAAS,UAAU,KAAK;AAC3E;AAEO,SAAS,aAAa,EAAE,IAAI,QAAQ,QAAQ,WAAW,MAAM,GAAc;AAIhF,QAAM,WAAO,yBAAS,CAAC,MAAsB;AAC3C,UAAM,MAAM,EAAE,WAAW,IAAI,MAAM;AACnC,UAAM,MAAM,EAAE,WAAW,IAAI,MAAM;AACnC,QAAI,CAAC,OAAO,CAAC,IAAK,QAAO;AAKzB,UAAM,gBAA0B,CAAC;AACjC,eAAW,KAAK,EAAE,WAAW,OAAO,GAAG;AACrC,UAAI,EAAE,SAAS,0BAA2B;AAC1C,oBAAc,KAAK,UAAU,CAAC,CAAC;AAAA,IACjC;AAKA,UAAM,QAAQ,UAAU,CAAC,GAAG,eAAe,UAAU,GAAG,GAAG,UAAU,GAAG,CAAC,GAAG,aAAa;AAEzF,WAAO;AAAA,MACL,EAAE,OAAO,UAAU,GAAG,GAAG,SAAS,QAAQ,GAAG,EAAE;AAAA,MAC/C,EAAE,OAAO,UAAU,GAAG,GAAG,SAAS,QAAQ,GAAG,EAAE;AAAA,MAC/C;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,CAAC,KAAM,QAAO;AAClB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,gBAAgB,KAAK;AAAA,MAC5B,cAAW;AAAA;AAAA,EACb;AAEJ;;;AGrFA,IAAAC,iBAAsD;AAEtD,IAAAA,iBAAyB;;;ACiBlB,SAAS,eACd,cACA,WACA,QACA,mBAAmB,GACJ;AACf,MAAI,sBAAsB;AAC1B,aAAW,KAAK,QAAQ;AACtB,UAAM,MAAM,EAAE,MAAM,EAAE,UAAU;AAChC,QAAI,KAAK,gBAAgB,KAAK,aAAa,EAAE,SAAS,qBAAqB;AACzE,4BAAsB,EAAE;AAAA,IAC1B;AAAA,EACF;AACA,MAAI,wBAAwB,UAAW,QAAO;AAC9C,SAAO,KAAK,KAAK,sBAAsB,aAAa,GAAG,YAAY,gBAAgB;AACrF;AAcO,SAAS,aACd,cACA,WACA,mBAAmB,GACJ;AACf,MAAI,UAAU,SAAS,EAAG,QAAO;AACjC,QAAM,aAAa,KAAK,IAAI,GAAG,SAAS;AAExC,SAAO,KAAK,KAAK,eAAe,cAAc,GAAG,aAAa,gBAAgB;AAChF;AAUO,SAAS,iBACd,UACA,eACe;AACf,SAAO,iBAAiB;AAC1B;;;ADKS,IAAAC,uBAAA;AAjEF,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAc;AAIZ,QAAM,YAAQ,yBAAS,CAAC,MAAsB;AAC5C,UAAM,MAAM,EAAE,WAAW,IAAI,MAAM;AACnC,UAAM,MAAM,EAAE,WAAW,IAAI,MAAM;AACnC,QAAI,CAAC,OAAO,CAAC,IAAK,QAAO;AACzB,UAAM,eAAe,IAAI,UAAU,iBAAiB,KAAK,IAAI,SAAS,UAAU;AAChF,UAAM,YAAY,IAAI,UAAU,iBAAiB;AAMjD,UAAM,YAAsB,CAAC;AAC7B,eAAW,KAAK,EAAE,OAAO;AACvB,UAAI,EAAE,WAAW,OAAQ;AACzB,UAAK,EAAE,MAAoC,SAAS,OAAQ;AAC5D,YAAM,IAAI,EAAE,WAAW,IAAI,EAAE,MAAM;AACnC,UAAI,KAAK,EAAE,SAAS,2BAA2B;AAC7C,kBAAU,KAAK,EAAE,UAAU,iBAAiB,CAAC;AAAA,MAC/C;AAAA,IACF;AACA,UAAM,MAAM,aAAa,cAAc,SAAS;AAGhD,UAAM,SAA2B,CAAC;AAClC,eAAW,KAAK,EAAE,WAAW,OAAO,GAAG;AACrC,UAAI,EAAE,OAAO,UAAU,EAAE,OAAO,OAAQ;AACxC,UAAI,EAAE,SAAS,0BAA2B;AAC1C,YAAM,MAAM,EAAE,UAAU,iBAAiB;AACzC,aAAO,KAAK,EAAE,KAAK,QAAQ,OAAO,EAAE,SAAS,UAAU,GAAG,CAAC;AAAA,IAC7D;AACA,UAAM,YAAY,eAAe,cAAc,WAAW,MAAM;AAIhE,WAAO,iBAAiB,KAAK,SAAS;AAAA,EACxC,CAAC;AAED,QAAM,CAAC,IAAI,QAAI,kCAAkB;AAAA,IAC/B;AAAA,IACA;AAAA,IACA,gBAAgB,kBAAkB,wBAAS;AAAA,IAC3C;AAAA,IACA;AAAA,IACA,gBAAgB,kBAAkB,wBAAS;AAAA;AAAA;AAAA,IAG3C,GAAI,UAAU,OAAO,EAAE,SAAS,MAAM,IAAI,CAAC;AAAA,EAC7C,CAAC;AAED,SAAO,8CAAC,2BAAS,IAAQ,MAAY,WAAsB,OAAc;AAC3E;;;AEjGA,IAAAC,iBAA0B;AAC1B,IAAAA,iBAA8C;;;ACsCvC,SAAS,0BACd,SAC4B;AAC5B,QAAM,QAAQ,oBAAI,IAA2B;AAC7C,aAAW,CAAC,IAAI,IAAI,KAAK,SAAS;AAChC,UAAM,QAAQ,KAAK,UAAU;AAC7B,UAAM,SAAS,KAAK,UAAU;AAC9B,QAAI,OAAO,UAAU,YAAY,OAAO,WAAW,YAAY,QAAQ,KAAK,SAAS,GAAG;AACtF,YAAM,IAAI,IAAI,EAAE,OAAO,KAAK,MAAM,KAAK,GAAG,QAAQ,KAAK,MAAM,MAAM,EAAE,CAAC;AAAA,IACxE;AAAA,EACF;AACA,SAAO;AACT;AAWO,SAAS,eACd,GACA,GACS;AACT,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,aAAW,CAAC,IAAI,CAAC,KAAK,GAAG;AACvB,UAAM,IAAI,EAAE,IAAI,EAAE;AAClB,QAAI,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,OAAQ,QAAO;AAAA,EACjE;AACA,SAAO;AACT;;;AD3BO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,qBAAqB;AACvB,GAAiC;AAC/B,QAAM,kBAAc,oCAAoB,EAAE,mBAAmB,CAAC;AAI9D,QAAM,YAAQ;AAAA,IACZ,CAAC,MAAsB,0BAA0B,EAAE,UAAU;AAAA,IAC7D;AAAA,EACF;AAEA,gCAAU,MAAM;AAId,QAAI,CAAC,eAAe,MAAM,SAAS,EAAG;AACtC,YAAQ,KAAK;AAAA,EACf,GAAG,CAAC,aAAa,OAAO,OAAO,CAAC;AAEhC,SAAO;AACT;;;AjB+eQ,IAAAC,uBAAA;AA7dR,IAAM,iBAAmC;AAAA,EACvC,SAAS,YAAY,OAAO;AAAA,EAC5B,MAAM,YAAY,OAAO;AAAA,EACzB,QAAQ,YAAY,OAAO;AAAA,EAC3B,OAAO,YAAY,OAAO;AAAA,EAC1B,MAAM,YAAY,OAAO;AAC3B;AAcA,IAAM,YAAiC,oBAAI,IAAY;AAEvD,SAAS,oBACP,MACA,cACA,eACA,cACA,kBACA,kBAQA;AACA,QAAM,SAAS,aAAa,IAAI,KAAK,EAAE;AAKvC,QAAM,WAAW,kBAAkB,KAAK,MAAM,iBAAiB,IAAI,KAAK,EAAE;AAC1E,QAAM,cAAc,UAAU;AAC9B,QAAM,WAAW,CAAC,CAAC;AACnB,QAAM,SAAS,CAAC,eAAe,iBAAiB,SAAS;AAGzD,MAAI;AACJ,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,OAAiB,CAAC;AACxB,aAAS,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;AAChD,UAAI,iBAAiB,CAAC,MAAM,KAAK,GAAI,MAAK,KAAK,IAAI,CAAC;AAAA,IACtD;AACA,QAAI,KAAK,SAAS,EAAG,eAAc;AAAA,EACrC;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,IACP;AAAA,IACA,GAAI,gBAAgB,EAAE,aAAa;AAAA,IACnC,GAAI,eAAe,EAAE,YAAY;AAAA,EACnC;AACF;AAEA,SAAS,uBACP,MACA,cACA,eACA,cACA,kBACA,kBACM;AACN,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,EAAE,OAAO,IAAI;AAwBnB,MAAI,KAAK,SAAS,UAAa,KAAK,SAAS,SAAS;AACpD,UAAM,eAAgB,KAAK,QAAQ,CAAC;AACpC,UAAM,iBAAiB,aAAa,WAAW;AAC/C,UAAM,eAAe,aAAa,SAAS;AAC3C,UAAM,gBAAgB,aAAa,UAAU;AAC7C,UAAM,cAAc,kBAAkB,cAAc;AACpD,UAAM,YAAY,gBAAgB,cAAc;AAChD,UAAM,aAAa,iBAAiB,cAAc;AAClD,UAAM,cAAc,CAAC,eAAe,CAAC,aAAa;AAClD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM;AAAA,QACJ,GAAG,KAAK;AAAA,QACR,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,OAAO;AAAA,QACP,GAAI,cAAc,iBAAiB,UACjC,aAAa,iBAAiB,UAAa;AAAA,UACzC,cAAc,cAAc;AAAA,QAC9B;AAAA,QACF,GAAI,eAAe,EAAE,QAAQ,KAAK;AAAA,QAClC,GAAI,cAAc,eAAe,EAAE,aAAa,cAAc,YAAY;AAAA,MAC5E;AAAA,MACA,GAAI,eAAe,EAAE,OAAO,EAAE,GAAI,KAAK,SAAS,CAAC,GAAI,SAAS,KAAK,EAAE;AAAA,IACvE;AAAA,EACF;AAEA,QAAM,YAA2B;AAAA,IAC/B,OAAO,KAAK,KAAK;AAAA,IACjB,WAAW,KAAK,KAAK;AAAA,IACrB,QAAQ,KAAK,KAAK;AAAA,IAClB,WAAW,KAAK,KAAK;AAAA,IACrB,GAAG;AAAA,IACH,GAAI,KAAK,KAAK,gBAAgB,UAAa,EAAE,aAAa,KAAK,KAAK,YAAY;AAAA,IAChF,GAAI,KAAK,KAAK,SAAS,UAAa,EAAE,MAAM,KAAK,KAAK,KAAK;AAAA,IAC3D,GAAI,KAAK,KAAK,cAAc,UAAa,EAAE,WAAW,KAAK,KAAK,UAAU;AAAA,IAC1E,GAAI,KAAK,KAAK,WAAW,QAAQ,EAAE,QAAQ,KAAK;AAAA,IAChD,GAAI,KAAK,KAAK,aAAa,UAAa,EAAE,UAAU,KAAK,KAAK,SAAS;AAAA,IACvE,GAAI,KAAK,KAAK,SAAS,UAAa,EAAE,MAAM,KAAK,KAAK,KAAK;AAAA,EAC7D;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM;AAAA,IACN,MAAM;AAAA,IACN,GAAI,UAAU,EAAE,OAAO,EAAE,SAAS,KAAK,EAAE;AAAA,EAC3C;AACF;AAEA,SAAS,qBACP,MACA,cACA,eACA,QACM;AACN,QAAM,OAAO,KAAK,MAAM,QAAQ;AAChC,QAAM,iBAAiB,aAAa,IAAI,KAAK,MAAM,KAAK,kBAAkB,KAAK;AAC/E,QAAM,iBAAiB,aAAa,IAAI,KAAK,MAAM,KAAK,kBAAkB,KAAK;AAC/E,QAAM,YAAY,kBAAkB;AACpC,QAAM,gBAAgB,kBAAkB,KAAK,UAAU,CAAC,aAAa,IAAI,KAAK,MAAM;AAEpF,MAAI,QAAgB,OAAO;AAC3B,MAAI,SAAS,OAAQ,SAAQ,OAAO;AAAA,WAC3B,cAAe,SAAQ,OAAO;AAAA,WAC9B,UAAW,SAAQ,OAAO;AAEnC,QAAM,SAAe;AAAA,IACnB,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOH,MAAM,SAAS,SAAS,aAAa;AAAA,IACrC,UAAU;AAAA,IACV,OAAO,EAAE,QAAQ,OAAO,aAAa,YAAY,IAAI,IAAI;AAAA,IACzD,WAAW,EAAE,MAAM,0BAAW,aAAa,OAAO,OAAO,IAAI,QAAQ,GAAG;AAAA,EAC1E;AACA,MAAI,SAAS,QAAQ;AACnB,WAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,iBAAiB,MAAM;AAAA,EAC3D;AACA,SAAO;AACT;AAgFA,IAAM,qBAAgC;AAAA,EACpC,WAAW;AAAA,EACX,gBAAgB;AAClB;AAMA,IAAM,qBAAgC,EAAE,UAAU,cAAc,WAAW,cAAc;AAElF,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoB;AAElB,QAAM,SAAS,cAAc;AAC7B,QAAM,aAAS;AAAA,IACb,OAAO,EAAE,GAAG,gBAAgB,GAAI,kBAAkB,CAAC,EAAG;AAAA,IACtD,CAAC,cAAc;AAAA,EACjB;AACA,QAAM,sBAAkB;AAAA,IACtB,MAAO,gBAAgB,EAAE,GAAG,oBAAoB,GAAG,cAAc,IAAI;AAAA,IACrE,CAAC,aAAa;AAAA,EAChB;AACA,QAAM,sBAAkB;AAAA,IACtB,MAAO,gBAAgB,EAAE,GAAG,oBAAoB,GAAG,cAAc,IAAI;AAAA,IACrE,CAAC,aAAa;AAAA,EAChB;AAGA,QAAM,QAAQ,gBAAgB,OAAO,eAAe;AACpD,QAAM,iBAAa,wBAAQ,MAAM,IAAI,IAAI,mBAAmB,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC;AAIlF,QAAM,oBAAgB,wBAAQ,MAAM;AAClC,UAAM,OAAO,oBAAoB,OAAO,MAAM,gBAAgB;AAC9D,QAAI,WAAW,SAAS,EAAG,QAAO;AAClC,UAAM,UAAU,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACnD,UAAM,aAAa,MAAM,MAAM;AAAA,MAC7B,CAAC,MACC,EAAE,MAAM,cAAc,UACtB,WAAW,IAAI,EAAE,KAAK,SAAS,KAC/B,CAAC,QAAQ,IAAI,EAAE,EAAE;AAAA,IACrB;AACA,QAAI,WAAW,WAAW,EAAG,QAAO;AACpC,UAAM,SAAS,oBAAI,IAAI,CAAC,GAAG,SAAS,GAAG,WAAW,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACnE,UAAM,cAAc,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACvD,UAAM,aAAa,MAAM,MAAM;AAAA,MAC7B,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,KAAK,OAAO,IAAI,EAAE,MAAM,KAAK,OAAO,IAAI,EAAE,MAAM;AAAA,IAC9E;AACA,WAAO,EAAE,OAAO,CAAC,GAAG,KAAK,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC,GAAG,KAAK,OAAO,GAAG,UAAU,EAAE;AAAA,EACxF,GAAG,CAAC,OAAO,MAAM,kBAAkB,UAAU,CAAC;AAC9C,QAAM,iBAAa;AAAA,IACjB,MAAM,uBAAuB,OAAO,MAAM,gBAAgB;AAAA,IAC1D,CAAC,OAAO,MAAM,gBAAgB;AAAA,EAChC;AAIA,QAAM,CAAC,eAAe,gBAAgB,QAAI,yBAA4C,IAAI;AAE1F,QAAM,iBAAa,wBAAoB,MAAM;AAO3C,UAAM,WAAyC,gBAC3C,CAAC,MAAM,cAAc,IAAI,EAAE,EAAE,IAC7B;AACJ,UAAM,WAAW,WAAW,EAAE,SAAS,IAAI,CAAC;AAG5C,UAAM,YAA6B;AAAA,MACjC;AAAA,QACE,uBAAuB,EAAE,GAAG,UAAU,SAAS,IAAI,SAAS,GAAG,CAAC;AAAA,QAChE;AAAA,MACF;AAAA,MACA,EAAE,GAAG,UAAU,SAAS,GAAG;AAAA;AAAA,IAC7B;AACA,UAAM,WACJ,WAAW,gBACP,CAAC,MAAkB,IACnB,eAAe,SACb,YACC;AAGT,QAAI,WAAW,OAAO,GAAG;AACvB,YAAM,UAAU,iBAAiB,eAAe;AAAA,QAC9C,mBAAmB,CAAC,GAAG,UAAU;AAAA,QACjC,YAAY;AAAA,MACd,CAAC;AAED,aAAO,eACH,mBAAmB,SAAS,EAAE,YAAY,CAAC,MAAM,GAAG,GAAG,aAAa,CAAC,IACrE;AAAA,IACN;AAIA,QAAI,cAAc;AAChB,aAAO,mBAAmB,eAAe,EAAE,YAAY,UAAU,GAAG,aAAa,CAAC;AAAA,IACpF;AAEA,WAAO,SAAS,aAAa;AAAA,EAC/B,GAAG,CAAC,eAAe,QAAQ,YAAY,YAAY,cAAc,aAAa,CAAC;AAS/E,QAAM,YAAQ,wBAAQ,MAAM;AAC1B,UAAM,QAAQ;AAAA,MACZ,cAAc,oBAAI,IAAY;AAAA,MAC9B,eAAe;AAAA,MACf,kBAAkB,oBAAI,IAAY;AAAA,MAClC,kBAAkB,CAAC;AAAA,MACnB,QAAQ,oBAAI,IAAoB;AAAA,IAClC;AACA,QAAI,CAAC,QAAS,QAAO;AACrB,UAAM,MAAM,cAAc,KAAK,IAAI,GAAG,QAAQ,eAAe,SAAS,CAAC;AACvE,WAAO,qBAAqB,aAAa,SAAS,GAAG,GAAG,OAAO,MAAM,gBAAgB;AAAA,EACvF,GAAG,CAAC,SAAS,YAAY,OAAO,MAAM,gBAAgB,CAAC;AAGvD,QAAM,qBAAiB;AAAA,IACrB,MACE,WAAW,MAAM;AAAA,MAAI,CAAC,MACpB;AAAA,QACE;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM,OAAO,IAAI,EAAE,EAAE;AAAA,QACrB,MAAM;AAAA,QACN,oBAAoB;AAAA,MACtB;AAAA,IACF;AAAA,IACF,CAAC,WAAW,OAAO,OAAO,gBAAgB;AAAA,EAC5C;AACA,QAAM,qBAAiB;AAAA,IACrB,MACE,WAAW,MAAM;AAAA,MAAI,CAAC,MACpB,qBAAqB,GAAG,MAAM,cAAc,MAAM,eAAe,MAAM;AAAA,IACzE;AAAA,IACF,CAAC,WAAW,OAAO,OAAO,MAAM;AAAA,EAClC;AAGA,QAAM,sBAAkB;AAAA,IACtB,CAAC,GAAY,SAAe;AAC1B,YAAM,OAAQ,KAAK,QAAQ,CAAC;AAG5B,UAAI,KAAK,aAAa,KAAK,aAAa,CAAC,WAAW,IAAI,KAAK,SAAS,GAAG;AACvE,cAAM,UAAU,KAAK,SAAS;AAAA,MAChC;AACA,oBAAc,KAAK,EAAE;AAAA,IACvB;AAAA,IACA,CAAC,OAAO,aAAa,UAAU;AAAA,EACjC;AAGA,QAAM,iBAAa,uBAAuB,IAAI;AAC9C,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAmC,IAAI;AAI3E,oBAAkB,YAAY,YAAY;AAAA;AAAA,IAExC,UAAU,GAAG,MAAM,oBAAoB,EAAE,IAAI,gBAAgB,aAAa,WAAW;AAAA,IACrF,SAAS;AAAA,EACX,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL;AAAA,MACA,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,SAAS;AAAA,QACT,eAAe;AAAA,QACf,GAAG;AAAA,MACL;AAAA,MAEC;AAAA,mBAAW,SAAS,KACnB;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,YAAY,MAAM;AAAA;AAAA,QACpB;AAAA,QAEF,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,GAClC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP,OAAO;AAAA,YACP,WAAW;AAAA,YACX,WAAW;AAAA,YACX,aAAa;AAAA,YACb,QAAQ;AAAA,YACR,SAAO;AAAA,YACP,gBAAgB,EAAE,SAAS,KAAK;AAAA,YAChC,SAAS;AAAA,YACT,YAAY,EAAE,iBAAiB,KAAK;AAAA,YAEpC;AAAA,4DAAC,qBAAkB,SAAS,kBAAkB;AAAA,cAC9C,8CAAC,6BAAW,SAAS,iCAAkB,MAAM,KAAK,IAAI,MAAM,GAAG;AAAA,cAC9D;AAAA;AAAA;AAAA,QACH,GACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;AmBnkBA,IAAAC,iBAA+B;;;ACE/B,IAAAC,iBAA8B;AAwCxB,IAAAC,uBAAA;AARC,IAAM,qBAAiB,qBAAK,SAASC,gBAAe;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,MAAI,OAAO,WAAW,GAAG;AACvB,WACE,+CAAC,SAAI,OAAO,EAAE,SAAS,kBAAkB,UAAU,IAAI,YAAY,KAAK,GACtE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,OAAO,MAAM;AAAA,YACb,eAAe;AAAA,YACf,eAAe;AAAA,YACf,YAAY;AAAA,YACZ,cAAc;AAAA,UAChB;AAAA,UACD;AAAA;AAAA,MAED;AAAA,MACA,8CAAC,SAAI,OAAO,EAAE,OAAO,MAAM,eAAe,cAAc,GAAG,GAAG,kHAG9D;AAAA,MACA,8CAAC,SAAI,OAAO,EAAE,OAAO,MAAM,WAAW,UAAU,GAAG,GAAG,+DAEtD;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,+CAAC,SAAI,OAAO,EAAE,SAAS,SAAS,UAAU,GAAG,GAC1C;AAAA,qBACC,+CAAC,SAAI,OAAO,EAAE,SAAS,eAAe,GACpC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,OAAO,MAAM;AAAA,YACb,eAAe;AAAA,YACf,eAAe;AAAA,YACf,YAAY;AAAA,UACd;AAAA,UACD;AAAA;AAAA,YACkB;AAAA;AAAA;AAAA,MACnB;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,OAAO,MAAM;AAAA,YACb,WAAW;AAAA,YACX,WAAW;AAAA,UACb;AAAA,UACD;AAAA;AAAA,MAED;AAAA,OACF;AAAA,IAED,OAAO,IAAI,CAAC,OAAO,MAClB;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA,SAAS,MAAM;AAAA,QACf,QAAQ,MAAM,OAAO,SAAS;AAAA,QAC9B,YAAY,MAAM,mBAAmB;AAAA,QACrC,SAAS;AAAA;AAAA,MALJ,MAAM;AAAA,IAMb,CACD;AAAA,KACH;AAEJ,CAAC;AAED,IAAM,qBAAiB,qBAAK,SAASC,gBAAe;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,MAAM,UAAU,MAAM,cAAc;AAAA,MAC7C,OAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,QACP,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,YAAY,aACR,+CACA;AAAA,QACJ,SAAS;AAAA,QACT,QAAQ,UAAU,YAAY;AAAA,QAC9B,YAAY,aACR,wCACA;AAAA,QACJ,OAAO;AAAA,QACP,UAAU;AAAA,MACZ;AAAA,MAGA;AAAA,uDAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAE,GAEzD;AAAA,WAAC,WACA,8CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,WAAW,UAAU,GAAG,GAAG,oBAEvD;AAAA,UAEF;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,YAAY,UAAU,MAAM;AAAA,gBAC5B,OAAO,UACH,8BACA,MAAM;AAAA,cACZ;AAAA,cAEC,gBAAM;AAAA;AAAA,UACT;AAAA,UACC,UAAU,CAAC,WACV;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,OAAO,MAAM;AAAA,gBACb,WAAW;AAAA,cACb;AAAA,cACD;AAAA;AAAA,UAED;AAAA,WAEJ;AAAA,QAGC,MAAM,YAAY,SAAS,KAC1B;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,UAAU;AAAA,cACV,OAAO,MAAM;AAAA,cACb,aAAa,UAAU,IAAI;AAAA,cAC3B,WAAW;AAAA,YACb;AAAA,YACD;AAAA;AAAA,cACQ;AAAA,cACP,8CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,cAAc,GACvC,gBAAM,YAAY,KAAK,IAAI,GAC9B;AAAA;AAAA;AAAA,QACF;AAAA,QAID,MAAM,YACL;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,UAAU;AAAA,cACV,OAAO;AAAA,cACP,aAAa;AAAA,cACb,WAAW;AAAA,YACb;AAAA,YACD;AAAA;AAAA,cACQ,MAAM;AAAA;AAAA;AAAA,QACf;AAAA;AAAA;AAAA,EAEJ;AAEJ,CAAC;;;ADpKK,IAAAC,uBAAA;AApBC,IAAM,qBAAiB,qBAAK,SAASC,gBAAe;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,CAAC,KAAK,MAAM,QAAI,yBAAuB,OAAO;AACpD,QAAM,kBAAkB,UAAU,aAAa;AAE/C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,UAAU;AAAA,MACZ;AAAA,MAGA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,SAAS;AAAA,cACT,cAAc,aAAa,MAAM,MAAM;AAAA,cACvC,YAAY;AAAA,YACd;AAAA,YAEA;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,QAAQ,QAAQ;AAAA,kBAChB,SAAS,MAAM,OAAO,OAAO;AAAA,kBAC7B,OAAM;AAAA;AAAA,cACR;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,QAAQ,QAAQ;AAAA,kBAChB,SAAS,MAAM,OAAO,OAAO;AAAA,kBAC7B,OAAM;AAAA,kBACN,OAAO,gBAAgB,SAAS,IAAI,OAAO,gBAAgB,MAAM,IAAI;AAAA;AAAA,cACvE;AAAA;AAAA;AAAA,QACF;AAAA,QAGA,+CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,OAAO,GACrC;AAAA,kBAAQ,WACP;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA;AAAA,UACF;AAAA,UAED,QAAQ,WACP;AAAA,YAAC;AAAA;AAAA,cACC,QAAQ;AAAA,cACR;AAAA,cACA,cAAc;AAAA,cACd,eAAe,iBAAiB;AAAA;AAAA,UAClC;AAAA,WAEJ;AAAA;AAAA;AAAA,EACF;AAEJ,CAAC;AAED,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,cAAc,SACV,wCACA;AAAA,QACJ,YAAY;AAAA,QACZ,OAAO,SAAS,8BAA8B,MAAM;AAAA,QACpD,YAAY,SAAS,MAAM;AAAA,QAC3B,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,MACP;AAAA,MAEC;AAAA;AAAA,QACA,SACC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,UAAU;AAAA,cACV,YAAY,SACR,8BACA,MAAM;AAAA,cACV,OAAO;AAAA,cACP,cAAc;AAAA,cACd,SAAS;AAAA,cACT,YAAY;AAAA,YACd;AAAA,YAEC;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;AEhIA,IAAAC,iBAA+B;AA6BzB,IAAAC,uBAAA;AAPC,IAAM,mBAAe,qBAAK,SAASC,cAAa;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,MAAI,SAAS,WAAW,GAAG;AACzB,WACE,8CAAC,SAAI,OAAO,EAAE,SAAS,IAAI,OAAO,MAAM,WAAW,UAAU,GAAG,GAAG,kEAEnE;AAAA,EAEJ;AAEA,MAAI,SAAS,QAAQ;AACnB,WAAO,8CAAC,eAAY,UAAoB;AAAA,EAC1C;AAEA,SAAO,8CAAC,eAAY,UAAoB,WAAW,YAAY;AACjE,CAAC;AAID,IAAM,kBAAc,qBAAK,SAASC,aAAY;AAAA,EAC5C;AAAA,EACA;AACF,GAGG;AACD,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,aAAa,SAAS,CAAC,GAAG,EAAE;AACrE,QAAM,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ,KAAK,SAAS,CAAC;AAEpE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,UAAU;AAAA,MACZ;AAAA,MAGA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,SAAS;AAAA,cACT,cAAc,aAAa,MAAM,MAAM;AAAA,cACvC,YAAY;AAAA,cACZ,WAAW;AAAA,YACb;AAAA,YAEC,mBAAS,IAAI,CAAC,YACb;AAAA,cAAC;AAAA;AAAA,gBAEC,SAAS,MAAM,YAAY,QAAQ,EAAE;AAAA,gBACrC,OAAO;AAAA,kBACL,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,cACE,aAAa,QAAQ,KACjB,wCACA;AAAA,kBACN,YAAY;AAAA,kBACZ,OACE,aAAa,QAAQ,KACjB,8BACA,MAAM;AAAA,kBACZ,YAAY,aAAa,QAAQ,KAAK,MAAM;AAAA,kBAC5C,UAAU;AAAA,kBACV,QAAQ;AAAA,kBACR,YAAY;AAAA,gBACd;AAAA,gBAEC,kBAAQ;AAAA;AAAA,cApBJ,QAAQ;AAAA,YAqBf,CACD;AAAA;AAAA,QACH;AAAA,QAGA,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,OAAO,GACrC,kBAAQ,OAAO,GAClB;AAAA;AAAA;AAAA,EACF;AAEJ,CAAC;AAID,IAAM,kBAAc,qBAAK,SAASC,aAAY;AAAA,EAC5C;AACF,GAEG;AACD,QAAM,OAAO,SAAS,UAAU,IAAI,IAAI;AAExC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,qBAAqB,UAAU,IAAI;AAAA,QACnC,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,KAAK;AAAA,QACL,YAAY,MAAM;AAAA,MACpB;AAAA,MAEC,mBAAS,IAAI,CAAC,YACb;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO;AAAA,YACL,YAAY;AAAA,YACZ,SAAS;AAAA,YACT,eAAe;AAAA,YACf,UAAU;AAAA,UACZ;AAAA,UAGA;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,SAAS;AAAA,kBACT,UAAU;AAAA,kBACV,YAAY;AAAA,kBACZ,OAAO,MAAM;AAAA,kBACb,eAAe;AAAA,kBACf,eAAe;AAAA,kBACf,cAAc,aAAa,MAAM,MAAM;AAAA,kBACvC,YAAY;AAAA,gBACd;AAAA,gBAEC;AAAA,0BAAQ;AAAA,kBACR,QAAQ,WACP;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,YAAY;AAAA,wBACZ,YAAY;AAAA,wBACZ,UAAU;AAAA,wBACV,OAAO,MAAM;AAAA,sBACf;AAAA,sBAEC,kBAAQ;AAAA;AAAA,kBACX;AAAA;AAAA;AAAA,YAEJ;AAAA,YAEA,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,OAAO,GACrC,kBAAQ,OAAO,GAClB;AAAA;AAAA;AAAA,QAtCK,QAAQ;AAAA,MAuCf,CACD;AAAA;AAAA,EACH;AAEJ,CAAC;;;AChLD,IAAAC,iBAA+B;AA0CvB,IAAAC,uBAAA;AA9BD,IAAM,sBAAkB,qBAAK,SAASC,iBAAgB;AAAA,EAC3D;AAAA,EACA;AAAA,EACA,kBAAkB;AACpB,GAAyB;AACvB,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,eAAe;AAExD,MAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,SACE,+CAAC,SAAI,OAAO,EAAE,WAAW,aAAa,MAAM,MAAM,GAAG,GAEnD;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;AAAA,QACpC,OAAO;AAAA,UACL,OAAO;AAAA,UACP,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,KAAK;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,OAAO,MAAM;AAAA,UACb,YAAY;AAAA,UACZ,eAAe;AAAA,UACf,eAAe;AAAA,QACjB;AAAA,QAEA;AAAA,wDAAC,UAAK,OAAO,EAAE,UAAU,GAAG,GAAI,qBAAW,WAAM,UAAI;AAAA,UAAO;AAAA,UAE5D,+CAAC,UAAK,OAAO,EAAE,YAAY,KAAK,UAAU,GAAG,GAC1C;AAAA,sBAAU;AAAA,YAAO;AAAA,aACpB;AAAA,UAGC,CAAC,YACA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,MAAM;AAAA,gBACN,SAAS;AAAA,gBACT,YAAY;AAAA,gBACZ,KAAK;AAAA,gBACL,YAAY;AAAA,cACd;AAAA,cAEC;AAAA,0BAAU,IAAI,CAAC,MAAM,MACpB;AAAA,kBAAC;AAAA;AAAA,oBAEC,OAAO;AAAA,sBACL,OAAO,MAAM,gBAAgB,IAAI;AAAA,sBACjC,QAAQ,MAAM,gBAAgB,IAAI;AAAA,sBAClC,cAAc;AAAA,sBACd,YACE,IAAI,gBACA,+BACA,MAAM,gBACJ,8BACA,MAAM,YAAY;AAAA,sBAC1B,YAAY;AAAA,sBACZ,YAAY;AAAA,oBACd;AAAA,oBACA,OAAO,KAAK;AAAA;AAAA,kBAdP;AAAA,gBAeP,CACD;AAAA,gBAED;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,MAAM;AAAA,sBACN,QAAQ;AAAA,sBACR,YAAY,MAAM,YAAY;AAAA,sBAC9B,YAAY;AAAA,sBACZ,aAAa;AAAA,oBACf;AAAA;AAAA,gBACF;AAAA;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IAEJ;AAAA,IAGC,YACC,8CAAC,SAAI,OAAO,EAAE,SAAS,aAAa,GAClC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA;AAAA,IACF,GACF;AAAA,KAEJ;AAEJ,CAAC;;;A9BiIK,IAAAC,uBAAA;AAlBN,IAAM,gBAAY,qBAAK,SAASC,WAAU;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,SACE,+CAAC,SAAI,OAAO;AAAA,IACV,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,SAAS;AAAA,EACX,GACE;AAAA,kDAAC,SAAI,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,MAAM,OAAO,GAAG;AAAA,IAC9D;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,KAAK;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,YAAY;AAAA,UACZ,OAAO,MAAM;AAAA,UACb,YAAY,MAAM;AAAA,UAClB,QAAQ,aAAa,MAAM,MAAM;AAAA,UACjC,cAAc;AAAA,UACd,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,eAAe;AAAA,UACf,eAAe;AAAA,UACf,YAAY;AAAA,QACd;AAAA,QAEA;AAAA,wDAAC,UAAK,OAAO,EAAE,UAAU,EAAE,GAAI,qBAAW,WAAM,UAAI;AAAA,UACnD;AAAA,UACA,UAAU,8CAAC,UAAK,OAAO,EAAE,YAAY,KAAK,SAAS,KAAK,UAAU,EAAE,GAAI,kBAAO;AAAA;AAAA;AAAA,IAClF;AAAA,IACA,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,MAAM,OAAO,GAAG;AAAA,KAChE;AAEJ,CAAC;AAOD,IAAM,gBAAY,qBAAK,SAASC,WAAU;AAAA,EACxC;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AACF,GAKG;AACD,QAAM,QAAQ,SAAS,UAClB,WAAW,WAAM,WACjB,WAAW,WAAM;AACtB,SACE,+CAAC,SAAI,OAAO;AAAA,IACV,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,SAAS;AAAA,EACX,GACE;AAAA,kDAAC,SAAI,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,MAAM,OAAO,GAAG;AAAA,IAC7D;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,KAAK;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,YAAY;AAAA,UACZ,OAAO,MAAM;AAAA,UACb,YAAY,MAAM;AAAA,UAClB,QAAQ,aAAa,MAAM,MAAM;AAAA,UACjC,cAAc;AAAA,UACd,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,eAAe;AAAA,UACf,eAAe;AAAA,UACf,aAAa;AAAA,UACb,YAAY;AAAA,QACd;AAAA,QAEA;AAAA,wDAAC,UAAK,OAAO,EAAE,UAAU,GAAG,aAAa,gBAAgB,GAAI,iBAAM;AAAA,UAClE;AAAA;AAAA;AAAA,IACH;AAAA,IACA,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,MAAM,OAAO,GAAG;AAAA,KAC/D;AAEJ,CAAC;AAWD,SAAS,iBAAiB,MAAmH;AAC3I,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,QAAM,MAAM;AACZ,aAAW,OAAO,OAAO,OAAO,GAAG,GAAG;AACpC,QAAI,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG,GAAG;AACzD,YAAM,UAAU,OAAO,QAAQ,GAA8B;AAC7D,UAAI,QAAQ,WAAW,EAAG;AAE1B,YAAM,wBAAwB,QAAQ,MAAM,CAAC,CAAC,EAAEC,EAAC,MAAM;AACrD,YAAI,CAACA,MAAK,OAAOA,OAAM,YAAY,MAAM,QAAQA,EAAC,EAAG,QAAO;AAC5D,eAAO,OAAO,OAAOA,EAA4B,EAAE,KAAK,CAAC,MAAM,OAAO,MAAM,QAAQ;AAAA,MACtF,CAAC;AACD,UAAI,uBAAuB;AACzB,cAAM,UAAU,QAAQ,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,GAAG,CAAC,IAAI,mBAAmB;AAC5E,eAAO,EAAE,OAAO,KAAgD,QAAQ;AAAA,MAC1E;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,mBAAmB,MAAoE;AAC9F,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,QAAM,MAAM;AACZ,MAAI,OAAO,IAAI,iBAAiB,YAAY,OAAO,IAAI,eAAe,UAAU;AAC9E,WAAO,EAAE,cAAc,IAAI,cAAc,YAAY,IAAI,WAAW;AAAA,EACtE;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AAAA,EACA,qBAAqB;AAAA,EACrB;AAAA,EACA;AACF,GAMG;AACD,QAAM,CAAC,eAAe,gBAAgB,QAAI,yBAAS,KAAK;AAExD,QAAM,eAAW,wBAAQ,MAAM,iBAAiB,IAAI,GAAG,CAAC,IAAI,CAAC;AAG7D,QAAM,kBAAc,wBAAQ,MAAM;AAChC,UAAM,OAAO,oBAAI,IAAY;AAC7B,aAAS,IAAI,GAAG,KAAK,iBAAiB,IAAI,UAAU,QAAQ,KAAK;AAC/D,YAAM,OAAO,UAAU,CAAC;AACxB,UAAI,UAAU,YAAY,kBAAkB;AAC1C,YAAI,KAAK,eAAgB,MAAK,IAAI,KAAK,cAAc;AAAA,MACvD,OAAO;AAEL,YAAI,KAAK,UAAW,MAAK,IAAI,KAAK,SAAS;AAC3C,YAAI,KAAK,WAAY,MAAK,IAAI,KAAK,UAAU;AAAA,MAC/C;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,WAAW,eAAe,UAAU,OAAO,CAAC;AAEhD,QAAM,UAAU,iBAAiB,UAAU,SAAS;AAEpD,MAAI,CAAC,UAAU;AAEb,WACE,8CAAC,SAAI,OAAO,EAAE,SAAS,IAAI,YAAY,MAAM,UAAU,UAAU,IAAI,YAAY,YAAY,UAAU,QAAQ,QAAQ,OAAO,GAC3H,iBAAO,SAAS,WAAW,OAAO,KAAK,UAAU,MAAM,MAAM,CAAC,GACjE;AAAA,EAEJ;AAEA,QAAM,QAAQ,SAAS;AACvB,QAAM,QAAQ,mBAAmB,IAAI;AACrC,QAAM,cAAc,OAAO,gBAAgB;AAG3C,QAAM,UAAU,OAAO,KAAK,KAAK;AACjC,QAAM,iBAAiB,QAAQ,OAAO,CAAC,MAAM,YAAY,IAAI,CAAC,CAAC;AAG/D,MAAI,eAAe;AACnB,MAAI,aAAa;AACf,eAAW,KAAK,gBAAgB;AAC9B,sBAAiB,MAAM,CAAC,EAAE,WAAW,KAAgB;AAAA,IACvD;AAAA,EACF;AAGA,QAAM,aAAa,OAAO,cAAc;AAExC,SACE,+CAAC,SAAI,OAAO,EAAE,UAAU,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,eAAe,SAAS,GACtF;AAAA,mBACC,8CAAC,SAAI,OAAO,EAAE,SAAS,YAAY,UAAU,IAAI,OAAO,MAAM,WAAW,WAAW,UAAU,cAAc,aAAa,MAAM,MAAM,IAAI,YAAY,EAAE,GACpJ,uBACH;AAAA,IAGF,+CAAC,SAAI,OAAO,EAAE,SAAS,IAAI,MAAM,GAAG,UAAU,OAAO,GAGlD;AAAA,6BAAuB;AAAA;AAAA,QAEtB,gFACG;AAAA,oBACC,8CAAC,SAAI,OAAO,EAAE,cAAc,GAAG,GAC5B,WAAC,gBACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS,MAAM,iBAAiB,IAAI;AAAA,cACpC,OAAO;AAAA,gBACL,YAAY,MAAM;AAAA,gBAAS,OAAO;AAAA,gBAAQ,QAAQ;AAAA,gBAAQ,cAAc;AAAA,gBACxE,SAAS;AAAA,gBAAa,UAAU;AAAA,gBAAI,YAAY;AAAA,gBAAK,QAAQ;AAAA,gBAC7D,YAAY;AAAA,gBAAW,OAAO;AAAA,cAChC;AAAA,cACD;AAAA;AAAA,UAED,IAEA,+CAAC,SAAI,OAAO,EAAE,SAAS,aAAa,YAAY,sBAAsB,MAAM,OAAO,sBAAsB,cAAc,GAAG,QAAQ,aAAa,MAAM,OAAO,KAAK,GAC/J;AAAA,0DAAC,SAAI,OAAO,EAAE,UAAU,IAAI,OAAO,MAAM,WAAW,eAAe,aAAa,eAAe,UAAU,cAAc,GAAG,YAAY,IAAI,GAAG,0CAE7I;AAAA,YACC,eACC,+CAAC,SAAI,OAAO,EAAE,UAAU,IAAI,YAAY,KAAK,OAAO,MAAM,QAAQ,GAC/D;AAAA,2BAAa,IAAI,WAAW,QAAQ,CAAC,IAAI,WAAW,QAAQ,CAAC;AAAA,cAC9D,+CAAC,UAAK,OAAO,EAAE,UAAU,IAAI,OAAO,MAAM,WAAW,YAAY,KAAK,YAAY,EAAE,GAAI;AAAA;AAAA,gBAAY;AAAA,gBAAW,QAAQ;AAAA,gBAAO;AAAA,iBAAM;AAAA,eACtI;AAAA,aAEJ,GAEJ,IAEA,+CAAC,SAAI,OAAO,EAAE,SAAS,aAAa,YAAY,sBAAsB,MAAM,SAAS,qBAAqB,cAAc,GAAG,cAAc,IAAI,QAAQ,cAAc,MAAM,MAAM,GAAG,GAChL;AAAA,0DAAC,SAAI,OAAO,EAAE,UAAU,IAAI,OAAO,MAAM,WAAW,eAAe,aAAa,eAAe,UAAU,YAAY,IAAI,GAAG,gCAE5H;AAAA,YACA,+CAAC,SAAI,OAAO,EAAE,UAAU,IAAI,OAAO,MAAM,WAAW,WAAW,EAAE,GAC9D;AAAA,6BAAe;AAAA,cAAO;AAAA,cAAK,QAAQ;AAAA,cAAO;AAAA,eAC7C;AAAA,aACF;AAAA,UAEF,8CAAC,SAAI,OAAO,EAAE,UAAU,IAAI,OAAO,MAAM,WAAW,eAAe,aAAa,eAAe,UAAU,cAAc,GAAG,YAAY,IAAI,GAAG,6BAE7I;AAAA,WACF;AAAA,UACE,uBAAuB;AAAA;AAAA,QAEzB,gFACG;AAAA,yBAAe,eAAe,SAAS,KACtC,+CAAC,SAAI,OAAO,EAAE,SAAS,aAAa,YAAY,sBAAsB,MAAM,OAAO,qBAAqB,cAAc,GAAG,cAAc,GAAG,GACxI;AAAA,0DAAC,SAAI,OAAO,EAAE,UAAU,IAAI,OAAO,MAAM,WAAW,eAAe,aAAa,eAAe,UAAU,cAAc,GAAG,YAAY,IAAI,GAAG,6DAE7I;AAAA,YACA,8CAAC,UAAK,OAAO,EAAE,YAAY,KAAK,UAAU,IAAI,OAAO,MAAM,QAAQ,GAChE,yBAAe,IAAI,aAAa,QAAQ,CAAC,IAAI,aAAa,QAAQ,CAAC,GACtE;AAAA,YACA,+CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,WAAW,YAAY,GAAG,UAAU,GAAG,GAChE;AAAA;AAAA,cAAY;AAAA,cAAW,eAAe;AAAA,cAAO;AAAA,cAAK,QAAQ;AAAA,cAAO;AAAA,eACpE;AAAA,aACF;AAAA,UAEF,8CAAC,SAAI,OAAO,EAAE,UAAU,IAAI,OAAO,MAAM,WAAW,eAAe,aAAa,eAAe,UAAU,cAAc,GAAG,YAAY,IAAI,GAAG,6BAE7I;AAAA,WACF;AAAA;AAAA;AAAA,QAGA,8CAAC,SAAI,OAAO,EAAE,UAAU,IAAI,OAAO,MAAM,WAAW,eAAe,aAAa,eAAe,UAAU,cAAc,GAAG,YAAY,IAAI,GAAG,8CAE7I;AAAA;AAAA,MAID,eAAe,IAAI,CAAC,QAAQ;AAC3B,cAAM,QAAQ,MAAM,GAAG;AACvB,cAAM,QAAS,MAAM,aAAwB;AAC7C,cAAM,SAAS,cAAe,MAAM,WAAW,IAAe;AAC9D,eACE,+CAAC,SAAc,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,SAAS,SAAS,UAAU,IAAI,YAAY,MAAM,UAAU,cAAc,aAAa,MAAM,MAAM,KAAK,GACrK;AAAA,wDAAC,UAAK,OAAO,EAAE,OAAO,MAAM,WAAW,OAAO,KAAK,YAAY,GAAG,UAAU,GAAG,GAAI,eAAI;AAAA,UACvF,8CAAC,UAAK,OAAO,EAAE,YAAY,KAAK,MAAM,EAAE,GAAI,iBAAM;AAAA,UACjD,WAAW,UACV,8CAAC,UAAK,OAAO,EAAE,OAAO,MAAM,SAAS,YAAY,KAAK,YAAY,EAAE,GACjE,mBAAS,IAAI,OAAO,QAAQ,CAAC,IAAI,OAAO,QAAQ,CAAC,GACpD;AAAA,aANM,GAQV;AAAA,MAEJ,CAAC;AAAA,MAEA,eAAe,WAAW,KACzB,8CAAC,SAAI,OAAO,EAAE,OAAO,MAAM,WAAW,UAAU,IAAI,WAAW,UAAU,SAAS,QAAQ,GAAG,mDAE7F;AAAA,OAGJ;AAAA,KACF;AAEJ;AAMA,IAAM,qBAAiB,qBAAK,SAASC,gBAAe;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AAED,QAAM,eAA+B;AAAA,IACnC;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ,CAAC,EAAE,WAAW,OAAO,eAAe,IAAI,MAC9C,8CAAC,eAAY,WAAW,OAAO,eAAe,KAAK,MAAY,OAAO,aAAa,EAAE,QAAQ,OAAO,IAAI,QAAW;AAAA,IAEvH;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ,CAAC,EAAE,WAAW,OAAO,eAAe,IAAI,MAC9C,8CAAC,kBAAe,WAAW,OAAO,eAAe,KAAK,kBAAoC,MAAY,OAAO,aAAa,EAAE,QAAQ,OAAO,IAAI,QAAW;AAAA,IAE9J;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,GAAG,cAAc,GAAI,cAAc,CAAC,CAAE;AACxD,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,SAAS,CAAC,GAAG,MAAM,QAAQ;AAG5E,QAAM,UAAU,SAAS,IAAI,CAACD,OAAMA,GAAE,EAAE,EAAE,KAAK,GAAG;AAClD,gCAAU,MAAM;AACd,QAAI,CAAC,SAAS,KAAK,CAACA,OAAMA,GAAE,OAAO,YAAY,GAAG;AAChD,sBAAgB,SAAS,CAAC,GAAG,MAAM,QAAQ;AAAA,IAC7C;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AACZ,QAAM,aAAa,SAAS,KAAK,CAACA,OAAMA,GAAE,OAAO,YAAY,KAAK,SAAS,CAAC;AAE5E,SACE,+CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,SAAS,QAAQ,eAAe,UAAU,UAAU,SAAS,GAElF;AAAA,kDAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,cAAc,aAAa,MAAM,MAAM,IAAI,YAAY,GAAG,WAAW,OAAO,GACxG,mBAAS,IAAI,CAAC,SAAS;AACtB,YAAM,SAAS,KAAK,OAAO;AAC3B,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,SAAS,MAAM,gBAAgB,KAAK,EAAE;AAAA,UACtC,OAAO;AAAA,YACL,MAAM,SAAS,UAAU,IAAI,IAAI;AAAA,YACjC,SAAS;AAAA,YAAW,UAAU;AAAA,YAC9B,YAAY,SAAS,MAAM;AAAA,YAC3B,OAAO,SAAS,MAAM,UAAU,MAAM;AAAA,YACtC,YAAY,SAAS,sBAAsB,MAAM,OAAO,sBAAsB;AAAA,YAC9E,QAAQ;AAAA,YACR,cAAc,SAAS,aAAa,MAAM,OAAO,KAAK;AAAA,YACtD,QAAQ;AAAA,YAAW,eAAe;AAAA,YAAa,eAAe;AAAA,YAAU,YAAY;AAAA,YACpF,YAAY;AAAA,UACd;AAAA,UAEC,eAAK;AAAA;AAAA,QAdD,KAAK;AAAA,MAeZ;AAAA,IAEJ,CAAC,GACH;AAAA,IACA,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,OAAO,GACrC,sBAAY,OAAO,EAAE,WAAW,cAAc,CAAC,GAClD;AAAA,KACF;AAEJ,CAAC;AAMD,SAAS,oBACP,YACA,iBACA,iBACA,kBACqB;AACrB,QAAM,WAAW,oBAAoB,YAAY,eAAe;AAChE,MAAI,CAAC,UAAU,iBAAkB,QAAO;AACxC,QAAM,aAAa,gBAAgB;AAAA,IACjC,CAAC,MAAM,EAAE,cAAc,mBAAmB,EAAE,eAAe;AAAA,EAC7D;AACA,MAAI,CAAC,YAAY,cAAe,QAAO;AAEvC,QAAM,OAAO,SAAS,aAAa;AACnC,QAAM,gBAAgB,SAAS,eAAe,SAAS;AACvD,QAAM,cAAc,mBAChB,wBAAwB,kBAAkB,MAAM,aAAa,IAC7D;AACJ,QAAM,cAAc,yBAAyB,WAAW,eAAe,WAAW;AAClF,MAAI,YAAY,WAAW,EAAG,QAAO;AACrC,SAAO;AAAA,IACL,WAAW,SAAS,aAAa;AAAA,IACjC,OAAO,SAAS,eAAe,SAAS;AAAA,IACxC,MAAM,SAAS;AAAA,IACf,WAAW;AAAA,EACb;AACF;AAEA,SAAS,oBAAoB,MAAgB,MAA+B;AAC1E,OAAK,KAAK,SAAS,QAAQ,KAAK,OAAO,SAAS,KAAK,cAAe,QAAO;AAC3E,MAAI,KAAK,UAAU;AAAE,eAAW,SAAS,KAAK,UAAU;AAAE,YAAM,IAAI,oBAAoB,OAAO,IAAI;AAAG,UAAI,EAAG,QAAO;AAAA,IAAG;AAAA,EAAE;AACzH,MAAI,KAAK,KAAM,QAAO,oBAAoB,KAAK,MAAM,IAAI;AACzD,SAAO;AACT;AAEA,SAAS,gBAAgB,MAAyB;AAChD,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,cAAe,QAAO;AAC/B,MAAI,KAAK,UAAU,KAAK,CAAC,MAAM,KAAK,gBAAgB,CAAC,CAAC,EAAG,QAAO;AAChE,MAAI,KAAK,QAAQ,gBAAgB,KAAK,IAAI,EAAG,QAAO;AACpD,SAAO;AACT;AAkBA,SAAS,eACP,WACA,sBACA,WAAW,IACoH;AAC/H,QAAM,MAAM;AACZ,MAAI,CAAC,KAAK,OAAQ,QAAO,CAAC;AAE1B,QAAM,SAAS,oBAAI,IAAoB;AACvC,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,QAAO,IAAI,IAAI,CAAC,EAAE,gBAAgB,CAAC;AAExE,QAAM,WAAW,OAAO,IAAI,oBAAoB;AAChD,MAAI,aAAa,OAAW,QAAO,CAAC;AAEpC,QAAM,cAAc,IAAI,QAAQ;AAChC,QAAM,SAAwI,CAAC;AAC/I,QAAM,UAAU,oBAAI,IAAY;AAIhC,MAAI,UAAU;AACd,MAAI,aAAa;AACjB,MAAI,QAAQ;AAEZ,SAAO,WAAW,SAAS,UAAU;AACnC,QAAI,QAAQ,IAAI,QAAQ,cAAc,EAAG;AACzC,YAAQ,IAAI,QAAQ,cAAc;AAElC,WAAO,KAAK;AAAA,MACV,gBAAgB,QAAQ;AAAA,MACxB,SAAS,QAAQ;AAAA,MACjB,WAAW,QAAQ;AAAA,MACnB,aAAa,QAAQ,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,MAC5C,UAAU,UAAU,IAAI,KAAK,QAAQ,MAAM,CAAC,GAAG,QAAQ;AAAA,MACvD;AAAA,IACF,CAAC;AAGD,QAAI,aAAa,GAAG;AAClB;AACA,gBAAU,IAAI,UAAU;AACxB;AAAA,IACF,OAAO;AACL;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAQA,IAAM,iBAAa,qBAAK,SAASE,YAAW;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAcG;AACD,SACE,gFAEE;AAAA,kDAAC,SAAI,OAAO;AAAA,MACV,SAAS;AAAA,MACT,cAAc,aAAa,MAAM,MAAM;AAAA,MACvC,YAAY;AAAA,MACZ,YAAY,MAAM;AAAA,IACpB,GACI,WAAC,YAAY,MAAM,EAAY,IAAI,CAAC,MACpC;AAAA,MAAC;AAAA;AAAA,QAEC,SAAS,MAAM,aAAa,CAAC;AAAA,QAC7B,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,UACT,UAAU;AAAA,UACV,YAAY,SAAS,IAAI,MAAM;AAAA,UAC/B,eAAe;AAAA,UACf,eAAe;AAAA,UACf,OAAO,SAAS,IAAI,MAAM,UAAU,MAAM;AAAA,UAC1C,YAAY;AAAA,UACZ,QAAQ;AAAA,UACR,cAAc,SAAS,IAAI,aAAa,MAAM,OAAO,KAAK;AAAA,UAC1D,QAAQ;AAAA,UACR,YAAY;AAAA,QACd;AAAA,QAEC,gBAAM,aAAa,aAAa;AAAA;AAAA,MAjB5B;AAAA,IAkBP,CACD,GACH;AAAA,IAGA,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,SAAS,GACvC,mBAAS,aACR;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,YAAY;AAAA,QACZ,UAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,YAAY,EAAE,OAAO,QAAQ,EAAE,IAAI,CAAC,SAAS;AAAA,UACpF,IAAI,IAAI;AAAA,UACR,MAAM,YAAY,IAAI,IAAI;AAAA,UAC1B,QAAQ,MAAM;AACZ,gBAAI,IAAI,OAAO,YAAa,QAAO,8CAAC,kBAAe,WAAsB,eAA8B,kBAAkB,wBAAwB,iBAAkC,MAAY,MAAY,OAAO,EAAE,QAAQ,OAAO,GAAG;AACtO,kBAAM,aAAa,eAAe,KAAK,CAACF,OAAMA,GAAE,OAAO,IAAI,EAAE;AAC7D,gBAAI,YAAY,OAAQ,QAAO,WAAW,OAAO,EAAE,WAAW,cAAc,CAAC;AAC7E,kBAAM,WAAW,kBAAkB,KAAK,CAACA,OAAMA,GAAE,OAAO,IAAI,EAAE;AAC9D,gBAAI,SAAU,QAAO,8CAAC,qBAAkB,MAAM,SAAS,MAAM,aAAa,SAAS,aAAa,oBAAoB,SAAS,oBAA2B,WAAsB,eAA8B;AAC5M,mBAAO;AAAA,UACT;AAAA,QACF,EAAE;AAAA;AAAA,IACJ,IAEA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,iBAAiB,iBAAiB,YAAY,eAAe,gBAAgB,WAAW,UAAU,aAAa,GAAG,kBAAkB,EAAE,IAAI,CAAC;AAAA,QAC3I,iBAAiB,UAAU,aAAa,GAAG;AAAA,QAC3C;AAAA;AAAA,IACF,GAEJ;AAAA,KACF;AAEJ,CAAC;AAGD,SAAS,YAAY,MAAsB;AACzC,QAAM,MAA8B;AAAA,IAClC,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AACA,SAAO,IAAI,IAAI,KAAK;AACtB;AAEO,SAAS,iBAAiB;AAAA,EAC/B,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,OAAO,CAAC;AAAA,EACR;AAAA,EACA,OAAO,CAAC,UAAU,aAAa;AAAA,EAC/B;AAAA,EACA,cAAc;AAAA,EACd,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAA0B;AAExB,QAAM,yBAAqB,wBAAQ,MAAM;AACvC,QAAI,CAAC,gBAAiB,QAAO;AAC7B,QAAI;AACF,YAAM,QAAQ,yBAAyB,iBAAwB,gBAAuB;AACtF,aAAO,EAAE,WAAW,OAAO,YAAY,gBAAgB,YAAY;AAAA,IACrE,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,iBAAiB,gBAAgB,CAAC;AAGtC,QAAM,YAAY,iBAAiB,oBAAoB,aAAa,CAAC;AACrE,QAAM,aAAa,kBAAkB,oBAAoB,cAAc;AAYvE,QAAM,yBAAqB,wBAAQ,MAAM;AACvC,QAAI,CAAC,WAAY,QAAO;AACxB,WAAO,CAAC,EAAE,eAAe,WAAAG,YAAW,YAAY,MAI1C;AAYJ,YAAM,aAAaA,WAAU,aAAa,GAAG;AAC7C,UAAI,aAAa;AACjB,UAAI,cAAc,gBAAgB;AAChC,cAAM,IAAI,eAAe,eAAe;AAAA,UACtC,CAAC,MAAM,EAAE,mBAAmB;AAAA,QAC9B;AACA,YAAI,KAAK,EAAG,cAAa;AAAA,MAC3B;AACA,aACE;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,SAAS,kBAAkB;AAAA,UAC3B,YAAY;AAAA,UACZ,aAAa,CAAC,YAAY,cAAc,OAAO;AAAA,UAC/C,iBAAiB,CAAC,YAAY;AAa5B,gBAAI,YAAY,KAAM,eAAc,OAAO;AAAA,UAC7C;AAAA;AAAA,MACF;AAAA,IAEJ;AAAA,EACF,GAAG,CAAC,YAAY,cAAc,CAAC;AAC/B,QAAM,2BAA2B,mBAAmB;AACpD,QAAM,YAAY,aAAa,YAAY;AAC3C,QAAM,aAAa,aAAa,WAAW;AAC3C,QAAM,cAAc,aAAa,YAAY;AAG7C,QAAM,eAAW,uBAAuB,IAAI;AAC5C,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,KAAK;AAC9C,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,KAAK;AAC9C,gCAAU,MAAM;AACd,UAAM,KAAK,SAAS;AACpB,QAAI,CAAC,GAAI;AACT,UAAM,KAAK,IAAI,eAAe,CAAC,CAAC,KAAK,MAAM;AACzC,YAAM,IAAI,MAAM,YAAY;AAC5B,kBAAY,IAAI,GAAG;AACnB,kBAAY,KAAK,OAAO,IAAI,GAAG;AAE/B,aAAO,cAAc,IAAI,MAAM,QAAQ,CAAC;AAAA,IAC1C,CAAC;AACD,OAAG,QAAQ,EAAE;AACb,WAAO,MAAM,GAAG,WAAW;AAAA,EAC7B,GAAG,CAAC,CAAC;AAGL,QAAM,wBAAoB,wBAAQ,MAAM;AACtC,UAAM,YAAa,iBAAyB;AAC5C,QAAI,CAAC,WAAW,OAAQ,QAAO,CAAC;AAEhC,UAAM,cAAc,IAAI,KAAK,iBAAiB,CAAC,GAAG,IAAI,CAACH,OAAMA,GAAE,EAAE,CAAC;AAClE,WAAO,UACJ,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC,EACpC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,MAAM,aAAa,EAAE,aAAa,oBAAoB,EAAE,oBAAoB,MAAM,EAAE,KAAK,EAAE;AAAA,EAChI,GAAG,CAAC,iBAAiB,aAAa,CAAC;AAInC,QAAM,eAAe,CAAC,CAAC,kBAAkB;AACzC,QAAM,cAAU,wBAAQ,MAAM;AAC5B,UAAMI,QAAkE;AAAA,MACtE,EAAE,IAAI,UAAU,MAAM,UAAU,aAAa,gCAAgC;AAAA,MAC7E,EAAE,IAAI,UAAU,MAAM,UAAU,aAAa,4DAAuD;AAAA,IACtG;AACA,QAAI,cAAc;AAChB,MAAAA,MAAK,KAAK,EAAE,IAAI,aAAa,MAAM,aAAa,aAAa,4FAAuF,CAAC;AAAA,IACvJ;AACA,eAAWJ,MAAK,iBAAiB,CAAC,GAAG;AACnC,MAAAI,MAAK,KAAK,EAAE,IAAIJ,GAAE,IAAI,MAAMA,GAAE,MAAM,aAAaA,GAAE,YAAY,CAAC;AAAA,IAClE;AACA,eAAWA,MAAK,mBAAmB;AACjC,MAAAI,MAAK,KAAK,EAAE,IAAIJ,GAAE,IAAI,MAAMA,GAAE,MAAM,aAAaA,GAAE,YAAY,CAAC;AAAA,IAClE;AAEA,UAAM,UAAU,IAAI,IAAI,gBAAgB,CAAC,CAAC;AAC1C,WAAO,QAAQ,OAAO,IAAII,MAAK,OAAO,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC,IAAIA;AAAA,EACrE,GAAG,CAAC,cAAc,eAAe,mBAAmB,YAAY,CAAC;AAEjE,QAAM,cAAc,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACpD,QAAM,kBAAkB,cAAc,YAAY,IAAI,UAAU,IAAI,aAAa,QAAQ,CAAC,GAAG,MAAM;AACnG,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAiB,eAAe;AAClE,QAAM,CAAC,aAAa,cAAc,QAAI,yBAAS,CAAC;AAChD,QAAM,CAAC,gBAAgB,iBAAiB,QAAI,yBAA2B,CAAC,CAAC;AACzE,QAAM,CAAC,eAAe,gBAAgB,QAAI,yBAAS,iBAAiB,WAAW,IAAI;AACnF,QAAM,CAAC,gBAAgB,iBAAiB,QAAI,yBAA8B,UAAU;AACpF,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,iBAAiB,YAAY,KAAK;AACnF,QAAM,CAAC,kBAAkB,mBAAmB,QAAI,yBAAS,iBAAiB,YAAY,KAAK;AAG3F,gCAAU,MAAM;AACd,QAAI,UAAU;AACZ,sBAAgB,KAAK;AACrB,uBAAiB,KAAK;AACtB,0BAAoB,KAAK;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,oBAAgB,4BAAY,MAAM;AAEtC,0BAAsB,MAAM,OAAO,cAAc,IAAI,MAAM,QAAQ,CAAC,CAAC;AACrE,eAAW,MAAM,OAAO,cAAc,IAAI,MAAM,QAAQ,CAAC,GAAG,GAAG;AAAA,EACjE,GAAG,CAAC,CAAC;AACL,QAAM,iBAAa,4BAAY,CAACJ,OAAe;AAAE,oBAAgBA,EAAC;AAAG,kBAAc;AAAA,EAAG,GAAG,CAAC,aAAa,CAAC;AACxG,QAAM,kBAAc,4BAAY,CAACA,OAAe;AAAE,qBAAiBA,EAAC;AAAG,kBAAc;AAAA,EAAG,GAAG,CAAC,aAAa,CAAC;AAC1G,QAAM,qBAAiB,4BAAY,MAAM;AAAE,wBAAoB,CAAC,MAAM,CAAC,CAAC;AAAG,kBAAc;AAAA,EAAG,GAAG,CAAC,aAAa,CAAC;AAE9G,QAAM,cAAc,eAAe,SAAS;AAE5C,QAAM,mBAAe,wBAAQ,MAAM;AACjC,QAAI,eAAe,SAAS,GAAG;AAC7B,YAAM,MAAM,eAAe,eAAe,SAAS,CAAC;AACpD,aAAO,EAAE,MAAM,IAAI,MAAM,WAAW,IAAI,UAAU;AAAA,IACpD;AACA,WAAO,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,EACzC,GAAG,CAAC,gBAAgB,MAAM,SAAS,CAAC;AAEpC,QAAM,kBAAkB,aAAa;AACrC,QAAM,aAAa,aAAa;AAChC,QAAM,UAAU,gBAAgB,SAAS,IACrC,KAAK,IAAI,GAAG,KAAK,IAAI,aAAa,gBAAgB,SAAS,CAAC,CAAC,IAC7D;AAEJ,QAAM,yBAAyB,cAAc,SAAY;AAEzD,QAAM,kBAAc,wBAAQ,MAAM;AAChC,UAAM,OAAO,EAAE,OAAO,SAAS,aAAa,MAAa,aAAa,MAAM,YAAY;AACxF,WAAO,CAAC,MAAM,GAAG,eAAe,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,MAAM,EAAE,MAAM,aAAa,OAAgC,EAAE,CAAC;AAAA,EAC9H,GAAG,CAAC,MAAM,OAAO,cAAc,CAAC;AAMhC,QAAM,sBAAkB,wBAAQ,MAAM;AACpC,QAAI,YAAY,OAAO,QAAQ;AAC7B,aAAO,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,cAAc,IAAI;AAAA,IAChE;AACA,WAAO,CAAC,CAAC,QAAQ,gBAAgB,IAAI;AAAA,EACvC,GAAG,CAAC,YAAY,IAAI,CAAC;AAErB,QAAM,kBAAc,wBAAQ,MAAM;AAChC,QAAI,eAAe,CAAC,UAAU,OAAQ,QAAO,EAAE,aAAa,QAAW,YAAY,OAAU;AAC7F,UAAM,aAAa,IAAI,IAAI,UAAU,MAAM,GAAG,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC;AAC/E,UAAM,cAAc,UAAU,OAAO,GAAG,cAAc;AACtD,WAAO,EAAE,aAAa,WAAW;AAAA,EACnC,GAAG,CAAC,aAAa,WAAW,OAAO,CAAC;AAGpC,QAAM,sBAAkB,4BAAY,CAAC,QAAkB;AACrD,iBAAa,GAAG;AAChB,sBAAkB,CAAC,CAAC;AAAA,EACtB,GAAG,CAAC,CAAC;AAEL,QAAM,2BAAuB,4BAAY,CAAC,QAAyB;AACjE,QAAI,OAAO,QAAQ,SAAU,gBAAe,GAAG;AAAA,EACjD,GAAG,CAAC,CAAC;AAEL,QAAM,sBAAkB;AAAA,IACtB,CAAC,aAAqB;AACpB,UAAI,CAAC,WAAY;AACjB,YAAM,QAAQ,oBAAoB,YAAY,iBAAiB,UAAU,gBAAgB;AACzF,UAAI,OAAO;AACT,0BAAkB,CAAC,SAAS,CAAC,GAAG,MAAM,EAAE,GAAG,OAAO,mBAAmB,YAAY,CAAC,CAAC;AACnF,uBAAe,CAAC;AAAA,MAClB;AAAA,IACF;AAAA,IACA,CAAC,YAAY,iBAAiB,kBAAkB,WAAW;AAAA,EAC7D;AAEA,QAAM,+BAA2B,4BAAY,CAAC,UAAkB;AAC9D,sBAAkB,CAAC,SAAS;AAC1B,YAAM,SAAS,UAAU,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK;AACjD,UAAI,OAAQ,gBAAe,OAAO,iBAAiB;AACnD,aAAO,UAAU,IAAI,CAAC,IAAI,KAAK,MAAM,GAAG,KAAK;AAAA,IAC/C,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,sBAAkB;AAAA,IACtB,CAAC,cAA+B;AAC9B,UAAI,OAAO,cAAc,UAAU;AAAE,uBAAe,SAAS;AAAG;AAAA,MAAQ;AACxE,UAAI,YAAY;AACd,cAAM,SAAS,oBAAoB,YAAY,SAAS;AACxD,YAAI,QAAQ,kBAAkB;AAAE,0BAAgB,SAAS;AAAG;AAAA,QAAQ;AAAA,MACtE;AACA,YAAM,MAAM,gBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,SAAS;AACvE,UAAI,OAAO,EAAG,gBAAe,GAAG;AAAA,IAClC;AAAA,IACA,CAAC,YAAY,iBAAiB,eAAe;AAAA,EAC/C;AAEA,QAAM,2BAAuB;AAAA,IAC3B,CAAC,MAAc,cAAuB;AACpC,UAAI,aAAa,MAAM;AACrB,0BAAkB,CAAC,CAAC;AACpB,cAAM,QAAQ,oBAAoB,MAAM,WAAW,MAAM,gBAAgB;AACzE,YAAI,OAAO;AAAE,4BAAkB,CAAC,EAAE,GAAG,OAAO,mBAAmB,YAAY,CAAC,CAAC;AAAG,yBAAe,CAAC;AAAA,QAAG;AAAA,MACrG,OAAO;AACL,0BAAkB,CAAC,CAAC;AACpB,cAAM,MAAM,UAAU,UAAU,CAAC,MAAM,EAAE,eAAe,IAAI;AAC5D,YAAI,OAAO,EAAG,gBAAe,GAAG;AAAA,MAClC;AAAA,IACF;AAAA,IACA,CAAC,MAAM,WAAW,kBAAkB,WAAW;AAAA,EACjD;AAGA,QAAM,YAAY,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAG5D,MAAI,UAAU;AACZ,WACE,+CAAC,SAAI,WAAsB,OAAc,WAAQ,qBAC/C;AAAA,oDAAC,SAAI,WAAQ,cACV,kBAAQ,IAAI,CAAC,QACZ,8CAAC,YAAoB,WAAQ,aAAY,eAAa,IAAI,OAAO,WAAW,SAAS,MAAM,gBAAgB,IAAI,EAAE,GAAI,cAAI,QAA5G,IAAI,EAA6G,CAC/H,GACH;AAAA,MACA,+CAAC,SAAI,WAAQ,iBAAgB,YAAU,WACpC;AAAA,sBAAc,YAAY,8CAAC,eAAY,MAAM,cAAc,MAAM,MAAY,aAA0B,UAAQ,MAAC;AAAA,SAC/G,cAAc,iBAAiB,cAAc,oBAC7C,gFACE;AAAA,wDAAC,sBAAmB,WAAW,iBAAiB,eAAe,SAAS,eAAe,sBAAsB,UAAQ,MAAC;AAAA,UACrH,eAAe,8CAAC,qBAAkB,aAA0B,YAAY,0BAA0B;AAAA,UAClG,cAAc,2BAA2B,EAAE,MAAM,YAAY,WAAW,iBAAiB,eAAe,SAAS,aAAa,iBAAiB,YAAY,CAAC;AAAA,UAC7J,8CAAC,eAAY,WAAW,iBAAiB,eAAe,SAAS,UAAQ,MAAC;AAAA,UAC1E,8CAAC,kBAAe,WAAW,iBAAiB,eAAe,SAAS,kBAAkB,wBAAwB,UAAQ,MAAC;AAAA,UACvH,8CAAC,iBAAc,WAAW,iBAAiB,eAAe,SAAS,UAAU,sBAAsB,UAAQ,MAAC;AAAA,WAC9G;AAAA,SAEJ;AAAA,OACF;AAAA,EAEJ;AAKA,QAAM,eAAe,CAAC,CAAC,4BAA4B,CAAC,CAAC;AAGrD,QAAM,qBAAiB,wBAAQ,MAAM;AACnC,QAAI,cAAc,UAAU;AAC1B,aAAO,8CAAC,eAAY,MAAM,cAAc,MAAM,MAAY,aAA0B,MAAY;AAAA,IAClG;AACA,QAAI,cAAc,UAAU;AAC1B,aAAO,8CAAC,eAAY,WAAW,iBAAiB,eAAe,SAAS,MAAY,OAAO,EAAE,QAAQ,OAAO,GAAG;AAAA,IACjH;AACA,QAAI,cAAc,aAAa;AAC7B,aAAO,8CAAC,kBAAe,WAAW,iBAAiB,eAAe,SAAS,kBAAkB,wBAAwB,MAAY,OAAO,EAAE,QAAQ,OAAO,GAAG;AAAA,IAC9J;AACA,UAAM,aAAa,eAAe,KAAK,CAACA,OAAMA,GAAE,OAAO,SAAS;AAChE,QAAI,YAAY,QAAQ;AACtB,aAAO,WAAW,OAAO,EAAE,WAAW,iBAAiB,eAAe,QAAQ,CAAC;AAAA,IACjF;AAEA,UAAM,WAAW,kBAAkB,KAAK,CAACA,OAAMA,GAAE,OAAO,SAAS;AACjE,QAAI,UAAU;AACZ,aACE;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,SAAS;AAAA,UACf,aAAa,SAAS;AAAA,UACtB,oBAAoB,SAAS;AAAA,UAC7B,WAAW;AAAA,UACX,eAAe;AAAA;AAAA,MACjB;AAAA,IAEJ;AACA,WAAO;AAAA,EACT,GAAG,CAAC,WAAW,YAAY,MAAM,aAAa,MAAM,iBAAiB,SAAS,wBAAwB,eAAe,iBAAiB,CAAC;AAGvI,QAAM,eACJ,+CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,QAAQ,QAAQ,UAAU,SAAS,GAEzF;AAAA,kDAAC,SAAI,OAAO;AAAA,MACV,SAAS;AAAA,MACT,cAAc,aAAa,MAAM,MAAM;AAAA,MACvC,YAAY,MAAM;AAAA,MAClB,YAAY;AAAA,MACZ,WAAW;AAAA,IACb,GACG,kBAAQ,IAAI,CAAC,QAAQ;AACpB,YAAM,SAAS,IAAI,OAAO;AAC1B,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,SAAS,MAAM,gBAAgB,IAAI,EAAc;AAAA,UACjD,OAAO,IAAI;AAAA,UACX,OAAO;AAAA,YACL,SAAS;AAAA,YACT,UAAU;AAAA,YACV,YAAY,SAAS,MAAM;AAAA,YAC3B,eAAe;AAAA,YACf,eAAe;AAAA,YACf,OAAO,SAAS,MAAM,UAAU,MAAM;AAAA,YACtC,YAAY;AAAA,YACZ,QAAQ;AAAA,YACR,cAAc,SAAS,aAAa,MAAM,OAAO,KAAK;AAAA,YACtD,QAAQ;AAAA,YACR,YAAY;AAAA,YACZ,YAAY;AAAA,UACd;AAAA,UAEC,cAAI;AAAA;AAAA,QAlBA,IAAI;AAAA,MAmBX;AAAA,IAEJ,CAAC,GACH;AAAA,IAEA,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,OAAO,GACrC,0BACH;AAAA,KACF;AAGF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL;AAAA,MACA,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,eAAe;AAAA,QACf,UAAU;AAAA,QACV,YAAY,MAAM;AAAA,QAClB,OAAO,MAAM;AAAA,QACb,YAAY,MAAM;AAAA,QAClB,UAAU;AAAA,QACV,GAAG;AAAA,MACL;AAAA,MACA,WAAQ;AAAA,MAGR;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,YACX,eAAe;AAAA,YACf,eAAe;AAAA,YACf;AAAA;AAAA,QACF;AAAA,QAGC,eACC,8CAAC,qBAAkB,aAA0B,YAAY,0BAA0B;AAAA,QAIrF,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,WAAW,SAAS,UAAU,SAAS,QAAQ,eAAe,SAAS,GACrG;AAAA;AAAA,UAEC,gFAEG;AAAA,4BACC,8CAAC,SAAI,OAAO,EAAE,QAAQ,KAAK,YAAY,GAAG,UAAU,SAAS,GAC1D,mCAA0B;AAAA,cACzB,MAAM;AAAA,cACN,WAAW;AAAA,cACX,eAAe;AAAA,cACf,aAAa;AAAA,cACb;AAAA,YACF,CAAC,GACH;AAAA,YAID,mBACC,gFACE;AAAA,4DAAC,aAAU,OAAO,WAAW,UAAU,cAAc,SAAS,MAAM,WAAW,CAAC,YAAY,GAAG;AAAA,cAC9F,gBACC,8CAAC,SAAI,OAAO,EAAE,WAAW,KAAK,UAAU,QAAQ,YAAY,EAAE,GAC5D;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO,cAAc,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAAA,kBAC5C,aAAa,YAAY;AAAA,kBACzB,YAAY,YAAY;AAAA,kBACxB,cAAc;AAAA;AAAA,cAChB,GACF;AAAA,eAEJ;AAAA,YAIF,8CAAC,aAAU,OAAO,YAAY,UAAU,eAAe,SAAS,MAAM,YAAY,CAAC,aAAa,GAAG;AAAA,YAClG,iBACC,8CAAC,SAAI,OAAO,EAAE,WAAW,KAAK,YAAY,GAAG,UAAU,SAAS,GAC7D,wBACH;AAAA,YAIF,8CAAC,aAAU,OAAO,aAAa,QAAQ,GAAG,gBAAgB,MAAM,WAAW,UAAU,kBAAkB,SAAS,gBAAgB;AAAA,YAC/H,oBACC,8CAAC,SAAI,OAAO,EAAE,YAAY,GAAG,UAAU,SAAS,GAC9C,wDAAC,iBAAc,WAAW,iBAAiB,eAAe,SAAS,UAAU,sBAAsB,MAAY,GACjH;AAAA,aAEJ;AAAA;AAAA;AAAA,UAGA,gFACE;AAAA,2DAAC,SAAI,OAAO,EAAE,MAAM,GAAG,SAAS,QAAQ,UAAU,SAAS,GAGxD;AAAA,kCACC,eACE,+CAAC,SAAI,OAAO,EAAE,OAAO,KAAK,YAAY,GAAG,SAAS,QAAQ,eAAe,OAAO,UAAU,SAAS,GACjG;AAAA,8DAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,OAAO,GACtC;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO,cAAc,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAAA,oBAC5C,aAAa,YAAY;AAAA,oBACzB,YAAY,YAAY;AAAA,oBACxB,cAAc;AAAA;AAAA,gBAChB,GACF;AAAA,gBACA,8CAAC,aAAU,OAAM,YAAW,UAAU,MAAM,MAAK,QAAO,SAAS,MAAM,WAAW,KAAK,GAAG;AAAA,iBAC5F,IAEA,8CAAC,aAAU,OAAM,YAAW,UAAU,OAAO,MAAK,QAAO,SAAS,MAAM,WAAW,IAAI,GAAG;AAAA,cAS7F,eACC,8CAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,UAAU,UAAU,EAAE,GACpD,mCAA0B;AAAA,gBACzB,MAAM;AAAA,gBACN,WAAW;AAAA,gBACX,eAAe;AAAA,gBACf,aAAa;AAAA,gBACf;AAAA,cACA,CAAC,GACH,IAEA,8CAAC,SAAI,OAAO,EAAE,MAAM,EAAE,GAAG;AAAA,cAI3B,8CAAC,aAAU,OAAM,WAAU,UAAU,eAAe,SAAS,MAAM,YAAY,CAAC,aAAa,GAAG;AAAA,cAG/F,iBACD,8CAAC,SAAI,OAAO,EAAE,OAAO,OAAO,UAAU,KAAK,UAAU,KAAK,SAAS,QAAQ,eAAe,UAAU,UAAU,SAAS,GACrH;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAM;AAAA,kBACN,cAAc;AAAA,kBACd,WAAW;AAAA,kBACX,eAAe;AAAA,kBACf;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA,mBAAmB,CAAC,OAAO;AACzB,0BAAM,MAAM,gBAAgB,UAAU,CAAC,MAAM,EAAE,mBAAmB,EAAE;AACpE,wBAAI,OAAO,EAAG,gBAAe,GAAG;AAAA,kBAClC;AAAA;AAAA,cACF,GACF;AAAA,eAEF;AAAA,YAGA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,gBACX,eAAe;AAAA,gBACf,iBAAiB;AAAA;AAAA,YACnB;AAAA,aACF;AAAA,WAEJ;AAAA;AAAA;AAAA,EACF;AAEJ;;;A+Bx1CA,YAAuB;AACvB,IAAAK,iBAAwB;AA+IpB,IAAAC,uBAAA;AA/FJ,SAAS,WAAW,OAGsB;AACxC,MAAI,SAAS,MAAM;AACjB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,EAAE,MAAM,gBAAgB,SAAS,qBAAqB;AAAA,IAC/D;AAAA,EACF;AAEA,MAAI,YAAqB;AACzB,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,CAAC,MAAM,KAAK,GAAG;AACjB,aAAO,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,gBAAgB,SAAS,eAAe,EAAE;AAAA,IAC/E;AACA,QAAI;AACF,kBAAY,KAAK,MAAM,KAAK;AAAA,IAC9B,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO,EAAE,MAAM,gBAAgB,SAAU,IAAc,QAAQ;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,aAAa,OAAO,cAAc,UAAU;AAC/C,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,EAAE,MAAM,cAAc,SAAS,+BAA+B;AAAA,IACvE;AAAA,EACF;AAEA,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,kBAAkB,UAAU;AACvC,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACA,MAAI,EAAE,kBAAkB,GAAG;AACzB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,6BAA6B,EAAE,aAAa;AAAA,QACrD,SAAS,EAAE;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,MAAM,OAAO,EAAE;AAC9B;AAEA,IAAM,eAA2B,CAAC,aAAa;AAExC,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAgD;AAC9C,QAAM,aAAS,wBAAQ,MAAM,WAAW,KAAK,GAAG,CAAC,KAAK,CAAC;AAGvD,EAAM,gBAAU,MAAM;AACpB,QAAI,CAAC,OAAO,MAAM,QAAS,SAAQ,OAAO,KAAK;AAAA,EACjD,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,QAAM,gBAAY,wBAAQ,MAAM;AAC9B,QAAI,CAAC,OAAO,MAAM,CAAC,OAAO,MAAM,SAAU,QAAO,CAAC;AAClD,QAAI;AACF,aAAO;AAAA,QACL,OAAO,MAAM;AAAA,QACZ,OAAO,MAAM,oBAAuE;AAAA,MACvF;AAAA,IACF,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,MAAI,CAAC,OAAO,MAAM,UAAU,WAAW,GAAG;AACxC,WAAQ,YAAY;AAAA,EACtB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAM,OAAO,MAAM;AAAA,MACnB,kBAAkB,OAAO,MAAM;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF;AAEJ;","names":["import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","v","import_jsx_runtime","import_react","import_jsx_runtime","fmt","v","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_jsx_runtime","v","import_react","import_jsx_runtime","TreeNode","SectionLabel","SubflowTree","import_react","import_jsx_runtime","SubflowBreadcrumb","import_react","dagre","import_react","import_jsx_runtime","StageNode","import_react","import_react","padding","import_jsx_runtime","import_react","import_jsx_runtime","import_react","DEFAULT_NODE_W","DEFAULT_NODE_H","padding","padding","DEFAULT_NODE_W","DEFAULT_NODE_H","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","DataTracePanel","DataTraceFrame","import_jsx_runtime","InspectorPanel","import_react","import_jsx_runtime","InsightPanel","InsightTabs","InsightGrid","import_react","import_jsx_runtime","CompactTimeline","import_jsx_runtime","HLinePill","VLinePill","v","DetailsContent","RightPanel","snapshots","tabs","import_react","import_jsx_runtime"]}
|