import React, { useState, useMemo, useRef, useCallback, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { ExcelRow } from '../types';
import { useColumns } from '../contexts/ColumnsContext';
import {
  AlertTriangle,
  AlertCircle,
  CheckCircle2,
  DollarSign,
  Package,
  Save,
  X,
  ChevronDown,
  Edit2,
  Filter,
  Check,
  Search,
  MessageSquare,
  Maximize2,
  Pin,
  PinOff,
} from 'lucide-react';
import { cn } from '../lib/utils';
import { ColumnFilterPopover } from './ColumnFilterPopover';
import { usePersistentState } from '../contexts/FilterContext';

interface PricingViewProps {
  data: ExcelRow[];
  headers: string[];
  onSaveRow: (index: number, updatedRow: ExcelRow) => void;
  onCaptureState: (message: string) => void;
  onEdit: (index: number) => void;
  rowStatuses: Record<string, string>;
}

interface DetectedCol {
  index: number;
  name: string;
}

type FilterMode = 'all' | 'all_errors' | 'pricing_errors' | 'units_errors';

interface EditingCell {
  rowIndex: number;
  colIndex: number;
  value: string;
}

// Flexible multi-keyword column finder
function findCol(headers: string[], ...keywords: string[]): number {
  return headers.findIndex(h =>
    keywords.every(kw => (h || '').toLowerCase().includes(kw.toLowerCase()))
  );
}

export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, rowStatuses }: PricingViewProps) {
  const COLUMNS = useColumns();
  const [filterMode, setFilterMode] = usePersistentState<FilterMode>('pricing-filterMode', 'all_errors');
  const [search, setSearch] = usePersistentState('pricing-search', '');
  const [currentPage, setCurrentPage] = useState(1);
  const [hoveredNote, setHoveredNote] = useState<{ text: string, pos: { top: number, left: number }, isAnna: boolean } | null>(null);
  const pageSize = 100;
  const [columnWidths, setColumnWidths] = useState<Record<string, number>>({
    articleNo: 100,
    articleName: 220,
    line: 100,
    classification: 130,
    productType: 140,
    itemToLogistic: 160,
    unitsOuter: 100,
    outerW: 80,
    outerL: 80,
    outerH: 80,
    moq: 80,
    check: 100,
    actions: 60,
  });
  const [resizingColumn, setResizingColumn] = useState<string | null>(null);
  const [resizeStartX, setResizeStartX] = useState<number | null>(null);
  const [resizeStartWidth, setResizeStartWidth] = useState<number | null>(null);
  const tableRef = useRef<HTMLTableElement>(null);
  const [editingCell, setEditingCell] = useState<EditingCell | null>(null);
  const [savingCell, setSavingCell] = useState<{ rowIndex: number; colIndex: number } | null>(null);
  const inputRef = useRef<HTMLInputElement>(null);
  const [editingType, setEditingType] = useState<{ rowIndex: number; value: string } | null>(null);
  const [editingLogistic, setEditingLogistic] = useState<{ rowIndex: number; value: string } | null>(null);
  const [typeSuggestions, setTypeSuggestions] = useState<string[]>([]);
  const typeInputRef = useRef<HTMLInputElement>(null);
  const logisticInputRef = useRef<HTMLInputElement>(null);
  const [sortConfig, setSortConfig] = usePersistentState<{ key: string | number; direction: 'asc' | 'desc' | null }>('pricing-sortConfig', { key: null, direction: null });
  const [isFullscreen, setIsFullscreen] = useState(false);

  const [lineMultiFilter, setLineMultiFilter] = usePersistentState<string[]>('pricing-lineFilter', []);
  const [classificationFilter, setClassificationFilter] = usePersistentState<string[]>('pricing-classificationFilter', []);
  const [productTypeFilter, setProductTypeFilter] = usePersistentState<string[]>('pricing-productTypeFilter', []);
  const [nameColFilter, setNameColFilter] = usePersistentState<{ terms: string[]; op: 'and' | 'or' }>('pricing-nameColFilter', { terms: [''], op: 'and' });
  const [articleNoColFilter, setArticleNoColFilter] = usePersistentState<{ terms: string[]; op: 'and' | 'or' }>('pricing-articleNoColFilter', { terms: [''], op: 'and' });
  const [globalAdvancedFilter, setGlobalAdvancedFilter] = usePersistentState<{ terms: string[]; op: 'and' | 'or' }>('pricing-globalAdvancedFilter', { terms: [''], op: 'and' });
  const [unitsOuterFilter, setUnitsOuterFilter] = usePersistentState<string[]>('pricing-unitsOuterFilter', []);
  const [itemToLogisticFilter, setItemToLogisticFilter] = usePersistentState<string[]>('pricing-itemToLogisticFilter', []);
  const [outerWFilter, setOuterWFilter] = usePersistentState<string[]>('pricing-outerWFilter', []);
  const [outerLFilter, setOuterLFilter] = usePersistentState<string[]>('pricing-outerLFilter', []);
  const [outerHFilter, setOuterHFilter] = usePersistentState<string[]>('pricing-outerHFilter', []);
  const [moqFilter, setMoqFilter] = usePersistentState<string[]>('pricing-moqFilter', []);
  const [checkYingFilter, setCheckYingFilter] = usePersistentState<string[]>('pricing-checkYingFilter', []);
  const [checkAnnaFilter, setCheckAnnaFilter] = usePersistentState<string[]>('pricing-checkAnnaFilter', []);
  const [dynamicColFilters, setDynamicColFilters] = usePersistentState<Record<number, string[]>>('pricing-dynamicColFilters', {});
  const [weightIssueFilter, setWeightIssueFilter] = usePersistentState<'all' | 'with' | 'without'>('pricing-weightIssueFilter', 'all');
  const [selectedSearchItems, setSelectedSearchItems] = usePersistentState<Set<string>>('pricing-selectedSearchItems', new Set());
  const [openFilter, setOpenFilter] = useState<string | null>(null);
  const [isSearchOpen, setIsSearchOpen] = useState(false);
  const searchDropdownRef = useRef<HTMLDivElement>(null);

  // Pinned columns state
  const [pinnedColumns, setPinnedColumns] = usePersistentState<Set<string>>('pricing-pinnedColumns', new Set(['articleNo', 'articleName']));
  const [showPinPanel, setShowPinPanel] = useState(false);

  // Drag-to-check state (Excel-style drag to toggle Check Ying)
  const [dragSelectedRows, setDragSelectedRows] = useState<Set<number>>(new Set());
  const isDraggingRef = useRef(false);
  const dragStartIndexRef = useRef<number | null>(null);
  const dragCheckValueRef = useRef<boolean>(true); // what value to set on mouseup
  const lastDragIndexRef = useRef<number | null>(null);
  const visibleDataIndexesRef = useRef<number[]>([]);
  const dataRef = useRef(data);
  dataRef.current = data;

  const handleRowMouseDown = useCallback((e: React.MouseEvent, dataIndex: number) => {
    if ((e.target as HTMLElement).closest('input, button, a')) return;
    e.preventDefault();
    isDraggingRef.current = true;
    dragStartIndexRef.current = dataIndex;
    lastDragIndexRef.current = dataIndex;
    // Toggle based on current state of the first row touched
    dragCheckValueRef.current = !dataRef.current[dataIndex]?.[COLUMNS.VALIDATED_CHECK];
    setDragSelectedRows(new Set([dataIndex]));
  }, [COLUMNS.VALIDATED_CHECK]);

  const handleRowMouseEnter = useCallback((dataIndex: number) => {
    if (!isDraggingRef.current || dragStartIndexRef.current === null) return;
    if (dataIndex === lastDragIndexRef.current) return;
    lastDragIndexRef.current = dataIndex;

    const start = dragStartIndexRef.current;
    const end = dataIndex;
    const [lo, hi] = start <= end ? [start, end] : [end, start];

    setDragSelectedRows(() => {
      const next = new Set<number>();
      visibleDataIndexesRef.current.forEach((idx: number) => {
        if (idx >= lo && idx <= hi) next.add(idx);
      });
      return next;
    });
  }, []);

  useEffect(() => {
    const handleMouseUp = async () => {
      if (!isDraggingRef.current) return;
      isDraggingRef.current = false;
      const rows = new Set(dragSelectedRows);
      if (rows.size === 0) return;
      setDragSelectedRows(new Set());
      const targetValue = dragCheckValueRef.current;
      for (const idx of Array.from(rows)) {
        await handleToggleCheck(idx as number, targetValue);
      }
    };
    document.addEventListener('mouseup', handleMouseUp);
    return () => document.removeEventListener('mouseup', handleMouseUp);
  }, [dragSelectedRows]);

  // Close search dropdown on click outside
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (searchDropdownRef.current && !searchDropdownRef.current.contains(event.target as Node)) {
        setIsSearchOpen(false);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  const searchSuggestions = useMemo(() => {
    if (!search) return data.slice(0, 50);
    
    const terms = search.toLowerCase().split(/\s+/).filter(Boolean);
    if (terms.length === 0) return data.slice(0, 50);

    return data.filter(r => {
      const articleNo = String(r[COLUMNS.ARTICLE_NO] || '').toLowerCase();
      const articleName = String(r[COLUMNS.ARTICLE_NAME] || '').toLowerCase();
      return terms.every(term => articleNo.includes(term) || articleName.includes(term));
    }).slice(0, 50);
  }, [data, search, selectedSearchItems, COLUMNS]);

  const handleSearchItemClick = (sku: string) => {
    const newSelected = new Set(selectedSearchItems);
    if (newSelected.has(sku)) {
      newSelected.delete(sku);
    } else {
      newSelected.add(sku);
    }
    setSelectedSearchItems(newSelected);
  };

  const handleApplySearch = () => {
    setIsSearchOpen(false);
  };

  const handleClearSearch = () => {
    setSelectedSearchItems(new Set());
  };

  const handleResizeStart = (e: React.MouseEvent, colKey: string, currentWidth: number) => {
    console.log('Resize started for:', colKey, 'at x:', e.clientX);
    e.preventDefault();
    e.stopPropagation();
    setResizingColumn(colKey);
    setResizeStartX(e.clientX);
    setResizeStartWidth(currentWidth);
  };

  React.useEffect(() => {
    if (!resizingColumn || resizeStartX === null || resizeStartWidth === null) return;

    const handleMouseMove = (e: MouseEvent) => {
      const delta = e.clientX - resizeStartX;
      const newWidth = Math.max(40, Math.min(800, resizeStartWidth + delta));
      setColumnWidths(prev => ({ ...prev, [resizingColumn]: newWidth }));
    };

    const handleMouseUp = () => {
      setResizingColumn(null);
      setResizeStartX(null);
      setResizeStartWidth(null);
    };

    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
    return () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };
  }, [resizingColumn, resizeStartX, resizeStartWidth]);

  // ── Dynamic column detection ──────────────────────────────────────────────
  const { uvpIdx, srpCols, containerCols, nwIdx, gwIdx, unitsOuterIdx } = useMemo(() => {
    const uvpIdx = findCol(headers, 'uvp');

    // All SRP columns, sorted: INT first, UK second, then alphabetically
    const srp: DetectedCol[] = headers
      .map((h, i) => ({ index: i, name: h || '' }))
      .filter(({ name }) => /srp/i.test(name))
      .sort((a, b) => {
        const order = (n: string) => {
          if (/int/i.test(n)) return 0;
          if (/uk/i.test(n)) return 1;
          return 2;
        };
        return order(a.name) - order(b.name);
      });

    // All 40' container columns (HC, HQ, etc.)
    const container: DetectedCol[] = headers
      .map((h, i) => ({ index: i, name: h || '' }))
      .filter(({ name }) => /40/i.test(name) && /h[cq]/i.test(name));

    // Net weight / Gross weight columns
    const nwIdx = findCol(headers, 'nw');
    const gwIdx = findCol(headers, 'gw');

    const unitsOuterIdx = COLUMNS.UNITS_OUTER;

    return { uvpIdx, srpCols: srp, containerCols: container, nwIdx, gwIdx, unitsOuterIdx };
  }, [headers, COLUMNS]);

  // ── Error analysis per row ────────────────────────────────────────────────
  const analyzedRows = useMemo(() => {
    return data.map((row, dataIndex) => {
      const pricingErrors: string[] = [];
      const unitErrors: string[] = [];

      // UVP check
      if (uvpIdx >= 0) {
        const v = row[uvpIdx];
        if (v === undefined || v === null || v === '' || Number(v) === 0) {
          pricingErrors.push('UVP missing');
        }
      }

      // SRP checks
      srpCols.forEach(({ index, name }) => {
        const v = row[index];
        if (v === undefined || v === null || v === '' || Number(v) === 0) {
          pricingErrors.push(`${name} missing`);
        }
      });

      // Units per Outer check
      const unitsOuter = Number(row[unitsOuterIdx]);
      if (!unitsOuter || unitsOuter === 0) {
        unitErrors.push('Units/Outer: missing');
      }

      // 40' container checks
      containerCols.forEach(({ index, name }) => {
        const v = Number(row[index]);
        if (!v || v === 0) unitErrors.push(`${name}: empty`);
        else if (v === 1) unitErrors.push(`${name}: value is 1`);
      });

      // NW > GW check
      if (nwIdx >= 0 && gwIdx >= 0) {
        const nw = parseFloat(String(row[nwIdx] ?? '').replace(',', '.'));
        const gw = parseFloat(String(row[gwIdx] ?? '').replace(',', '.'));
        if (!isNaN(nw) && !isNaN(gw) && nw > gw) {
          unitErrors.push(`NW (${nw}) > GW (${gw})`);
        }
      }

      return {
        row,
        dataIndex,
        pricingErrors,
        unitErrors,
        hasErrors: pricingErrors.length > 0 || unitErrors.length > 0,
        isCritical: unitErrors.length > 0,
      };
    });
  }, [data, uvpIdx, srpCols, containerCols]);

  // ── Stats ─────────────────────────────────────────────────────────────────
  const stats = useMemo(() => {
    const withPricing = analyzedRows.filter(r => r.pricingErrors.length > 0).length;
    const withUnits = analyzedRows.filter(r => r.unitErrors.length > 0).length;
    const withAny = analyzedRows.filter(r => r.hasErrors).length;
    const allOk = analyzedRows.length - withAny;
    return { total: analyzedRows.length, withPricing, withUnits, withAny, allOk };
  }, [analyzedRows]);

  // ── Unique values for column filters ─────────────────────────────────────
  const uniqueLines = useMemo(() =>
    Array.from(new Set(data.map(r => String(r[COLUMNS.LINE] || '')))).sort(),
  [data]);

  const uniqueClassifications = useMemo(() =>
    Array.from(new Set(data.map(r => String(r[COLUMNS.CLASSIFICATION] || '')))).sort(),
  [data]);

  const uniqueProductTypes = useMemo(() =>
    Array.from(new Set(data.map(r => String(r[COLUMNS.PRODUCT_TYPE] || '')).filter(Boolean))).sort(),
  [data]);

  const uniqueUnitsOuter = useMemo(() =>
    Array.from(new Set(data.map(r => String(r[unitsOuterIdx] || '')))).filter(v => v).sort(),
  [data, unitsOuterIdx]);

  const uniqueOuterW = useMemo(() =>
    Array.from(new Set(data.map(r => String(r[COLUMNS.OUTER_W] || '')))).filter(v => v).sort((a, b) => Number(a) - Number(b)),
  [data]);

  const uniqueOuterL = useMemo(() =>
    Array.from(new Set(data.map(r => String(r[COLUMNS.OUTER_L] || '')))).filter(v => v).sort((a, b) => Number(a) - Number(b)),
  [data]);

  const uniqueOuterH = useMemo(() =>
    Array.from(new Set(data.map(r => String(r[COLUMNS.OUTER_H] || '')))).filter(v => v).sort((a, b) => Number(a) - Number(b)),
  [data]);

  const uniqueMoq = useMemo(() =>
    Array.from(new Set(data.map(r => String(r[COLUMNS.MOQ] || '')))).filter(v => v).sort((a, b) => Number(a) - Number(b)),
  [data]);

  const uniqueItemToLogistic = useMemo(() =>
    Array.from(new Set(data.map(r => String(r[COLUMNS.ITEM_TO_LOGISTIC] || '')))).filter(v => v).sort(),
  [data]);

  const uniqueCheckYing = useMemo(() =>
    Array.from(new Set(data.map(r => r[COLUMNS.VALIDATED_CHECK] ? 'Checked' : 'Unchecked'))).sort(),
  [data, COLUMNS.VALIDATED_CHECK]);

  const uniqueCheckAnna = useMemo(() =>
    Array.from(new Set(data.map(r => r[COLUMNS.ANNA_CHECK] ? 'Checked' : 'Unchecked'))).sort(),
  [data, COLUMNS.ANNA_CHECK]);

  // ── Filtered rows ─────────────────────────────────────────────────────────
  const filteredRows = useMemo(() => {
    let result = analyzedRows;

    // Mode filter
    switch (filterMode) {
      case 'all_errors':   result = analyzedRows.filter(r => r.hasErrors); break;
      case 'pricing_errors': result = analyzedRows.filter(r => r.pricingErrors.length > 0); break;
      case 'units_errors': result = analyzedRows.filter(r => r.unitErrors.length > 0); break;
    }

    // Global search (SKU + Name) - Multi-word AND support
    if (search) {
      const terms = search.toLowerCase().split(/\s+/).filter(Boolean);
      if (terms.length > 0) {
        result = result.filter(r => {
          const articleNo = String(r.row[COLUMNS.ARTICLE_NO] || '').toLowerCase();
          const articleName = String(r.row[COLUMNS.ARTICLE_NAME] || '').toLowerCase();
          return terms.every(term => articleNo.includes(term) || articleName.includes(term));
        });
      }
    }

    // Global Advanced Filter (Multi-term AND/OR)
    if (globalAdvancedFilter.terms.some(t => t.trim() !== '')) {
      result = result.filter(r => {
        const articleNo = String(r.row[COLUMNS.ARTICLE_NO] || '').toLowerCase();
        const articleName = String(r.row[COLUMNS.ARTICLE_NAME] || '').toLowerCase();
        const activeTerms = globalAdvancedFilter.terms.filter(t => t.trim() !== '').map(t => t.toLowerCase());
        if (activeTerms.length === 0) return true;

        return globalAdvancedFilter.op === 'and'
          ? activeTerms.every(term => articleNo.includes(term) || articleName.includes(term))
          : activeTerms.some(term => articleNo.includes(term) || articleName.includes(term));
      });
    }

    // Selected items from search dropdown
    if (selectedSearchItems.size > 0) {
      result = result.filter(r => {
        const articleNo = String(r.row[COLUMNS.ARTICLE_NO] || '');
        return selectedSearchItems.has(articleNo);
      });
    }

    // Column filters
    // Column-specific name filter - Multi-term AND/OR
    if (nameColFilter.terms.some(t => t.trim() !== '')) {
      result = result.filter(r => {
        const name = String(r.row[COLUMNS.ARTICLE_NAME] || '').toLowerCase();
        const activeTerms = nameColFilter.terms.filter(t => t.trim() !== '').map(t => t.toLowerCase());
        if (activeTerms.length === 0) return true;
        
        return nameColFilter.op === 'and' 
          ? activeTerms.every(term => name.includes(term))
          : activeTerms.some(term => name.includes(term));
      });
    }

    // Column-specific SKU filter - Multi-term AND/OR
    if (articleNoColFilter.terms.some(t => t.trim() !== '')) {
      result = result.filter(r => {
        const sku = String(r.row[COLUMNS.ARTICLE_NO] || '').toLowerCase();
        const activeTerms = articleNoColFilter.terms.filter(t => t.trim() !== '').map(t => t.toLowerCase());
        if (activeTerms.length === 0) return true;

        return articleNoColFilter.op === 'and'
          ? activeTerms.every(term => sku.includes(term))
          : activeTerms.some(term => sku.includes(term));
      });
    }
    if ((lineMultiFilter || []).length > 0) {
      result = result.filter(r => (lineMultiFilter || []).includes(String(r.row[COLUMNS.LINE] || '')));
    }
    if ((classificationFilter || []).length > 0) {
      result = result.filter(r => (classificationFilter || []).includes(String(r.row[COLUMNS.CLASSIFICATION] || '')));
    }
    if ((productTypeFilter || []).length > 0) {
      result = result.filter(r => (productTypeFilter || []).includes(String(r.row[COLUMNS.PRODUCT_TYPE] || '')));
    }
    if ((unitsOuterFilter || []).length > 0) {
      result = result.filter(r => (unitsOuterFilter || []).includes(String(r.row[unitsOuterIdx] || '')));
    }
    if ((outerWFilter || []).length > 0) {
      result = result.filter(r => (outerWFilter || []).includes(String(r.row[COLUMNS.OUTER_W] || '')));
    }
    if ((outerLFilter || []).length > 0) {
      result = result.filter(r => (outerLFilter || []).includes(String(r.row[COLUMNS.OUTER_L] || '')));
    }
    if ((outerHFilter || []).length > 0) {
      result = result.filter(r => (outerHFilter || []).includes(String(r.row[COLUMNS.OUTER_H] || '')));
    }
    if ((moqFilter || []).length > 0) {
      result = result.filter(r => (moqFilter || []).includes(String(r.row[COLUMNS.MOQ] || '')));
    }
    if ((itemToLogisticFilter || []).length > 0) {
      result = result.filter(r => (itemToLogisticFilter || []).includes(String(r.row[COLUMNS.ITEM_TO_LOGISTIC] || '')));
    }
    if ((checkYingFilter || []).length > 0) {
      result = result.filter(r => (checkYingFilter || []).includes(r.row[COLUMNS.VALIDATED_CHECK] ? 'Checked' : 'Unchecked'));
    }
    if ((checkAnnaFilter || []).length > 0) {
      result = result.filter(r => (checkAnnaFilter || []).includes(r.row[COLUMNS.ANNA_CHECK] ? 'Checked' : 'Unchecked'));
    }

    // Dynamic column filters (SRP, container)
    (Object.keys(dynamicColFilters) as string[]).forEach(colIdx => {
      const filterVals = dynamicColFilters[Number(colIdx)];
      if (filterVals && filterVals.length > 0) {
        const col = Number(colIdx);
        result = result.filter(r => filterVals.includes(String(r.row[col] || '')));
      }
    });

    // Weight issue filter
    if (weightIssueFilter === 'with') {
      result = result.filter(r => r.unitErrors.some(e => e.startsWith('NW')));
    } else if (weightIssueFilter === 'without') {
      result = result.filter(r => !r.unitErrors.some(e => e.startsWith('NW')));
    }

    return result;
  }, [analyzedRows, filterMode, search, nameColFilter, articleNoColFilter, globalAdvancedFilter, lineMultiFilter, classificationFilter, productTypeFilter, unitsOuterFilter, outerWFilter, outerLFilter, outerHFilter, moqFilter, dynamicColFilters, weightIssueFilter, selectedSearchItems]);

  // ── Sorted rows ──────────────────────────────────────────────────────────
  const sortedRows = useMemo(() => {
    if (sortConfig.key === null || sortConfig.direction === null) return filteredRows;

    const { key, direction } = sortConfig;
    let colIndex: number;
    
    if (typeof key === 'number') {
      colIndex = key;
    } else {
      // Map string keys to COLUMNS indices
      switch (key) {
        case 'articleNo': colIndex = COLUMNS.ARTICLE_NO; break;
        case 'articleName': colIndex = COLUMNS.ARTICLE_NAME; break;
        case 'line': colIndex = COLUMNS.LINE; break;
        case 'classification': colIndex = COLUMNS.CLASSIFICATION; break;
        case 'productType': colIndex = COLUMNS.PRODUCT_TYPE; break;
        case 'unitsOuter': colIndex = unitsOuterIdx; break;
        case 'outerW': colIndex = COLUMNS.OUTER_W; break;
        case 'outerL': colIndex = COLUMNS.OUTER_L; break;
        case 'outerH': colIndex = COLUMNS.OUTER_H; break;
        case 'moq': colIndex = COLUMNS.MOQ; break;
        case 'itemToLogistic': colIndex = COLUMNS.ITEM_TO_LOGISTIC; break;
        default: return filteredRows;
      }
    }

    if (colIndex === undefined || colIndex === null) return filteredRows;

    const sorted = [...filteredRows].sort((a, b) => {
      const valA = a.row[colIndex];
      const valB = b.row[colIndex];

      // Handle null/undefined
      if (valA === valB) return 0;
      if (valA === null || valA === undefined || valA === '') return 1;
      if (valB === null || valB === undefined || valB === '') return -1;

      // Handle numeric comparison
      const numA = typeof valA === 'number' ? valA : parseFloat(String(valA).replace(',', '.'));
      const numB = typeof valB === 'number' ? valB : parseFloat(String(valB).replace(',', '.'));

      if (!isNaN(numA) && !isNaN(numB)) {
        return direction === 'asc' ? numA - numB : numB - numA;
      }

      // Handle string comparison
      const strA = String(valA).toLowerCase();
      const strB = String(valB).toLowerCase();
      
      if (strA < strB) return direction === 'asc' ? -1 : 1;
      if (strA > strB) return direction === 'asc' ? 1 : -1;
      return 0;
    });

    return sorted;
  }, [filteredRows, sortConfig]);

  // ── Pagination ─────────────────────────────────────────────────────────
  const paginatedRows = useMemo(() => {
    const start = (currentPage - 1) * pageSize;
    return sortedRows.slice(start, start + pageSize);
  }, [sortedRows, currentPage]);

  // Keep ref in sync so drag handlers can read current visible indexes without stale closure
  visibleDataIndexesRef.current = paginatedRows.map((r: { dataIndex: number }) => r.dataIndex);

  const totalPages = Math.ceil(sortedRows.length / pageSize);

  const handleSort = (key: string | number) => {
    setSortConfig(prev => {
      if (prev.key === key) {
        if (prev.direction === 'asc') return { key, direction: 'desc' };
        return { key: null, direction: null };
      }
      return { key, direction: 'asc' };
    });
  };

  // ── Inline edit helpers ───────────────────────────────────────────────────
  const startEdit = (rowIndex: number, colIndex: number, currentValue: string) => {
    setEditingCell({ rowIndex, colIndex, value: currentValue });
    setTimeout(() => inputRef.current?.focus(), 0);
  };

  const commitEdit = useCallback(async () => {
    if (!editingCell) return;
    const { rowIndex, colIndex, value } = editingCell;
    const original = data[rowIndex];
    const newRow = [...original];
    newRow[colIndex] = value;
    setSavingCell({ rowIndex, colIndex });
    setEditingCell(null);
    onCaptureState(`Updated pricing for ${original[COLUMNS.ARTICLE_NO]}`);
    await onSaveRow(rowIndex, newRow);
    setSavingCell(null);
  }, [editingCell, data, onSaveRow, onCaptureState]);

  const cancelEdit = () => setEditingCell(null);

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === 'Enter') commitEdit();
    if (e.key === 'Escape') cancelEdit();
  };

  // ── All unique product types (for autocomplete) ───────────────────────────
  const allProductTypes = useMemo(() =>
    Array.from(new Set(data.map(r => String(r[COLUMNS.PRODUCT_TYPE] || '')).filter(Boolean))).sort()
  , [data]);

  const startEditType = (rowIndex: number, currentValue: string) => {
    setEditingType({ rowIndex, value: currentValue });
    setTypeSuggestions(allProductTypes);
    setTimeout(() => typeInputRef.current?.focus(), 0);
  };

  const commitTypeEdit = useCallback(async (rowIndex: number, value: string) => {
    setEditingType(null);
    setTypeSuggestions([]);
    const original = data[rowIndex];
    const newRow = [...original];
    newRow[COLUMNS.PRODUCT_TYPE] = value;
    onCaptureState(`Updated type for ${original[COLUMNS.ARTICLE_NO]}`);
    await onSaveRow(rowIndex, newRow);
  }, [data, onSaveRow, onCaptureState]);

  const handleTypeInputChange = (value: string) => {
    setEditingType(prev => prev ? { ...prev, value } : null);
    const lower = value.toLowerCase();
    setTypeSuggestions(
      lower ? allProductTypes.filter(t => t.toLowerCase().includes(lower)) : allProductTypes
    );
  };

  const startEditLogistic = (rowIndex: number, currentValue: string) => {
    setEditingLogistic({ rowIndex, value: currentValue });
    setTimeout(() => logisticInputRef.current?.focus(), 0);
  };

  const commitLogisticEdit = useCallback(async (rowIndex: number, value: string) => {
    setEditingLogistic(null);
    const original = data[rowIndex];
    const newRow = [...original];
    newRow[COLUMNS.ITEM_TO_LOGISTIC] = value;
    onCaptureState(`Updated logistic info for ${original[COLUMNS.ARTICLE_NO]}`);
    await onSaveRow(rowIndex, newRow);
  }, [data, onSaveRow, onCaptureState, COLUMNS]);

  // ── Column helpers ────────────────────────────────────────────────────────
  const pricingEditableCols: DetectedCol[] = [
    ...(uvpIdx >= 0 ? [{ index: uvpIdx, name: headers[uvpIdx] || 'UVP' }] : []),
    ...srpCols,
  ];

  // ── Pinned columns for freeze ──────────────────────────────────────────────
  const allPinnableColumns = useMemo(() => {
    const cols: { key: string; label: string; index: number }[] = [
      { key: 'articleNo', label: 'Article No', index: COLUMNS.ARTICLE_NO },
      { key: 'articleName', label: 'Article Name', index: COLUMNS.ARTICLE_NAME },
      { key: 'line', label: 'Line', index: COLUMNS.LINE },
      { key: 'classification', label: 'Classification', index: COLUMNS.CLASSIFICATION },
      { key: 'productType', label: 'Type', index: COLUMNS.PRODUCT_TYPE },
      { key: 'itemToLogistic', label: 'Item to Logistic', index: COLUMNS.ITEM_TO_LOGISTIC },
      { key: 'unitsOuter', label: 'Units/Outer', index: unitsOuterIdx },
      { key: 'outerW', label: 'Outer W', index: COLUMNS.OUTER_W },
      { key: 'outerL', label: 'Outer L', index: COLUMNS.OUTER_L },
      { key: 'outerH', label: 'Outer H', index: COLUMNS.OUTER_H },
      { key: 'moq', label: 'MOQ', index: COLUMNS.MOQ },
    ];
    pricingEditableCols.forEach(col => {
      cols.push({ key: `prc_${col.index}`, label: col.name, index: col.index });
    });
    containerCols.forEach(col => {
      cols.push({ key: `con_${col.index}`, label: col.name, index: col.index });
    });
    return cols;
  }, [COLUMNS, unitsOuterIdx, pricingEditableCols, containerCols]);

  const togglePinnedColumn = (key: string) => {
    setPinnedColumns(prev => {
      const next = new Set(prev);
      if (next.has(key)) {
        next.delete(key);
      } else {
        next.add(key);
      }
      return next;
    });
  };

  // Calculate sticky left position for each pinned column
  const getStickyLeft = useMemo(() => {
    const baseOrder = ['articleNo', 'articleName', 'line', 'classification', 'productType', 'itemToLogistic', 'unitsOuter', 'outerW', 'outerL', 'outerH', 'moq'];
    const dynamicOrder: string[] = [];
    pricingEditableCols.forEach(col => dynamicOrder.push(`prc_${col.index}`));
    containerCols.forEach(col => dynamicOrder.push(`con_${col.index}`));
    const fullOrder = [...baseOrder, ...dynamicOrder];
    
    const pinnedOrder = fullOrder.filter(k => pinnedColumns.has(k));
    return (key: string): number | null => {
      if (!pinnedColumns.has(key)) return null;
      const idx = pinnedOrder.indexOf(key);
      if (idx === -1) return null;
      let left = 0;
      for (let i = 0; i < idx; i++) {
        const k = pinnedOrder[i];
        const width = k.startsWith('prc_') || k.startsWith('con_') 
          ? (columnWidths[k] ?? 100)
          : (columnWidths[k] || 100);
        left += width;
      }
      return left;
    };
  }, [pinnedColumns, pricingEditableCols, containerCols, columnWidths]);

  // Calculate z-index for sticky columns (so they stack correctly)
  const getStickyRank = useMemo(() => {
    const baseOrder = ['articleNo', 'articleName', 'line', 'classification', 'productType', 'itemToLogistic', 'unitsOuter', 'outerW', 'outerL', 'outerH', 'moq'];
    const dynamicOrder: string[] = [];
    pricingEditableCols.forEach(col => dynamicOrder.push(`prc_${col.index}`));
    containerCols.forEach(col => dynamicOrder.push(`con_${col.index}`));
    const fullOrder = [...baseOrder, ...dynamicOrder];

    const pinnedOrder = fullOrder.filter(k => pinnedColumns.has(k));
    return (key: string): number | null => {
      if (!pinnedColumns.has(key)) return null;
      const idx = pinnedOrder.indexOf(key);
      if (idx === -1) return null;
      return pinnedOrder.length - idx + 10;
    };
  }, [pinnedColumns, pricingEditableCols, containerCols]);

  // Header pinned cells need a stacking context above ALL body pinned cells
  // so filter popovers (rendered inside <th>) appear over sticky body columns.
  const getHeaderStickyRank = (key: string): number | null => {
    const rank = getStickyRank(key);
    return rank === null ? null : rank + 100;
  };

  const isPinned = (key: string) => pinnedColumns.has(key);

  // ═ Unique values for dynamic pricing columns ═════════════════════════════
  const dynamicColUniqueValues = useMemo(() => {
    const result: Record<number, string[]> = {};
    pricingEditableCols.forEach(col => {
      result[col.index] = Array.from(new Set(data.map(r => String(r[col.index] || '')))).filter(v => v).sort();
    });
    containerCols.forEach(col => {
      result[col.index] = Array.from(new Set(data.map(r => String(r[col.index] || '')))).filter(v => v).sort();
    });
    return result;
  }, [data, uvpIdx, srpCols, containerCols, headers]);

  const formatPrice = (val: any) => {
    if (val === undefined || val === null || val === '') return '';
    const n = parseFloat(String(val).replace(',', '.'));
    return isNaN(n) ? String(val) : n.toFixed(2);
  };

  const formatUnits = (val: any) => {
    if (val === undefined || val === null || val === '') return '—';
    return String(val);
  };

  const unitBadge = (val: any, label: string) => {
    const n = Number(val);
    if (!val || n === 0) return (
      <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-bold bg-red-500/20 text-red-400 border border-red-500/40">
        <AlertCircle className="w-3 h-3" /> 0
      </span>
    );
    if (n === 1) return (
      <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-bold bg-amber-500/20 text-amber-400 border border-amber-500/40">
        <AlertTriangle className="w-3 h-3" /> 1
      </span>
    );
    return (
      <span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-semibold bg-emerald-500/10 text-emerald-400 border border-emerald-500/30">
        {n.toLocaleString()}
      </span>
    );
  };

  const unitOuterBadge = (val: any) => {
    const n = Number(val);
    if (!val || n === 0) return (
      <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-bold bg-red-500/20 text-red-400 border border-red-500/40">
        <AlertCircle className="w-3 h-3" /> Missing
      </span>
    );
    return (
      <span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-semibold bg-slate-500/20 text-slate-300 border border-slate-600/50">
        {n}
      </span>
    );
  };

  // ── Matrix columns (the rest) ─────────────────────────────────────────────
  const displayedIndices = useMemo(() => {
    const set = new Set<number>([
      COLUMNS.ARTICLE_NO,
      COLUMNS.ARTICLE_NAME,
      COLUMNS.LINE,
      COLUMNS.CLASSIFICATION,
      unitsOuterIdx,
      COLUMNS.OUTER_W,
      COLUMNS.OUTER_L,
      COLUMNS.OUTER_H,
      COLUMNS.VALIDATED_CHECK,
      COLUMNS.VALIDATED_NOTE,
      COLUMNS.ANNA_CHECK,
      COLUMNS.ANNA_NOTE,
      COLUMNS.MOQ,
    ]);
    if (uvpIdx >= 0) set.add(uvpIdx);
    srpCols.forEach(c => set.add(c.index));
    containerCols.forEach(c => set.add(c.index));
    return set;
  }, [uvpIdx, srpCols, containerCols]);

  const matrixCols = useMemo(() => {
    return headers
      .map((h, i) => ({ index: i, name: h || '' }))
      .filter(({ index }) => !displayedIndices.has(index))
      .filter(({ name }) => name.trim() !== ''); // Skip empty headers
  }, [headers, displayedIndices]);

  const [noteEditor, setNoteEditor] = useState<{ rowIndex: number; text: string } | null>(null);
  const [annaEditor, setAnnaEditor] = useState<{ rowIndex: number; text: string } | null>(null);

  const handleToggleCheck = async (rowIndex: number, checked: boolean) => {
    const original = data[rowIndex];
    const newRow = [...original];
    newRow[COLUMNS.VALIDATED_CHECK] = checked;
    onCaptureState(`${checked ? 'Checked' : 'Unchecked'} ${original[COLUMNS.ARTICLE_NO]}`);
    await onSaveRow(rowIndex, newRow);
  };

  const saveNote = async () => {
    if (!noteEditor) return;
    const { rowIndex, text } = noteEditor;
    const original = data[rowIndex];
    const newRow = [...original];
    newRow[COLUMNS.VALIDATED_NOTE] = text;
    setNoteEditor(null);
    onCaptureState(`Updated note for ${original[COLUMNS.ARTICLE_NO]}`);
    await onSaveRow(rowIndex, newRow);
  };

  const handleToggleAnnaCheck = async (rowIndex: number, checked: boolean) => {
    const original = data[rowIndex];
    const newRow = [...original];
    newRow[COLUMNS.ANNA_CHECK] = checked;
    onCaptureState(`${checked ? 'Anna checked' : 'Anna unchecked'} ${original[COLUMNS.ARTICLE_NO]}`);
    await onSaveRow(rowIndex, newRow);
  };

  const saveAnnaNote = async () => {
    if (!annaEditor) return;
    const { rowIndex, text } = annaEditor;
    const original = data[rowIndex];
    const newRow = [...original];
    newRow[COLUMNS.ANNA_NOTE] = text;
    setAnnaEditor(null);
    onCaptureState(`Updated Anna note for ${original[COLUMNS.ARTICLE_NO]}`);
    await onSaveRow(rowIndex, newRow);
  };

  // ── Column detection notice ───────────────────────────────────────────────
  const missingCols: string[] = [];
  if (uvpIdx < 0) missingCols.push('UVP');
  if (srpCols.length === 0) missingCols.push('SRP');
  if (containerCols.length === 0) missingCols.push('Units/40\'');

  const FILTERS: { id: FilterMode; label: string; count: number; color: string }[] = [
    { id: 'all',          label: 'All Products',    count: stats.total,      color: 'text-slate-300' },
    { id: 'all_errors',   label: 'All Issues',      count: stats.withAny,    color: 'text-red-400' },
    { id: 'pricing_errors', label: 'Pricing Issues', count: stats.withPricing, color: 'text-amber-400' },
    { id: 'units_errors', label: 'Units Issues',    count: stats.withUnits,  color: 'text-orange-400' },
  ];

  return (
    <div className={isFullscreen ? "fixed inset-0 z-[100] bg-[#041021] p-6 overflow-auto" : "space-y-6"}>
      {isFullscreen && (
        <button
          onClick={() => setIsFullscreen(false)}
          className="fixed top-4 right-4 z-[110] p-2 bg-slate-800 hover:bg-slate-700 text-slate-200 rounded-md transition-colors border border-slate-700"
        >
          <X className="w-5 h-5" />
        </button>
      )}
      {/* ── Anna Note Editor Modal ── */}
      {annaEditor && createPortal(
        <div className="fixed inset-0 bg-slate-950/50 backdrop-blur-sm z-[10000] flex items-center justify-center p-4">
          <div className="bg-slate-800 border border-slate-700 rounded-xl shadow-2xl w-full max-w-md animate-in zoom-in-95 duration-200">
            <div className="p-4 border-b border-slate-700 flex items-center justify-between">
              <h3 className="font-semibold text-white flex items-center gap-2">
                <MessageSquare className="w-4 h-4 text-pink-400" />
                Anna Note
              </h3>
              <p className="text-[10px] text-slate-500 font-mono">{data[annaEditor.rowIndex][COLUMNS.ARTICLE_NO]}</p>
            </div>
            <div className="p-4">
              <textarea
                value={annaEditor.text}
                onChange={e => setAnnaEditor(prev => prev ? { ...prev, text: e.target.value } : null)}
                placeholder="Write a note about this product..."
                className="w-full h-32 bg-slate-900 border border-slate-700 rounded-lg p-3 text-sm text-white focus:outline-none focus:border-pink-500 resize-none"
                autoFocus
              />
            </div>
            <div className="p-4 bg-slate-900/50 rounded-b-xl flex justify-end gap-3">
              <button onClick={() => setAnnaEditor(null)} className="px-4 py-2 text-sm text-slate-400 hover:text-white transition-colors">Cancel</button>
              <button
                onClick={saveAnnaNote}
                className="px-4 py-2 bg-pink-600 hover:bg-pink-700 text-white text-sm font-bold rounded-lg shadow-lg active:scale-95 transition-all"
              >
                Save Note
              </button>
            </div>
          </div>
        </div>,
        document.body
      )}

      {/* ── Note Editor Modal ── */}
      {noteEditor && createPortal(
        <div className="fixed inset-0 bg-slate-950/50 backdrop-blur-sm z-[10000] flex items-center justify-center p-4">
          <div className="bg-slate-800 border border-slate-700 rounded-xl shadow-2xl w-full max-w-md animate-in zoom-in-95 duration-200">
            <div className="p-4 border-b border-slate-700 flex items-center justify-between">
              <h3 className="font-semibold text-white flex items-center gap-2">
                <MessageSquare className="w-4 h-4 text-blue-400" />
                Validation Note
              </h3>
              <p className="text-[10px] text-slate-500 font-mono">{data[noteEditor.rowIndex][COLUMNS.ARTICLE_NO]}</p>
            </div>
            <div className="p-4">
              <textarea
                value={noteEditor.text}
                onChange={e => setNoteEditor(prev => prev ? { ...prev, text: e.target.value } : null)}
                placeholder="Write a note about this product..."
                className="w-full h-32 bg-slate-900 border border-slate-700 rounded-lg p-3 text-sm text-white focus:outline-none focus:border-blue-500 resize-none"
                autoFocus
              />
            </div>
            <div className="p-4 bg-slate-900/50 rounded-b-xl flex justify-end gap-3">
              <button onClick={() => setNoteEditor(null)} className="px-4 py-2 text-sm text-slate-400 hover:text-white transition-colors">Cancel</button>
              <button 
                onClick={saveNote}
                className="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-bold rounded-lg shadow-lg active:scale-95 transition-all"
              >
                Save Note
              </button>
            </div>
          </div>
        </div>,
        document.body
      )}

      {/* ── Tooltip Portal ── */}
      {hoveredNote && createPortal(
        <div 
          style={{ top: hoveredNote.pos.top, left: hoveredNote.pos.left, transform: 'translateX(-50%)' }}
          className={cn(
            "fixed w-48 p-2 border rounded text-xs text-white shadow-xl z-[99999] pointer-events-none animate-in fade-in zoom-in-95 duration-100",
            hoveredNote.isAnna ? "bg-pink-900/95 border-pink-500/50" : "bg-amber-900/95 border-amber-500/50"
          )}
        >
          {hoveredNote.text}
        </div>,
        document.body
      )}

      <div className="flex items-center justify-between gap-4">
        {/* ── Search bar with Dropdown ── */}
        <div className="flex-1 max-w-md relative" ref={searchDropdownRef}>
          <div className="relative">
            <input
              type="text"
              placeholder="Search SKU or Name (multiple words supported)..."
              value={search}
              onChange={e => {
                setSearch(e.target.value);
                setIsSearchOpen(true);
              }}
              onFocus={() => setIsSearchOpen(true)}
              className="w-full pl-4 pr-10 py-2 bg-slate-800 border border-slate-700 rounded-lg text-sm text-white focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all"
            />
            {selectedSearchItems.size > 0 ? (
              <button
                onClick={(e) => {
                  e.stopPropagation();
                  handleClearSearch();
                }}
                className="absolute right-2 top-1/2 -translate-y-1/2 bg-blue-600 hover:bg-blue-700 text-white flex items-center gap-1.5 px-2 py-1 rounded-md transition-all shadow-lg active:scale-95"
                title="Clear selection"
              >
                <span className="text-[10px] font-bold">
                  {selectedSearchItems.size}
                </span>
                <X className="w-3.5 h-3.5" />
              </button>
            ) : search ? (
              <button
                onClick={() => setSearch('')}
                className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white"
              >
                <X className="w-4 h-4" />
              </button>
            ) : (
              <div className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-500">
                <Package className="w-4 h-4" />
              </div>
            )}
          </div>

          <button
            onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'global' ? null : 'global'); }}
            className={cn(
              'absolute -right-10 top-1/2 -translate-y-1/2 p-2 rounded-lg border transition-all active:scale-95',
              globalAdvancedFilter.terms.some(t => t.trim() !== '') 
                ? 'bg-blue-600 border-blue-500 text-white shadow-lg shadow-blue-900/20' 
                : 'bg-slate-800 border-slate-700 text-slate-400 hover:text-white hover:border-slate-600'
            )}
            title="Advanced Search"
          >
            <Filter className="w-4 h-4" />
          </button>

          {openFilter === 'global' && (
            <div className="absolute top-full left-0 z-[10000]">
              <TextFilterPopover
                triggerId="global-filter-trigger"
                value={globalAdvancedFilter}
                onChange={setGlobalAdvancedFilter}
                onClose={() => setOpenFilter(null)}
              />
            </div>
          )}

          {/* Search Dropdown Panel */}
          {isSearchOpen && searchSuggestions.length > 0 && (
            <div className="absolute top-full left-0 right-0 mt-1 bg-slate-800 border border-slate-700 rounded-lg shadow-2xl z-[10000] overflow-hidden animate-in fade-in slide-in-from-top-2 duration-200">
              <div className="max-h-64 overflow-y-auto">
                {searchSuggestions.map((row, idx) => {
                  return (
                    <button
                      key={`${row[COLUMNS.ARTICLE_NO]}-${idx}`}
                      onMouseDown={(e) => e.preventDefault()}
                      onClick={(e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        const key = String(row[COLUMNS.ARTICLE_NO]);
                        setSelectedSearchItems(prev => {
                          const next = new Set(prev);
                          if (next.has(key)) next.delete(key);
                          else next.add(key);
                          return next;
                        });
                      }}
                      className="w-full text-left px-4 py-2.5 hover:bg-slate-700/50 flex items-center gap-3 border-b border-slate-700/30 last:border-0 transition-colors"
                    >
                      <div className={cn(
                        "w-4 h-4 rounded border flex items-center justify-center shrink-0",
                        selectedSearchItems.has(String(row[COLUMNS.ARTICLE_NO])) 
                          ? "bg-blue-600 border-blue-600" 
                          : "border-slate-600"
                      )}>
                        {selectedSearchItems.has(String(row[COLUMNS.ARTICLE_NO])) && (
                          <svg className="w-3 h-3 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
                          </svg>
                        )}
                      </div>
                      <div className="flex flex-col gap-0.5">
                        <span className="text-xs font-mono font-bold text-blue-400">{row[COLUMNS.ARTICLE_NO]}</span>
                        <span className="text-xs text-slate-300 truncate">{row[COLUMNS.ARTICLE_NAME]}</span>
                      </div>
                    </button>
                  );
                })}
              </div>
              <div className="flex items-center justify-between px-4 py-2 bg-slate-900/50 border-t border-slate-700">
                <button
                  onClick={(e) => {
                    e.stopPropagation();
                    handleClearSearch();
                  }}
                  className="flex items-center gap-1 text-xs text-red-400 hover:text-red-300 font-medium transition-colors"
                >
                  <X className="w-3 h-3" />
                  Clear Selection ({selectedSearchItems.size})
                </button>
                <button
                  onClick={handleApplySearch}
                  className="px-3 py-1 bg-blue-600 hover:bg-blue-700 text-white text-xs rounded"
                >
                  Apply
                </button>
              </div>
              {searchSuggestions.length === 50 && (
                <div className="px-4 py-1.5 bg-slate-900/50 text-[10px] text-slate-500 border-t border-slate-700 italic">
                  Showing first 50 results...
                </div>
              )}
            </div>
          )}
        </div>

        {/* ── Filter tabs ── */}
        <div className="flex items-center gap-1 bg-slate-800/60 rounded-lg p-1 border border-slate-700/50 w-fit">
          {FILTERS.map(f => (
            <button
              key={f.id}
              onClick={() => { setFilterMode(f.id); setCurrentPage(1); }}
              className={cn(
                'flex items-center gap-2 px-3 py-1.5 rounded-md text-sm font-medium transition-colors',
                filterMode === f.id
                  ? 'bg-slate-700 text-white shadow-sm'
                  : 'text-slate-400 hover:text-slate-200 hover:bg-slate-700/40'
              )}
            >
              {f.label}
              <span className={cn(
                'text-xs font-bold px-1.5 py-0.5 rounded-full min-w-[22px] text-center',
                filterMode === f.id
                  ? 'bg-slate-600 text-white'
                  : f.count > 0 ? `${f.color} bg-current/10` : 'text-slate-500'
              )}>
                {f.count}
              </span>
            </button>
          ))}
        </div>
      </div>

      {/* ── Column detection warning ── */}
      {missingCols.length > 0 && (
        <div className="flex items-center gap-3 px-4 py-2.5 bg-amber-500/10 border border-amber-500/30 rounded-lg text-amber-300 text-sm">
          <AlertTriangle className="w-4 h-4 shrink-0" />
          <span>
            Could not auto-detect columns for: <strong>{missingCols.join(', ')}</strong>.
            Check that the Excel headers contain "UVP", "SRP", or "40HC"/"40HQ".
          </span>
        </div>
      )}

      {/* ── Stat cards ── */}
      <div className="grid grid-cols-4 gap-3">
        <StatCard label="Total Products" value={stats.total} icon={<Package className="w-4 h-4" />} color="slate" />
        <StatCard label="Pricing Issues" value={stats.withPricing} icon={<DollarSign className="w-4 h-4" />} color="amber" />
        <StatCard label="Units Issues" value={stats.withUnits} icon={<AlertCircle className="w-4 h-4" />} color="red" />
        <StatCard label="All OK" value={stats.allOk} icon={<CheckCircle2 className="w-4 h-4" />} color="emerald" />
        <button
          onClick={() => setIsFullscreen(true)}
          className="flex items-center justify-center w-full h-full min-h-[80px] bg-slate-800/60 hover:bg-slate-700 border border-slate-700/50 rounded-xl transition-colors"
          title="Maximize view"
        >
          <Maximize2 className="w-5 h-5 text-slate-400" />
        </button>
      </div>

      {/* ── Pin columns control ── */}
      <div className="flex items-center gap-3 bg-slate-800/60 border border-slate-700/50 rounded-xl p-3">
        <div className="relative">
          <button
            onClick={() => setShowPinPanel(!showPinPanel)}
            className={cn(
              'flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-all',
              pinnedColumns.size > 0
                ? 'bg-blue-600 text-white shadow-lg shadow-blue-900/20'
                : 'bg-slate-700 text-slate-300 hover:bg-slate-600'
            )}
          >
            <Pin className="w-4 h-4" />
            <span>Pin Columns</span>
            {pinnedColumns.size > 0 && (
              <span className="bg-white/20 px-1.5 py-0.5 rounded text-xs font-bold">{pinnedColumns.size}</span>
            )}
          </button>
          
          {showPinPanel && (
            <div className="absolute top-full left-0 mt-2 w-72 bg-slate-800 border border-slate-700 rounded-xl shadow-2xl z-50 overflow-hidden animate-in fade-in zoom-in-95 duration-100">
              <div className="p-3 border-b border-slate-700 bg-slate-900/50">
                <p className="text-xs font-bold text-slate-300">Select columns to pin (freeze)</p>
              </div>
              <div className="max-h-64 overflow-y-auto p-2 grid grid-cols-2 gap-1">
                {allPinnableColumns.map(col => (
                  <button
                    key={col.key}
                    onClick={() => togglePinnedColumn(col.key)}
                    className={cn(
                      'flex items-center gap-2 px-3 py-2 rounded-lg text-xs transition-all text-left',
                      pinnedColumns.has(col.key)
                        ? 'bg-blue-600/20 text-blue-400 border border-blue-500/40'
                        : 'bg-slate-700/50 text-slate-300 hover:bg-slate-700 border border-transparent'
                    )}
                  >
                    <div className={cn(
                      'w-4 h-4 rounded border flex items-center justify-center shrink-0',
                      pinnedColumns.has(col.key)
                        ? 'bg-blue-600 border-blue-600'
                        : 'border-slate-600'
                    )}>
                      {pinnedColumns.has(col.key) && (
                        <svg className="w-3 h-3 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
                        </svg>
                      )}
                    </div>
                    <span className="truncate">{col.label}</span>
                  </button>
                ))}
              </div>
              <div className="p-2 border-t border-slate-700 bg-slate-900/50 flex gap-2">
                <button
                  onClick={() => setPinnedColumns(new Set(['articleNo', 'articleName']))}
                  className="flex-1 px-3 py-1.5 text-xs text-slate-400 hover:text-white hover:bg-slate-700 rounded transition-colors"
                >
                  Reset
                </button>
                <button
                  onClick={() => setPinnedColumns(new Set())}
                  className="flex-1 px-3 py-1.5 text-xs text-red-400 hover:text-red-300 hover:bg-red-500/10 rounded transition-colors"
                >
                  Unpin All
                </button>
              </div>
            </div>
          )}
        </div>
        <div className="flex items-center gap-2 text-xs text-slate-500">
          <PinOff className="w-3.5 h-3.5" />
          <span>Pinned:</span>
          {pinnedColumns.size === 0 ? (
            <span className="text-slate-600">None</span>
          ) : (
            <div className="flex flex-wrap gap-1">
              {Array.from(pinnedColumns).map(key => {
                const col = allPinnableColumns.find(c => c.key === key);
                return col ? (
                  <span key={key} className="bg-blue-500/10 text-blue-400 px-2 py-0.5 rounded border border-blue-500/20">
                    {col.label}
                  </span>
                ) : null;
              })}
            </div>
          )}
        </div>
      </div>

      {/* ── Table ── */}
      <div className="flex-1 overflow-auto bg-slate-800 rounded-xl border border-slate-700 shadow-xl">
        {sortedRows.length === 0 ? (
          <div className="flex flex-col items-center justify-center h-64 text-slate-400">
            <CheckCircle2 className="w-12 h-12 text-emerald-500 mb-3" />
            <p className="text-lg font-medium text-emerald-400">No issues found</p>
            <p className="text-sm mt-1">All products are correctly configured.</p>
          </div>
        ) : (
          <table ref={tableRef} className="w-full text-sm border-collapse table-fixed">
            <thead className="sticky top-0 z-[100] bg-slate-900 border-b border-slate-700">
              <tr>
                <th style={{ 
                  width: columnWidths.articleNo, 
                  ...(isPinned('articleNo') 
                    ? { left: getStickyLeft('articleNo') ?? 0, zIndex: openFilter === 'sku' ? 500 : (getHeaderStickyRank('articleNo') ?? 0) } 
                    : (openFilter === 'sku' ? { zIndex: 500, position: 'relative' } : {})) 
                }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('articleNo') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('articleNo')}>
                  <div className="flex items-center gap-1">
                    <span className="truncate flex items-center gap-1">
                      {isPinned('articleNo') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                      Article No <SortIcon current={sortConfig.key === 'articleNo' ? sortConfig.direction : null} />
                    </span>
                    <button
                      id="filter-trigger-sku"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'sku' ? null : 'sku'); }}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        articleNoColFilter.terms.some(t => t.trim() !== '') ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'sku' && (
                    <TextFilterPopover
                      triggerId="filter-trigger-sku"
                      value={articleNoColFilter}
                      onChange={setArticleNoColFilter}
                      onClose={() => setOpenFilter(null)}
                      zIndex={50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'articleNo', columnWidths.articleNo); }} />
                </th>
                <th style={{ 
                  width: columnWidths.articleName, 
                  ...(isPinned('articleName') 
                    ? { left: getStickyLeft('articleName') ?? 0, zIndex: openFilter === 'name' ? 500 : (getHeaderStickyRank('articleName') ?? 0) } 
                    : (openFilter === 'name' ? { zIndex: 500, position: 'relative' } : {})) 
                }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('articleName') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('articleName')}>
                  <div className="flex items-center gap-1">
                    <span className="truncate flex items-center gap-1">
                      {isPinned('articleName') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                      Article Name <SortIcon current={sortConfig.key === 'articleName' ? sortConfig.direction : null} /></span>
                    <button
                      id="filter-trigger-name"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'name' ? null : 'name'); }}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        nameColFilter.terms.some(t => t.trim() !== '') ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'name' && (
                    <TextFilterPopover
                      triggerId="filter-trigger-name"
                      value={nameColFilter}
                      onChange={setNameColFilter}
                      onClose={() => setOpenFilter(null)}
                      zIndex={500}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'articleName', columnWidths.articleName); }} />
                </th>
                <th style={{ 
                  width: columnWidths.line, 
                  ...(isPinned('line') 
                    ? { left: getStickyLeft('line') ?? 0, zIndex: openFilter === 'line' ? 500 : (getHeaderStickyRank('line') ?? 0) } 
                    : (openFilter === 'line' ? { zIndex: 500, position: 'relative' } : {})) 
                }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('line') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('line')}>
                  <div className="flex items-center gap-1">
                    <span className="truncate flex items-center gap-1">
                      {isPinned('line') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                      Line <SortIcon current={sortConfig.key === 'line' ? sortConfig.direction : null} /></span>
                    <button
                      id="filter-trigger-line"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'line' ? null : 'line'); }}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        (lineMultiFilter || []).length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'line' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-line"
                      uniqueValues={uniqueLines || []}
                      selectedValues={lineMultiFilter || []}
                      onToggle={val => setLineMultiFilter(prev => (prev || []).includes(val) ? (prev || []).filter(v => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setLineMultiFilter(vals || [])}
                      onClear={() => { setLineMultiFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={500}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'line', columnWidths.line); }} />
                </th>
                <th style={{ 
                  width: columnWidths.classification, 
                  ...(isPinned('classification') 
                    ? { left: getStickyLeft('classification') ?? 0, zIndex: openFilter === 'classification' ? 500 : (getHeaderStickyRank('classification') ?? 0) } 
                    : (openFilter === 'classification' ? { zIndex: 500, position: 'relative' } : {})) 
                }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('classification') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('classification')}>
                  <div className="flex items-center gap-1">
                    <span className="truncate flex items-center gap-1">
                      {isPinned('classification') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                      Classification <SortIcon current={sortConfig.key === 'classification' ? sortConfig.direction : null} /></span>
                    <button
                      id="filter-trigger-class"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'classification' ? null : 'classification'); }}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        (classificationFilter || []).length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'classification' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-class"
                      uniqueValues={uniqueClassifications || []}
                      selectedValues={classificationFilter || []}
                      onToggle={val => setClassificationFilter(prev => (prev || []).includes(val) ? (prev || []).filter(v => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setClassificationFilter(vals || [])}
                      onClear={() => { setClassificationFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'classification', columnWidths.classification); }} />
                </th>

                <th style={{ width: columnWidths.productType, ...(isPinned('productType') ? { left: getStickyLeft('productType') ?? 0, zIndex: getHeaderStickyRank('productType') ?? 0 } : {}) }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-purple-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('productType') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('productType')}>
                  <span className="flex items-center gap-1">
                    {isPinned('productType') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                    Type <SortIcon current={sortConfig.key === 'productType' ? sortConfig.direction : null} />
                    <button
                      id="filter-trigger-type"
                      onClick={(e: React.MouseEvent) => { e.stopPropagation(); setOpenFilter(openFilter === 'productType' ? null : 'productType'); }}
                      className={cn('ml-1 p-0.5 rounded transition-colors filter-trigger-btn', (productTypeFilter || []).length > 0 ? 'text-purple-400 bg-purple-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100')}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </span>
                  {openFilter === 'productType' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-type"
                      uniqueValues={uniqueProductTypes || []}
                      selectedValues={productTypeFilter || []}
                      onToggle={(val: string) => setProductTypeFilter((prev: string[]) => (prev || []).includes(val) ? (prev || []).filter((v: string) => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setProductTypeFilter(vals || [])}
                      onClear={() => { setProductTypeFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'productType', columnWidths.productType); }} />
                </th>

                <th style={{ 
                  width: columnWidths.itemToLogistic, 
                  ...(isPinned('itemToLogistic') 
                    ? { left: getStickyLeft('itemToLogistic') ?? 0, zIndex: openFilter === 'logistic' ? 500 : (getHeaderStickyRank('itemToLogistic') ?? 0) } 
                    : (openFilter === 'logistic' ? { zIndex: 500, position: 'relative' } : {})) 
                }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-pink-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('itemToLogistic') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('itemToLogistic')}>
                  <span className="flex items-center gap-1">
                    {isPinned('itemToLogistic') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                    Item to Logistic <SortIcon current={sortConfig.key === 'itemToLogistic' ? sortConfig.direction : null} />
                    <button
                      id="filter-trigger-logistic"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'logistic' ? null : 'logistic'); }}
                      className={cn(
                        'ml-1 p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        (itemToLogisticFilter || []).length > 0 ? 'text-pink-400 bg-pink-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </span>
                  {openFilter === 'logistic' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-logistic"
                      uniqueValues={uniqueItemToLogistic || []}
                      selectedValues={itemToLogisticFilter || []}
                      onToggle={val => setItemToLogisticFilter(prev => (prev || []).includes(val) ? (prev || []).filter(v => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setItemToLogisticFilter(vals || [])}
                      onClear={() => { setItemToLogisticFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'itemToLogistic', columnWidths.itemToLogistic); }} />
                </th>

                {pricingEditableCols.map(col => {
                  const colKey = `prc_${col.index}`;
                  const width = columnWidths[colKey] ?? 100;
                  return (
                    <th key={col.index} style={{ 
                      width, 
                      ...(isPinned(colKey) 
                        ? { left: getStickyLeft(colKey) ?? 0, zIndex: openFilter === colKey ? 500 : (getHeaderStickyRank(colKey) ?? 0) } 
                        : (openFilter === colKey ? { zIndex: 500, position: 'relative' } : {})) 
                    }} className={cn(
                      "text-left px-3 py-3 text-xs font-semibold text-blue-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                      isPinned(colKey) && "sticky bg-slate-900"
                    )} onClick={() => handleSort(col.index)}>
                      <div className="flex items-center gap-1">
                        <span className="truncate flex items-center gap-1">
                          {isPinned(colKey) && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                          {col.name} <SortIcon current={sortConfig.key === col.index ? sortConfig.direction : null} /></span>
                        <button
                          id={`filter-trigger-${colKey}`}
                          onClick={(e) => {
                            e.stopPropagation();
                            setOpenFilter(openFilter === colKey ? null : colKey);
                          }}
                          className={cn(
                            'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                            dynamicColFilters[col.index]?.length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                          )}
                        >
                          <Filter className="w-3 h-3" />
                        </button>
                      </div>
                      {openFilter === colKey && (
                        <ColumnFilterPopover
                          triggerId={`filter-trigger-${colKey}`}
                          uniqueValues={dynamicColUniqueValues[col.index] || []}
                          selectedValues={dynamicColFilters[col.index] || []}
                            onToggle={val => setDynamicColFilters(prev => {
                              const current = prev[col.index] || [];
                              return current.includes(val) 
                                ? { ...prev, [col.index]: current.filter(v => v !== val) }
                                : { ...prev, [col.index]: [...current, val] };
                            })}
                            onSelectAll={vals => setDynamicColFilters(prev => ({ ...prev, [col.index]: vals }))}
                            onClear={() => { setDynamicColFilters(prev => { const next = { ...prev }; delete next[col.index]; return next; }); setOpenFilter(null); }}
                            onClose={() => setOpenFilter(null)}
                            zIndex={isPinned(colKey) ? 200 : 50}
                          />
                        )}
                      <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, colKey, width); }} />
                    </th>
                  );
                })}

                <th style={{ 
                  width: columnWidths.unitsOuter, 
                  ...(isPinned('unitsOuter') 
                    ? { left: getStickyLeft('unitsOuter') ?? 0, zIndex: openFilter === 'unitsOuter' ? 500 : (getHeaderStickyRank('unitsOuter') ?? 0) } 
                    : (openFilter === 'unitsOuter' ? { zIndex: 500, position: 'relative' } : {})) 
                }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('unitsOuter') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('unitsOuter')}>
                  <div className="flex items-center gap-1">
                    <span className="truncate flex items-center gap-1">
                      {isPinned('unitsOuter') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                      Units/Outer <SortIcon current={sortConfig.key === 'unitsOuter' ? sortConfig.direction : null} /></span>
                    <button
                      id="filter-trigger-unitsOuter"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'unitsOuter' ? null : 'unitsOuter'); }}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        (unitsOuterFilter || []).length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'unitsOuter' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-unitsOuter"
                      uniqueValues={uniqueUnitsOuter || []}
                      selectedValues={unitsOuterFilter || []}
                      onToggle={val => setUnitsOuterFilter(prev => (prev || []).includes(val) ? (prev || []).filter(v => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setUnitsOuterFilter(vals || [])}
                      onClear={() => { setUnitsOuterFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'unitsOuter', columnWidths.unitsOuter); }} />
                </th>

                <th style={{ 
                  width: columnWidths.outerW, 
                  ...(isPinned('outerW') 
                    ? { left: getStickyLeft('outerW') ?? 0, zIndex: openFilter === 'outerW' ? 500 : (getHeaderStickyRank('outerW') ?? 0) } 
                    : (openFilter === 'outerW' ? { zIndex: 500, position: 'relative' } : {})) 
                }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('outerW') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('outerW')}>
                  <div className="flex items-center gap-1">
                    <span className="truncate flex items-center gap-1">
                      {isPinned('outerW') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                      Outer W <SortIcon current={sortConfig.key === 'outerW' ? sortConfig.direction : null} /></span>
                    <button
                      id="filter-trigger-outerW"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'outerW' ? null : 'outerW'); }}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        (outerWFilter || []).length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'outerW' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-outerW"
                      uniqueValues={uniqueOuterW || []}
                      selectedValues={outerWFilter || []}
                      onToggle={val => setOuterWFilter(prev => (prev || []).includes(val) ? (prev || []).filter(v => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setOuterWFilter(vals || [])}
                      onClear={() => { setOuterWFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'outerW', columnWidths.outerW); }} />
                </th>

                <th style={{ 
                  width: columnWidths.outerL, 
                  ...(isPinned('outerL') 
                    ? { left: getStickyLeft('outerL') ?? 0, zIndex: openFilter === 'outerL' ? 500 : (getHeaderStickyRank('outerL') ?? 0) } 
                    : (openFilter === 'outerL' ? { zIndex: 500, position: 'relative' } : {})) 
                }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('outerL') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('outerL')}>
                  <div className="flex items-center gap-1">
                    <span className="truncate flex items-center gap-1">
                      {isPinned('outerL') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                      Outer L <SortIcon current={sortConfig.key === 'outerL' ? sortConfig.direction : null} /></span>
                    <button
                      id="filter-trigger-outerL"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'outerL' ? null : 'outerL'); }}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        (outerLFilter || []).length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'outerL' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-outerL"
                      uniqueValues={uniqueOuterL || []}
                      selectedValues={outerLFilter || []}
                      onToggle={val => setOuterLFilter(prev => (prev || []).includes(val) ? (prev || []).filter(v => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setOuterLFilter(vals || [])}
                      onClear={() => { setOuterLFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'outerL', columnWidths.outerL); }} />
                </th>

                <th style={{ 
                  width: columnWidths.outerH, 
                  ...(isPinned('outerH') 
                    ? { left: getStickyLeft('outerH') ?? 0, zIndex: openFilter === 'outerH' ? 500 : (getHeaderStickyRank('outerH') ?? 0) } 
                    : (openFilter === 'outerH' ? { zIndex: 500, position: 'relative' } : {})) 
                }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('outerH') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('outerH')}>
                  <div className="flex items-center gap-1">
                    <span className="truncate flex items-center gap-1">
                      {isPinned('outerH') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                      Outer H <SortIcon current={sortConfig.key === 'outerH' ? sortConfig.direction : null} /></span>
                    <button
                      id="filter-trigger-outerH"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'outerH' ? null : 'outerH'); }}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        (outerHFilter || []).length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'outerH' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-outerH"
                      uniqueValues={uniqueOuterH || []}
                      selectedValues={outerHFilter || []}
                      onToggle={val => setOuterHFilter(prev => (prev || []).includes(val) ? (prev || []).filter(v => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setOuterHFilter(vals || [])}
                      onClear={() => { setOuterHFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'outerH', columnWidths.outerH); }} />
                </th>

{containerCols.map(col => {
                  const colKey = `con_${col.index}`;
                  const width = columnWidths[colKey] ?? 110;
                  return (
                    <th key={col.index} style={{ 
                      width,
                      ...(isPinned(colKey) 
                        ? { left: getStickyLeft(colKey) ?? 0, zIndex: openFilter === colKey ? 500 : (getHeaderStickyRank(colKey) ?? 0) } 
                        : (openFilter === colKey ? { zIndex: 500, position: 'relative' } : {})) 
                    }} className={cn(
                      "text-left px-3 py-3 text-xs font-semibold text-orange-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                      isPinned(colKey) && "sticky bg-slate-900"
                    )} onClick={() => handleSort(col.index)}>
                      <div className="flex items-center gap-1">
                        <span className="truncate flex items-center gap-1">
                          {isPinned(colKey) && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                          {col.name} <SortIcon current={sortConfig.key === col.index ? sortConfig.direction : null} /></span>
                        <button
                          id={`filter-trigger-${colKey}`}
                          onClick={(e) => {
                            e.stopPropagation();
                            setOpenFilter(openFilter === colKey ? null : colKey);
                          }}
                          className={cn(
                            'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                            dynamicColFilters[col.index]?.length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                          )}
                        >
                          <Filter className="w-3 h-3" />
                        </button>
                      </div>
                      {openFilter === colKey && (
                        <ColumnFilterPopover
                          triggerId={`filter-trigger-${colKey}`}
                          uniqueValues={dynamicColUniqueValues[col.index] || []}
                          selectedValues={dynamicColFilters[col.index] || []}
                          onToggle={val => setDynamicColFilters(prev => {
                            const current = prev[col.index] || [];
                            return current.includes(val)
                              ? { ...prev, [col.index]: current.filter(v => v !== val) }
                              : { ...prev, [col.index]: [...current, val] };
                          })}
                          onSelectAll={vals => setDynamicColFilters(prev => ({ ...prev, [col.index]: vals }))}
                          onClear={() => { setDynamicColFilters(prev => { const next = { ...prev }; delete next[col.index]; return next; }); setOpenFilter(null); }}
                          onClose={() => setOpenFilter(null)}
                          zIndex={isPinned(colKey) ? 200 : 50}
                        />
                      )}
                      <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, colKey, width); }} />
                    </th>
                  );
                })}

                <th style={{ 
                  width: columnWidths.moq, 
                  ...(isPinned('moq') 
                    ? { left: getStickyLeft('moq') ?? 0, zIndex: openFilter === 'moq' ? 500 : (getHeaderStickyRank('moq') ?? 0) } 
                    : (openFilter === 'moq' ? { zIndex: 500, position: 'relative' } : {})) 
                }} className={cn(
                    "text-left px-3 py-3 text-xs font-semibold text-cyan-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative",
                    isPinned('moq') && "sticky bg-slate-900"
                  )} onClick={() => handleSort('moq')}>
                  <div className="flex items-center gap-1">
                    <span className="truncate flex items-center gap-1">
                      {isPinned('moq') && <Pin className="w-3 h-3 text-blue-400 shrink-0" />}
                      MOQ <SortIcon current={sortConfig.key === 'moq' ? sortConfig.direction : null} /></span>
                    <button
                      id="filter-trigger-moq"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'moq' ? null : 'moq'); }}
                      className={cn(
                        'ml-1 p-0.5 rounded transition-colors filter-trigger-btn',
                        (moqFilter || []).length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'moq' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-moq"
                      uniqueValues={uniqueMoq || []}
                      selectedValues={moqFilter || []}
                      onToggle={val => setMoqFilter(prev => (prev || []).includes(val) ? (prev || []).filter(v => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setMoqFilter(vals || [])}
                      onClear={() => { setMoqFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={isPinned('moq') ? 200 : 50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'moq', columnWidths.moq); }} />
                </th>

                <th style={{ width: 180 }} className="text-left px-3 py-3 text-xs font-semibold text-red-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap group relative">
                  <div className="flex items-center gap-1">
                    <span>Weight Issues</span>
                    <button
                      onClick={() => setOpenFilter(openFilter === 'weightIssue' ? null : 'weightIssue')}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0',
                        weightIssueFilter !== 'all' ? 'text-red-400 bg-red-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'weightIssue' && (
                    <div className="absolute top-full left-0 mt-1 w-44 bg-slate-800 border border-slate-700 rounded-lg shadow-2xl z-50 p-1 flex flex-col gap-0.5 animate-in fade-in zoom-in-95 duration-100">
                      {(['all', 'with', 'without'] as const).map(opt => (
                        <button
                          key={opt}
                          onClick={() => { setWeightIssueFilter(opt); setOpenFilter(null); }}
                          className={cn(
                            'w-full text-left px-3 py-1.5 rounded text-xs transition-colors',
                            weightIssueFilter === opt ? 'bg-red-500/20 text-red-400' : 'text-slate-300 hover:bg-slate-700'
                          )}
                        >
                          {opt === 'all' ? 'All' : opt === 'with' ? 'With weight issue' : 'No weight issue'}
                        </button>
                      ))}
                    </div>
                  )}
                </th>

                <th style={{ width: columnWidths.check }} className="text-left px-3 py-3 text-xs font-semibold text-blue-400 uppercase tracking-wider group cursor-pointer hover:bg-slate-800/50 transition-colors relative" onClick={() => handleSort(COLUMNS.VALIDATED_CHECK)}>
                  <div className="flex items-center gap-1">
                    <span className="flex items-center gap-1">Check Ying <SortIcon current={sortConfig.key === COLUMNS.VALIDATED_CHECK ? sortConfig.direction : null} /></span>
                    <button
                      id="filter-trigger-check"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'check' ? null : 'check'); }}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        (checkYingFilter || []).length > 0 ? 'text-blue-400 bg-blue-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'check' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-check"
                      uniqueValues={uniqueCheckYing || []}
                      selectedValues={checkYingFilter || []}
                      onToggle={val => setCheckYingFilter(prev => (prev || []).includes(val) ? (prev || []).filter(v => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setCheckYingFilter(vals || [])}
                      onClear={() => { setCheckYingFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'check', columnWidths.check); }} />
                </th>

                <th style={{ width: columnWidths.checkAnna ?? 100 }} className="text-left px-3 py-3 text-xs font-semibold text-pink-400 uppercase tracking-wider group cursor-pointer hover:bg-slate-800/50 transition-colors relative" onClick={() => handleSort(COLUMNS.ANNA_CHECK)}>
                  <div className="flex items-center gap-1">
                    <span className="flex items-center gap-1">Check Anna <SortIcon current={sortConfig.key === COLUMNS.ANNA_CHECK ? sortConfig.direction : null} /></span>
                    <button
                      id="filter-trigger-checkAnna"
                      onClick={(e) => { e.stopPropagation(); setOpenFilter(openFilter === 'checkAnna' ? null : 'checkAnna'); }}
                      className={cn(
                        'p-0.5 rounded hover:bg-slate-700 transition-colors shrink-0 filter-trigger-btn',
                        (checkAnnaFilter || []).length > 0 ? 'text-pink-400 bg-pink-400/10' : 'text-slate-500 opacity-0 group-hover:opacity-100'
                      )}
                    >
                      <Filter className="w-3 h-3" />
                    </button>
                  </div>
                  {openFilter === 'checkAnna' && (
                    <ColumnFilterPopover
                      triggerId="filter-trigger-checkAnna"
                      uniqueValues={uniqueCheckAnna || []}
                      selectedValues={checkAnnaFilter || []}
                      onToggle={val => setCheckAnnaFilter(prev => (prev || []).includes(val) ? (prev || []).filter(v => v !== val) : [...(prev || []), val])}
                      onSelectAll={vals => setCheckAnnaFilter(vals || [])}
                      onClear={() => { setCheckAnnaFilter([]); setOpenFilter(null); }}
                      onClose={() => setOpenFilter(null)}
                      zIndex={50}
                    />
                  )}
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'checkAnna', columnWidths.checkAnna ?? 100); }} />
                </th>

                {matrixCols.map(col => {
                  const colKey = `mat_${col.index}`;
                  const width = columnWidths[colKey] ?? 120;
                  return (
                    <th key={col.index} style={{ width }} className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider whitespace-nowrap group cursor-pointer hover:bg-slate-800/50 transition-colors relative" title={col.name} onClick={() => handleSort(col.index)}>
                      <span className="truncate flex items-center gap-1">{col.name} <SortIcon current={sortConfig.key === col.index ? sortConfig.direction : null} /></span>
                      <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, colKey, width); }} />
                    </th>
                  );
                })}

                <th style={{ width: columnWidths.actions }} className="px-3 py-3 border-b border-slate-700 sticky right-0 bg-slate-900 shadow-[-4px_0_8px_rgba(0,0,0,0.2)]">
                  <ResizeHandle onMouseDown={e => { e.stopPropagation(); handleResizeStart(e, 'actions', columnWidths.actions); }} />
                </th>
              </tr>
            </thead>
            <tbody>
              {paginatedRows.map(({ row, dataIndex, pricingErrors, unitErrors, isCritical }) => {
                const saveStatus = rowStatuses[String(row[COLUMNS.ARTICLE_NO])];
                const isValidated = !!row[COLUMNS.VALIDATED_CHECK];
                const note = String(row[COLUMNS.VALIDATED_NOTE] || '');

                const isRowSelected = dragSelectedRows.has(dataIndex);

                return (
                  <tr
                    key={dataIndex}
                    onMouseDown={(e: React.MouseEvent<HTMLTableRowElement>) => handleRowMouseDown(e, dataIndex)}
                    onMouseEnter={() => handleRowMouseEnter(dataIndex)}
                    style={{ userSelect: 'none' }}
                    className={cn(
                      'border-b border-slate-700/50 transition-colors group relative hover:z-50 cursor-default',
                      isRowSelected
                        ? 'bg-blue-500/20 border-l-4 border-l-blue-400'
                        : isValidated
                          ? 'bg-green-400/30 border-l-4 border-l-green-400'
                          : saveStatus === 'error'
                            ? 'bg-red-400/20 border-l-4 border-l-red-500'
                            : saveStatus === 'pending'
                              ? 'bg-amber-400/20 border-l-4 border-l-amber-400'
                              : isCritical
                                ? 'bg-red-950/20'
                                : pricingErrors.length > 0
                                  ? 'bg-amber-950/10'
                                  : ''
                    )}
                  >
                    {/* Art. No. */}
                    <td className={cn("px-3 py-2.5 font-mono text-xs text-slate-300 whitespace-nowrap truncate", isPinned('articleNo') && "sticky bg-slate-800")} style={isPinned('articleNo') ? { left: getStickyLeft('articleNo') ?? 0, zIndex: getStickyRank('articleNo') ?? 0 } : {}}>
                      {row[COLUMNS.ARTICLE_NO]}
                    </td>

                    {/* Article Name */}
                    <td className={cn("px-3 py-2.5 text-slate-200 max-w-[200px]", isPinned('articleName') && "sticky bg-slate-800")} style={isPinned('articleName') ? { left: getStickyLeft('articleName') ?? 0, zIndex: getStickyRank('articleName') ?? 0 } : {}}>
                      <span className="line-clamp-1" title={row[COLUMNS.ARTICLE_NAME]}>
                        {row[COLUMNS.ARTICLE_NAME] || '—'}
                      </span>
                    </td>

                    {/* Line */}
                    <td className={cn("px-3 py-2.5 text-slate-400 whitespace-nowrap text-xs truncate", isPinned('line') && "sticky bg-slate-800")} style={isPinned('line') ? { left: getStickyLeft('line') ?? 0, zIndex: getStickyRank('line') ?? 0 } : {}}>
                      {row[COLUMNS.LINE] || '—'}
                    </td>

                    {/* Classification */}
                    <td className={cn("px-3 py-2.5", isPinned('classification') && "sticky bg-slate-800")} style={isPinned('classification') ? { left: getStickyLeft('classification') ?? 0, zIndex: getStickyRank('classification') ?? 0 } : {}}>
                      <span className={cn(
                        'px-2 py-0.5 rounded text-[10px] font-bold border whitespace-nowrap inline-block max-w-full truncate',
                        String(row[COLUMNS.CLASSIFICATION] || '').toUpperCase().includes('CORE')
                          ? 'bg-blue-500/10 text-blue-400 border-blue-500/20'
                          : String(row[COLUMNS.CLASSIFICATION] || '').toUpperCase().includes('OOC')
                            ? 'bg-amber-500/10 text-amber-500 border-amber-500/20'
                            : 'bg-slate-700/50 text-slate-400 border-slate-600/50'
                      )}>
                        {row[COLUMNS.CLASSIFICATION] || '—'}
                      </span>
                    </td>

                    {/* TYPE cell */}
                    <td className={cn("px-3 py-2 overflow-visible relative", isPinned('productType') && "sticky bg-slate-800")} style={isPinned('productType') ? { left: getStickyLeft('productType') ?? 0, zIndex: getStickyRank('productType') ?? 0 } : {}}>
                      {editingType?.rowIndex === dataIndex ? (
                        <div className="relative">
                          <input
                            ref={typeInputRef}
                            type="text"
                            value={editingType.value}
                            onChange={e => handleTypeInputChange(e.target.value)}
                            onKeyDown={e => {
                              if (e.key === 'Enter') commitTypeEdit(dataIndex, editingType.value);
                              if (e.key === 'Escape') { setEditingType(null); setTypeSuggestions([]); }
                            }}
                            onBlur={() => setTimeout(() => { commitTypeEdit(dataIndex, editingType?.value ?? ''); }, 150)}
                            className="w-full bg-slate-900 border border-purple-500 rounded px-2 py-1 text-sm text-white focus:outline-none focus:ring-1 focus:ring-purple-500"
                          />
                          {typeSuggestions.length > 0 && (
                            <ul className="absolute top-full left-0 mt-1 w-full min-w-[160px] bg-slate-800 border border-slate-600 rounded-lg shadow-2xl z-50 max-h-48 overflow-y-auto">
                              {typeSuggestions.map(t => (
                                <li
                                  key={t}
                                  onMouseDown={e => { e.preventDefault(); commitTypeEdit(dataIndex, t); }}
                                  className="px-3 py-1.5 text-xs text-slate-200 hover:bg-purple-500/20 cursor-pointer truncate"
                                >
                                  {t}
                                </li>
                              ))}
                            </ul>
                          )}
                        </div>
                      ) : (
                        <button
                          onClick={() => startEditType(dataIndex, String(row[COLUMNS.PRODUCT_TYPE] || ''))}
                          className={cn(
                            'group flex items-center gap-1.5 px-2 py-1 rounded text-xs transition-colors hover:bg-slate-700/60 w-full overflow-hidden',
                            row[COLUMNS.PRODUCT_TYPE]
                              ? 'text-purple-300 border border-transparent hover:border-slate-600'
                              : 'text-slate-500 border border-dashed border-slate-600 hover:border-purple-500/50'
                          )}
                        >
                          <span className="truncate">{row[COLUMNS.PRODUCT_TYPE] || 'Add type…'}</span>
                          <Edit2 className="w-2.5 h-2.5 opacity-0 group-hover:opacity-50 shrink-0" />
                        </button>
                      )}
                    </td>

                    {/* ITEM TO LOGISTIC cell */}
                    <td className={cn("px-3 py-2 overflow-visible relative", isPinned('itemToLogistic') && "sticky bg-slate-800")} style={isPinned('itemToLogistic') ? { left: getStickyLeft('itemToLogistic') ?? 0, zIndex: getStickyRank('itemToLogistic') ?? 0 } : {}}>
                      {editingLogistic?.rowIndex === dataIndex ? (
                        <input
                          ref={logisticInputRef}
                          type="text"
                          value={editingLogistic.value}
                          onChange={e => setEditingLogistic(prev => prev ? { ...prev, value: e.target.value } : null)}
                          onKeyDown={e => {
                            if (e.key === 'Enter') commitLogisticEdit(dataIndex, editingLogistic.value);
                            if (e.key === 'Escape') setEditingLogistic(null);
                          }}
                          onBlur={() => commitLogisticEdit(dataIndex, editingLogistic.value)}
                          className="w-full bg-slate-900 border border-pink-500 rounded px-2 py-1 text-sm text-white focus:outline-none focus:ring-1 focus:ring-pink-500"
                        />
                      ) : (
                        <button
                          onClick={() => startEditLogistic(dataIndex, String(row[COLUMNS.ITEM_TO_LOGISTIC] || ''))}
                          className={cn(
                            'group flex items-center gap-1.5 px-2 py-1 rounded text-xs transition-colors hover:bg-slate-700/60 w-full overflow-hidden',
                            row[COLUMNS.ITEM_TO_LOGISTIC]
                              ? 'text-pink-300 border border-transparent hover:border-slate-600'
                              : 'text-slate-500 border border-dashed border-slate-600 hover:border-pink-500/50'
                          )}
                        >
                          <span className="truncate">{row[COLUMNS.ITEM_TO_LOGISTIC] || 'Add info…'}</span>
                          <Edit2 className="w-2.5 h-2.5 opacity-0 group-hover:opacity-50 shrink-0" />
                        </button>
                      )}
                    </td>

                    {/* Pricing editable cells */}
                    {pricingEditableCols.map(col => {
                      const isEditing = editingCell?.rowIndex === dataIndex && editingCell?.colIndex === col.index;
                      const isSaving = savingCell?.rowIndex === dataIndex && savingCell?.colIndex === col.index;
                      const val = formatPrice(row[col.index]);
                      const isEmpty = !row[col.index] || row[col.index] === '' || Number(row[col.index]) === 0;
                      const colKey = `prc_${col.index}`;

                      return (
                        <td key={col.index} className={cn("px-3 py-2", isPinned(colKey) && "sticky bg-slate-800")} style={isPinned(colKey) ? { left: getStickyLeft(colKey) ?? 0, zIndex: getStickyRank(colKey) ?? 0 } : {}}>
                          {isEditing ? (
                            <div className="flex items-center gap-1">
                              <input
                                ref={inputRef}
                                type="text"
                                value={editingCell.value}
                                onChange={e => setEditingCell(prev => prev ? { ...prev, value: e.target.value } : null)}
                                onKeyDown={handleKeyDown}
                                onBlur={commitEdit}
                                className="w-full bg-slate-900 border border-blue-500 rounded px-2 py-1 text-sm text-white focus:outline-none focus:ring-1 focus:ring-blue-500"
                              />
                            </div>
                          ) : (
                            <button
                              onClick={() => startEdit(dataIndex, col.index, val)}
                              className={cn(
                                'group flex items-center gap-1.5 px-2 py-1 rounded text-xs font-mono transition-colors hover:bg-slate-700/60 w-full overflow-hidden',
                                isEmpty
                                  ? 'text-amber-400 border border-amber-500/40 bg-amber-500/5'
                                  : 'text-slate-200 border border-transparent hover:border-slate-600'
                              )}
                              title={isSaving ? 'Saving…' : `Click to edit ${col.name}`}
                            >
                              {isSaving ? (
                                <span className="text-slate-500 italic truncate">saving…</span>
                              ) : isEmpty ? (
                                <div className="flex items-center gap-1 truncate"><AlertTriangle className="w-3 h-3 shrink-0" /><span>Missing</span></div>
                              ) : (
                                <div className="flex items-center justify-between w-full truncate">
                                  <span>{val}</span>
                                  <Edit2 className="w-2.5 h-2.5 opacity-0 group-hover:opacity-50 shrink-0" />
                                </div>
                              )}
                            </button>
                          )}
                        </td>
                      );
                    })}

                    {/* Units columns */}
                    <td className={cn("px-3 py-2.5", isPinned('unitsOuter') && "sticky bg-slate-800")} style={isPinned('unitsOuter') ? { left: getStickyLeft('unitsOuter') ?? 0, zIndex: getStickyRank('unitsOuter') ?? 0 } : {}}>
                      {unitOuterBadge(row[unitsOuterIdx])}
                    </td>
                    <td className={cn("px-3 py-2.5 text-slate-400 font-mono text-xs truncate", isPinned('outerW') && "sticky bg-slate-800")} style={isPinned('outerW') ? { left: getStickyLeft('outerW') ?? 0, zIndex: getStickyRank('outerW') ?? 0 } : {}}>
                      {row[COLUMNS.OUTER_W] ?? '-'}
                    </td>
                    <td className={cn("px-3 py-2.5 text-slate-400 font-mono text-xs truncate", isPinned('outerL') && "sticky bg-slate-800")} style={isPinned('outerL') ? { left: getStickyLeft('outerL') ?? 0, zIndex: getStickyRank('outerL') ?? 0 } : {}}>
                      {row[COLUMNS.OUTER_L] ?? '-'}
                    </td>
                    <td className={cn("px-3 py-2.5 text-slate-400 font-mono text-xs truncate", isPinned('outerH') && "sticky bg-slate-800")} style={isPinned('outerH') ? { left: getStickyLeft('outerH') ?? 0, zIndex: getStickyRank('outerH') ?? 0 } : {}}>
                      {row[COLUMNS.OUTER_H] ?? '-'}
                    </td>

                    {/* Container units columns */}
                    {containerCols.map(col => {
                      const colKey = `con_${col.index}`;
                      return (
                        <td key={col.index} className={cn("px-3 py-2.5 truncate", isPinned(colKey) && "sticky bg-slate-800")} style={isPinned(colKey) ? { left: getStickyLeft(colKey) ?? 0, zIndex: getStickyRank(colKey) ?? 0 } : {}}>
                        {unitBadge(row[col.index], col.name)}
                      </td>
                      );
                    })}

                    {/* MOQ cell */}
                    <td className={cn("px-3 py-2.5 truncate", isPinned('moq') && "sticky bg-slate-800")} style={isPinned('moq') ? { left: getStickyLeft('moq') ?? 0, zIndex: getStickyRank('moq') ?? 0 } : {}}>
                      {row[COLUMNS.MOQ] !== undefined && row[COLUMNS.MOQ] !== null ? row[COLUMNS.MOQ] : '-'}
                    </td>

                    {/* Issues column (weight only) */}
                    <td className="px-3 py-2 overflow-hidden">
                      {(() => {
                        const weightError = unitErrors.find(e => e.startsWith('NW'));
                        return weightError ? (
                          <span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-semibold bg-red-500/15 text-red-400 border border-red-500/30 whitespace-nowrap">
                            <AlertCircle className="w-3 h-3 shrink-0" />{weightError}
                          </span>
                        ) : (
                          <span className="text-slate-600 text-xs">—</span>
                        );
                      })()}
                    </td>

                    {/* Check Ying Column (Validated + Note) */}
                    <td className="px-3 py-2.5">
                      <div className="flex items-center gap-2">
                        <input
                          type="checkbox"
                          checked={isValidated}
                          onChange={(e) => handleToggleCheck(dataIndex, e.target.checked)}
                          className="w-4 h-4 rounded border-slate-600 bg-slate-900 text-blue-600 focus:ring-blue-500 focus:ring-offset-slate-800 cursor-pointer"
                        />
                        <button
                          onClick={() => setNoteEditor({ rowIndex: dataIndex, text: note })}
                          onMouseEnter={(e) => {
                            if (!note) return;
                            const rect = e.currentTarget.getBoundingClientRect();
                            setHoveredNote({
                              text: note,
                              isAnna: false,
                              pos: { top: rect.bottom + window.scrollY + 8, left: rect.left + window.scrollX + rect.width / 2 }
                            });
                          }}
                          onMouseLeave={() => setHoveredNote(null)}
                          className={cn(
                            "p-1.5 rounded-md transition-all shrink-0",
                            note
                              ? "bg-amber-500/10 text-amber-400 border border-amber-500/20 hover:bg-amber-500/20"
                              : "text-slate-500 hover:text-slate-300 hover:bg-slate-700/50"
                          )}
                        >
                          <MessageSquare className={cn("w-3.5 h-3.5", note && "fill-amber-400/20")} />
                        </button>
                      </div>
                    </td>

                    {/* Check Anna Column */}
                    {(() => {
                      const annaChecked = !!row[COLUMNS.ANNA_CHECK];
                      const annaNote = String(row[COLUMNS.ANNA_NOTE] || '');
                      return (
                        <td className="px-3 py-2.5">
                          <div className="flex items-center gap-2">
                            <input
                              type="checkbox"
                              checked={annaChecked}
                              onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleToggleAnnaCheck(dataIndex, e.target.checked)}
                              className="w-4 h-4 rounded border-slate-600 bg-slate-900 text-pink-600 focus:ring-pink-500 focus:ring-offset-slate-800 cursor-pointer"
                            />
                            <button
                              onClick={() => setAnnaEditor({ rowIndex: dataIndex, text: annaNote })}
                              onMouseEnter={(e) => {
                                if (!annaNote) return;
                                const rect = e.currentTarget.getBoundingClientRect();
                                setHoveredNote({
                                  text: annaNote,
                                  isAnna: true,
                                  pos: { top: rect.bottom + window.scrollY + 8, left: rect.left + window.scrollX + rect.width / 2 }
                                });
                              }}
                              onMouseLeave={() => setHoveredNote(null)}
                              className={cn(
                                "p-1.5 rounded-md transition-all shrink-0",
                                annaNote
                                  ? "bg-pink-500/10 text-pink-400 border border-pink-500/20 hover:bg-pink-500/20"
                                  : "text-slate-500 hover:text-slate-300 hover:bg-slate-700/50"
                              )}
                            >
                              <MessageSquare className={cn("w-3.5 h-3.5", annaNote && "fill-pink-400/20")} />
                            </button>
                          </div>
                        </td>
                      );
                    })()}

                    {/* Matrix columns cells */}
                    {matrixCols.map(col => (
                      <td key={col.index} className="px-3 py-2.5 text-slate-500 text-xs max-w-[150px] truncate" title={String(row[col.index] || '')}>
                        {row[col.index] ?? '—'}
                      </td>
                    ))}

                    <td className={cn(
                      "px-2 py-2.5 sticky right-0 shadow-[-4px_0_8px_rgba(0,0,0,0.1)] transition-colors",
                      isValidated ? "bg-[#1b4d24]" : "bg-slate-800",
                      "group-hover:bg-slate-700/40"
                    )}>
                      <button
                        onClick={() => onEdit(dataIndex)}
                        className="p-1.5 text-slate-500 hover:text-slate-200 hover:bg-slate-700 rounded transition-colors"
                      >
                        <Edit2 className="w-3.5 h-3.5" />
                      </button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </div>

      {/* ── Footer count & Pagination ── */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <p className="text-xs text-slate-500 pb-1">
            Showing {paginatedRows.length} of {sortedRows.length} products {totalPages > 1 && `(${currentPage}/${totalPages})`}
            {pricingEditableCols.length > 0 && (
              <> · Click any <span className="text-blue-400">price cell</span> to edit inline</>
            )}
          </p>
          {dragSelectedRows.size > 0 && (
            <span className="flex items-center gap-1.5 text-xs text-blue-400 bg-blue-500/10 border border-blue-500/20 px-2 py-0.5 rounded mb-1">
              {dragSelectedRows.size} selected
              <button
                onClick={() => setDragSelectedRows(new Set())}
                className="ml-1 text-blue-300 hover:text-white transition-colors"
                title="Clear selection"
              >
                <X className="w-3 h-3" />
              </button>
            </span>
          )}
        </div>
        {totalPages > 1 && (
          <div className="flex items-center gap-1">
            <button
              onClick={() => setCurrentPage(1)}
              disabled={currentPage === 1}
              className="px-2 py-1 text-xs bg-slate-800 hover:bg-slate-700 rounded disabled:opacity-50 disabled:cursor-not-allowed"
            >
              ««
            </button>
            <button
              onClick={() => setCurrentPage(p => Math.max(1, p - 1))}
              disabled={currentPage === 1}
              className="px-2 py-1 text-xs bg-slate-800 hover:bg-slate-700 rounded disabled:opacity-50 disabled:cursor-not-allowed"
            >
              «
            </button>
            <span className="text-xs text-slate-400 px-2">
              {currentPage} / {totalPages}
            </span>
            <button
              onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}
              disabled={currentPage === totalPages}
              className="px-2 py-1 text-xs bg-slate-800 hover:bg-slate-700 rounded disabled:opacity-50 disabled:cursor-not-allowed"
            >
              »
            </button>
            <button
              onClick={() => setCurrentPage(totalPages)}
              disabled={currentPage === totalPages}
              className="px-2 py-1 text-xs bg-slate-800 hover:bg-slate-700 rounded disabled:opacity-50 disabled:cursor-not-allowed"
            >
              »»
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

// ── Text filter popover ───────────────────────────────────────────────────────
function TextFilterPopover({ value, onChange, onClose, triggerId, zIndex = 9999 }: {
  value: { terms: string[]; op: 'and' | 'or' };
  onChange: (v: { terms: string[]; op: 'and' | 'or' }) => void;
  onClose: () => void;
  triggerId: string;
  zIndex?: number;
}) {
  const [position, setPosition] = useState({ top: 0, left: 0 });

  const updatePosition = useCallback(() => {
    const trigger = document.getElementById(triggerId);
    if (trigger) {
      const rect = trigger.getBoundingClientRect();
      setPosition({
        top: rect.bottom + window.scrollY + 4,
        left: Math.min(rect.left + window.scrollX, window.innerWidth + window.scrollX - 300)
      });
    }
  }, [triggerId]);

  useEffect(() => {
    updatePosition();
    window.addEventListener('scroll', updatePosition, true);
    window.addEventListener('resize', updatePosition);
    return () => {
      window.removeEventListener('scroll', updatePosition, true);
      window.removeEventListener('resize', updatePosition);
    };
  }, [updatePosition]);

  const addTerm = () => {
    if (value.terms.length < 5) {
      onChange({ ...value, terms: [...value.terms, ''] });
    }
  };

  const removeTerm = (index: number) => {
    if (value.terms.length > 1) {
      const next = [...value.terms];
      next.splice(index, 1);
      onChange({ ...value, terms: next });
    } else {
      onChange({ ...value, terms: [''] });
    }
  };

  const updateTerm = (index: number, text: string) => {
    const next = [...value.terms];
    next[index] = text;
    onChange({ ...value, terms: next });
  };

  return createPortal(
    <div 
      className="absolute z-[9999] w-72 bg-slate-800 border border-slate-700 rounded-lg shadow-2xl p-4 flex flex-col gap-4 animate-in fade-in zoom-in-95 duration-100" 
      style={{ 
        top: position.top, 
        left: position.left 
      }} 
      onClick={e => e.stopPropagation()}
    >
      <div className="flex flex-col gap-3">
        <label className="text-[10px] font-bold text-slate-500 uppercase tracking-wider">Show rows where field contains:</label>
        
        <div className="flex flex-col gap-2.5">
          {value.terms.map((term, idx) => (
            <div key={idx} className="relative group">
              <Search className="absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-slate-500" />
              <input
                type="text"
                placeholder={`Term ${idx + 1}...`}
                value={term}
                onChange={e => updateTerm(idx, e.target.value)}
                onKeyDown={e => e.key === 'Enter' && onClose()}
                autoFocus={idx === value.terms.length - 1}
                className="w-full bg-slate-900 border border-slate-700 rounded-md p-2 pl-8 pr-8 text-xs text-white focus:outline-none focus:border-blue-500 transition-all"
              />
              {value.terms.length > 1 && (
                <button 
                  onClick={() => removeTerm(idx)}
                  className="absolute right-2 top-1/2 -translate-y-1/2 text-slate-500 hover:text-red-400 opacity-0 group-hover:opacity-100 transition-all"
                >
                  <X className="w-3.5 h-3.5" />
                </button>
              )}
            </div>
          ))}
        </div>

        {value.terms.length < 5 && (
          <button 
            onClick={addTerm}
            className="flex items-center gap-1.5 text-[10px] font-bold text-blue-400 hover:text-blue-300 transition-colors w-fit px-1"
          >
            + Add another term (max 5)
          </button>
        )}

        <div className="flex items-center gap-4 px-1 py-1 bg-slate-900/30 rounded-md">
          <label className="flex items-center gap-2 cursor-pointer group">
            <input 
              type="radio" 
              name={`op-${value.terms.length}`} 
              checked={value.op === 'and'} 
              onChange={() => onChange({ ...value, op: 'and' })}
              className="w-3 h-3 text-blue-600 bg-slate-900 border-slate-700 focus:ring-blue-500"
            />
            <span className={cn("text-[10px] font-bold transition-colors", value.op === 'and' ? "text-blue-400" : "text-slate-500 group-hover:text-slate-300")}>AND (All match)</span>
          </label>
          <label className="flex items-center gap-2 cursor-pointer group">
            <input 
              type="radio" 
              name={`op-${value.terms.length}`} 
              checked={value.op === 'or'} 
              onChange={() => onChange({ ...value, op: 'or' })}
              className="w-3 h-3 text-blue-600 bg-slate-900 border-slate-700 focus:ring-blue-500"
            />
            <span className={cn("text-[10px] font-bold transition-colors", value.op === 'or' ? "text-blue-400" : "text-slate-500 group-hover:text-slate-300")}>OR (Any match)</span>
          </label>
        </div>
      </div>

      <div className="flex items-center justify-between pt-2 border-t border-slate-700/50">
        <button 
          onClick={() => { onChange({ terms: [''], op: 'and' }); onClose(); }} 
          className="text-[10px] font-bold text-slate-500 hover:text-red-400 transition-colors"
        >
          Clear All
        </button>
        <button 
          onClick={onClose} 
          className="px-4 py-1.5 bg-blue-600 hover:bg-blue-700 text-white text-[10px] font-bold rounded shadow-lg shadow-blue-900/20 active:scale-95 transition-all"
        >
          Apply Filter
        </button>
      </div>
    </div>,
    document.body
  );
}

// ── Sort Icon Helper ───────────────────────────────────────────────────
function SortIcon({ current }: { current: 'asc' | 'desc' | null }) {
  return (
    <span className="inline-flex flex-col ml-1">
      <ChevronDown className={cn(
        "w-2.5 h-2.5 -mb-0.5 transition-colors",
        current === 'asc' ? "text-blue-400 rotate-180" : "text-slate-600 group-hover:text-slate-400"
      )} />
      <ChevronDown className={cn(
        "w-2.5 h-2.5 transition-colors",
        current === 'desc' ? "text-blue-400" : "text-slate-600 group-hover:text-slate-400"
      )} />
    </span>
  );
}

// ── Resize Handle Component ─────────────────────────────────────────────
function ResizeHandle({ onMouseDown }: { onMouseDown: (e: React.MouseEvent) => void }) {
  return (
    <div 
      onMouseDown={onMouseDown}
      onClick={e => e.stopPropagation()}
      className="absolute right-0 top-0 bottom-0 w-1.5 hover:bg-blue-500/50 cursor-col-resize group/resizer flex items-center justify-center z-20"
      title="Drag to resize"
    >
      <div className="w-[1px] h-4 bg-slate-700 group-hover/resizer:bg-blue-400 transition-colors" />
    </div>
  );
}

// ── Stat card ─────────────────────────────────────────────────────────────────
function StatCard({
  label,
  value,
  icon,
  color,
}: {
  label: string;
  value: number;
  icon: React.ReactNode;
  color: 'slate' | 'amber' | 'red' | 'emerald';
}) {
  const colors = {
    slate:   { bg: 'bg-slate-800',   border: 'border-slate-700',   text: 'text-slate-200',   icon: 'text-slate-400' },
    amber:   { bg: 'bg-amber-950/30', border: 'border-amber-700/40', text: 'text-amber-300',  icon: 'text-amber-500' },
    red:     { bg: 'bg-red-950/30',   border: 'border-red-700/40',   text: 'text-red-300',    icon: 'text-red-500' },
    emerald: { bg: 'bg-emerald-950/20', border: 'border-emerald-700/30', text: 'text-emerald-300', icon: 'text-emerald-500' },
  };
  const c = colors[color];
  return (
    <div className={cn('rounded-xl border p-4 flex items-center gap-4', c.bg, c.border)}>
      <span className={c.icon}>{icon}</span>
      <div>
        <p className={cn('text-2xl font-bold', c.text)}>{value}</p>
        <p className="text-xs text-slate-400">{label}</p>
      </div>
    </div>
  );
}
