{"version":3,"file":"link-analysis.mjs","sources":["../src/components/Tooltip.tsx","../src/components/GraphVisualization.tsx","../src/utils/normalize.ts","../src/utils/detachedNodes.ts","../src/contexts/ThemeContext.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport type { Node, Edge } from '../types/graph';\n\ninterface TooltipProps {\n  visible: boolean;\n  x: number;\n  y: number;\n  node?: Node;\n  edge?: Edge;\n  content?: React.ReactNode;\n  idAttr?: string;\n  pinned?: boolean;\n  onClose?: () => void;\n}\n\nconst NODE_FIELD_MAPPINGS: { key: string; label: string }[] = [\n  { key: 'first_name', label: 'First Name' },\n  { key: 'middle_name', label: 'Middle Name' },\n  { key: 'last_name', label: 'Last Name' },\n  { key: 'nick_name', label: 'Nick Name' },\n  { key: 'national_id', label: 'National ID' },\n  { key: 'phone_number', label: 'Phone Number' },\n  { key: 'family_name', label: 'Family Name' },\n  { key: 'gender', label: 'Gender' },\n  { key: 'height', label: 'Height' },\n  { key: 'weight', label: 'Weight' },\n  { key: 'face_colour', label: 'Face Colour' },\n  { key: 'eye_colour', label: 'Eye Colour' },\n  { key: 'physical_injury', label: 'Physical Injury' },\n  { key: 'birth_date', label: 'Birth Date' },\n  { key: 'education_status', label: 'Education' },\n  { key: 'background_history', label: 'Background' },\n  { key: 'marriage_status', label: 'Marital Status' },\n  { key: 'job_status', label: 'Job Status' },\n  { key: 'target_details', label: 'Target Details' },\n  { key: 'status', label: 'Status' },\n  { key: 'approved_date', label: 'Approved Date' },\n  { key: 'rejected_date', label: 'Rejected Date' },\n  { key: 'comment', label: 'Comment' },\n  { key: 'created_at', label: 'Created At' },\n  { key: 'updated_at', label: 'Updated At' },\n  { key: 'is_active', label: 'Active' },\n  { key: 'target_person', label: 'Target Person' },\n];\n\nconst Tooltip: React.FC<TooltipProps> = ({ visible, x, y, node, edge, content, idAttr, pinned = false, onClose }) => {\n  const [position, setPosition] = useState({ x, y });\n\n  useEffect(() => {\n    if (!visible) return;\n\n    // Adjust position to keep tooltip in viewport\n    const tooltip = document.getElementById(idAttr || 'graph-tooltip');\n    if (tooltip) {\n      const rect = tooltip.getBoundingClientRect();\n      const viewportWidth = window.innerWidth;\n      const viewportHeight = window.innerHeight;\n      \n      let adjustedX = x;\n      let adjustedY = y;\n\n      // Adjust horizontal position\n      if (x + rect.width > viewportWidth - 20) {\n        adjustedX = x - rect.width - 10;\n      }\n      \n      // Adjust vertical position\n      if (y + rect.height > viewportHeight - 20) {\n        adjustedY = y - rect.height - 10;\n      }\n\n      setPosition({ x: adjustedX, y: adjustedY });\n    } else {\n      setPosition({ x, y });\n    }\n  }, [visible, x, y, idAttr]);\n\n  if (!visible || (!node && !edge && !content)) return null;\n\n  const formatDate = (dateString?: string) => {\n    if (!dateString) return 'N/A';\n    return new Date(dateString).toLocaleDateString('en-US', {\n      year: 'numeric',\n      month: 'short',\n      day: 'numeric'\n    });\n  };\n\n  const renderNodeTooltip = (node: Node) => {\n    const missingFields = []\n    if (!node.type) missingFields.push('Type')\n    if (!node.metadata?.category) missingFields.push('Category')\n    if (!node.metadata?.description) missingFields.push('Description')\n    if (!node.image) missingFields.push('Image')\n\n    // Check if this is a virtual node for isolated edges\n    const isVirtualNode = node.metadata?.isVirtual\n    const isFloatingEdge = node.metadata?.isFloating\n\n    const propertySource = {\n      ...(node.metadata?.properties || {}),\n      ...(node.data || {}),\n    };\n\n    const detailEntries = NODE_FIELD_MAPPINGS.map(({ key, label }) => {\n      const value = propertySource?.[key];\n      if (value === null || value === undefined || value === '') {\n        return null;\n      }\n      return {\n        key,\n        label,\n        value,\n      };\n    }).filter(Boolean) as { key: string; label: string; value: any }[];\n\n    const renderValue = (val: any) => {\n      if (val === null || val === undefined) return 'N/A';\n      if (typeof val === 'boolean') return val ? 'Yes' : 'No';\n      if (val instanceof Date) return formatDate(val.toString());\n      if (typeof val === 'object') return JSON.stringify(val);\n      return String(val);\n    };\n\n    return (\n      <div className=\"relative bg-theme-card border border-theme-border rounded-lg shadow-lg p-4 max-w-xs z-50\">\n        {pinned && onClose && (\n          <button\n            onClick={onClose}\n            className=\"absolute top-2 right-2 text-theme-text-secondary hover:text-theme-text transition-colors text-xs\"\n            aria-label=\"Close tooltip\"\n          >\n            ✕\n          </button>\n        )}\n        <div className=\"flex items-start space-x-3 mb-3\">\n          {isVirtualNode ? (\n            <div className={`w-12 h-12 rounded-full flex items-center justify-center text-white text-lg font-bold flex-shrink-0 ${\n              isFloatingEdge ? 'bg-gray-800 border-2 border-gray-600' : 'bg-black border-2 border-red-500 border-dotted'\n            }`}>\n              {isFloatingEdge ? '●' : '⚠️'}\n            </div>\n          ) : node.image ? (\n            <img \n              src={node.image} \n              alt={node.label}\n              className=\"w-12 h-12 rounded-full object-cover flex-shrink-0\"\n              onError={(e) => {\n                (e.target as HTMLImageElement).style.display = 'none';\n              }}\n            />\n          ) : (\n            <div className=\"w-12 h-12 rounded-full bg-theme-bg-secondary flex items-center justify-center text-theme-text-secondary text-lg font-bold flex-shrink-0\">\n              {node.label.charAt(0).toUpperCase()}\n            </div>\n          )}\n          <div className=\"flex-1 min-w-0\">\n            <h3 className=\"font-semibold text-theme-text text-sm truncate\">{node.label}</h3>\n            <div className=\"flex items-center space-x-2 mt-1\">\n              {isVirtualNode ? (\n                <span className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${\n                  isFloatingEdge ? 'bg-gray-200 text-gray-800' : 'bg-red-100 text-red-800'\n                }`}>\n                  {isFloatingEdge ? 'Floating Edge' : 'Missing Node'}\n                </span>\n              ) : (\n                <span className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${\n                  node.type \n                    ? 'bg-theme-info/10 text-theme-info' \n                    : 'bg-theme-warning/10 text-theme-warning'\n                }`}>\n                  {node.type || 'No Type'}\n                </span>\n              )}\n              {node.metadata?.category ? (\n                <span className=\"inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-theme-success/10 text-theme-success\">\n                  {node.metadata.category}\n                </span>\n              ) : (\n                <span className=\"inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-theme-warning/10 text-theme-warning\">\n                  No Category\n                </span>\n              )}\n            </div>\n          </div>\n        </div>\n      \n        {isVirtualNode ? (\n          <div className=\"mb-3 p-3 bg-gray-50 rounded border border-gray-200\">\n            {isFloatingEdge ? (\n              <>\n                <div className=\"text-sm text-gray-800 font-medium mb-2\">● Floating Edge</div>\n                <p className=\"text-sm text-gray-700 mb-2\">\n                  {node.metadata?.hasEmptyFields \n                    ? 'This edge has empty source and target fields'\n                    : 'This edge has no connected nodes'\n                  }\n                </p>\n                <div className=\"text-xs text-gray-600\">\n                  <div><strong>Label:</strong> {node.metadata?.edgeLabel || 'No label'}</div>\n                  <div><strong>Source:</strong> {node.metadata?.originalSource || 'empty'} (missing)</div>\n                  <div><strong>Target:</strong> {node.metadata?.originalTarget || 'empty'} (missing)</div>\n                </div>\n              </>\n            ) : (\n              <>\n                <div className=\"text-sm text-red-800 font-medium mb-2\">⚠️ Isolated Edge Detected</div>\n                <p className=\"text-sm text-red-700 mb-2\">{node.metadata?.description}</p>\n                <div className=\"text-xs text-red-600\">\n                  <div><strong>Original ID:</strong> {node.metadata?.originalId}</div>\n                  <div><strong>Edge ID:</strong> {node.metadata?.edgeId}</div>\n                  <div><strong>Edge Label:</strong> {node.metadata?.edgeLabel || 'No label'}</div>\n                </div>\n              </>\n            )}\n          </div>\n        ) : node.metadata?.description ? (\n          <div className=\"mb-3\">\n            <p className=\"text-sm text-theme-text\">{node.metadata.description}</p>\n          </div>\n        ) : (\n          <div className=\"mb-3 p-2 bg-theme-warning/10 rounded border border-theme-warning/20\">\n            <p className=\"text-xs text-theme-warning\">⚠️ No description provided</p>\n          </div>\n        )}\n        \n        {node.metadata?.tags && node.metadata.tags.length > 0 ? (\n          <div className=\"mb-3\">\n            <p className=\"text-xs font-medium text-theme-text mb-1\">Tags:</p>\n            <div className=\"flex flex-wrap gap-1\">\n              {node.metadata.tags.map(tag => (\n                <span \n                  key={tag} \n                  className=\"inline-flex items-center px-1.5 py-0.5 rounded text-xs bg-theme-bg-secondary text-theme-text-secondary\"\n                >\n                  {tag}\n                </span>\n              ))}\n            </div>\n          </div>\n        ) : (\n          <div className=\"mb-3 p-2 bg-theme-info/10 rounded border border-theme-info/20\">\n            <p className=\"text-xs text-theme-info\">ℹ️ No tags added</p>\n          </div>\n        )}\n\n        {missingFields.length > 0 && (\n          <div className=\"mb-3 p-2 bg-theme-warning/10 rounded border border-theme-warning/20\">\n            <p className=\"text-xs font-medium text-theme-warning mb-1\">Missing Information:</p>\n            <div className=\"flex flex-wrap gap-1\">\n              {missingFields.map(field => (\n                <span \n                  key={field} \n                  className=\"inline-flex items-center px-1.5 py-0.5 rounded text-xs bg-theme-warning/20 text-theme-warning\"\n                >\n                  {field}\n                </span>\n              ))}\n            </div>\n          </div>\n        )}\n        \n        {detailEntries.length > 0 && (\n          <div className=\"mb-3\">\n            <p className=\"text-xs font-medium text-theme-text mb-1\">Details</p>\n            <div className=\"space-y-1 text-xs text-theme-text-secondary max-h-48 overflow-y-auto pr-1\">\n              {detailEntries.map(({ key, label, value }) => (\n                <div key={key} className=\"flex justify-between gap-2\">\n                  <span className=\"font-medium text-theme-text\">{label}:</span>\n                  <span className=\"text-right truncate flex-1\">{renderValue(value)}</span>\n                </div>\n              ))}\n            </div>\n          </div>\n        )}\n\n        <div className=\"border-t border-theme-border pt-2 mt-2 text-xs text-theme-text-secondary\">\n          <div className=\"flex justify-between items-center\">\n            <span>ID: {node.id}</span>\n            {node.metadata?.createdAt && (\n              <span>Created: {formatDate(node.metadata.createdAt)}</span>\n            )}\n          </div>\n          {node.metadata?.updatedAt && (\n            <div className=\"mt-1\">\n              <span>Updated: {formatDate(node.metadata.updatedAt)}</span>\n            </div>\n          )}\n        </div>\n      </div>\n    );\n  };\n\n  const renderEdgeTooltip = (edge: Edge) => {\n    const missingFields = []\n    if (!edge.label) missingFields.push('Label')\n\n    // Check if this is an isolated edge\n    const isIsolated = (edge as any).isIsolated\n\n    return (\n      <div className=\"relative bg-theme-card border border-theme-border rounded-lg shadow-lg p-3 max-w-xs z-50\">\n        {pinned && onClose && (\n          <button\n            onClick={onClose}\n            className=\"absolute top-2 right-2 text-theme-text-secondary hover:text-theme-text transition-colors text-xs\"\n            aria-label=\"Close tooltip\"\n          >\n            ✕\n          </button>\n        )}\n        <div className=\"mb-2\">\n          <h3 className=\"font-semibold text-theme-text text-sm\">Connection</h3>\n          <div className=\"text-sm text-theme-text mt-1\">\n            <span className=\"font-medium\">{edge.source}</span>\n            {edge.label ? (\n              <>\n                <span className=\"mx-2 text-theme-text-secondary\">→</span>\n                <span className=\"italic text-theme-accent\">{edge.label}</span>\n                <span className=\"mx-2 text-theme-text-secondary\">→</span>\n              </>\n            ) : (\n              <>\n                <span className=\"mx-2 text-theme-text-secondary\">→</span>\n                <span className=\"italic text-theme-warning\">No Label</span>\n                <span className=\"mx-2 text-theme-text-secondary\">→</span>\n              </>\n            )}\n            <span className=\"font-medium\">{edge.target}</span>\n          </div>\n          {isIsolated && (\n            <div className=\"mt-2 p-2 bg-red-50 rounded border border-red-200\">\n              <div className=\"text-xs text-red-800 font-medium\">⚠️ Isolated Edge</div>\n              <div className=\"text-xs text-red-600 mt-1\">\n                This edge references nodes that don't exist in the dataset\n              </div>\n            </div>\n          )}\n        </div>\n        \n        {edge.weight !== undefined ? (\n          <div className=\"mb-2\">\n            <span className=\"text-xs font-medium text-theme-text\">Weight: </span>\n            <span className=\"text-xs text-theme-text-secondary\">{edge.weight}</span>\n          </div>\n        ) : (\n          <div className=\"mb-2 p-2 bg-theme-info/10 rounded border border-theme-info/20\">\n            <p className=\"text-xs text-theme-info\">ℹ️ No weight specified</p>\n          </div>\n        )}\n\n        {missingFields.length > 0 && (\n          <div className=\"mb-2 p-2 bg-theme-warning/10 rounded border border-theme-warning/20\">\n            <p className=\"text-xs font-medium text-theme-warning mb-1\">Missing Information:</p>\n            <div className=\"flex flex-wrap gap-1\">\n              {missingFields.map(field => (\n                <span \n                  key={field} \n                  className=\"inline-flex items-center px-1.5 py-0.5 rounded text-xs bg-theme-warning/20 text-theme-warning\"\n                >\n                  {field}\n                </span>\n              ))}\n            </div>\n          </div>\n        )}\n        \n        <div className=\"border-t border-theme-border pt-2 text-xs text-theme-text-secondary\">\n          <span>Edge ID: {edge.id}</span>\n        </div>\n        \n        {edge.data && Object.keys(edge.data).length > 0 ? (\n          <div className=\"mt-2 pt-2 border-t border-theme-border\">\n            <p className=\"text-xs font-medium text-theme-text mb-1\">Additional Data:</p>\n            <div className=\"text-xs text-theme-text-secondary\">\n              {Object.entries(edge.data).map(([key, value]) => (\n                <div key={key} className=\"flex justify-between\">\n                  <span className=\"capitalize\">{key}:</span>\n                  <span className=\"ml-2 truncate\">{String(value)}</span>\n                </div>\n              ))}\n            </div>\n          </div>\n        ) : (\n          <div className=\"mt-2 pt-2 border-t border-theme-border\">\n            <p className=\"text-xs text-theme-info\">ℹ️ No additional data</p>\n          </div>\n        )}\n      </div>\n    );\n  };\n\n  return (\n    <div\n      id={idAttr || 'graph-tooltip'}\n      className=\"fixed z-50\"\n      style={{\n        left: `${position.x + 10}px`,\n        top: `${position.y + 10}px`,\n        transform: visible ? 'translateY(0) opacity(1)' : 'translateY(-10px) opacity(0)',\n        transition: 'all 0.2s ease-out',\n        pointerEvents: pinned ? 'auto' : 'none',\n      }}\n    >\n      {node ? renderNodeTooltip(node) : edge ? renderEdgeTooltip(edge) : content ? (\n        <div className=\"bg-white border border-gray-300 rounded-lg shadow-lg p-4 max-w-sm z-50 relative\">\n          {pinned && onClose && (\n            <button\n              onClick={onClose}\n              className=\"absolute top-2 right-2 text-gray-500 hover:text-gray-800 text-xs\"\n              aria-label=\"Close tooltip\"\n            >\n              ✕\n            </button>\n          )}\n          {content}\n        </div>\n      ) : null}\n    </div>\n  );\n};\n\nexport default Tooltip; ","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport CytoscapeComponent from 'react-cytoscapejs';\nimport cytoscape from 'cytoscape';\nimport coseBilkent from 'cytoscape-cose-bilkent';\nimport cola from 'cytoscape-cola';\nimport avsdf from 'cytoscape-avsdf';\nimport type { GraphData, GraphLayoutOptions, Node, Edge, DetachedNodesFilter } from '../types/graph';\nimport Tooltip from './Tooltip';\n\ninterface GraphVisualizationProps {\n  data: GraphData;\n  layout?: GraphLayoutOptions;\n  style?: React.CSSProperties;\n  selectedNodeIds?: string[];\n  onNodeClick?: (nodeId: string) => void;\n  onEdgeClick?: (edgeId: string) => void;\n  onSelectionChange?: (selectedNodeIds: string[]) => void;\n  includeFilters?: string[];\n  excludeFilters?: string[];\n  onIncludeFiltersChange?: (values: string[]) => void;\n  onExcludeFiltersChange?: (values: string[]) => void;\n  graphFilter?: DetachedNodesFilter;\n  onGraphFilterChange?: (next: DetachedNodesFilter) => void;\n  filterOptions?: {\n    categories: string[];\n    types: string[];\n    tags?: string[];\n  };\n  layoutOptions?: { name: string; description: string; config: GraphLayoutOptions }[];\n  selectedLayoutName?: string;\n  onLayoutSelect?: (name: string) => void;\n  onOpenDataManager?: () => void;\n}\n\nconst defaultLayout: GraphLayoutOptions = {\n  name: 'cose',\n  animate: true,\n  padding: 50,\n  nodeSpacing: 100,\n  edgeLength: 200,\n};\n\nconst defaultStyle: React.CSSProperties = {\n  width: '100%',\n  height: '600px',\n  border: 'none',\n  borderRadius: '8px',\n  backgroundColor: 'transparent',\n};\n\n// Neo4j-inspired color palette\nconst nodeTypeColors: Record<string, string> = {\n  person: '#5dade2',       // Steel blue\n  organization: '#58d68d', // Mint green\n  website: '#f4d03f',      // Golden\n  user: '#af7ac5',         // Lavender\n  location: '#ec7063',     // Coral\n  phone: '#3498db',\n  default: '#5dade2',\n};\n\nconst neoColors = {\n  background: '#07111f',\n  grid: 'rgba(255, 255, 255, 0.04)',\n  nodeLabel: '#ecf0f1',\n  nodeHalo: '#66e0ff',\n  nodeBorder: '#102337',\n  edgeDefault: '#7fb3d5',\n  edgeHover: '#f8c471',\n  edgeSelected: '#f1948a',\n  missing: '#f5b041',\n  virtual: '#95a5a6',\n};\n\nconst identifierKeys = ['phone_number', 'phoneNumber', 'phone', 'msisdn', 'target_person'];\n\nconst createIdentifierVariants = (value: unknown): string[] => {\n  if (value === null || value === undefined) return [];\n  const raw = String(value).trim();\n  if (!raw) return [];\n  const lower = raw.toLowerCase();\n  const digits = raw.replace(/[^0-9+]/g, '');\n  const variants = new Set<string>([lower]);\n  if (digits && digits !== lower) {\n    variants.add(digits);\n  }\n  return Array.from(variants);\n};\n\nconst buildIdentifierSetFromNode = (node: Node): Set<string> => {\n  const identifiers = new Set<string>();\n  const add = (value: unknown) => {\n    createIdentifierVariants(value).forEach((variant) => identifiers.add(variant));\n  };\n\n  add(node.id);\n  add(node.label);\n  add(node.type);\n  add(node.metadata?.category);\n  add(node.metadata?.primaryPhone);\n  node.metadata?.phoneAliases?.forEach(add);\n\n  const metaProps = node.metadata?.properties || {};\n  identifierKeys.forEach((key) => add((metaProps as Record<string, any>)[key]));\n\n  const nodeData = node.data || {};\n  identifierKeys.forEach((key) => add((nodeData as Record<string, any>)[key]));\n\n  return identifiers;\n};\n\ncytoscape.use(coseBilkent);\ncytoscape.use(cola);\ncytoscape.use(avsdf);\n\nconst GraphVisualization: React.FC<GraphVisualizationProps> = ({\n  data,\n  layout = defaultLayout,\n  style = defaultStyle,\n  selectedNodeIds,\n  onNodeClick,\n  onEdgeClick,\n  onSelectionChange,\n  includeFilters = [],\n  excludeFilters = [],\n  onIncludeFiltersChange,\n  onExcludeFiltersChange,\n  graphFilter,\n  onGraphFilterChange,\n  filterOptions,\n  layoutOptions,\n  selectedLayoutName,\n  onLayoutSelect,\n  onOpenDataManager,\n}) => {\n  const cyRef = useRef<cytoscape.Core | null>(null);\n  const [zoomLevel, setZoomLevel] = useState(1);\n  const [searchQuery, setSearchQuery] = useState('');\n  const [searchResults, setSearchResults] = useState<Node[]>([]);\n  const [highlightedNodeId, setHighlightedNodeId] = useState<string | null>(null);\n  const [mousePosition, setMousePosition] = useState<{ x: number; y: number } | null>(null);\n  const [showHelpPanel, setShowHelpPanel] = useState(false);\n  const [isFullscreen, setIsFullscreen] = useState(false);\n  const canvasRef = useRef<HTMLDivElement | null>(null);\n  const [showFilterOverlay, setShowFilterOverlay] = useState(true);\n  const [includeInput, setIncludeInput] = useState('');\n  const [excludeInput, setExcludeInput] = useState('');\n  const [controlTab, setControlTab] = useState<'basic' | 'advanced'>('basic');\n  const nodeIdentifierMap = useMemo(() => {\n    const map = new Map<string, Set<string>>();\n    data.nodes.forEach((node) => {\n      map.set(node.id, buildIdentifierSetFromNode(node));\n    });\n    return map;\n  }, [data.nodes]);\n\n  const getNodesMatchingValue = useCallback(\n    (value: string) => {\n      const variants = createIdentifierVariants(value);\n      if (variants.length === 0) return [];\n      return data.nodes.filter((node) => {\n        const identifiers = nodeIdentifierMap.get(node.id);\n        if (!identifiers) return false;\n        return variants.some((variant) => identifiers.has(variant));\n      });\n    },\n    [data.nodes, nodeIdentifierMap]\n  );\n\n  const includeSummaries = useMemo(\n    () =>\n      includeFilters.map((value) => ({\n        value,\n        nodes: getNodesMatchingValue(value),\n      })),\n    [includeFilters, getNodesMatchingValue]\n  );\n\n  const excludeSummaries = useMemo(\n    () =>\n      excludeFilters.map((value) => ({\n        value,\n        nodes: getNodesMatchingValue(value),\n      })),\n    [excludeFilters, getNodesMatchingValue]\n  );\n\n  const currentFilter = graphFilter || {};\n  const filterOptionsSafe = filterOptions || { categories: [], types: [], tags: [] };\n  const filtersEnabled = !!onGraphFilterChange;\n\n  const updateGraphFilter = (patch: Partial<DetachedNodesFilter>) => {\n    if (!onGraphFilterChange) return;\n    onGraphFilterChange({\n      ...currentFilter,\n      ...patch,\n    });\n  };\n\n  const handleIncludeSubmit = () => {\n    addFilterValue(includeInput, includeFilters, onIncludeFiltersChange, () => setIncludeInput(''));\n  };\n\n  const handleExcludeSubmit = () => {\n    addFilterValue(excludeInput, excludeFilters, onExcludeFiltersChange, () => setExcludeInput(''));\n  };\n\n  const handleIncludeKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n    if (event.key === 'Enter' || event.key === ',') {\n      event.preventDefault();\n      handleIncludeSubmit();\n    }\n  };\n\n  const handleExcludeKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n    if (event.key === 'Enter' || event.key === ',') {\n      event.preventDefault();\n      handleExcludeSubmit();\n    }\n  };\n\n  \n  // Tooltip state\n  const [tooltip, setTooltip] = useState<{\n    visible: boolean;\n    x: number;\n    y: number;\n    node?: Node;\n    edge?: Edge;\n    pinned: boolean;\n  }>({\n    visible: false,\n    x: 0,\n    y: 0,\n    pinned: false,\n  });\n\n  const hideTooltip = (force = false) => {\n    setTooltip(prev => {\n      if (!force && prev.pinned) {\n        return prev;\n      }\n      return {\n        visible: false,\n        x: prev.x,\n        y: prev.y,\n        pinned: false,\n        node: undefined,\n        edge: undefined,\n      };\n    });\n  };\n\n  const addFilterValue = (\n    value: string,\n    current: string[],\n    setter?: (values: string[]) => void,\n    resetInput?: () => void,\n  ) => {\n    if (!setter) return;\n    const normalized = value.trim();\n    if (!normalized) return;\n    const exists = current.some(v => v.toLowerCase() === normalized.toLowerCase());\n    if (exists) {\n      resetInput?.();\n      return;\n    }\n    setter([...current, normalized]);\n    resetInput?.();\n  };\n\n  const removeFilterValue = (\n    value: string,\n    current: string[],\n    setter?: (values: string[]) => void,\n  ) => {\n    if (!setter) return;\n    setter(current.filter(v => v !== value));\n  };\n\n  // Create sets/maps for node bookkeeping\n  const existingNodeIds = new Set(data.nodes.map(node => node.id))\n  const augmentedNodeIds = new Set(existingNodeIds)\n  const detailNodeMap = new Map<string, cytoscape.ElementDefinition>()\n  \n  const getDetailNodeId = (detail: string, role?: 'source' | 'target') => {\n    const clean = detail.trim()\n    if (!clean) return null\n    const safe = clean.replace(/[^a-zA-Z0-9+.-]/g, '_')\n    const nodeId = `cdr-${safe}`\n    const existing = detailNodeMap.get(nodeId)\n    if (existing) {\n      if (role) {\n        const roles = new Set(existing.data.roles || [])\n        roles.add(role)\n        existing.data.roles = Array.from(roles)\n      }\n      return nodeId\n    }\n\n    const roles = role ? [role] : []\n    detailNodeMap.set(nodeId, {\n      data: {\n        id: nodeId,\n        label: clean,\n        nodeType: 'cdr',\n        detail: clean,\n        roles,\n        hasImage: false,\n        backgroundColor: '#1f3a5f',\n        missingFields: [],\n        hasMissingInfo: false,\n      },\n      classes: 'cdr-node virtual-node'\n    })\n    augmentedNodeIds.add(nodeId)\n    return nodeId\n  }\n  \n  // Find isolated edges (only when explicit node ids reference missing nodes)\n  const isolatedEdges = data.edges.filter(edge => {\n    const hasExplicitSource = !!(edge.source && edge.source.trim() !== '')\n    const hasExplicitTarget = !!(edge.target && edge.target.trim() !== '')\n    const missingSource = hasExplicitSource && !existingNodeIds.has(edge.source!)\n    const missingTarget = hasExplicitTarget && !existingNodeIds.has(edge.target!)\n    return missingSource || missingTarget\n  })\n  \n  // Create virtual nodes for isolated edges\n  const virtualNodes = isolatedEdges.map((edge) => {\n    const isSourceMissing = !existingNodeIds.has(edge.source)\n    const isTargetMissing = !existingNodeIds.has(edge.target)\n    \n    // Create virtual nodes for missing source/target\n    const virtualNodes = []\n    \n    if (isSourceMissing) {\n      virtualNodes.push({\n        id: `virtual-source-${edge.source}`,\n        label: `Missing: ${edge.source}`,\n        type: 'isolated-edge-source',\n        metadata: {\n          originalId: edge.source,\n          edgeId: edge.id,\n          edgeLabel: edge.label,\n          isVirtual: true,\n          description: `This node is referenced by edge \"${edge.label || 'unnamed'}\" but doesn't exist in the dataset.`\n        },\n        classes: 'isolated-edge-node virtual-node'\n      })\n    }\n    \n    if (isTargetMissing) {\n      virtualNodes.push({\n        id: `virtual-target-${edge.target}`,\n        label: `Missing: ${edge.target}`,\n        type: 'isolated-edge-target',\n        metadata: {\n          originalId: edge.target,\n          edgeId: edge.id,\n          edgeLabel: edge.label,\n          isVirtual: true,\n          description: `This node is referenced by edge \"${edge.label || 'unnamed'}\" but doesn't exist in the dataset.`\n        },\n        classes: 'isolated-edge-node virtual-node'\n      })\n    }\n    \n    return virtualNodes\n  }).flat()\n\n  const unmatchedEdges: Edge[] = []\n  \n  const processedEdges = data.edges.map((edge, index) => {\n    const trimmedSource = edge.source?.trim() || ''\n    const trimmedTarget = edge.target?.trim() || ''\n    \n    let sourceId: string | null = trimmedSource || null\n    let targetId: string | null = trimmedTarget || null\n    \n    if (!sourceId && edge.source_detail) {\n      sourceId = getDetailNodeId(edge.source_detail, 'source')\n    }\n    \n    if (!targetId && edge.target_detail) {\n      targetId = getDetailNodeId(edge.target_detail, 'target')\n    }\n    \n    if (!sourceId || !targetId) {\n      unmatchedEdges.push(edge)\n      return null\n    }\n    \n    const missingFields: string[] = []\n    if (!edge.label) missingFields.push('label')\n    \n    const isIsolated = !augmentedNodeIds.has(sourceId) || !augmentedNodeIds.has(targetId)\n    \n    const validEdgeId = edge.id && edge.id.trim() !== '' ? edge.id : `edge-${index}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n    \n    return {\n      originalEdge: edge,\n      elementData: {\n        ...edge,\n        id: validEdgeId,\n        source: sourceId,\n        target: targetId,\n        hasMissingInfo: missingFields.length > 0,\n        missingFields,\n        isIsolated,\n        interactionCount: 1,\n      },\n      classNames: [\n        missingFields.length > 0 ? 'has-missing-info' : 'complete-info',\n        isIsolated ? 'isolated-edge' : 'connected-edge'\n      ].join(' '),\n    }\n  }).filter(Boolean) as {\n    originalEdge: Edge\n    elementData: Edge & {\n      hasMissingInfo: boolean\n      missingFields: string[]\n      isIsolated: boolean\n      interactionCount: number\n    }\n    classNames: string\n  }[]\n\n  const aggregationMap = new Map<string, typeof processedEdges>()\n  processedEdges.forEach(edge => {\n    const key = `${edge.elementData.source}||${edge.elementData.target}`\n    const existing = aggregationMap.get(key) || []\n    existing.push(edge)\n    aggregationMap.set(key, existing)\n  })\n\n  const aggregatedEdges = Array.from(aggregationMap.values()).map((group, index) => {\n    const base = group[0]\n    const interactionCount = group.length\n    const combinedLabels = group\n      .map(item => item.originalEdge.label)\n      .filter((label): label is string => Boolean(label))\n    const aggregatedLabel =\n      interactionCount > 1\n        ? `${combinedLabels[0] || base.originalEdge.label || 'Interactions'} (${interactionCount})`\n        : combinedLabels[0] || base.originalEdge.label || ''\n    const description =\n      interactionCount > 1\n        ? `${interactionCount} interactions between ${base.elementData.source} and ${base.elementData.target}`\n        : base.originalEdge.label || 'Interaction'\n    \n    return {\n      data: {\n        ...base.elementData,\n        id:\n          interactionCount === 1\n            ? base.elementData.id\n            : `${base.elementData.source}-${base.elementData.target}-bundle-${index}`,\n        label: aggregatedLabel,\n        interactionCount,\n        interactionDescription: description,\n        aggregatedEdgeIds: group.map(item => item.elementData.id),\n        aggregatedLabels: combinedLabels,\n      },\n      classes: [\n        base.classNames,\n        interactionCount > 1 ? 'multiple-interactions' : '',\n      ]\n        .filter(Boolean)\n        .join(' '),\n    } as cytoscape.ElementDefinition\n  })\n\n  const reciprocalMap = new Map<string, cytoscape.ElementDefinition[]>()\n  aggregatedEdges.forEach(edge => {\n    const source = String(edge.data.source)\n    const target = String(edge.data.target)\n    const key = [source, target].sort().join('::')\n    const existing = reciprocalMap.get(key) || []\n    existing.push(edge)\n    reciprocalMap.set(key, existing)\n  })\n\n  reciprocalMap.forEach(edges => {\n    if (edges.length < 2) return\n    edges.forEach(edge => {\n      const existingClasses = edge.classes || []\n      const classes = Array.isArray(existingClasses)\n        ? [...existingClasses]\n        : String(existingClasses)\n            .split(' ')\n            .filter(Boolean)\n      classes.push('reciprocal-edge')\n      const source = String(edge.data.source)\n      const target = String(edge.data.target)\n      if (source.localeCompare(target) < 0) {\n        classes.push('reciprocal-forward')\n      } else {\n        classes.push('reciprocal-backward')\n      }\n      edge.classes = Array.from(new Set(classes)).join(' ')\n      edge.data = {\n        ...edge.data,\n        isReciprocal: true,\n        reciprocalKey: [source, target].sort().join('::'),\n      }\n    })\n  })\n  \n  const detailNodes = Array.from(detailNodeMap.values()).map(node => ({\n    data: node.data,\n    classes: `${node.classes} complete-info`,\n  }))\n  \n  // Create simple dark circles for completely floating edges (no ids or details)\n  const floatingVirtualNodes = unmatchedEdges.map((edge, index) => {\n    const hasEmptySource = (!edge.source || edge.source.trim() === '') && (!edge.source_detail || edge.source_detail.trim() === '')\n    const hasEmptyTarget = (!edge.target || edge.target.trim() === '') && (!edge.target_detail || edge.target_detail.trim() === '')\n    const hasEmptyBoth = hasEmptySource && hasEmptyTarget\n    \n    const validEdgeId = edge.id && edge.id.trim() !== '' ? edge.id : `floating-edge-${index}`\n    \n    return {\n      id: `floating-${validEdgeId}`,\n      label: edge.label || 'unnamed',\n      type: 'floating-edge',\n      metadata: {\n        originalEdgeId: edge.id,\n        originalSource: edge.source_detail || edge.source || 'empty',\n        originalTarget: edge.target_detail || edge.target || 'empty',\n        edgeLabel: edge.label,\n        isVirtual: true,\n        isFloating: true,\n        hasEmptyFields: hasEmptyBoth,\n        description: hasEmptyBoth \n          ? `Floating edge: ${edge.label || 'unnamed'} (no caller/callee detail)`\n          : `Floating edge: ${edge.label || 'unnamed'}`\n      },\n      classes: 'floating-edge-node'\n    }\n  })\n\n  const elements = [\n    // Regular nodes\n    ...data.nodes.map((node) => {\n      const missingFields = []\n      if (!node.type) missingFields.push('type')\n      if (!node.metadata?.category) missingFields.push('category')\n      if (!node.metadata?.description) missingFields.push('description')\n      if (!node.image) missingFields.push('image')\n\n      // Ensure node has a valid ID\n      const validNodeId = node.id && node.id.trim() !== '' ? node.id : `node-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n\n      return {\n      data: { \n        ...node,\n          id: validNodeId,\n        // Add computed properties for styling\n        nodeType: node.type || 'default',\n        hasImage: !!node.image,\n        backgroundColor: nodeTypeColors[node.type || 'default'] || nodeTypeColors.default,\n          missingFields: missingFields,\n          hasMissingInfo: missingFields.length > 0,\n      },\n      classes: [\n        node.type ? node.type : 'default',\n          node.image ? 'has-image' : 'no-image',\n          missingFields.length > 0 ? 'has-missing-info' : 'complete-info'\n      ].join(' '),\n      }\n    }),\n    // Detail nodes synthesized from CDR data\n    ...detailNodes,\n    // Virtual nodes for isolated edges\n    ...virtualNodes.map((node) => ({\n      data: {\n        ...node,\n        nodeType: 'isolated-edge',\n        backgroundColor: '#000000',\n        hasImage: false,\n        missingFields: ['node'],\n        hasMissingInfo: true,\n      },\n      classes: 'isolated-edge-node virtual-node has-missing-info'\n    })),\n    // Virtual nodes for floating edges\n    ...floatingVirtualNodes.map((node) => ({\n      data: {\n        ...node,\n        nodeType: 'floating-edge',\n        backgroundColor: '#000000',\n        hasImage: false,\n        missingFields: ['edge'],\n        hasMissingInfo: true,\n      },\n      classes: 'floating-edge-node virtual-node has-missing-info'\n    })),\n    // Directional edges (including synthesized detail endpoints)\n    ...aggregatedEdges,\n  ];\n\n  const stylesheet: cytoscape.StylesheetCSS[] = [\n    {\n      selector: 'node',\n      css: {\n        'label': 'data(label)',\n        'color': neoColors.nodeLabel,\n        'text-valign': 'bottom',\n        'text-halign': 'center',\n        'font-size': '12px',\n        'font-weight': 600,\n        'text-outline-width': 3,\n        'text-outline-color': 'rgba(7, 17, 31, 0.85)',\n        'text-margin-y': 10,\n        'width': 65,\n        'height': 65,\n        'background-color': 'data(backgroundColor)',\n        'border-width': 3,\n        'border-color': neoColors.nodeBorder,\n        'border-opacity': 0.9,\n        'background-opacity': 0.92,\n        'shadow-blur': 20,\n        'shadow-color': 'rgba(102, 224, 255, 0.25)',\n        'shadow-offset-x': 0,\n        'shadow-offset-y': 0,\n        'transition-property': 'background-color, border-width, width, height, color, shadow-blur',\n        'transition-duration': '160ms',\n      },\n    },\n    {\n      selector: 'node.has-image',\n      css: {\n        'background-image': 'data(image)',\n        'background-fit': 'cover',\n        'background-opacity': 1,\n        'shape': 'ellipse',\n        'border-width': 3,\n        'border-color': '#ffffff1f',\n      },\n    },\n    {\n      selector: 'node.no-image',\n      css: {\n        'text-valign': 'center',\n        'text-margin-y': 0,\n      },\n    },\n    {\n      selector: 'node.person',\n      css: {\n        'shape': 'ellipse',\n      },\n    },\n    {\n      selector: 'node.organization',\n      css: {\n        'shape': 'round-rectangle',\n        'border-radius': 12,\n      },\n    },\n    {\n      selector: 'node.website',\n      css: {\n        'shape': 'diamond',\n      },\n    },\n    {\n      selector: 'node.user',\n      css: {\n        'shape': 'octagon',\n      },\n    },\n    {\n      selector: 'node.location',\n      css: {\n        'shape': 'vee',\n      },\n    },\n    {\n      selector: 'node.phone',\n      css: {\n        'shape': 'hexagon',\n        'width': 55,\n        'height': 55,\n      },\n    },\n    {\n      selector: 'node.cdr-node',\n      css: {\n        'shape': 'round-rectangle',\n        'width': 50,\n        'height': 28,\n        'background-color': '#1f3a5f',\n        'border-color': '#7fb3d5',\n        'border-width': 2,\n        'color': '#d6eaf8',\n        'font-size': '10px',\n        'text-valign': 'center',\n        'text-margin-y': 0,\n      },\n    },\n    {\n      selector: 'node:hover',\n      css: {\n        'width': 75,\n        'height': 75,\n        'border-width': 4,\n        'border-color': neoColors.nodeHalo,\n        'shadow-blur': 30,\n        'shadow-color': 'rgba(102, 224, 255, 0.4)',\n        'color': '#ffffff',\n        'font-size': '13px',\n      },\n    },\n    {\n      selector: 'node:selected',\n      css: {\n        'width': 78,\n        'height': 78,\n        'border-width': 5,\n        'border-color': neoColors.nodeHalo,\n        'background-color': 'data(backgroundColor)',\n        'shadow-blur': 35,\n        'shadow-color': 'rgba(255, 197, 120, 0.55)',\n        'color': '#ffffff',\n        'font-size': '13px',\n      },\n    },\n    {\n      selector: 'node.multi-selected',\n      css: {\n        'border-color': '#8e44ad',\n        'border-width': 4,\n      },\n    },\n    {\n      selector: 'node.has-missing-info',\n      css: {\n        'border-style': 'dashed',\n        'border-color': neoColors.missing,\n        'border-width': 3,\n        'background-opacity': 0.85,\n      },\n    },\n    {\n      selector: 'node.complete-info',\n      css: {\n        'border-style': 'solid',\n        'border-color': '#d0e8ff',\n      },\n    },\n    {\n      selector: 'node.isolated-edge-node',\n      css: {\n        'background-color': '#142034',\n        'border-color': neoColors.missing,\n        'border-width': 2,\n        'width': 22,\n        'height': 22,\n        'color': neoColors.missing,\n        'font-size': 9,\n        'text-outline-width': 2,\n      },\n    },\n    {\n      selector: 'node.virtual-node',\n      css: {\n        'background-color': '#0e1828',\n        'border-color': neoColors.virtual,\n        'border-style': 'dotted',\n        'border-width': 2,\n        'width': 24,\n        'height': 24,\n      },\n    },\n    {\n      selector: 'node.floating-edge-node',\n      css: {\n        'background-color': '#0e1828',\n        'border-color': neoColors.missing,\n        'border-width': 3,\n        'width': 36,\n        'height': 36,\n        'label': 'data(label)',\n        'color': neoColors.nodeLabel,\n        'text-outline-width': 2,\n        'text-outline-color': 'rgba(7, 17, 31, 0.9)',\n        'font-size': 10,\n        'font-weight': 600,\n      },\n    },\n    {\n      selector: 'node.highlighted',\n      css: {\n        'border-color': neoColors.nodeHalo,\n        'border-width': 5,\n        'shadow-blur': 40,\n        'shadow-color': 'rgba(102, 224, 255, 0.6)',\n      },\n    },\n    {\n      selector: 'edge',\n      css: {\n        'width': 1.8,\n        'line-color': neoColors.edgeDefault,\n        'target-arrow-color': neoColors.edgeDefault,\n        'target-arrow-shape': 'triangle',\n        'curve-style': 'bezier',\n        'opacity': 0.7,\n        'label': 'data(label)',\n        'font-size': 9,\n        'font-weight': 500,\n        'text-background-color': 'rgba(4, 9, 16, 0.8)',\n        'text-background-opacity': 0.8,\n        'text-background-padding': '2px',\n        'text-border-width': 0,\n        'color': '#d6eaf8',\n      },\n    },\n    {\n      selector: 'edge:hover',\n      css: {\n        'width': 3,\n        'line-color': neoColors.edgeHover,\n        'target-arrow-color': neoColors.edgeHover,\n        'opacity': 1,\n        'color': neoColors.edgeHover,\n        'text-background-opacity': 1,\n      },\n    },\n    {\n      selector: 'edge:selected',\n      css: {\n        'width': 3.5,\n        'line-color': neoColors.edgeSelected,\n        'target-arrow-color': neoColors.edgeSelected,\n        'color': neoColors.edgeSelected,\n        'opacity': 1,\n      },\n    },\n    {\n      selector: 'edge.has-missing-info',\n      css: {\n        'line-style': 'dashed',\n        'line-color': neoColors.missing,\n        'target-arrow-color': neoColors.missing,\n      },\n    },\n    {\n      selector: 'edge.isolated-edge',\n      css: {\n        'line-style': 'dotted',\n        'line-color': '#d98880',\n        'target-arrow-color': '#d98880',\n        'opacity': 0.6,\n      },\n    },\n    {\n      selector: 'edge.connected-edge',\n      css: {\n        'line-style': 'solid',\n      },\n    },\n    {\n      selector: 'edge.multiple-interactions',\n      css: {\n        'width': 3,\n        'color': '#f5b041',\n        'line-color': '#f5b041',\n        'target-arrow-color': '#f5b041',\n        'font-weight': 600,\n      },\n    },\n    {\n      selector: 'edge.reciprocal-edge',\n      css: {\n        'curve-style': 'unbundled-bezier',\n        'control-point-step-size': 50,\n        'opacity': 0.95,\n      },\n    },\n    {\n      selector: 'edge.reciprocal-forward',\n      css: {\n        'control-point-distance': 60,\n        'control-point-weight': 0.8,\n      },\n    },\n    {\n      selector: 'edge.reciprocal-backward',\n      css: {\n        'control-point-distance': -60,\n        'control-point-weight': 0.2,\n      },\n    },\n  ] as any;\n\n  // Center and fit the graph\n  const centerGraph = () => {\n    if (cyRef.current) {\n      cyRef.current.fit(undefined, 50); // 50px padding\n      cyRef.current.center();\n      updateZoomLevel();\n    }\n  };\n\n  // Zoom controls\n  const zoomIn = () => {\n    if (cyRef.current) {\n      cyRef.current.zoom(cyRef.current.zoom() * 1.2);\n      updateZoomLevel();\n    }\n  };\n\n  const zoomOut = () => {\n    if (cyRef.current) {\n      cyRef.current.zoom(cyRef.current.zoom() * 0.8);\n      updateZoomLevel();\n    }\n  };\n\n  const resetZoom = () => {\n    if (cyRef.current) {\n      cyRef.current.fit(undefined, 50);\n      updateZoomLevel();\n    }\n  };\n\n  const updateZoomLevel = () => {\n    if (cyRef.current) {\n      setZoomLevel(cyRef.current.zoom());\n    }\n  };\n\n  // Fit to selection\n  const fitToSelection = () => {\n    if (cyRef.current) {\n      const selected = cyRef.current.$('node:selected');\n      if (selected.length > 0) {\n        cyRef.current.fit(selected, 50);\n        updateZoomLevel();\n      } else {\n        centerGraph();\n      }\n    }\n  };\n\n  // Navigate to specific node\n  const navigateToNode = (nodeId: string) => {\n    if (cyRef.current) {\n      const node = cyRef.current.$(`#${nodeId}`);\n      if (node.length > 0) {\n        cyRef.current.fit(node, 100);\n        node.select();\n        onNodeClick?.(nodeId);\n        handleSelectionChange();\n        updateZoomLevel();\n        // Highlight briefly\n        setHighlightedNodeId(nodeId);\n        setTimeout(() => setHighlightedNodeId(null), 2000);\n      }\n    }\n  };\n\n  // Search nodes\n  useEffect(() => {\n    if (searchQuery.trim()) {\n      const query = searchQuery.toLowerCase();\n      const results = data.nodes.filter(node => \n        node.label?.toLowerCase().includes(query) ||\n        node.id.toLowerCase().includes(query) ||\n        node.type?.toLowerCase().includes(query) ||\n        node.metadata?.category?.toLowerCase().includes(query)\n      );\n      setSearchResults(results);\n    } else {\n      setSearchResults([]);\n    }\n  }, [searchQuery, data.nodes]);\n\n  // Handle selection changes\n  const handleSelectionChange = () => {\n    if (cyRef.current && onSelectionChange) {\n      const selectedNodes = cyRef.current.$('node:selected');\n      const selectedIds = selectedNodes.map(node => node.id());\n      onSelectionChange(selectedIds);\n    }\n  };\n\n  useEffect(() => {\n    if (cyRef.current) {\n      const cy = cyRef.current;\n      \n      console.log('GraphVisualization: Initializing canvas with', {\n        nodes: data.nodes.length,\n        edges: data.edges.length,\n        layout: layout.name\n      });\n\n      // Enable various selection modes\n      cy.boxSelectionEnabled(true);\n      cy.userPanningEnabled(true);\n      cy.userZoomingEnabled(true);\n\n      // Event handlers\n      cy.on('tap', 'node', (evt) => {\n        const node = evt.target;\n        const originalEvent = evt.originalEvent;\n        const renderedPosition = node.renderedPosition();\n        const containerOffset = cy.container()?.getBoundingClientRect() || { left: 0, top: 0 };\n        \n        // Handle multi-selection with Ctrl/Cmd key\n        if (originalEvent?.ctrlKey || originalEvent?.metaKey) {\n          if (node.selected()) {\n            node.unselect();\n          } else {\n            node.select();\n          }\n          hideTooltip();\n        } else {\n          // Single selection - clear others and select this one\n          cy.$('node:selected').unselect();\n          node.select();\n          onNodeClick?.(node.id());\n\n          const nodeData = data.nodes.find(n => n.id === node.id());\n          if (nodeData) {\n            setTooltip({\n              visible: true,\n              x: containerOffset.left + renderedPosition.x,\n              y: containerOffset.top + renderedPosition.y,\n              node: nodeData,\n              edge: undefined,\n              pinned: true,\n            });\n          }\n        }\n        \n        handleSelectionChange();\n      });\n\n      cy.on('tap', 'edge', (evt) => {\n        const edge = evt.target;\n        const originalEvent = evt.originalEvent;\n        \n        if (originalEvent?.ctrlKey || originalEvent?.metaKey) {\n          if (edge.selected()) {\n            edge.unselect();\n          } else {\n            edge.select();\n          }\n        } else {\n          cy.$('edge:selected').unselect();\n          edge.select();\n          onEdgeClick?.(edge.id());\n        }\n      });\n\n      // Clear selection when clicking empty space (without Ctrl/Cmd)\n      cy.on('tap', (evt) => {\n        if (evt.target === cy) {\n          const originalEvent = evt.originalEvent;\n          if (!originalEvent?.ctrlKey && !originalEvent?.metaKey) {\n            cy.$(':selected').unselect();\n            handleSelectionChange();\n            hideTooltip(true);\n          }\n        }\n      });\n\n      // Handle box selection\n      cy.on('boxend', () => {\n        handleSelectionChange();\n      });\n\n      // Tooltip event handlers\n      cy.on('mouseover', 'node', (evt) => {\n        const node = evt.target;\n        const renderedPosition = node.renderedPosition();\n        const containerOffset = cy.container()?.getBoundingClientRect() || { left: 0, top: 0 };\n        \n        // Prefer real node data; fallback to virtual node's embedded metadata to show edge info for floating nodes\n        const nodeData = data.nodes.find(n => n.id === node.id());\n        if (nodeData) {\n          setTooltip(prev => {\n            if (prev.pinned) return prev;\n            return {\n            visible: true,\n            x: containerOffset.left + renderedPosition.x,\n            y: containerOffset.top + renderedPosition.y,\n            node: nodeData,\n              edge: undefined,\n              pinned: false,\n            };\n          });\n        } else {\n          // Virtual node path (e.g., floating-edge-node). Build a minimal pseudo-edge from node data to show details\n          const nd = node.data();\n          const pseudoEdge = {\n            id: String(nd?.metadata?.originalEdgeId || nd?.id || ''),\n            source: String(nd?.metadata?.originalSource || ''),\n            target: String(nd?.metadata?.originalTarget || ''),\n            label: String(nd?.metadata?.edgeLabel || nd?.label || ''),\n            data: nd?.metadata ? { ...nd.metadata } : undefined,\n          } as Edge;\n          setTooltip(prev => {\n            if (prev.pinned) return prev;\n            return {\n            visible: true,\n            x: containerOffset.left + renderedPosition.x,\n            y: containerOffset.top + renderedPosition.y,\n              node: undefined,\n            edge: pseudoEdge,\n              pinned: false,\n            };\n          });\n        }\n      });\n\n      cy.on('mouseout', 'node', () => {\n        setTooltip(prev => prev.pinned ? prev : { ...prev, visible: false, node: undefined, edge: prev.edge, pinned: false });\n      });\n\n      cy.on('mouseover', 'edge', (evt) => {\n        const edge = evt.target;\n        const renderedMidpoint = edge.renderedMidpoint();\n        const containerOffset = cy.container()?.getBoundingClientRect() || { left: 0, top: 0 };\n        \n        const edgeData = data.edges.find(e => e.id === edge.id());\n        if (edgeData) {\n          setTooltip(prev => {\n            if (prev.pinned) return prev;\n            return {\n            visible: true,\n            x: containerOffset.left + renderedMidpoint.x,\n            y: containerOffset.top + renderedMidpoint.y,\n              node: undefined,\n            edge: edgeData,\n              pinned: false,\n            };\n          });\n        }\n      });\n\n      cy.on('mouseout', 'edge', () => {\n        setTooltip(prev => prev.pinned ? prev : { ...prev, visible: false, edge: undefined, pinned: false });\n      });\n\n      // Hide tooltip on pan/zoom\n      cy.on('pan zoom', () => {\n        setTooltip(prev => (prev.pinned ? prev : { ...prev, visible: false, pinned: false }));\n        updateZoomLevel();\n      });\n\n      // Track zoom changes\n      cy.on('zoom', () => {\n        updateZoomLevel();\n      });\n\n      // Handle keyboard shortcuts\n      const handleKeyDown = (event: KeyboardEvent) => {\n        // Allow search input to work normally\n        if ((event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) && \n            !(event.key === 'Enter' && (event.target as HTMLElement).id === 'node-search')) {\n          return;\n        }\n\n        switch (event.key.toLowerCase()) {\n          case 'a':\n            if (event.ctrlKey || event.metaKey) {\n              event.preventDefault();\n              cy.$('node').select();\n              handleSelectionChange();\n            }\n            break;\n          case 'escape':\n            if (isFullscreen) {\n              toggleFullscreen();\n            } else {\n            cy.$(':selected').unselect();\n            handleSelectionChange();\n              setSearchQuery('');\n              setSearchResults([]);\n            }\n            break;\n          case 'f':\n            if (event.ctrlKey || event.metaKey) {\n              event.preventDefault();\n              centerGraph();\n            }\n            break;\n          case '=':\n          case '+':\n            if (event.ctrlKey || event.metaKey) {\n              event.preventDefault();\n              zoomIn();\n            }\n            break;\n          case '-':\n          case '_':\n            if (event.ctrlKey || event.metaKey) {\n              event.preventDefault();\n              zoomOut();\n            }\n            break;\n          case '0':\n            if (event.ctrlKey || event.metaKey) {\n              event.preventDefault();\n              resetZoom();\n            }\n            break;\n          case 'f11':\n            event.preventDefault();\n            toggleFullscreen();\n            break;\n          case 'enter':\n            if ((event.target as HTMLElement).id === 'node-search' && searchResults.length > 0) {\n              event.preventDefault();\n              navigateToNode(searchResults[0].id);\n            }\n            break;\n          case '/':\n            if (!event.ctrlKey && !event.metaKey) {\n              event.preventDefault();\n              document.getElementById('node-search')?.focus();\n            }\n            break;\n          case 'delete':\n          case 'backspace':\n            if (event.ctrlKey || event.metaKey) {\n              event.preventDefault();\n              // Could implement node deletion here if needed\n              console.log('Delete selected nodes:', cy.$('node:selected').map(n => n.id()));\n            }\n            break;\n        }\n      };\n\n      document.addEventListener('keydown', handleKeyDown);\n\n      // Auto-center graph when data changes\n      if (data.nodes.length > 0) {\n        // Small delay to ensure layout is applied\n        setTimeout(() => {\n          centerGraph();\n        }, 100);\n      }\n\n      // Hide tooltip on window scroll/resize\n      const handleWindowEvent = () => {\n        setTooltip(prev => (prev.pinned ? prev : { ...prev, visible: false, pinned: false }));\n      };\n\n      window.addEventListener('scroll', handleWindowEvent);\n      window.addEventListener('resize', handleWindowEvent);\n\n      return () => {\n        cy.removeAllListeners();\n        document.removeEventListener('keydown', handleKeyDown);\n        window.removeEventListener('scroll', handleWindowEvent);\n        window.removeEventListener('resize', handleWindowEvent);\n      };\n    }\n  }, [onNodeClick, onEdgeClick, onSelectionChange, data]);\n\n  // Re-center when layout changes\n  useEffect(() => {\n    if (cyRef.current && data.nodes.length > 0) {\n      setTimeout(() => {\n        centerGraph();\n      }, 200);\n    }\n  }, [layout]);\n\n  // Sync external selectedNodeIds with graph selection\n  useEffect(() => {\n    if (cyRef.current && selectedNodeIds) {\n      const cy = cyRef.current;\n      \n      // Clear current selection\n      cy.$(':selected').unselect();\n      \n      // Select nodes based on selectedNodeIds\n      selectedNodeIds.forEach(nodeId => {\n        const node = cy.$(`#${nodeId}`);\n        if (node.length > 0) {\n          node.select();\n        }\n      });\n    }\n  }, [selectedNodeIds]);\n\n  // Apply highlighting to searched/highlighted nodes\n  useEffect(() => {\n    if (cyRef.current) {\n      const cy = cyRef.current;\n      \n      // Remove all highlights\n      cy.$('node').removeClass('highlighted');\n      \n      // Add highlight to searched nodes\n      searchResults.forEach(node => {\n        const cyNode = cy.$(`#${node.id}`);\n        if (cyNode.length > 0) {\n          cyNode.addClass('highlighted');\n        }\n      });\n      \n      // Add highlight to manually highlighted node\n      if (highlightedNodeId) {\n        const cyNode = cy.$(`#${highlightedNodeId}`);\n        if (cyNode.length > 0) {\n          cyNode.addClass('highlighted');\n        }\n      }\n    }\n  }, [searchResults, highlightedNodeId, data.nodes]);\n\n  // Initialize zoom level after graph loads\n  useEffect(() => {\n    if (cyRef.current && data.nodes.length > 0) {\n      const timeoutId = setTimeout(() => {\n        updateZoomLevel();\n      }, 100);\n      return () => clearTimeout(timeoutId);\n    }\n  }, [data.nodes.length]);\n\n  // Handle mouse movement for illuminating effect\n  const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {\n    if (canvasRef.current) {\n      const rect = canvasRef.current.getBoundingClientRect();\n      setMousePosition({\n        x: e.clientX - rect.left,\n        y: e.clientY - rect.top,\n      });\n    }\n  };\n\n  const handleMouseLeave = () => {\n    setMousePosition(null);\n  };\n\n  // Fullscreen functionality\n  const toggleFullscreen = async () => {\n    if (!canvasRef.current) return;\n\n    try {\n      const isCurrentlyFullscreen = !!(document.fullscreenElement || \n        (document as any).webkitFullscreenElement ||\n        (document as any).mozFullScreenElement ||\n        (document as any).msFullscreenElement);\n\n      if (!isCurrentlyFullscreen) {\n        // Enter fullscreen\n        if (canvasRef.current.requestFullscreen) {\n          await canvasRef.current.requestFullscreen();\n        } else if ((canvasRef.current as any).webkitRequestFullscreen) {\n          await (canvasRef.current as any).webkitRequestFullscreen();\n        } else if ((canvasRef.current as any).mozRequestFullScreen) {\n          await (canvasRef.current as any).mozRequestFullScreen();\n        } else if ((canvasRef.current as any).msRequestFullscreen) {\n          await (canvasRef.current as any).msRequestFullscreen();\n        }\n      } else {\n        // Exit fullscreen\n        if (document.exitFullscreen) {\n          await document.exitFullscreen();\n        } else if ((document as any).webkitExitFullscreen) {\n          await (document as any).webkitExitFullscreen();\n        } else if ((document as any).mozCancelFullScreen) {\n          await (document as any).mozCancelFullScreen();\n        } else if ((document as any).msExitFullscreen) {\n          await (document as any).msExitFullscreen();\n        }\n      }\n    } catch (error) {\n      console.error('Error toggling fullscreen:', error);\n    }\n  };\n\n  // Listen for fullscreen changes and resize canvas\n  useEffect(() => {\n    const handleFullscreenChange = () => {\n      const nowFullscreen = !!(document.fullscreenElement || \n        (document as any).webkitFullscreenElement || \n        (document as any).mozFullScreenElement ||\n        (document as any).msFullscreenElement);\n      \n      setIsFullscreen(nowFullscreen);\n      \n      // Resize canvas when entering/exiting fullscreen\n      if (cyRef.current) {\n        setTimeout(() => {\n          if (cyRef.current) {\n            cyRef.current.resize();\n            if (data.nodes.length > 0) {\n              cyRef.current.fit(undefined, 50);\n              cyRef.current.center();\n              updateZoomLevel();\n            }\n          }\n        }, 100);\n      }\n    };\n\n    document.addEventListener('fullscreenchange', handleFullscreenChange);\n    document.addEventListener('webkitfullscreenchange', handleFullscreenChange);\n    document.addEventListener('mozfullscreenchange', handleFullscreenChange);\n    document.addEventListener('MSFullscreenChange', handleFullscreenChange);\n\n    return () => {\n      document.removeEventListener('fullscreenchange', handleFullscreenChange);\n      document.removeEventListener('webkitfullscreenchange', handleFullscreenChange);\n      document.removeEventListener('mozfullscreenchange', handleFullscreenChange);\n      document.removeEventListener('MSFullscreenChange', handleFullscreenChange);\n    };\n  }, [data.nodes.length]);\n\n  return (\n    <div \n      ref={canvasRef}\n      className={`relative w-full h-full ${isFullscreen ? 'fixed inset-0 z-50 bg-theme-bg-secondary' : ''}`}\n      id=\"graph-canvas\" \n      style={{ minHeight: isFullscreen ? '100vh' : '400px' }}\n      role=\"application\"\n      aria-label=\"Interactive network graph visualization\"\n      aria-live=\"polite\"\n      onMouseMove={handleMouseMove}\n      onMouseLeave={handleMouseLeave}\n    >\n      {/* Neo4j-inspired depth background */}\n      <div \n        className={`absolute inset-0 ${isFullscreen ? 'rounded-none' : 'rounded-lg'} overflow-hidden`}\n        style={{\n          background: `\n            radial-gradient(circle at 20% 20%, rgba(102, 224, 255, 0.15) 0%, transparent 40%),\n            radial-gradient(circle at 80% 15%, rgba(245, 176, 65, 0.15) 0%, transparent 35%),\n            linear-gradient(135deg, #050c16 0%, #0f1b2d 55%, #081225 100%)\n          `,\n          backgroundSize: '100% 100%',\n          border: isFullscreen ? 'none' : '1px solid rgba(255, 255, 255, 0.08)',\n        }}\n      />\n      \n      {/* Soft grid overlay */}\n      <div \n        className=\"absolute inset-0 pointer-events-none\"\n        style={{\n          backgroundImage: `\n            linear-gradient(${neoColors.grid} 1px, transparent 1px),\n            linear-gradient(90deg, ${neoColors.grid} 1px, transparent 1px)\n          `,\n          backgroundSize: '50px 50px',\n          opacity: 0.35,\n        }}\n      />\n      \n      {/* Corner frame markers */}\n      <div className=\"absolute top-0 left-0 w-8 h-8 border-t-2 border-l-2 border-[#66e0ff] opacity-25\" />\n      <div className=\"absolute top-0 right-0 w-8 h-8 border-t-2 border-r-2 border-[#66e0ff] opacity-25\" />\n      <div className=\"absolute bottom-0 left-0 w-8 h-8 border-b-2 border-l-2 border-[#66e0ff] opacity-25\" />\n      <div className=\"absolute bottom-0 right-0 w-8 h-8 border-b-2 border-r-2 border-[#66e0ff] opacity-25\" />\n      \n      {/* Mouse spotlight */}\n      {mousePosition && (\n        <div\n          className=\"absolute pointer-events-none transition-opacity duration-300\"\n          style={{\n            left: mousePosition.x - 200,\n            top: mousePosition.y - 200,\n            width: '400px',\n            height: '400px',\n            background: `radial-gradient(\n              circle,\n              rgba(102, 224, 255, 0.18) 0%,\n              rgba(72, 201, 176, 0.08) 30%,\n              rgba(102, 224, 255, 0.04) 55%,\n              transparent 70%\n            )`,\n            borderRadius: '50%',\n            filter: 'blur(40px)',\n            zIndex: 0,\n            opacity: 1,\n          }}\n        />\n      )}\n      \n      {/* Secondary glow */}\n      {mousePosition && (\n        <div\n          className=\"absolute pointer-events-none transition-opacity duration-200\"\n          style={{\n            left: mousePosition.x - 100,\n            top: mousePosition.y - 100,\n            width: '200px',\n            height: '200px',\n            background: `radial-gradient(\n              circle,\n              rgba(245, 208, 63, 0.12) 0%,\n              rgba(95, 189, 255, 0.08) 45%,\n              transparent 70%\n            )`,\n            borderRadius: '50%',\n            filter: 'blur(20px)',\n            zIndex: 0,\n            opacity: 0.8,\n          }}\n        />\n      )}\n\n      <CytoscapeComponent\n        elements={elements}\n        layout={layout}\n        stylesheet={stylesheet}\n        style={{\n          ...style,\n          backgroundColor: 'transparent',\n          position: 'relative',\n          zIndex: 1,\n          width: '100%',\n          height: isFullscreen ? '100vh' : style.height || '600px',\n        }}\n        cy={(cy: cytoscape.Core) => {\n          cyRef.current = cy;\n          console.log('Cytoscape canvas initialized:', cy);\n          \n          // Set canvas background to transparent\n          const container = cy.container();\n          if (container) {\n            container.style.backgroundColor = 'transparent';\n          }\n        }}\n      />\n      \n      {/* Command Center */}\n      <div\n        className=\"absolute top-2 left-2 bg-theme-card rounded-lg shadow-lg border border-theme-border p-2 space-y-2 z-20 max-w-[280px]\"\n        data-tour=\"command-center\"\n      >\n        <div className=\"flex items-center gap-1 border-b border-theme-border pb-2\">\n          {(['basic', 'advanced'] as const).map(tab => (\n            <button\n              key={tab}\n              type=\"button\"\n              onClick={() => setControlTab(tab)}\n              className={`flex-1 px-2 py-1 text-xs font-semibold rounded ${\n                controlTab === tab ? 'bg-theme-accent text-white' : 'text-theme-text-secondary hover:text-theme-text'\n              }`}\n            >\n              {tab === 'basic' ? 'Basic' : 'Advanced'}\n            </button>\n          ))}\n        </div>\n\n        {controlTab === 'basic' ? (\n          <>\n            {/* Search */}\n            <div className=\"relative\">\n              <input\n                id=\"node-search\"\n                type=\"text\"\n                value={searchQuery}\n                onChange={(e) => setSearchQuery(e.target.value)}\n                placeholder=\"Search nodes (/)\"\n                className=\"w-full px-2 py-1 text-xs border border-theme-border bg-theme-bg-secondary text-theme-text rounded focus:outline-none focus:ring-2 focus:ring-theme-accent\"\n                aria-label=\"Search nodes in graph\"\n                aria-describedby=\"search-results-count\"\n              />\n              {searchResults.length > 0 && (\n                <div className=\"absolute top-full left-0 right-0 mt-1 bg-theme-card border border-theme-border rounded shadow-lg max-h-48 overflow-y-auto z-30\">\n                  {searchResults.slice(0, 5).map((node) => (\n                    <button\n                      key={node.id}\n                      onClick={() => navigateToNode(node.id)}\n                      className=\"w-full px-2 py-1 text-left text-xs hover:bg-theme-card-hover text-theme-text flex items-center justify-between\"\n                      aria-label={`Navigate to node ${node.label}`}\n                    >\n                      <span className=\"truncate\">{node.label || node.id}</span>\n                      <span className=\"text-theme-text-secondary ml-2\">{node.type}</span>\n                    </button>\n                  ))}\n                  {searchResults.length > 5 && (\n                    <div className=\"px-2 py-1 text-xs text-theme-text-secondary text-center\">\n                      +{searchResults.length - 5} more\n                    </div>\n                  )}\n                </div>\n              )}\n              <span id=\"search-results-count\" className=\"sr-only\">\n                {searchResults.length > 0 ? `${searchResults.length} results found` : ''}\n              </span>\n            </div>\n\n            {/* Zoom Controls */}\n            <div className=\"flex items-center space-x-1 border-t border-theme-border pt-2\">\n              <button\n                onClick={zoomOut}\n                className=\"flex items-center justify-center w-7 h-7 text-xs font-medium text-theme-text hover:bg-theme-card-hover rounded transition-colors\"\n                title=\"Zoom Out (Ctrl+-)\"\n                aria-label=\"Zoom out\"\n                aria-keyshortcuts=\"Ctrl+-\"\n              >\n                <svg className=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n                  <path fillRule=\"evenodd\" d=\"M3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z\" clipRule=\"evenodd\" />\n                </svg>\n              </button>\n              <button\n                onClick={resetZoom}\n                className=\"flex items-center justify-center w-7 h-7 text-xs font-medium text-theme-text hover:bg-theme-card-hover rounded transition-colors\"\n                title=\"Reset Zoom (Ctrl+0)\"\n                aria-label=\"Reset zoom to fit\"\n                aria-keyshortcuts=\"Ctrl+0\"\n              >\n                <span className=\"text-xs\">{(zoomLevel * 100).toFixed(0)}%</span>\n              </button>\n              <button\n                onClick={zoomIn}\n                className=\"flex items-center justify-center w-7 h-7 text-xs font-medium text-theme-text hover:bg-theme-card-hover rounded transition-colors\"\n                title=\"Zoom In (Ctrl++)\"\n                aria-label=\"Zoom in\"\n                aria-keyshortcuts=\"Ctrl++\"\n              >\n                <svg className=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n                  <path fillRule=\"evenodd\" d=\"M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z\" clipRule=\"evenodd\" />\n                </svg>\n              </button>\n            </div>\n\n            {/* Navigation Controls */}\n            <div className=\"flex flex-col space-y-1 border-t border-theme-border pt-2\">\n              <button\n                onClick={toggleFullscreen}\n                className=\"flex items-center space-x-1 px-2 py-1 text-xs font-medium text-theme-text hover:bg-theme-card-hover rounded transition-colors\"\n                title={isFullscreen ? \"Exit Fullscreen (F11)\" : \"Enter Fullscreen (F11)\"}\n                aria-label={isFullscreen ? \"Exit fullscreen\" : \"Enter fullscreen\"}\n                aria-keyshortcuts=\"F11\"\n              >\n                {isFullscreen ? (\n                  <svg className=\"w-3 h-3\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n                    <path fillRule=\"evenodd\" d=\"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z\" clipRule=\"evenodd\" />\n                  </svg>\n                ) : (\n                  <svg className=\"w-3 h-3\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n                    <path d=\"M3 4a1 1 0 011-1h4a1 1 0 010 2H6.414l2.293 2.293a1 1 0 01-1.414 1.414L5 6.414V8a1 1 0 01-2 0V4zM17 4a1 1 0 00-1-1h-4a1 1 0 100 2h1.586l-2.293 2.293a1 1 0 101.414 1.414L15 6.414V8a1 1 0 002 0V4zM3 16a1 1 0 001 1h4a1 1 0 100-2H6.414l-2.293-2.293a1 1 0 10-1.414-1.414L5 13.586V12a1 1 0 10-2 0v4zM17 16a1 1 0 01-1 1h-4a1 1 0 110-2h1.586l-2.293-2.293a1 1 0 111.414-1.414L15 13.586V12a1 1 0 112 0v4z\" />\n                  </svg>\n                )}\n                <span>{isFullscreen ? 'Exit' : 'Fullscreen'}</span>\n              </button>\n              <button\n                onClick={centerGraph}\n                className=\"flex items-center space-x-1 px-2 py-1 text-xs font-medium text-theme-text hover:bg-theme-card-hover rounded transition-colors\"\n                title=\"Center Graph (Ctrl+F)\"\n                aria-label=\"Center and fit graph\"\n                aria-keyshortcuts=\"Ctrl+F\"\n              >\n                <svg className=\"w-3 h-3\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n                  <path fillRule=\"evenodd\" d=\"M3 4a1 1 0 011-1h4a1 1 0 010 2H6.414l2.293 2.293a1 1 0 11-1.414 1.414L5 6.414V8a1 1 0 01-2 0V4zM17 4a1 1 0 01-1 1h-1.586l-2.293 2.293a1 1 0 01-1.414-1.414L12.586 4H12a1 1 0 010-2h4a1 1 0 011 1v4a1 1 0 01-2 0V4zM3 16a1 1 0 001 1v-1.586l2.293-2.293a1 1 0 011.414 1.414L5.414 17H8a1 1 0 010 2H4a1 1 0 01-1-1v-4a1 1 0 012 0v2zM17 16a1 1 0 01-1-1v1.586l-2.293-2.293a1 1 0 00-1.414 1.414L14.586 17H12a1 1 0 000 2h4a1 1 0 001-1v-4a1 1 0 00-2 0v2z\" clipRule=\"evenodd\" />\n                </svg>\n                <span>Center</span>\n              </button>\n              <button\n                onClick={fitToSelection}\n                className=\"flex items-center space-x-1 px-2 py-1 text-xs font-medium text-theme-text hover:bg-theme-card-hover rounded transition-colors\"\n                title=\"Fit to Selection\"\n                aria-label=\"Fit view to selected nodes\"\n              >\n                <svg className=\"w-3 h-3\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n                  <path fillRule=\"evenodd\" d=\"M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z\" clipRule=\"evenodd\" />\n                </svg>\n                <span>Fit</span>\n              </button>\n              <button\n                onClick={() => {\n                  if (cyRef.current) {\n                    cyRef.current.$(':selected').unselect();\n                    handleSelectionChange();\n                  }\n                }}\n                className=\"flex items-center space-x-1 px-2 py-1 text-xs font-medium text-theme-text hover:bg-theme-card-hover rounded transition-colors\"\n                title=\"Clear Selection (Esc)\"\n                aria-label=\"Clear all selections\"\n                aria-keyshortcuts=\"Escape\"\n              >\n                <svg className=\"w-3 h-3\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n                  <path fillRule=\"evenodd\" d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\" clipRule=\"evenodd\" />\n                </svg>\n                <span>Clear</span>\n              </button>\n            </div>\n          </>\n        ) : (\n          <div className=\"space-y-3 text-[11px] text-theme-text\">\n            {(onOpenDataManager || (layoutOptions && layoutOptions.length > 0)) && (\n              <div className=\"grid grid-cols-2 gap-2\">\n                {onOpenDataManager && (\n                  <button\n                    type=\"button\"\n                    onClick={onOpenDataManager}\n                    id=\"btn-manage-data\"\n                    className=\"px-2 py-1.5 text-xs font-semibold rounded bg-theme-accent text-white hover:bg-theme-accent-hover transition-colors\"\n                  >\n                    Manage Data\n                  </button>\n                )}\n                {layoutOptions && layoutOptions.length > 0 && (\n                  <select\n                    id=\"layout-select\"\n                    value={selectedLayoutName || layoutOptions[0].name}\n                    onChange={(e) => onLayoutSelect?.(e.target.value)}\n                    className=\"px-2 py-1.5 text-xs rounded border border-theme-border bg-theme-bg-secondary text-theme-text\"\n                  >\n                    {layoutOptions.map(option => (\n                      <option key={option.name} value={option.name}>\n                        {option.name}\n                      </option>\n                    ))}\n                  </select>\n                )}\n              </div>\n            )}\n\n            <div className=\"space-y-1 bg-theme-bg-secondary/50 rounded-md p-2 border border-theme-border/70\">\n              <input\n                type=\"text\"\n                placeholder=\"Search label, desc, tag...\"\n                value={currentFilter.searchTerm || ''}\n                onChange={(e) => updateGraphFilter({ searchTerm: e.target.value || undefined })}\n                disabled={!filtersEnabled}\n                className=\"w-full px-1.5 py-0.5 rounded border border-theme-border bg-theme-card text-theme-text focus:border-theme-accent disabled:opacity-60\"\n              />\n              <select\n                value={currentFilter.category || ''}\n                onChange={(e) => updateGraphFilter({ category: e.target.value || undefined })}\n                disabled={!filtersEnabled}\n                className=\"w-full px-1.5 py-0.5 rounded border border-theme-border bg-theme-card text-theme-text focus:border-theme-accent disabled:opacity-60\"\n              >\n                <option value=\"\">All categories</option>\n                {filterOptionsSafe.categories.map((c) => (\n                  <option key={c} value={c}>{c}</option>\n                ))}\n              </select>\n              <select\n                value={currentFilter.type || ''}\n                onChange={(e) => updateGraphFilter({ type: e.target.value || undefined })}\n                disabled={!filtersEnabled}\n                className=\"w-full px-1.5 py-0.5 rounded border border-theme-border bg-theme-card text-theme-text focus:border-theme-accent disabled:opacity-60\"\n              >\n                <option value=\"\">All types</option>\n                {filterOptionsSafe.types.map((t) => (\n                  <option key={t} value={t}>{t}</option>\n                ))}\n              </select>\n              <input\n                type=\"text\"\n                placeholder=\"tags: a,b,c\"\n                value={(currentFilter.tags || []).join(',')}\n                onChange={(e) => {\n                  const raw = e.target.value;\n                  const tags = raw.split(',').map(tag => tag.trim()).filter(Boolean);\n                  updateGraphFilter({ tags: tags.length > 0 ? tags : undefined });\n                }}\n                disabled={!filtersEnabled}\n                className=\"w-full px-1.5 py-0.5 rounded border border-theme-border bg-theme-card text-theme-text focus:border-theme-accent disabled:opacity-60\"\n              />\n            </div>\n\n            <div className=\"space-y-2 border-t border-theme-border pt-2\">\n              <div className=\"flex items-center justify-between\">\n                <span className=\"text-[11px] font-semibold uppercase tracking-wide text-theme-text\">Include / Exclude</span>\n                <button\n                  type=\"button\"\n                  onClick={() => setShowFilterOverlay(!showFilterOverlay)}\n                  className=\"text-theme-text-secondary hover:text-theme-text text-[11px]\"\n                >\n                  {showFilterOverlay ? 'Hide' : 'Show'}\n                </button>\n              </div>\n\n              {showFilterOverlay && (\n                <div className=\"space-y-3\">\n                  <div className=\"bg-theme-bg-secondary/50 rounded-md p-2 border border-theme-border/70 space-y-1\">\n                    <div className=\"flex items-center justify-between\">\n                      <span className=\"font-semibold\">Include ({includeFilters.length})</span>\n                      {!!includeFilters.length && (\n                        <button\n                          type=\"button\"\n                          onClick={() => onIncludeFiltersChange?.([])}\n                          disabled={!onIncludeFiltersChange}\n                          className=\"text-theme-text-secondary hover:text-theme-text disabled:opacity-50\"\n                        >\n                          Clear\n                        </button>\n                      )}\n                    </div>\n                    <div className=\"flex flex-wrap gap-1 min-h-[20px]\">\n                      {includeFilters.length === 0 ? (\n                        <span className=\"text-theme-text-secondary\">Showing all nodes</span>\n                      ) : (\n                        includeFilters.map(value => (\n                          <span\n                            key={value}\n                            className=\"inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full bg-theme-accent/15 text-theme-text border border-theme-accent/40\"\n                          >\n                            <span className=\"truncate max-w-[110px]\" title={value}>{value}</span>\n                            <button\n                              type=\"button\"\n                              onClick={() => removeFilterValue(value, includeFilters, onIncludeFiltersChange)}\n                              className=\"text-theme-text-secondary hover:text-theme-text\"\n                              aria-label={`Remove include ${value}`}\n                            >\n                              ✕\n                            </button>\n                          </span>\n                        ))\n                      )}\n                    </div>\n                    <div className=\"flex items-center gap-1\">\n                      <input\n                        type=\"text\"\n                        value={includeInput}\n                        onChange={(e) => setIncludeInput(e.target.value)}\n                        onKeyDown={handleIncludeKeyDown}\n                        placeholder=\"Phone or ID\"\n                        disabled={!onIncludeFiltersChange}\n                        className=\"flex-1 px-1.5 py-0.5 rounded border border-theme-border bg-theme-card text-theme-text focus:border-theme-accent disabled:opacity-60\"\n                      />\n                      <button\n                        type=\"button\"\n                        onClick={handleIncludeSubmit}\n                        disabled={!onIncludeFiltersChange || !includeInput.trim()}\n                        className=\"px-2 py-0.5 rounded bg-theme-accent text-white font-semibold disabled:opacity-50 disabled:cursor-not-allowed\"\n                      >\n                        +\n                      </button>\n                    </div>\n                    {includeSummaries.length > 0 && (\n                      <div className=\"max-h-20 overflow-y-auto rounded bg-theme-card/50 border border-theme-border/60 divide-y divide-theme-border/40 mt-1\">\n                        {includeSummaries.map(({ value, nodes }) => (\n                          <div key={`include-summary-${value}`} className=\"py-1 px-1.5\">\n                            <p className=\"font-medium truncate\">{value}</p>\n                            {nodes.length > 0 ? (\n                              <div className=\"flex flex-wrap gap-1 text-theme-text-secondary\">\n                                {nodes.slice(0, 2).map(node => (\n                                  <span key={node.id} className=\"px-1 py-0.5 rounded bg-theme-bg-secondary\">\n                                    {node.label}\n                                  </span>\n                                ))}\n                                {nodes.length > 2 && <span>+{nodes.length - 2} more</span>}\n                              </div>\n                            ) : (\n                              <p className=\"text-theme-warning\">No matches in current data</p>\n                            )}\n                          </div>\n                        ))}\n                      </div>\n                    )}\n                  </div>\n\n                  <div className=\"bg-theme-bg-secondary/50 rounded-md p-2 border border-theme-border/70 space-y-1\">\n                    <div className=\"flex items-center justify-between\">\n                      <span className=\"font-semibold\">Exclude ({excludeFilters.length})</span>\n                      {!!excludeFilters.length && (\n                        <button\n                          type=\"button\"\n                          onClick={() => onExcludeFiltersChange?.([])}\n                          disabled={!onExcludeFiltersChange}\n                          className=\"text-theme-text-secondary hover:text-theme-text disabled:opacity-50\"\n                        >\n                          Clear\n                        </button>\n                      )}\n                    </div>\n                    <div className=\"flex flex-wrap gap-1 min-h-[20px]\">\n                      {excludeFilters.length === 0 ? (\n                        <span className=\"text-theme-text-secondary\">Nothing excluded</span>\n                      ) : (\n                        excludeFilters.map(value => (\n                          <span\n                            key={value}\n                            className=\"inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full bg-theme-warning/15 text-theme-text border border-theme-warning/40\"\n                          >\n                            <span className=\"truncate max-w-[110px]\" title={value}>{value}</span>\n                            <button\n                              type=\"button\"\n                              onClick={() => removeFilterValue(value, excludeFilters, onExcludeFiltersChange)}\n                              className=\"text-theme-text-secondary hover:text-theme-text\"\n                              aria-label={`Remove exclude ${value}`}\n                            >\n                              ✕\n                            </button>\n                          </span>\n                        ))\n                      )}\n                    </div>\n                    <div className=\"flex items-center gap-1\">\n                      <input\n                        type=\"text\"\n                        value={excludeInput}\n                        onChange={(e) => setExcludeInput(e.target.value)}\n                        onKeyDown={handleExcludeKeyDown}\n                        placeholder=\"Phone or ID\"\n                        disabled={!onExcludeFiltersChange}\n                        className=\"flex-1 px-1.5 py-0.5 rounded border border-theme-border bg-theme-card text-theme-text focus:border-theme-accent disabled:opacity-60\"\n                      />\n                      <button\n                        type=\"button\"\n                        onClick={handleExcludeSubmit}\n                        disabled={!onExcludeFiltersChange || !excludeInput.trim()}\n                        className=\"px-2 py-0.5 rounded bg-theme-warning text-gray-900 font-semibold disabled:opacity-50 disabled:cursor-not-allowed\"\n                      >\n                        +\n                      </button>\n                    </div>\n                    {excludeSummaries.length > 0 && (\n                      <div className=\"max-h-20 overflow-y-auto rounded bg-theme-card/50 border border-theme-border/60 divide-y divide-theme-border/40 mt-1\">\n                        {excludeSummaries.map(({ value, nodes }) => (\n                          <div key={`exclude-summary-${value}`} className=\"py-1 px-1.5\">\n                            <p className=\"font-medium truncate\">{value}</p>\n                            {nodes.length > 0 ? (\n                              <div className=\"flex flex-wrap gap-1 text-theme-text-secondary\">\n                                {nodes.slice(0, 2).map(node => (\n                                  <span key={node.id} className=\"px-1 py-0.5 rounded bg-theme-warning/20 text-theme-text\">\n                                    {node.label}\n                                  </span>\n                                ))}\n                                {nodes.length > 2 && <span>+{nodes.length - 2} more</span>}\n                              </div>\n                            ) : (\n                              <p className=\"text-theme-text-secondary\">Hidden or not present</p>\n                            )}\n                          </div>\n                        ))}\n                      </div>\n                    )}\n                  </div>\n                </div>\n              )}\n            </div>\n          </div>\n        )}\n      </div>\n\n      {/* Toggleable Help Panel */}\n      {showHelpPanel && (\n        <div className=\"absolute bottom-2 left-2 bg-theme-card rounded-lg shadow-lg border border-theme-border p-2 text-xs text-theme-text-secondary max-w-xs z-30\">\n          <div className=\"flex items-center justify-between mb-2\">\n            <div className=\"font-semibold text-theme-text\">Navigation Guide</div>\n            <button\n              onClick={() => setShowHelpPanel(false)}\n              className=\"text-theme-text-secondary hover:text-theme-text transition-colors\"\n              aria-label=\"Hide navigation guide\"\n              title=\"Hide\"\n            >\n              <svg className=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n                <path fillRule=\"evenodd\" d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\" clipRule=\"evenodd\" />\n              </svg>\n            </button>\n          </div>\n        <div className=\"space-y-1\">\n            <div className=\"font-semibold text-theme-text mb-1\">Navigation</div>\n            <div>🔍 <strong>Search:</strong> Press / to search nodes</div>\n            <div>🔎 <strong>Zoom:</strong> Ctrl++ / Ctrl+- or mouse wheel</div>\n            <div>🎯 <strong>Reset:</strong> Ctrl+0 to reset zoom</div>\n            <div>📐 <strong>Center:</strong> Ctrl+F to center view</div>\n            <div className=\"pt-1 border-t border-theme-border mt-1 font-semibold text-theme-text\">Selection</div>\n          <div>💡 <strong>Multi-select:</strong> Ctrl+Click nodes</div>\n          <div>📦 <strong>Box select:</strong> Drag to select area</div>\n          <div>⌨️ <strong>Select all:</strong> Ctrl+A</div>\n            <div>❌ <strong>Clear:</strong> Esc to clear selection</div>\n            <div className=\"pt-1 border-t border-theme-border mt-1 font-semibold text-theme-text\">Visual Cues</div>\n            <div>⚠️ <strong>Dashed:</strong> Missing information</div>\n            <div>✅ <strong>Solid:</strong> Complete data</div>\n            <div>🖱️ <strong>Hover:</strong> See node/edge details</div>\n        </div>\n      </div>\n      )}\n      \n      {/* Help Panel Toggle Button (when hidden) */}\n      {!showHelpPanel && (\n        <button\n          onClick={() => setShowHelpPanel(true)}\n          className=\"absolute bottom-2 left-2 bg-theme-card hover:bg-theme-card-hover rounded-lg shadow-lg border border-theme-border p-2 text-xs text-theme-text-secondary hover:text-theme-text transition-colors z-30\"\n          aria-label=\"Show navigation guide\"\n          title=\"Show Navigation Guide\"\n        >\n          <svg className=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n            <path fillRule=\"evenodd\" d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-3a1 1 0 00-.867.5 1 1 0 11-1.731-1A3 3 0 0113 8a3.001 3.001 0 01-2 2.83V11a1 1 0 11-2 0v-1a1 1 0 011-1 1 1 0 100-2zm0 8a1 1 0 100-2 1 1 0 000 2z\" clipRule=\"evenodd\" />\n          </svg>\n        </button>\n      )}\n\n      {/* Tooltip */}\n      <Tooltip\n        visible={tooltip.visible}\n        x={tooltip.x}\n        y={tooltip.y}\n        node={tooltip.node}\n        edge={tooltip.edge}\n        pinned={tooltip.pinned}\n        onClose={() => hideTooltip(true)}\n      />\n    </div>\n  );\n};\n\nexport default GraphVisualization; ","import type { GraphData, Node, Edge } from '../types/graph'\n\nfunction generateId(prefix: string): string {\n  return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n}\n\nfunction coerceStringId(value: unknown, fallbackPrefix: string): string {\n  const s = value == null ? '' : String(value).trim()\n  if (!s || s === '-' || s === 'null' || s === 'undefined') {\n    return generateId(fallbackPrefix)\n  }\n  return s\n}\n\nfunction buildLabel(record: any): string {\n  const parts: string[] = []\n  if (record.first_name) parts.push(String(record.first_name))\n  if (record.middle_name) parts.push(String(record.middle_name))\n  if (record.last_name) parts.push(String(record.last_name))\n  const full = parts.join(' ').trim()\n  if (full) return full\n  if (record.nick_name) return String(record.nick_name)\n  if (record.national_id) return String(record.national_id)\n  if (record.target_id != null) return String(record.target_id)\n  return 'Unnamed'\n}\n\nfunction isAlreadyGraphData(data: any): data is GraphData {\n  return data && Array.isArray(data.nodes) && Array.isArray(data.edges) &&\n    (data.nodes.length === 0 || typeof data.nodes[0]?.id !== 'undefined')\n}\n\nconst PHONE_KEYS = [\n  'phone_number',\n  'phoneNumber',\n  'phone',\n  'msisdn',\n  'source_detail',\n  'target_detail',\n]\n\nconst normalizePhoneValue = (value: string) => value.replace(/[^\\d+]/g, '')\nconst sanitizeId = (value: string) => value.replace(/[^a-zA-Z0-9_\\-:]/g, '_')\n\nconst findPhone = (record: any): string | null => {\n  for (const key of PHONE_KEYS) {\n    const raw = record?.[key]\n    if (raw == null) continue\n    const trimmed = String(raw).trim()\n    if (trimmed) return trimmed\n  }\n  return null\n}\n\nconst mergeMetadata = (existing?: Node['metadata'], incoming?: Node['metadata']): Node['metadata'] => {\n  if (!existing) return incoming\n  if (!incoming) return existing\n  return {\n    ...existing,\n    ...incoming,\n    tags: Array.from(new Set([...(existing.tags || []), ...(incoming.tags || [])])),\n    properties: {\n      ...(existing.properties || {}),\n      ...(incoming.properties || {}),\n    },\n    phoneAliases: Array.from(\n      new Set([...(existing.phoneAliases || []), ...(incoming.phoneAliases || [])])\n    ),\n  }\n}\n\n// Accepts multiple shapes and returns GraphData with safe IDs and fields coerced to strings\nexport function normalizeToGraphData(input: any): GraphData {\n  // If API wraps data under .data\n  const raw: any = input && input.data ? input.data : input\n\n  if (isAlreadyGraphData(raw)) {\n    // Ensure basic coercions (ids as strings, empty source/target allowed)\n    const nodes: Node[] = (raw.nodes || []).map((n: any) => {\n      const id = coerceStringId(n.id, 'node')\n      return {\n        id,\n        label: n.label || id,\n        type: n.type,\n        image: n.image,\n        metadata: n.metadata,\n        data: n.data,\n      }\n    })\n    const edges: Edge[] = (raw.edges || []).map((e: any) => {\n      const id = coerceStringId(e.id, 'edge')\n      const source = e.source == null ? '' : String(e.source)\n      const target = e.target == null ? '' : String(e.target)\n      return { id, source, target, label: e.label, weight: e.weight, data: e.data }\n    })\n    return { nodes, edges }\n  }\n\n  // New API shape example: { status, nodes: [{ target_id, ... }], edges: [{ id:'-', source:null, target:null, ... }] }\n  if (raw && Array.isArray(raw.nodes) && Array.isArray(raw.edges)) {\n    const canonicalNodes = new Map<string, Node>()\n    const aliasToCanonical = new Map<string, string>()\n    const phoneLookup = new Map<string, { id: string; label: string; raw: string }>()\n\n    const registerAlias = (alias: string | number | null | undefined, canonicalId: string) => {\n      if (alias == null) return\n      const value = String(alias).trim()\n      if (!value) return\n      aliasToCanonical.set(value, canonicalId)\n      aliasToCanonical.set(sanitizeId(value), canonicalId)\n    }\n\n    const getOrCreatePhoneId = (rawPhone: string) => {\n      const normalized = normalizePhoneValue(rawPhone.trim())\n      if (!normalized) return null\n      const existing = phoneLookup.get(normalized)\n      if (existing) return existing\n      const canonicalId = `phone-${sanitizeId(normalized)}`\n      const label = rawPhone.trim() || normalized\n      const payload = { id: canonicalId, label, raw: rawPhone.trim() || normalized }\n      phoneLookup.set(normalized, payload)\n      return payload\n    }\n\n    const ensureNode = (canonicalId: string, nodeData: Partial<Node>) => {\n      const incoming: Node = {\n        id: canonicalId,\n        label: nodeData.label || canonicalId,\n        type: nodeData.type || 'entity',\n        image: nodeData.image,\n        metadata: nodeData.metadata,\n        data: nodeData.data,\n      }\n\n      if (!canonicalNodes.has(canonicalId)) {\n        canonicalNodes.set(canonicalId, incoming)\n        return\n      }\n\n      const existing = canonicalNodes.get(canonicalId)!\n      canonicalNodes.set(canonicalId, {\n        ...existing,\n        label:\n          existing.label === existing.id && incoming.label\n            ? incoming.label\n            : existing.label || incoming.label || canonicalId,\n        type: incoming.type || existing.type,\n        image: existing.image || incoming.image,\n        metadata: mergeMetadata(existing.metadata, incoming.metadata),\n        data: {\n          ...(existing.data || {}),\n          ...(incoming.data || {}),\n        },\n      })\n    }\n\n    const ensurePhoneNode = (rawPhone: string, context?: Partial<Node>) => {\n      const payload = getOrCreatePhoneId(rawPhone)\n      if (!payload) return null\n      const metadata: Node['metadata'] = {\n        ...(context?.metadata || {}),\n        primaryPhone: rawPhone.trim(),\n        phoneAliases: Array.from(\n          new Set([...(context?.metadata?.phoneAliases || []), rawPhone.trim()])\n        ),\n        properties: {\n          ...(context?.metadata?.properties || {}),\n          phone_number: rawPhone.trim(),\n        },\n        synthetic: context?.metadata?.synthetic ?? context?.metadata?.isVirtual ?? false,\n      }\n      ensureNode(payload.id, {\n        id: payload.id,\n        label: context?.label || payload.label,\n        type: context?.type || 'phone',\n        metadata,\n        data: {\n          ...(context?.data || {}),\n          phone_number: rawPhone.trim(),\n        },\n      })\n      registerAlias(rawPhone, payload.id)\n      registerAlias(normalizePhoneValue(rawPhone), payload.id)\n      return payload.id\n    }\n\n    const resolveAlias = (value: any): string | null => {\n      if (value == null) return null\n      const str = String(value).trim()\n      if (!str) return null\n      if (aliasToCanonical.has(str)) return aliasToCanonical.get(str)!\n      const sanitized = sanitizeId(str)\n      if (aliasToCanonical.has(sanitized)) return aliasToCanonical.get(sanitized)!\n      if (canonicalNodes.has(str)) return str\n      return null\n    }\n\n    // Process base nodes and index aliases/phones\n    raw.nodes.forEach((record: any) => {\n      const phone = findPhone(record)\n      const fallbackId = coerceStringId(record.id ?? record.target_id, 'node')\n      let canonicalId = fallbackId\n\n      if (phone) {\n        const phoneInfo = getOrCreatePhoneId(phone)\n        if (phoneInfo) {\n          canonicalId = phoneInfo.id\n          registerAlias(phone, canonicalId)\n          registerAlias(normalizePhoneValue(phone), canonicalId)\n        }\n      } else {\n        canonicalId = sanitizeId(fallbackId)\n      }\n\n      registerAlias(record.id, canonicalId)\n      registerAlias(record.target_id, canonicalId)\n      registerAlias(canonicalId, canonicalId)\n\n      ensureNode(canonicalId, {\n        id: canonicalId,\n        label: buildLabel(record) || (phone || canonicalId),\n        type: record.type || (phone ? 'person' : 'entity'),\n        image: record.image_path || record.image || undefined,\n        metadata: {\n          properties: { ...record },\n          primaryPhone: phone || undefined,\n          phoneAliases: phone ? [phone] : undefined,\n          canonicalId,\n        },\n        data: { ...record, canonicalId },\n      })\n    })\n\n    const ensureGenericNode = (value: string) => {\n      const alias = resolveAlias(value)\n      if (alias) return alias\n      const sanitized = sanitizeId(value)\n      ensureNode(sanitized, {\n        id: sanitized,\n        label: value,\n        type: 'entity',\n        metadata: {\n          properties: { placeholderFrom: 'edge' },\n        },\n        data: {\n          placeholderFrom: 'edge',\n        },\n      })\n      registerAlias(value, sanitized)\n      return sanitized\n    }\n\n    const resolveFromDetail = (detail?: string | null) => {\n      if (!detail) return null\n      const phoneId = ensurePhoneNode(detail, {\n        label: detail,\n        type: 'phone',\n        metadata: {\n          synthetic: true,\n          isVirtual: true,\n        },\n      })\n      return phoneId\n    }\n\n    const edges: Edge[] = raw.edges.map((entry: any, idx: number) => {\n      const edgeId = coerceStringId(entry.id, 'edge')\n      let sourceId =\n        resolveFromDetail(entry.source_detail) ||\n        resolveAlias(entry.source) ||\n        (entry.source ? ensureGenericNode(String(entry.source)) : '')\n      let targetId =\n        resolveFromDetail(entry.target_detail) ||\n        resolveAlias(entry.target) ||\n        (entry.target ? ensureGenericNode(String(entry.target)) : '')\n\n      if (!sourceId && entry.source_detail) {\n        sourceId = ensureGenericNode(entry.source_detail)\n      }\n      if (!targetId && entry.target_detail) {\n        targetId = ensureGenericNode(entry.target_detail)\n      }\n\n      const data = { ...entry }\n      if (entry.source_detail != null) data.source_detail = entry.source_detail\n      if (entry.target_detail != null) data.target_detail = entry.target_detail\n\n      return {\n        id: edgeId || `edge-${idx}`,\n        source: sourceId || '',\n        target: targetId || '',\n        label: entry.label || entry.type || entry.relationship || undefined,\n        data,\n      }\n    })\n\n    const nodes = Array.from(canonicalNodes.values())\n    return { nodes, edges }\n  }\n\n  throw new Error('Unsupported data format: expected { nodes, edges } or API response with nodes/edges')\n}\n\n\n","import type { Node, Edge, DetachedNodeGroup, DetachedNodesFilter, OrganizationMode } from '../types/graph';\n\n/**\n * Identifies nodes that have no connections (edges)\n */\nexport function getDetachedNodes(nodes: Node[], edges: Edge[]): Node[] {\n  const connectedNodeIds = new Set<string>();\n  \n  // Collect all node IDs that appear in edges\n  edges.forEach(edge => {\n    connectedNodeIds.add(edge.source);\n    connectedNodeIds.add(edge.target);\n  });\n  \n  // Return nodes that are not in the connected set\n  return nodes.filter(node => !connectedNodeIds.has(node.id));\n}\n\n/**\n * Filters detached nodes based on provided criteria\n */\nconst normalizeValue = (value: unknown): string[] => {\n  if (value === null || value === undefined) return []\n  const raw = String(value).trim()\n  if (!raw) return []\n  const lower = raw.toLowerCase()\n  const digits = raw.replace(/[^0-9+]/g, '')\n  const variants = new Set<string>([lower])\n  if (digits && digits !== lower) {\n    variants.add(digits)\n  }\n  return Array.from(variants)\n}\n\nconst collectNodeIdentifiers = (node: Node): Set<string> => {\n  const identifiers = new Set<string>()\n  const push = (value: unknown) => {\n    normalizeValue(value).forEach(val => identifiers.add(val))\n  }\n\n  push(node.id)\n  push(node.label)\n  push(node.type)\n  push(node.metadata?.category)\n  push(node.metadata?.primaryPhone)\n  node.metadata?.phoneAliases?.forEach(push)\n\n  const properties = node.metadata?.properties || {}\n  push(properties.phone_number)\n  push(properties.phoneNumber)\n  push(properties.phone)\n  push(properties.msisdn)\n  push(properties.target_person)\n\n  const data = node.data || {}\n  push(data.phone_number)\n  push(data.phoneNumber)\n  push(data.phone)\n  push(data.msisdn)\n\n  return identifiers\n}\n\nconst matchesTerm = (identifiers: Set<string>, term: string): boolean => {\n  const normalized = normalizeValue(term)\n  if (normalized.length === 0) return false\n  return normalized.some(value => identifiers.has(value))\n}\n\nexport function filterDetachedNodes(nodes: Node[], filter: DetachedNodesFilter): Node[] {\n  return nodes.filter(node => {\n    const identifiers = collectNodeIdentifiers(node)\n\n    if (filter.includeValues && filter.includeValues.length > 0) {\n      const hasMatch = filter.includeValues.some(term => matchesTerm(identifiers, term))\n      if (!hasMatch) return false\n    }\n\n    if (filter.excludeValues && filter.excludeValues.length > 0) {\n      const isExcluded = filter.excludeValues.some(term => matchesTerm(identifiers, term))\n      if (isExcluded) return false\n    }\n\n    // Category filter\n    if (filter.category) {\n      const nodeCategory = node.metadata?.category || 'uncategorized';\n      if (nodeCategory !== filter.category) return false;\n    }\n    \n    // Type filter\n    if (filter.type) {\n      const nodeType = node.type || 'unknown';\n      if (nodeType !== filter.type) return false;\n    }\n    \n    // Tags filter\n    if (filter.tags && filter.tags.length > 0) {\n      const nodeTags = node.metadata?.tags || [];\n      const hasMatchingTag = filter.tags.some(tag => nodeTags.includes(tag));\n      if (!hasMatchingTag) return false;\n    }\n    \n    // Search term filter\n    if (filter.searchTerm) {\n      const searchTerm = filter.searchTerm.toLowerCase();\n      const matchesLabel = node.label.toLowerCase().includes(searchTerm);\n      const matchesDescription = node.metadata?.description?.toLowerCase().includes(searchTerm) || false;\n      const matchesTags = node.metadata?.tags?.some(tag => tag.toLowerCase().includes(searchTerm)) || false;\n      const matchesIdentifiers = matchesTerm(identifiers, searchTerm);\n      if (!matchesLabel && !matchesDescription && !matchesTags && !matchesIdentifiers) return false;\n    }\n    \n    return true;\n  });\n}\n\n/**\n * Groups detached nodes by the specified organization mode\n */\nexport function groupDetachedNodes(nodes: Node[], organizationMode: OrganizationMode): DetachedNodeGroup[] {\n  const groups = new Map<string, Node[]>();\n  \n  nodes.forEach(node => {\n    let groupKey: string;\n    \n    switch (organizationMode) {\n      case 'category':\n        groupKey = node.metadata?.category || 'uncategorized';\n        break;\n      case 'type':\n        groupKey = node.type || 'unknown';\n        break;\n      case 'tags':\n        const primaryTag = node.metadata?.tags?.[0] || 'untagged';\n        groupKey = primaryTag;\n        break;\n      case 'alphabetical':\n        groupKey = node.label.charAt(0).toUpperCase();\n        break;\n      case 'date':\n        const date = node.metadata?.createdAt;\n        if (date) {\n          const dateObj = new Date(date);\n          groupKey = dateObj.toISOString().split('T')[0]; // YYYY-MM-DD\n        } else {\n          groupKey = 'no date';\n        }\n        break;\n      default:\n        groupKey = 'all';\n    }\n    \n    if (!groups.has(groupKey)) {\n      groups.set(groupKey, []);\n    }\n    groups.get(groupKey)!.push(node);\n  });\n  \n  // Convert to DetachedNodeGroup array and sort\n  const result = Array.from(groups.entries()).map(([category, nodes]) => ({\n    category,\n    nodes: sortNodesInGroup(nodes, organizationMode),\n    count: nodes.length,\n  }));\n  \n  // Sort groups by category name\n  return result.sort((a, b) => {\n    // Special handling for certain categories\n    if (a.category === 'uncategorized') return 1;\n    if (b.category === 'uncategorized') return -1;\n    if (a.category === 'unknown') return 1;\n    if (b.category === 'unknown') return -1;\n    if (a.category === 'untagged') return 1;\n    if (b.category === 'untagged') return -1;\n    if (a.category === 'no date') return 1;\n    if (b.category === 'no date') return -1;\n    \n    return a.category.localeCompare(b.category);\n  });\n}\n\n/**\n * Sorts nodes within a group based on organization mode\n */\nfunction sortNodesInGroup(nodes: Node[], organizationMode: OrganizationMode): Node[] {\n  return [...nodes].sort((a, b) => {\n    switch (organizationMode) {\n      case 'date':\n        const dateA = a.metadata?.createdAt ? new Date(a.metadata.createdAt).getTime() : 0;\n        const dateB = b.metadata?.createdAt ? new Date(b.metadata.createdAt).getTime() : 0;\n        return dateB - dateA; // Most recent first\n      case 'alphabetical':\n      case 'category':\n      case 'type':\n      case 'tags':\n      default:\n        return a.label.localeCompare(b.label);\n    }\n  });\n}\n\n/**\n * Gets unique values for filter options\n */\nexport function getFilterOptions(nodes: Node[]) {\n  const categories = new Set<string>();\n  const types = new Set<string>();\n  const tags = new Set<string>();\n  \n  nodes.forEach(node => {\n    categories.add(node.metadata?.category || 'uncategorized');\n    types.add(node.type || 'unknown');\n    node.metadata?.tags?.forEach(tag => tags.add(tag));\n  });\n  \n  return {\n    categories: Array.from(categories).sort(),\n    types: Array.from(types).sort(),\n    tags: Array.from(tags).sort(),\n  };\n}\n\n/**\n * Bulk updates category for multiple nodes\n */\nexport function bulkUpdateNodeCategory(nodes: Node[], nodeIds: string[], newCategory: string): Node[] {\n  return nodes.map(node => {\n    if (nodeIds.includes(node.id)) {\n      return {\n        ...node,\n        metadata: {\n          ...node.metadata,\n          category: newCategory,\n          updatedAt: new Date().toISOString(),\n        },\n      };\n    }\n    return node;\n  });\n}\n\n/**\n * Bulk updates type for multiple nodes\n */\nexport function bulkUpdateNodeType(nodes: Node[], nodeIds: string[], newType: string): Node[] {\n  return nodes.map(node => {\n    if (nodeIds.includes(node.id)) {\n      return {\n        ...node,\n        type: newType,\n        metadata: {\n          ...node.metadata,\n          updatedAt: new Date().toISOString(),\n        },\n      };\n    }\n    return node;\n  });\n}\n\n/**\n * Adds tags to multiple nodes\n */\nexport function bulkAddTags(nodes: Node[], nodeIds: string[], newTags: string[]): Node[] {\n  return nodes.map(node => {\n    if (nodeIds.includes(node.id)) {\n      const existingTags = node.metadata?.tags || [];\n      const updatedTags = [...new Set([...existingTags, ...newTags])]; // Remove duplicates\n      return {\n        ...node,\n        metadata: {\n          ...node.metadata,\n          tags: updatedTags,\n          updatedAt: new Date().toISOString(),\n        },\n      };\n    }\n    return node;\n  });\n} ","import React, { createContext, useContext, useEffect, useState } from 'react'\n\nexport type Theme = 'light' | 'dark' | 'system'\n\ninterface ThemeContextType {\n  theme: Theme\n  setTheme: (theme: Theme) => void\n  isDark: boolean\n}\n\nconst ThemeContext = createContext<ThemeContextType | undefined>(undefined)\n\nexport const useTheme = () => {\n  const context = useContext(ThemeContext)\n  if (context === undefined) {\n    throw new Error('useTheme must be used within a ThemeProvider')\n  }\n  return context\n}\n\ninterface ThemeProviderProps {\n  children: React.ReactNode\n}\n\nexport const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {\n  const [theme, setTheme] = useState<Theme>(() => {\n    const saved = localStorage.getItem('la-theme')\n    return (saved as Theme) || 'system'\n  })\n\n  const [isDark, setIsDark] = useState(() => {\n    if (theme === 'dark') return true\n    if (theme === 'light') return false\n    return window.matchMedia('(prefers-color-scheme: dark)').matches\n  })\n\n  useEffect(() => {\n    const updateTheme = () => {\n      if (theme === 'system') {\n        setIsDark(window.matchMedia('(prefers-color-scheme: dark)').matches)\n      } else {\n        setIsDark(theme === 'dark')\n      }\n    }\n\n    updateTheme()\n    localStorage.setItem('la-theme', theme)\n\n    if (theme === 'system') {\n      const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n      mediaQuery.addEventListener('change', updateTheme)\n      return () => mediaQuery.removeEventListener('change', updateTheme)\n    }\n  }, [theme])\n\n  useEffect(() => {\n    const root = document.documentElement\n    root.classList.remove('light', 'dark')\n    root.classList.add(isDark ? 'dark' : 'light')\n  }, [isDark])\n\n  return (\n    <ThemeContext.Provider value={{ theme, setTheme, isDark }}>\n      {children}\n    </ThemeContext.Provider>\n  )\n}\n"],"names":["NODE_FIELD_MAPPINGS","Tooltip","visible","x","y","node","edge","content","idAttr","pinned","onClose","position","setPosition","useState","useEffect","tooltip","rect","viewportWidth","viewportHeight","adjustedX","adjustedY","formatDate","dateString","renderNodeTooltip","missingFields","isVirtualNode","isFloatingEdge","propertySource","detailEntries","key","label","value","renderValue","val","jsxs","jsx","e","Fragment","tag","field","renderEdgeTooltip","isIsolated","defaultLayout","defaultStyle","nodeTypeColors","neoColors","identifierKeys","createIdentifierVariants","raw","lower","digits","variants","buildIdentifierSetFromNode","identifiers","add","variant","_a","_b","_d","_c","metaProps","_e","nodeData","cytoscape","coseBilkent","cola","avsdf","GraphVisualization","data","layout","style","selectedNodeIds","onNodeClick","onEdgeClick","onSelectionChange","includeFilters","excludeFilters","onIncludeFiltersChange","onExcludeFiltersChange","graphFilter","onGraphFilterChange","filterOptions","layoutOptions","selectedLayoutName","onLayoutSelect","onOpenDataManager","cyRef","useRef","zoomLevel","setZoomLevel","searchQuery","setSearchQuery","searchResults","setSearchResults","highlightedNodeId","setHighlightedNodeId","mousePosition","setMousePosition","showHelpPanel","setShowHelpPanel","isFullscreen","setIsFullscreen","canvasRef","showFilterOverlay","setShowFilterOverlay","includeInput","setIncludeInput","excludeInput","setExcludeInput","controlTab","setControlTab","nodeIdentifierMap","useMemo","map","getNodesMatchingValue","useCallback","includeSummaries","excludeSummaries","currentFilter","filterOptionsSafe","filtersEnabled","updateGraphFilter","patch","handleIncludeSubmit","addFilterValue","handleExcludeSubmit","handleIncludeKeyDown","event","handleExcludeKeyDown","setTooltip","hideTooltip","force","prev","current","setter","resetInput","normalized","v","removeFilterValue","existingNodeIds","augmentedNodeIds","detailNodeMap","getDetailNodeId","detail","role","clean","nodeId","existing","roles","virtualNodes","hasExplicitSource","hasExplicitTarget","missingSource","missingTarget","isSourceMissing","isTargetMissing","unmatchedEdges","processedEdges","index","trimmedSource","trimmedTarget","sourceId","targetId","validEdgeId","aggregationMap","aggregatedEdges","group","base","interactionCount","combinedLabels","item","aggregatedLabel","description","reciprocalMap","source","target","edges","existingClasses","classes","detailNodes","floatingVirtualNodes","hasEmptySource","hasEmptyTarget","hasEmptyBoth","elements","validNodeId","stylesheet","centerGraph","updateZoomLevel","zoomIn","zoomOut","resetZoom","fitToSelection","selected","navigateToNode","handleSelectionChange","query","results","selectedIds","cy","evt","originalEvent","renderedPosition","containerOffset","n","nd","pseudoEdge","renderedMidpoint","edgeData","handleKeyDown","toggleFullscreen","handleWindowEvent","cyNode","timeoutId","handleMouseMove","handleMouseLeave","error","handleFullscreenChange","nowFullscreen","CytoscapeComponent","container","tab","option","c","t","tags","nodes","generateId","prefix","coerceStringId","fallbackPrefix","s","buildLabel","record","parts","full","isAlreadyGraphData","PHONE_KEYS","normalizePhoneValue","sanitizeId","findPhone","trimmed","mergeMetadata","incoming","normalizeToGraphData","input","id","canonicalNodes","aliasToCanonical","phoneLookup","registerAlias","alias","canonicalId","getOrCreatePhoneId","rawPhone","payload","ensureNode","ensurePhoneNode","context","metadata","resolveAlias","str","sanitized","phone","fallbackId","phoneInfo","ensureGenericNode","resolveFromDetail","entry","idx","edgeId","normalizeValue","collectNodeIdentifiers","push","properties","matchesTerm","term","filterDetachedNodes","filter","nodeTags","searchTerm","matchesLabel","matchesDescription","matchesTags","_f","matchesIdentifiers","getFilterOptions","categories","types","ThemeContext","createContext","useTheme","useContext","ThemeProvider","children","theme","setTheme","isDark","setIsDark","updateTheme","mediaQuery","root"],"mappings":"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"}