diff --git a/flowsint-app/src/components/graphs/graph-main.tsx b/flowsint-app/src/components/graphs/graph-main.tsx
index 62b320de..4e5e96ba 100644
--- a/flowsint-app/src/components/graphs/graph-main.tsx
+++ b/flowsint-app/src/components/graphs/graph-main.tsx
@@ -1,9 +1,8 @@
import { useGraphStore } from '@/stores/graph-store'
import React, { useRef, useCallback } from 'react'
-// import GraphViewer from './graph-viewer'
+import GraphViewer from './graph-viewer'
// import WebGLGraphViewer from './webgl'
import ContextMenu from './context-menu'
-import GraphViewer from './graph-viewer'
import { useParams } from '@tanstack/react-router'
const GraphMain = () => {
@@ -58,12 +57,12 @@ const GraphMain = () => {
return (
{/* */}
void
- onNodeRightClick?: (node: GraphNode, event: MouseEvent) => void
- onBackgroundClick?: () => void
- showIcons?: boolean
- showLabels?: boolean
- layoutMode?: 'none' | 'force' | 'dagre'
-}
-
-/**
- * WebGL Graph Viewer Component
- * High-performance graph visualization using WebGL (Pixi.js) and D3-force
- *
- * @deprecated This is a legacy wrapper. Import from './webgl' for the new modular version.
- */
-const WebGLGraphViewerLegacy: React.FC = (props) => {
- return
-}
-
-export default WebGLGraphViewerLegacy
diff --git a/flowsint-app/src/components/graphs/webgl/CHANGELOG.md b/flowsint-app/src/components/graphs/webgl/CHANGELOG.md
deleted file mode 100644
index a3c587f1..00000000
--- a/flowsint-app/src/components/graphs/webgl/CHANGELOG.md
+++ /dev/null
@@ -1,395 +0,0 @@
-# Changelog - WebGL Graph Viewer
-
-## [2.3.0] - Layout Modes Architecture
-
-### šļø Architecture Refactoring: Unified View System
-
-**Major architectural change**: Graph views consolidated into a single "graph" view with switchable layout modes.
-
-#### ⨠New Features
-
-##### Unified View Architecture
-- **4 Views instead of 5**: `graph`, `table`, `relationships`, `map`
-- **Graph view with layout modes**: `none` (default), `force`, `dagre`
-- **Dynamic layout switching**: Change layouts without changing views
-- **Layout buttons**: Only visible when in graph view
-
-##### Layout Mode Support
-```typescript
-type LayoutMode = 'none' | 'force' | 'dagre'
-
-// none: Static grid layout (default)
-// force: D3 force-directed physics simulation
-// dagre: Hierarchical top-down layout
-```
-
-##### Store Updates
-```typescript
-// graph-controls-store.ts
-view: 'graph' | 'table' | 'map' | 'relationships'
-layoutMode: 'none' | 'force' | 'dagre'
-setLayoutMode: (mode: LayoutMode) => void
-```
-
-### š§ Technical Changes
-
-#### Updated Files
-
-**`use-force-simulation.ts`**
-- Now supports 3 layout modes
-- Static grid layout for `layoutMode === 'none'`
-- Force simulation only runs when `layoutMode === 'force'`
-- Dagre hierarchical layout for `layoutMode === 'dagre'`
-
-**`toolbar.tsx`**
-- Layout buttons (Force/Dagre) only visible in graph view
-- View buttons always visible
-- Updated disabled states to use `view !== 'graph'`
-
-**`graph-main.tsx`**
-- Passes `layoutMode` prop to WebGLGraphViewer
-- Removed separate hierarchy/force view logic
-
-**`WebGLGraphViewer`**
-- Added `layoutMode?: LayoutMode` prop
-- Defaults to `'none'` (static grid)
-
-### š Migration Guide
-
-#### For Users
-
-**Before:**
-- Separate views: "Force" and "Hierarchy"
-- Switching between force/hierarchy changed the entire view
-
-**After:**
-- Single "Graph" view
-- Toggle between Force/Dagre layouts within graph view
-- Default: Static grid (no automatic layout)
-
-#### For Developers
-
-**Old imports (still work):**
-```typescript
-import WebGLGraphViewer from './webgl-graph-viewer'
-// Legacy wrapper, automatically redirects to new module
-```
-
-**New imports (recommended):**
-```typescript
-import WebGLGraphViewer from './webgl'
-```
-
-**Props:**
-```typescript
-
-```
-
-### šÆ User Experience
-
-**Graph View Workflow:**
-1. Open graph view (default: static grid layout)
-2. Click "Force Layout" button ā activates physics simulation
-3. Click "Dagre Layout" button ā applies hierarchical layout
-4. Layout buttons hidden when switching to table/map/relationships views
-
-### ā ļø Breaking Changes
-
-None! Fully backward compatible via legacy wrapper.
-
-### š Performance
-
-- Static grid layout (none): Instant rendering, no CPU overhead
-- Force layout: Same performance as before
-- Dagre layout: One-time calculation, then static
-
----
-
-## [2.2.0] - Smart Label Decluttering
-
-### š Major Feature: Intelligent Label Selection
-
-**No more overlapping labels!** Complete redesign of the labeling system with collision detection and priority-based selection.
-
-#### ⨠New Features
-
-##### Smart Decluttering Algorithm
-- **Collision detection**: Labels never overlap (4px minimum margin)
-- **Priority-based selection**: Important nodes get labels first
-- **Bounding box calculation**: Accurate screen-space dimensions
-- **Greedy algorithm**: Optimal label placement without overlap
-- **Spatial hashing**: Fast collision detection for large graphs (10,000+ nodes)
-
-##### Priority Scoring System
-```typescript
-priority = connectionScore * 0.7 + centerScore * 0.3
-```
-- **Connection score (70%)**: Highly connected nodes prioritized
-- **Center score (30%)**: Viewport-centered nodes prioritized
-- **Selection-aware**: Selected/highlighted nodes always show labels
-
-##### Performance Optimizations
-- Small graphs (< 500 nodes): Accurate O(n²) collision detection
-- Large graphs (ā„ 500 nodes): Fast O(1) spatial hashing
-- Max 200 labels by default (configurable)
-- Throttled recalculation (200ms)
-- Zoom hiding (labels hidden during active zoom)
-
-### š Performance Impact
-
-| Graph Size | Before | After | Result |
-|------------|--------|-------|--------|
-| 100 nodes | 60 FPS (overlaps) | 60 FPS | ā
No overlap |
-| 1,000 nodes | 50 FPS (overlaps) | 58 FPS | ā
+16% + Clean |
-| 5,000 nodes | 45 FPS (overlaps) | 55 FPS | ā
+22% + Clean |
-| 10,000 nodes | 35 FPS (overlaps) | 50 FPS | ā
+43% + Clean |
-
-**Benefits:**
-- šØ **Cleaner visuals**: No overlapping labels
-- š§ **Smarter selection**: Important nodes prioritized
-- š **Better performance**: Fewer labels = faster rendering
-- š **Viewport-aware**: Relevant labels shown
-
-### š§ Technical Changes
-
-#### New Module: `label-decluttering.ts`
-```typescript
-// New functions
-calculateLabelBoundingBox() // Exact screen-space dimensions
-boundingBoxesOverlap() // Collision detection
-selectLabelsWithDecluttering() // Accurate selection
-selectLabelsWithDeclutteringFast() // Fast selection for large graphs
-```
-
-#### New Type: `LabelBoundingBox`
-```typescript
-interface LabelBoundingBox {
- nodeId: string
- x: number
- y: number
- width: number
- height: number
- priority: number // 0-1, higher = more important
-}
-```
-
-#### Updated: `use-graph-renderer.ts`
-- Replaced `calculateVisibleLabels()` with `selectLabelsWithDeclutteringFast()`
-- Integrated viewport and camera position
-- Added decluttering to zoom throttling
-
-### š New Files
-
-- `utils/label-decluttering.ts` - Core decluttering algorithms
-- `DECLUTTERING.md` - Comprehensive documentation
-
-### š Documentation
-
-- New [DECLUTTERING.md](./DECLUTTERING.md) with detailed explanation
-- Updated [README.md](./README.md) with decluttering section
-- Updated exports with new functions
-
-### ā ļø Breaking Changes
-
-None! Fully backward compatible.
-
-### š Migration
-
-No migration needed - decluttering is automatic!
-
-Old function still available (deprecated):
-```typescript
-// Old way (deprecated, no collision detection)
-calculateVisibleLabels(nodes, zoomLevel)
-
-// New way (automatic in renderer)
-selectLabelsWithDeclutteringFast(...)
-```
-
----
-
-## [2.1.0] - Styled Label Backgrounds
-
-### ⨠New Features
-
-#### Cosmograph-Inspired Label Backgrounds
-- **Beautiful label backgrounds** with rounded corners
-- **Subtle borders** for better visibility
-- **Configurable styling** (padding, radius, colors, opacity)
-- **Responsive alpha** based on highlight state
-- **Performance optimized** - backgrounds update with labels
-
-#### Visual Improvements
-- Labels now stand out clearly against any background
-- Better readability in dense graphs
-- Professional, polished appearance
-- Consistent with modern graph visualization tools
-
-### šØ Style Configuration
-
-```ts
-NODE_LABEL_PADDING_X: 6 // Horizontal padding
-NODE_LABEL_PADDING_Y: 3 // Vertical padding
-NODE_LABEL_BORDER_RADIUS: 4 // Rounded corners
-NODE_LABEL_BORDER_WIDTH: 1 // Border thickness
-LABEL_BG_COLOR: 0x1a1a1a // Dark background
-LABEL_BG_BORDER_COLOR: 0x404040 // Subtle gray border
-NODE_LABEL_BG_ALPHA: 0.92 // 92% opacity
-NODE_LABEL_BG_BORDER_ALPHA: 0.3 // 30% opacity
-```
-
-### š§ Technical Changes
-
-- Added `NodeLabelObjects` type with `text` and `background`
-- Updated `createNodeLabel()` to return label objects
-- Modified `updateNodeLabel()` to manage backgrounds
-- Optimized rendering order (backgrounds before text)
-
----
-
-## [2.0.0] - LOD System + Context-Aware Labels
-
-### š Major Features
-
-#### Level of Details (LOD) System
-- **Adaptive rendering** based on zoom level
-- **4 LOD levels**: minimal, low, medium, high
-- **Automatic optimization** - no configuration needed
-- **Performance gain**: +80% when zoomed out
-
-#### Context-Aware Edge Labels
-- Edge labels **only appear when nodes are active**
-- Active = hovered, selected, or highlighted
-- **90% reduction** in visual clutter
-- **50% fewer labels** rendered on average
-
-### ⨠Improvements
-
-#### Architecture
-- **Modular structure**: 16 specialized files
-- **Hooks-based**: Clean separation of concerns
-- **Type-safe**: Full TypeScript coverage
-- **Testable**: Each module can be tested independently
-
-#### Performance
-- **Texture caching**: Icons loaded once, reused globally
-- **Batch rendering**: Edges grouped by style
-- **Early returns**: Skip calculations for invisible elements
-- **Manual rendering**: Better control over frame timing
-
-#### Developer Experience
-- **LOD Indicator**: Debug component for development
-- **Comprehensive docs**: README with examples
-- **Public exports**: Hooks and utilities available
-- **Backward compatible**: Old imports still work
-
-### š Performance Metrics
-
-| Nodes | Zoom Out (0.25x) | Medium (1.0x) | Zoomed In (2.0x) |
-|-------|------------------|---------------|------------------|
-| 1K | 60 FPS | 60 FPS | 60 FPS |
-| 5K | 60 FPS | 55 FPS | 50 FPS |
-| 10K | 55-60 FPS | 50 FPS | 45 FPS |
-| 50K | 45-60 FPS | 35 FPS | 25-35 FPS |
-
-### š§ Technical Details
-
-#### LOD Thresholds
-```ts
-LOD_ICON_MIN_ZOOM: 0.6 // Icons visible at zoom >= 0.6
-LOD_NODE_LABEL_MIN_ZOOM: 0.5 // Node labels visible at zoom >= 0.5
-LOD_EDGE_LABEL_MIN_ZOOM: 1.2 // Edge labels enabled at zoom >= 1.2
-LOD_HIGH_DETAIL_ZOOM: 1.5 // High quality mode at zoom >= 1.5
-```
-
-#### Edge Label Logic
-```ts
-// Show edge label if:
-// 1. Zoom >= LOD_EDGE_LABEL_MIN_ZOOM
-// 2. Source node is active OR target node is active
-// Active = hovered || selected || highlighted
-```
-
-### š File Structure
-
-```
-webgl/
-āāā index.tsx # Main component (150 lines)
-āāā constants.ts # Configuration
-āāā exports.ts # Public API
-āāā README.md # Documentation
-āāā CHANGELOG.md # This file
-āāā components/
-ā āāā lod-indicator.tsx # Debug component
-āāā hooks/ # Business logic
-ā āāā use-pixi-app.ts
-ā āāā use-force-simulation.ts
-ā āāā use-graph-interactions.ts
-ā āāā use-zoom-pan.ts
-ā āāā use-graph-renderer.ts
-āāā renderers/ # Rendering logic
-ā āāā node-renderer.ts
-ā āāā edge-renderer.ts
-ā āāā label-renderer.ts
-āāā utils/ # Utilities
-ā āāā texture-cache.ts
-ā āāā visibility-calculator.ts
-ā āāā color-utils.ts
-āāā types/
- āāā graph.types.ts # TypeScript types
-```
-
-### šÆ Breaking Changes
-
-None - fully backward compatible!
-
-### š Bug Fixes
-
-- Fixed edge label overlap issues
-- Fixed icon flickering on zoom
-- Fixed memory leak on component unmount
-
-### š Migration Guide
-
-#### From v1.0 (monolithic)
-```tsx
-// Old way - still works!
-import WebGLGraphViewer from './webgl-graph-viewer'
-
-// New way - recommended
-import WebGLGraphViewer from './webgl'
-```
-
-#### Using new features
-```tsx
-// Enable LOD indicator for debugging
-import { LODIndicator } from './webgl/exports'
-
-// Use LOD utilities
-import { getLODLevel, shouldShowNodeIcons } from './webgl/exports'
-
-const lodLevel = getLODLevel(zoomLevel)
-console.log(`Current LOD: ${lodLevel}`) // 'minimal', 'low', 'medium', 'high'
-```
-
-### š„ Contributors
-
-- Refactored from monolithic 1000-line component
-- Implemented modular architecture
-- Added LOD system
-- Context-aware edge labels
-
----
-
-## [1.0.0] - Initial Release
-
-- Basic WebGL graph visualization
-- Pixi.js + D3-force
-- Node interactions (hover, click, drag)
-- Zoom/pan controls
-- Basic icon and label support
diff --git a/flowsint-app/src/components/graphs/webgl/DECLUTTERING.md b/flowsint-app/src/components/graphs/webgl/DECLUTTERING.md
deleted file mode 100644
index bbab1f16..00000000
--- a/flowsint-app/src/components/graphs/webgl/DECLUTTERING.md
+++ /dev/null
@@ -1,418 +0,0 @@
-# Label Decluttering System
-
-This document explains the intelligent label decluttering system that prevents labels from overlapping.
-
-## Overview
-
-The decluttering system automatically selects which labels to display based on:
-1. **Collision detection** - Labels never overlap
-2. **Priority scoring** - Important nodes get labels first
-3. **Spatial awareness** - Viewport-centered labels preferred
-4. **Selection state** - Selected/highlighted nodes always show labels
-
-## Architecture
-
-### Before: Simple Selection
-```typescript
-// Old system (basic, no collision detection)
-calculateVisibleLabels(nodes, zoomLevel)
-// - Selected top N nodes by connection count
-// - No collision detection
-// - Labels could overlap completely
-```
-
-### After: Intelligent Decluttering
-```typescript
-// New system (collision-aware, priority-based)
-selectLabelsWithDeclutteringFast(
- nodes,
- nodeSize,
- zoomLevel,
- fontSizeSetting,
- viewportWidth,
- viewportHeight,
- cameraX,
- cameraY,
- selectedNodeIds,
- highlightedNodeIds
-)
-// - Calculates real bounding boxes
-// - Detects collisions
-// - Greedy selection by priority
-// - Optimized with spatial hashing for large graphs
-```
-
-## Key Components
-
-### 1. Bounding Box Calculation
-
-Each label's exact screen space is calculated:
-
-```typescript
-interface LabelBoundingBox {
- nodeId: string
- x: number // Center X position
- y: number // Top Y position
- width: number // Background width (text + padding)
- height: number // Background height (text + padding)
- priority: number // 0-1, higher = more important
-}
-```
-
-**Calculation includes:**
-- Text length estimation (`fontSize * 0.6` per character)
-- Background padding (`NODE_LABEL_PADDING_X`, `NODE_LABEL_PADDING_Y`)
-- Label position (below node: `node.y + nodeSize + fontSize * 0.6`)
-- Zoom-adjusted font size
-
-### 2. Priority Scoring
-
-Labels are prioritized using multiple factors:
-
-```typescript
-priority = connectionScore * 0.7 + centerScore * 0.3
-```
-
-**Connection Score (70% weight):**
-- Normalized by neighbor count
-- `Math.min(node.neighbors.length / 20, 1)`
-- Highly connected nodes = more important
-
-**Center Score (30% weight):**
-- Distance from viewport center
-- Closer to center = more important
-- Calculated as: `1 - distanceFromCenter / maxDistance`
-
-**Result:**
-- Nodes with many connections in viewport center get highest priority
-- Peripheral or less-connected nodes deprioritized
-
-### 3. Collision Detection
-
-Two methods for different graph sizes:
-
-#### Accurate Detection (< 500 nodes)
-```typescript
-function boundingBoxesOverlap(a: LabelBoundingBox, b: LabelBoundingBox): boolean {
- // Add 4px margin for breathing room
- const margin = 4
-
- // Calculate bounds with margin
- const aLeft = a.x - a.width / 2 - margin
- const aRight = a.x + a.width / 2 + margin
- const aTop = a.y - margin
- const aBottom = a.y + a.height + margin
-
- // Check for overlap
- return !(aRight < bLeft || aLeft > bRight || aBottom < bTop || aTop > bBottom)
-}
-```
-
-#### Spatial Hashing (ā„ 500 nodes)
-For large graphs, uses a grid-based approach:
-
-```typescript
-const gridSize = 100 // 100px grid cells
-const occupiedCells = new Set()
-
-// Mark cell as occupied
-const cellKey = `${Math.floor(x / gridSize)},${Math.floor(y / gridSize)}`
-occupiedCells.add(cellKey)
-
-// Also mark adjacent cells (9 cells total)
-for (let dx = -1; dx <= 1; dx++) {
- for (let dy = -1; dy <= 1; dy++) {
- occupiedCells.add(`${cellX + dx},${cellY + dy}`)
- }
-}
-```
-
-**Benefits:**
-- O(1) collision check instead of O(n²)
-- 10-100x faster for large graphs
-- Slight accuracy tradeoff acceptable for performance
-
-### 4. Greedy Selection Algorithm
-
-Labels are selected in order of priority:
-
-```typescript
-// Step 1: Sort all labels by priority (highest first)
-boundingBoxes.sort((a, b) => b.priority - a.priority)
-
-// Step 2: Always add selected/highlighted nodes first
-const placedBboxes = [...selectedBboxes, ...highlightedBboxes]
-visibleSet.add(selectedNodeIds)
-visibleSet.add(highlightedNodeIds)
-
-// Step 3: Greedily add non-colliding labels
-for (const candidate of regularBboxes) {
- let hasCollision = false
-
- for (const placed of placedBboxes) {
- if (boundingBoxesOverlap(candidate, placed)) {
- hasCollision = true
- break
- }
- }
-
- if (!hasCollision) {
- placedBboxes.push(candidate)
- visibleSet.add(candidate.nodeId)
- }
-}
-```
-
-**Guarantees:**
-- ā
Selected/highlighted nodes always have visible labels
-- ā
No two labels ever overlap (4px minimum margin)
-- ā
Higher priority nodes get labels before lower priority
-- ā
Maximum label density without collisions
-
-## Performance Optimizations
-
-### 1. Algorithm Selection
-```typescript
-if (nodes.length < 500) {
- // Use accurate collision detection
- selectLabelsWithDecluttering(...)
-} else {
- // Use spatial hashing
- selectLabelsWithDeclutteringFast(..., maxLabels: 200)
-}
-```
-
-### 2. Throttling
-```typescript
-// Recalculate max once every 200ms during zoom
-if (now - lastLabelUpdateRef.current > 200) {
- lastLabelUpdateRef.current = now
- setVisibleLabels(selectLabelsWithDeclutteringFast(...))
-}
-```
-
-### 3. Zoom Hiding
-```typescript
-// Hide ALL labels during active zoom (< 300ms since last zoom change)
-if (isZoomingRef.current) {
- labelObjects.text.visible = false
- labelObjects.background.visible = false
- return
-}
-```
-
-### 4. Frame Limiting
-```typescript
-// Still limit to 100 labels rendered per frame
-const MAX_LABELS_PER_FRAME = 100
-let renderedLabelCount = 0
-
-// In render loop:
-if (renderedLabelCount >= MAX_LABELS_PER_FRAME) {
- label.visible = false
- return
-}
-```
-
-## Performance Metrics
-
-| Graph Size | Old System | New System | Improvement |
-|------------|-----------|------------|-------------|
-| 100 nodes | 60 FPS | 60 FPS | Same |
-| 500 nodes | 55 FPS (overlaps) | 60 FPS (clean) | +9% + No overlap |
-| 1,000 nodes | 50 FPS (overlaps) | 58 FPS (clean) | +16% + No overlap |
-| 5,000 nodes | 45 FPS (overlaps) | 55 FPS (clean) | +22% + No overlap |
-| 10,000 nodes | 35 FPS (overlaps) | 50 FPS (clean) | +43% + No overlap |
-
-**Benefits:**
-- š **Better performance** (fewer labels = faster rendering)
-- šØ **Cleaner visuals** (no overlapping labels)
-- š§ **Smarter selection** (important nodes prioritized)
-- š **Viewport-aware** (relevant labels shown)
-
-## Customization
-
-### Adjust Priority Weighting
-```typescript
-// In label-decluttering.ts > calculateNodePriority()
-priority = connectionScore * 0.7 + centerScore * 0.3
-// ^^^^ ^^^^
-// Importance Position
-
-// Make position more important:
-priority = connectionScore * 0.5 + centerScore * 0.5
-
-// Make connections more important:
-priority = connectionScore * 0.9 + centerScore * 0.1
-```
-
-### Adjust Collision Margin
-```typescript
-// In boundingBoxesOverlap()
-const margin = 4 // Increase for more spacing
-```
-
-### Adjust Grid Size (Large Graphs)
-```typescript
-// In selectLabelsWithDeclutteringFast()
-const gridSize = 100 // Smaller = more accurate, slower
- // Larger = faster, less accurate
-```
-
-### Adjust Max Labels
-```typescript
-selectLabelsWithDeclutteringFast(
- ...,
- maxLabels: 200 // Increase for more labels, decrease for performance
-)
-```
-
-## Integration
-
-The decluttering system is automatically used in `use-graph-renderer.ts`:
-
-```typescript
-// On zoom change (throttled)
-const visibleLabels = selectLabelsWithDeclutteringFast(
- simulationNodes,
- forceSettings.nodeSize.value,
- zoomLevel,
- forceSettings.nodeLabelFontSize?.value ?? 50,
- viewport.width,
- viewport.height,
- -stage.position.x / stage.scale.x, // Camera X
- -stage.position.y / stage.scale.y, // Camera Y
- selectedNodeIds,
- highlightedNodeIds
-)
-setVisibleLabels(visibleLabels)
-
-// In render loop
-const shouldShow = showLabelsLOD && visibleLabels.has(node.id) && !isZoomingRef.current
-updateNodeLabel(labelObjects, node, nodeSize, shouldShow, ...)
-```
-
-## Future Enhancements
-
-Potential improvements:
-
-1. **Dynamic repulsion**: Slightly adjust label positions to fit more
-2. **Multi-line labels**: Wrap long text instead of truncating
-3. **Leader lines**: Connect labels to nodes when repositioned
-4. **Semantic zoom**: Different label content at different zoom levels
-5. **Animation**: Smooth fade in/out when labels change
-6. **GPU acceleration**: Move collision detection to compute shader
-
-## Comparison: Before vs After
-
-### Before (Simple Selection)
-```
- ā ā
- Long Label Name Another Label
- ā
- Third Label
-
-ā Labels overlap
-ā Hard to read
-ā No spatial awareness
-ā Random selection
-```
-
-### After (Decluttering)
-```
- ā ā
- Long Label Name
-
- ā
- Another Label
-
- ā
-
-ā
No overlap (4px margin)
-ā
Clear and readable
-ā
Viewport-centered priority
-ā
Smart selection
-```
-
-## Debug & Testing
-
-### Visualize Bounding Boxes (Development)
-```typescript
-// In use-graph-renderer.ts render loop
-if (process.env.NODE_ENV === 'development') {
- const bbox = calculateLabelBoundingBox(node, ...)
- if (bbox) {
- const debugRect = new Graphics()
- debugRect.rect(
- bbox.x - bbox.width / 2,
- bbox.y,
- bbox.width,
- bbox.height
- )
- debugRect.stroke({ width: 1, color: 0xff0000, alpha: 0.5 })
- debugContainer.addChild(debugRect)
- }
-}
-```
-
-### Log Priority Scores
-```typescript
-const visibleLabels = selectLabelsWithDeclutteringFast(...)
-console.log('Visible labels:', visibleLabels.size)
-console.log('Top priority nodes:',
- boundingBoxes.slice(0, 10).map(b => ({
- id: b.nodeId,
- priority: b.priority
- }))
-)
-```
-
-## API Reference
-
-### `calculateLabelBoundingBox()`
-Calculates the exact screen-space bounding box for a node label.
-
-**Parameters:**
-- `node: SimulationNode` - The node
-- `nodeSize: number` - Visual node size
-- `zoomLevel: number` - Current zoom
-- `fontSizeSetting: number` - Font size %
-- `viewportWidth: number` - Viewport width
-- `viewportHeight: number` - Viewport height
-- `cameraX: number` - Camera X position
-- `cameraY: number` - Camera Y position
-
-**Returns:** `LabelBoundingBox | null`
-
-### `boundingBoxesOverlap()`
-Checks if two bounding boxes collide (with 4px margin).
-
-**Parameters:**
-- `a: LabelBoundingBox` - First box
-- `b: LabelBoundingBox` - Second box
-
-**Returns:** `boolean` - True if overlap
-
-### `selectLabelsWithDecluttering()`
-Accurate greedy selection with full collision detection.
-
-**Use for:** < 500 nodes
-
-**Returns:** `Set` - Node IDs with visible labels
-
-### `selectLabelsWithDeclutteringFast()`
-Fast selection with spatial hashing for large graphs.
-
-**Use for:** ā„ 500 nodes
-
-**Parameters:**
-- All same as `calculateLabelBoundingBox()`
-- `selectedNodeIds: Set` - Always show
-- `highlightedNodeIds: Set` - Always show
-- `maxLabels: number` - Max labels (default: 200)
-
-**Returns:** `Set` - Node IDs with visible labels
-
-## License
-
-Internal use only.
diff --git a/flowsint-app/src/components/graphs/webgl/LABEL_STYLES.md b/flowsint-app/src/components/graphs/webgl/LABEL_STYLES.md
deleted file mode 100644
index 5dbc7d24..00000000
--- a/flowsint-app/src/components/graphs/webgl/LABEL_STYLES.md
+++ /dev/null
@@ -1,194 +0,0 @@
-# Label Styling Guide
-
-This document explains the label background styling system inspired by Cosmograph.
-
-## Visual Appearance
-
-### Node Labels with Backgrounds (Active Only)
-
-**Important**: Backgrounds are shown ONLY for active nodes (hovered or selected) to maintain optimal performance.
-
-```
-Normal Node: Active Node (hover/selected):
- ā ā
- Node Label āāāāāāāāāāāāāāāā
- ā Node Label ā ā Background appears
- āāāāāāāāāāāāāāāā
-```
-
-### Anatomy of a Label Background
-
-```
- āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā Border (1px, #404040, 30% opacity)
- ā āā Padding (6px horizontal) ā
- ā ā ā
- ā ā Text Content ā ā Text (#e0e0e0)
- ā ā ā
- ā āā Padding (3px vertical) ā
- āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
- Background (#1a1a1a, 92% opacity)
- Border Radius: 4px
-```
-
-## Configuration
-
-### Default Values
-
-```typescript
-NODE_LABEL_PADDING_X: 6 // 6px left and right
-NODE_LABEL_PADDING_Y: 3 // 3px top and bottom
-NODE_LABEL_BORDER_RADIUS: 4 // 4px rounded corners
-NODE_LABEL_BORDER_WIDTH: 1 // 1px border
-LABEL_BG_COLOR: 0x1a1a1a // Dark gray (#1a1a1a)
-LABEL_BG_BORDER_COLOR: 0x404040 // Medium gray (#404040)
-NODE_LABEL_BG_ALPHA: 0.92 // 92% opacity
-NODE_LABEL_BG_BORDER_ALPHA: 0.3 // 30% opacity
-```
-
-### State-Based Styling
-
-Labels and backgrounds adapt based on interaction state:
-
-| State | Label Visible | Background Visible | Alpha |
-|-------|---------------|-------------------|-------|
-| **Normal** | ā
(if in visible set) | ā No background | 1.0 |
-| **Hovered** | ā
Always | ā
**Background shown** | 1.0 |
-| **Selected** | ā
Always | ā
**Background shown** | 1.0 |
-| **Dimmed** | ā
(if visible) | ā No background | 0.2 |
-
-**Performance Note**: Backgrounds only render for active nodes (hovered/selected), reducing GPU load by ~99%.
-
-## Customization Examples
-
-### Lighter Background
-```typescript
-LABEL_BG_COLOR: 0x2a2a2a // Lighter gray
-NODE_LABEL_BG_ALPHA: 0.95 // More opaque
-```
-
-### More Prominent Border
-```typescript
-LABEL_BG_BORDER_COLOR: 0x606060 // Lighter border
-NODE_LABEL_BG_BORDER_ALPHA: 0.5 // More visible
-NODE_LABEL_BORDER_WIDTH: 2 // Thicker
-```
-
-### More Padding
-```typescript
-NODE_LABEL_PADDING_X: 8 // More horizontal space
-NODE_LABEL_PADDING_Y: 4 // More vertical space
-```
-
-### Sharper Corners
-```typescript
-NODE_LABEL_BORDER_RADIUS: 2 // Less rounded
-```
-
-### Glass Morphism Effect
-```typescript
-LABEL_BG_COLOR: 0x1a1a1a
-NODE_LABEL_BG_ALPHA: 0.7 // More transparent
-LABEL_BG_BORDER_COLOR: 0xffffff // White border
-NODE_LABEL_BG_BORDER_ALPHA: 0.2 // Subtle glow
-```
-
-## Rendering Details
-
-### Rendering Order
-
-1. **Background graphics** (rendered first)
-2. **Text content** (rendered on top)
-
-This ensures text is always readable and clickable.
-
-### Dynamic Sizing
-
-Backgrounds automatically adapt to text size:
-```typescript
-const textMetrics = label.getBounds()
-const bgWidth = textMetrics.width + PADDING_X * 2
-const bgHeight = textMetrics.height + PADDING_Y * 2
-```
-
-### Performance Optimizations
-
-ā
**Context-Aware Rendering**: Backgrounds shown ONLY for active nodes (hovered/selected)
-ā
**Dimension Estimation**: Fast approximation instead of expensive `getBounds()`
-ā
**Dirty Checking**: Only redraw when dimensions change
-ā
**Cached Calculations**: Store width to avoid recalculation
-ā
**Combined Draw Calls**: Fill and stroke in one operation
-ā
**GPU Compositing**: Alpha blending handled by hardware
-
-**Result**: ~99% reduction in background rendering cost! š
-
-## Comparison with Cosmograph
-
-| Feature | Cosmograph | This Implementation |
-|---------|-----------|---------------------|
-| Background | ā
| ā
|
-| Border | ā
| ā
|
-| Rounded corners | ā
| ā
|
-| Adaptive opacity | ā
| ā
|
-| Configurable | Limited | ā
Fully |
-| Performance | High | High |
-
-## Tips
-
-1. **Readability**: Keep background alpha > 0.8 for best readability
-2. **Contrast**: Ensure border color contrasts with background
-3. **Padding**: More padding = clearer labels but larger footprint
-4. **Border**: Keep border subtle (alpha 0.2-0.4) to avoid visual noise
-
-## Examples in Code
-
-### Basic Label
-```typescript
-const label = createNodeLabel("John Doe")
-// Returns: { text: Text, background: Graphics }
-```
-
-### Update Label
-```typescript
-updateNodeLabel(
- labelObjects,
- node,
- nodeSize,
- shouldShow,
- zoomLevel,
- fontSizeSetting,
- isHighlighted,
- hasAnyHighlight
-)
-// Automatically updates both text and background
-```
-
-### Custom Styling (in constants.ts)
-```typescript
-export const GRAPH_CONSTANTS = {
- // ... other constants
-
- // Custom label style
- NODE_LABEL_PADDING_X: 8,
- NODE_LABEL_PADDING_Y: 5,
- NODE_LABEL_BORDER_RADIUS: 6,
- LABEL_BG_COLOR: 0x2a2a2a,
- NODE_LABEL_BG_ALPHA: 0.95,
-
- // ... rest of constants
-}
-```
-
-## Browser Rendering
-
-Labels use Pixi.js Graphics API which:
-- Renders via WebGL for maximum performance
-- Supports anti-aliasing for smooth borders
-- Hardware accelerated alpha blending
-- Batches similar draw calls automatically
-
-## Accessibility
-
-While this is a canvas-based visualization (not DOM), consider:
-- High contrast mode support via color constants
-- Font size adjustments via zoom level
-- Clear backgrounds improve readability for all users
diff --git a/flowsint-app/src/components/graphs/webgl/README.md b/flowsint-app/src/components/graphs/webgl/README.md
deleted file mode 100644
index 299be5db..00000000
--- a/flowsint-app/src/components/graphs/webgl/README.md
+++ /dev/null
@@ -1,358 +0,0 @@
-# WebGL Graph Viewer
-
-A high-performance, modular graph visualization component built with Pixi.js (WebGL) and D3-force.
-
-## Features
-
-- **High Performance**: WebGL-based rendering with Pixi.js
-- **Physics Simulation**: D3-force for realistic node interactions
-- **Modular Architecture**: Clean separation of concerns
-- **Type Safe**: Full TypeScript support
-- **Customizable**: Extensive configuration options
-- **Interactive**: Zoom, pan, drag, hover, and click interactions
-- **Smart Decluttering**: Intelligent label selection with collision detection
-- **Progressive Disclosure**: Priority-based label visibility
-- **Icon Support**: SVG icon rendering with texture caching
-- **Styled Labels**: Cosmograph-inspired label backgrounds with borders
-- **Context-Aware**: Edge labels only appear when nodes are active
-
-## Architecture
-
-```
-webgl/
-āāā index.tsx # Main component
-āāā constants.ts # Configuration constants
-āāā types/
-ā āāā graph.types.ts # TypeScript types
-āāā hooks/
-ā āāā use-pixi-app.ts # Pixi.js app management
-ā āāā use-force-simulation.ts # D3-force simulation
-ā āāā use-graph-interactions.ts # User interactions
-ā āāā use-zoom-pan.ts # Zoom/pan controls
-ā āāā use-graph-renderer.ts # Main rendering logic
-āāā renderers/
-ā āāā node-renderer.ts # Node rendering
-ā āāā edge-renderer.ts # Edge rendering
-ā āāā label-renderer.ts # Label rendering
-āāā utils/
- āāā texture-cache.ts # Icon texture caching
- āāā visibility-calculator.ts # LOD thresholds
- āāā label-decluttering.ts # Smart label selection
- āāā color-utils.ts # Color utilities
-```
-
-## Usage
-
-### Basic Example
-
-```tsx
-import WebGLGraphViewer from '@/components/graphs/webgl'
-
-function MyGraph() {
- const nodes = [
- { id: '1', data: { label: 'Node 1', type: 'person' } },
- { id: '2', data: { label: 'Node 2', type: 'company' } },
- ]
-
- const edges = [
- { source: '1', target: '2', label: 'works at' },
- ]
-
- return (
- console.log('Clicked:', node)}
- showIcons={true}
- showLabels={true}
- />
- )
-}
-```
-
-### With Custom Handlers
-
-```tsx
- {
- if (event.ctrlKey) {
- // Multi-select
- } else {
- // Single select
- }
- }}
- onNodeRightClick={(node, event) => {
- // Show context menu
- }}
- onBackgroundClick={() => {
- // Deselect all
- }}
- className="my-graph"
- style={{ width: '100%', height: '600px' }}
-/>
-```
-
-## Props
-
-| Prop | Type | Default | Description |
-|------|------|---------|-------------|
-| `nodes` | `GraphNode[]` | Required | Array of graph nodes |
-| `edges` | `GraphEdge[]` | Required | Array of graph edges |
-| `className` | `string` | `''` | CSS class name |
-| `style` | `React.CSSProperties` | `undefined` | Inline styles |
-| `onNodeClick` | `(node, event) => void` | `undefined` | Node click handler |
-| `onNodeRightClick` | `(node, event) => void` | `undefined` | Node right-click handler |
-| `onBackgroundClick` | `() => void` | `undefined` | Background click handler |
-| `showIcons` | `boolean` | `true` | Show node icons |
-| `showLabels` | `boolean` | `true` | Show node/edge labels |
-
-## Performance Optimizations
-
-### 1. Smart Label Decluttering
-
-**Intelligent label selection with collision detection**
-
-The graph uses an advanced decluttering algorithm that:
-- ā
**Prevents overlap**: Labels never collide (4px minimum margin)
-- ā
**Priority-based**: Important nodes (highly connected, viewport-centered) get labels first
-- ā
**Collision detection**: Real bounding box calculations
-- ā
**Spatial hashing**: O(1) collision checks for large graphs (10,000+ nodes)
-- ā
**Selection-aware**: Selected/highlighted nodes always show labels
-
-**How it works:**
-
-```typescript
-// Combines multiple factors for smart selection
-priority = connectionScore * 0.7 + centerScore * 0.3
-
-// Greedy algorithm:
-// 1. Sort nodes by priority (highest first)
-// 2. Always add selected/highlighted nodes
-// 3. Add remaining nodes if they don't collide
-```
-
-**Performance:**
-- Small graphs (< 500 nodes): Accurate collision detection
-- Large graphs (ā„ 500 nodes): Fast spatial hashing
-- 200 max labels by default (configurable)
-
-See [DECLUTTERING.md](./DECLUTTERING.md) for detailed documentation.
-
-### 2. Level of Details (LOD) System
-Automatically adjusts visual complexity based on zoom level:
-
-| Zoom Level | LOD | Features Visible |
-|------------|-----|------------------|
-| < 0.5 | **Minimal** | Nodes + Edges only |
-| 0.5 - 0.6 | **Low** | + Basic node labels |
-| 0.6 - 1.2 | **Medium** | + Icons |
-| 1.2 - 1.5 | **High** | + Edge labels* |
-| > 1.5 | **Ultra** | All features at max quality |
-
-**Edge labels are context-aware**: They only appear when at least one of their connected nodes is active (hovered or selected), reducing visual clutter and improving performance.
-
-```ts
-import { getLODLevel, shouldShowNodeIcons } from './exports'
-
-const lodLevel = getLODLevel(zoomLevel) // 'minimal', 'low', 'medium', 'high'
-const showIcons = shouldShowNodeIcons(zoomLevel) // boolean
-```
-
-**Benefits:**
-- š **60 FPS maintained** even with 10,000+ nodes when zoomed out
-- š¾ **Reduced GPU load** by hiding unnecessary details
-- ā” **Instant zoom** response without lag
-
-### 3. Texture Caching
-Icons are loaded once and cached globally:
-```ts
-import { textureCache } from './utils/texture-cache'
-
-// Preload textures
-await textureCache.preloadBatch(['person', 'company'])
-
-// Get cached texture
-const texture = textureCache.get('person')
-```
-
-### 4. Batch Rendering
-Edges are grouped by style and rendered in batches:
-- Highlighted edges (orange)
-- Dimmed edges (low opacity)
-- Default edges (normal)
-
-### 5. Progressive Label Disclosure (Deprecated)
-
-**Note:** Progressive disclosure is now handled by the Smart Decluttering system (see above).
-
-
-Labels appear based on:
-- Node importance (connection count)
-- Current zoom level
-- Selection/highlight state
-- **LOD thresholds**
-
-**Smart Edge Labels:**
-- Edge labels are **context-aware** and only appear when their nodes are active
-- Active = hovered, selected, or highlighted
-- This reduces visual clutter by 90% in typical use cases
-- Performance improvement: ~50% fewer labels rendered at any time
-
-### 6. Manual Rendering
-Pixi.js app uses manual rendering (`autoStart: false`) for better control.
-
-### 7. Optimized Updates
-- Refs used for values that don't need re-renders
-- Memoized calculations
-- Debounced resize handler
-- **LOD-based early returns** (skip calculations for invisible elements)
-
-## Customization
-
-### Constants
-Edit `constants.ts` to customize:
-- Node sizes and colors
-- Edge widths and colors
-- Zoom limits
-- Label visibility thresholds
-- **LOD thresholds** (when to show/hide features)
-- **Label styling** (background, border, padding)
-- Animation durations
-
-**LOD Configuration:**
-```ts
-// In constants.ts
-LOD_ICON_MIN_ZOOM: 0.6, // Show icons when zoom >= 0.6
-LOD_NODE_LABEL_MIN_ZOOM: 0.5, // Show node labels when zoom >= 0.5
-LOD_EDGE_LABEL_MIN_ZOOM: 1.2, // Enable edge labels when zoom >= 1.2
- // (only shown when nodes are active)
-LOD_HIGH_DETAIL_ZOOM: 1.5, // High detail mode when zoom >= 1.5
-```
-
-**Label Styling:**
-```ts
-// Node label backgrounds (Cosmograph-inspired)
-NODE_LABEL_PADDING_X: 6, // Horizontal padding
-NODE_LABEL_PADDING_Y: 3, // Vertical padding
-NODE_LABEL_BORDER_RADIUS: 4, // Rounded corners
-NODE_LABEL_BORDER_WIDTH: 1, // Border thickness
-LABEL_BG_COLOR: 0x1a1a1a, // Background color
-LABEL_BG_BORDER_COLOR: 0x404040, // Border color
-NODE_LABEL_BG_ALPHA: 0.92, // Background opacity
-NODE_LABEL_BG_BORDER_ALPHA: 0.3, // Border opacity
-```
-
-**Edge Label Behavior:**
-Edge labels are now **context-aware** - they only appear when:
-1. Zoom level >= `LOD_EDGE_LABEL_MIN_ZOOM` (LOD check)
-2. At least one connected node is **active** (hovered or selected)
-
-This dramatically reduces visual clutter while keeping relevant information visible.
-
-### Renderers
-Modify renderer functions to change visual appearance:
-- `renderNode()` - Node shapes and colors
-- `renderEdges()` - Edge styles
-- `updateNodeLabel()` - Label positioning and styling
-
-### Hooks
-Extend or replace hooks for custom behavior:
-- `useForceSimulation()` - Custom physics
-- `useGraphInteractions()` - Custom interactions
-- `useZoomPan()` - Custom zoom/pan behavior
-
-## Debugging
-
-### LOD Indicator
-Enable the LOD indicator to see current zoom level and active LOD mode:
-
-```tsx
-// In index.tsx, uncomment the import and component:
-import { LODIndicator } from './components/lod-indicator'
-
-// In the return statement:
-
-```
-
-The indicator shows:
-- Current LOD level (color-coded)
-- Description of visible features
-- Exact zoom value
-
-**Color Legend:**
-- š“ Red: Minimal (nodes + edges only)
-- š Orange: Low (+ basic labels)
-- š” Yellow: Medium (+ icons)
-- š¢ Green: High (all features)
-
-### Performance Profiling
-```tsx
-// Use Chrome DevTools Performance tab
-// Look for "render" calls in the flame graph
-// LOD should reduce GPU time when zoomed out
-```
-
-## Testing
-
-### Unit Tests
-```bash
-npm test -- webgl
-```
-
-### Visual Testing
-```tsx
-// In Storybook
-import WebGLGraphViewer from '@/components/graphs/webgl'
-
-export default {
- title: 'Graph/WebGLGraphViewer',
- component: WebGLGraphViewer,
-}
-```
-
-### LOD Testing
-1. Zoom out completely - should see minimal LOD (no icons, no labels)
-2. Zoom to 0.6x - icons should appear
-3. Zoom to 1.2x - edge labels **enabled** (but only visible on hover/select)
-4. Hover over a node - edge labels for connected edges should appear
-5. Select a node - edge labels remain visible
-6. Deselect/unhover - edge labels disappear
-7. Use LODIndicator component to verify thresholds
-
-## Performance Metrics
-
-Tested with LOD system:
-- **1,000 nodes**: 60 FPS (all zoom levels)
-- **5,000 nodes**: 60 FPS (zoomed out), 50-60 FPS (zoomed in)
-- **10,000 nodes**: 55-60 FPS (zoomed out), 40-50 FPS (zoomed in)
-- **50,000 nodes**: 45-60 FPS (zoomed out), 25-35 FPS (zoomed in)
-
-Performance depends on:
-- Device capabilities
-- **Zoom level (LOD)** ā Major factor
-- Number of visible labels
-- Active interactions
-
-**LOD Impact:**
-- Zoomed out (LOD: minimal): **+80% performance**
-- Medium zoom (LOD: medium): **+40% performance**
-- Fully zoomed in (LOD: high): Baseline performance
-- **Context-aware edge labels**: **+50% fewer labels** rendered on average
-
-## Browser Compatibility
-
-- Chrome 90+
-- Firefox 88+
-- Safari 14+
-- Edge 90+
-
-Requires WebGL support.
-
-## License
-
-Internal use only.