// ─── PDF.js config ───
        pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.worker.min.js';

        // ─── DOM refs ───
        const fileInput = document.getElementById('fileInput');
        const dropZone = document.getElementById('dropZone');
        const resultadoBody = document.getElementById('resultadoBody');
        const btnExport = document.getElementById('btnExport');
        const btnSaveDB = document.getElementById('btnSaveDB');
        const btnClear = document.getElementById('btnClear');
        const progressCont = document.getElementById('progressContainer');
        const progressBar = document.getElementById('progressBar');
        const progressText = document.getElementById('progressText');
        const progressCount = document.getElementById('progressCount');
        const statsRow = document.getElementById('statsRow');
        const debugSection = document.getElementById('debugSection');
        const debugLog = document.getElementById('debugLog');

        // ─── State ───
        let inventario = {};
        let processedItems = [];
        let totalFacturas = 0;
        let debugTexts = [];
        let catalogos = { lugares: [], categorias: [] };

        // ─── Event listeners ───
        dropZone.onclick = () => fileInput.click();
        fileInput.onchange = (e) => handleFiles(e.target.files);

        // Drag & drop
        ['dragenter', 'dragover'].forEach(evt => {
            dropZone.addEventListener(evt, (e) => {
                e.preventDefault();
                dropZone.classList.add('drop-active');
            });
        });
        ['dragleave', 'drop'].forEach(evt => {
            dropZone.addEventListener(evt, (e) => {
                e.preventDefault();
                dropZone.classList.remove('drop-active');
            });
        });
        dropZone.addEventListener('drop', (e) => {
            const files = e.dataTransfer.files;
            if (files.length) handleFiles(files);
        });

        // ─────────────────────────────────────────────
        //  MAIN: Process uploaded files (XML + PDF)
        // ─────────────────────────────────────────────
        async function handleFiles(files) {
            const validFiles = Array.from(files).filter(f => {
                const ext = f.name.toLowerCase().split('.').pop();
                return ext === 'xml' || ext === 'pdf' || f.type === 'application/pdf' || f.type === 'text/xml' || f.type === 'application/xml';
            });
            if (validFiles.length === 0) return;

            // Reset
            inventario = {};
            totalFacturas = validFiles.length;
            debugTexts = [];

            // Show progress
            progressCont.classList.remove('hidden');
            progressBar.style.width = '0%';

            let xmlCount = 0, pdfCount = 0;

            for (let idx = 0; idx < validFiles.length; idx++) {
                const file = validFiles[idx];
                const ext = file.name.toLowerCase().split('.').pop();

                progressText.textContent = `Procesando: ${file.name}`;
                progressCount.textContent = `${idx + 1}/${validFiles.length}`;
                progressBar.style.width = `${((idx + 1) / validFiles.length * 100).toFixed(0)}%`;

                try {
                    if (ext === 'xml') {
                        await procesarXML(file);
                        xmlCount++;
                    } else {
                        // PDF fallback
                        const tokens = await extraerTodoElTexto(file);
                        debugTexts.push({ name: file.name, tokens, tipo: 'PDF' });
                        analizarContenidoFEL(tokens);
                        pdfCount++;
                    }
                } catch (err) {
                    console.error(`Error procesando ${file.name}:`, err);
                    debugTexts.push({ name: file.name, tokens: [`ERROR: ${err.message}`], tipo: ext.toUpperCase() });
                }
            }

            // Hide progress, show results
            progressCont.classList.add('hidden');
            mostrarResultados();
            mostrarDebug();

            // Show format info
            if (xmlCount > 0) {
                const msg = pdfCount > 0 
                    ? `${xmlCount} XML (exacto) + ${pdfCount} PDF (heurístico)` 
                    : `${xmlCount} XML procesados con datos 100% exactos`;
                console.log(`📊 Formato: ${msg}`);
            }
        }

        // ─────────────────────────────────────────────
        //  XML FEL PARSER (Guatemala DTE)
        // ─────────────────────────────────────────────
        async function procesarXML(file) {
            const text = await file.text();
            const parser = new DOMParser();
            const xmlDoc = parser.parseFromString(text, 'text/xml');

            // Check for parse errors
            const parseError = xmlDoc.querySelector('parsererror');
            if (parseError) throw new Error('XML inválido: ' + parseError.textContent.substring(0, 100));

            // ── Helper: Find elements ignoring namespace prefix ──
            function findElements(parent, localName) {
                // Try with common DTE namespaces
                const namespaces = [
                    'http://www.sat.gob.gt/dte/fel/0.2.0',
                    'http://www.sat.gob.gt/dte/fel/0.1.0',
                    'http://www.sat.gob.gt/dte/fel/ComprobantesElectronicos/0.2.0',
                    'http://www.sat.gob.gt/dte/fel/ComprobantesElectronicos/0.1.0',
                    ''
                ];
                for (const ns of namespaces) {
                    const els = parent.getElementsByTagNameNS(ns, localName);
                    if (els.length > 0) return Array.from(els);
                }
                // Fallback: search by local name (strip namespace)
                const all = parent.getElementsByTagName('*');
                const results = [];
                for (let i = 0; i < all.length; i++) {
                    if (all[i].localName === localName) results.push(all[i]);
                }
                return results;
            }

            function findElement(parent, localName) {
                const els = findElements(parent, localName);
                return els.length > 0 ? els[0] : null;
            }

            function getAttr(el, ...names) {
                if (!el) return '';
                for (const name of names) {
                    const val = el.getAttribute(name);
                    if (val) return val.trim();
                }
                return '';
            }

            // ── Extract header data ──
            const emisorEl = findElement(xmlDoc, 'Emisor');
            const receptorEl = findElement(xmlDoc, 'Receptor');
            const datosGeneralesEl = findElement(xmlDoc, 'DatosGenerales');
            const certificacionEl = findElement(xmlDoc, 'NumeroAutorizacion');

            const emisorNombre = getAttr(emisorEl, 'NombreComercial', 'NombreEmisor') || 'Desconocido';
            const emisorNIT = getAttr(emisorEl, 'NITEmisor');
            const fechaEmision = getAttr(datosGeneralesEl, 'FechaHoraEmision');
            
            // UUID / Número de Autorización
            let numAutorizacion = 'S/N';
            if (certificacionEl) {
                numAutorizacion = certificacionEl.textContent?.trim() || getAttr(certificacionEl, 'Numero') || 'S/N';
            }
            // Also try from Certificacion element
            if (numAutorizacion === 'S/N') {
                const certEl = findElement(xmlDoc, 'Certificacion');
                if (certEl) {
                    const numAuth = findElement(certEl, 'NumeroAutorizacion');
                    if (numAuth) numAutorizacion = numAuth.textContent?.trim() || 'S/N';
                }
            }

            // Format date
            let fechaFormateada = 'S/F';
            if (fechaEmision) {
                try {
                    const d = new Date(fechaEmision);
                    if (!isNaN(d)) {
                        fechaFormateada = `${String(d.getDate()).padStart(2,'0')}-${String(d.getMonth()+1).padStart(2,'0')}-${d.getFullYear()}`;
                    } else {
                        fechaFormateada = fechaEmision.split('T')[0];
                    }
                } catch(e) {
                    fechaFormateada = fechaEmision.split('T')[0] || 'S/F';
                }
            }

            // ── Extract items ──
            const items = findElements(xmlDoc, 'Item');
            const debugLines = [
                `EMISOR: ${emisorNombre} (NIT: ${emisorNIT})`,
                `FECHA: ${fechaFormateada}`,
                `UUID: ${numAutorizacion}`,
                `ITEMS: ${items.length} productos encontrados`,
                '---'
            ];

            items.forEach((item, idx) => {
                const cantidad = parseFloat(findElement(item, 'Cantidad')?.textContent || '0');
                const descripcion = (findElement(item, 'Descripcion')?.textContent || '').trim();
                const precioUnitario = parseFloat(findElement(item, 'PrecioUnitario')?.textContent || '0');
                const descuento = parseFloat(findElement(item, 'Descuento')?.textContent || '0');
                const total = parseFloat(findElement(item, 'Total')?.textContent || '0');
                const bienOServicio = getAttr(item, 'BienOServicio');

                if (!descripcion || cantidad <= 0) return;

                // Detect bonificaciones
                let esBonif = false;
                if (total < 0.01) {
                    if (descripcion.includes('*') || descuento > 0 || precioUnitario === 0) {
                        esBonif = true;
                    }
                }

                // Detect taxes / IVA zero
                const impuestos = findElements(item, 'Impuesto');
                let esExento = true; // Assume exento until proven otherwise (if IVA found)
                let tieneIVA = false;
                
                impuestos.forEach(imp => {
                    const nombre = findElement(imp, 'NombreCorto')?.textContent || '';
                    if (nombre.toUpperCase() === 'IVA') {
                        tieneIVA = true;
                        const monto = parseFloat(findElement(imp, 'MontoImpuesto')?.textContent || '0');
                        const codigoExento = findElement(imp, 'CodigoUnidadGravable')?.textContent === '2';
                        if (monto > 0 && !codigoExento) {
                            esExento = false;
                        }
                    }
                });
                
                // If no IVA found, it's not strictly "exento" in the way the user wants to highlight
                if (!tieneIVA) esExento = false;

                debugLines.push(`[${idx+1}] ${descripcion} | Cant: ${cantidad} | P.U: Q${precioUnitario} | Desc: Q${descuento} | Total: Q${total}${esBonif ? ' [BONIF]' : ''}${esExento ? ' [EXENTO]' : ''}`);

                const producto = {
                    descripcion: descripcion.replace(/^\*+/, '').trim(),
                    cantidad: cantidad,
                    precioUnitario: precioUnitario,
                    descuento: descuento,
                    totalLinea: total,
                    esBonificacion: esBonif,
                    esExento: esExento
                };

                agregarAlInventario(producto, emisorNombre, fechaFormateada, numAutorizacion);
            });

            debugTexts.push({ name: file.name, tokens: debugLines, tipo: 'XML ✅' });
        }

        // ─────────────────────────────────────────────
        //  PDF TEXT EXTRACTION (fallback)
        // ─────────────────────────────────────────────
        async function extraerTodoElTexto(file) {
            const arrayBuffer = await file.arrayBuffer();
            const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
            let allTokens = [];

            for (let p = 1; p <= pdf.numPages; p++) {
                const page = await pdf.getPage(p);
                const content = await page.getTextContent();
                const pageTokens = content.items
                    .map(item => item.str.trim())
                    .filter(s => s.length > 0);
                allTokens.push(...pageTokens);
            }
            return allTokens;
        }

        // ─────────────────────────────────────────────
        //  FEL CONTENT ANALYSIS (multi-strategy)
        // ─────────────────────────────────────────────
        function analizarContenidoFEL(tokens) {
            let emisor = "Desconocido";
            let fechaDoc = "S/F";
            let numFactura = "S/N";

            // ── 1. Robust Header Data Extraction ──

            // Strategy A: Standard FEL format often places the company name at the very top (first token).
            if (tokens.length > 0) {
                const first = tokens[0].trim();
                // A company name is usually long, starts with letters, and doesn't contain dashes like a UUID.
                if (first.length > 10 && !first.includes("-") && isNaN(first.charAt(0))) {
                    emisor = first;
                }
            }

            for (let i = 0; i < tokens.length; i++) {
                const t = tokens[i].toUpperCase();

                // Strategy B: Search after NIT EMISOR
                if (t.includes("NIT EMISOR")) {
                    for (let j = i + 1; j < Math.min(i + 15, tokens.length); j++) {
                        const candidate = tokens[j].trim();
                        const canUp = candidate.toUpperCase();

                        // Ignore labels, numbers, and UUIDs (which contain dashes)
                        if (candidate.length > 5 &&
                            isNaN(candidate.replace(/[-\s]/g, '')) &&
                            !canUp.includes("NOMBRE RECEPTOR") &&
                            !canUp.includes("NIT RECEPTOR") &&
                            !candidate.includes("-")
                        ) {
                            // If Strategy A failed or we found a longer name here, use it.
                            if (emisor === "Desconocido" || candidate.length > emisor.length) {
                                emisor = candidate;
                            }
                            break;
                        }
                    }
                }

                // Authorization Number: Look for UUID pattern (detect by dashes and length)
                if (t.includes("AUTORIZACI") && t.includes("N") && t.includes("MERO")) {
                    for (let j = Math.max(0, i - 1); j < Math.min(i + 8, tokens.length); j++) {
                        const val = tokens[j].trim();
                        // UUID format (8-4-4-4-12)
                        if (val.split('-').length === 5 && val.length > 20) {
                            numFactura = val;
                            break;
                        }
                    }
                }
            }

            // ── 2. Extract Date ──
            // Strategy A: Look for "Fecha y hora de emision"
            for (let i = 0; i < tokens.length; i++) {
                const t = tokens[i].toLowerCase();
                if (t.includes("fecha") && (t.includes("emisi") || t.includes("emisión"))) {
                    // Check same token after colon
                    if (tokens[i].includes(":")) {
                        const afterColon = tokens[i].split(":").slice(1).join(":").trim();
                        if (afterColon.length >= 8) {
                            fechaDoc = afterColon.split(' ')[0];
                            break;
                        }
                    }
                    // Check next tokens for date pattern
                    for (let j = i + 1; j < Math.min(i + 4, tokens.length); j++) {
                        if (esFormatoFecha(tokens[j])) {
                            fechaDoc = tokens[j].split(' ')[0];
                            break;
                        }
                    }
                    if (fechaDoc !== "S/F") break;
                }
            }

            // Strategy B: Scan all tokens for dd-mmm-yyyy or dd/mm/yyyy pattern
            if (fechaDoc === "S/F") {
                for (let i = 0; i < tokens.length; i++) {
                    if (esFormatoFecha(tokens[i])) {
                        fechaDoc = tokens[i].split(' ')[0];
                        break;
                    }
                }
            }

            // ── 3. Extract Products with robust anchor detection ──
            for (let i = 0; i < tokens.length; i++) {
                const tokenRaw = tokens[i].trim();
                // Check if token IS "Bien" or "Servicio" (case-insensitive)
                if (!/^(bien|servicio)$/i.test(tokenRaw)) continue;

                try {
                    const producto = extraerProductoFEL(tokens, i);
                    if (producto) {
                        agregarAlInventario(producto, emisor, fechaDoc, numFactura);
                    }
                } catch (e) {
                    console.error("Error en fila:", e);
                }
            }
        }

        // ── Unified product extraction based on Visual FEL standard ──
        function extraerProductoFEL(tokens, i) {
            // Rule: Column layout is #No (i-1), B/S (i), Cantidad (i+1), Descripcion (i+2...)
            const cantToken = tokens[i + 1];
            const cant = parseNumero(cantToken);

            // If i+1 is not a number, maybe the PDF extraction swapped #No and Cantidad?
            // But based on user image, B/S is 2nd column, Cantidad is 3rd.
            if (cant === null || cant <= 0) return null;

            // Rule: Description tokens start at i + 2. We search for the Price column.
            let pUnitIdx = -1;
            let descTokens = [];

            // Search for the Price column (j) where (Price * Cant) - Discount = Total
            // We search from i + 2 forward
            for (let j = i + 2; j < Math.min(i + 25, tokens.length); j++) {
                const pUnit = parseNumero(tokens[j]);
                if (pUnit !== null && !esFormatoFecha(tokens[j])) {
                    // Pattern: [P.Unit] [Descuento] [Total]
                    const descVal = parseNumero(tokens[j + 1]);
                    const totalVal = parseNumero(tokens[j + 2]);

                    if (descVal !== null && totalVal !== null) {
                        // MATH VALIDATION: (P.Unit * Cant) - Discount = Total
                        const expectedTotal = (pUnit * cant) - descVal;
                        if (Math.abs(expectedTotal - totalVal) < 0.1) {
                            pUnitIdx = j;
                            break;
                        }
                    }
                }
                descTokens.push(tokens[j]);
            }

            if (pUnitIdx === -1 || descTokens.length === 0) return null;

            const fullDesc = descTokens.join(" ").trim();
            const precioUnitario = parseNumero(tokens[pUnitIdx]);
            const descuento = parseNumero(tokens[pUnitIdx + 1]);
            const totalLinea = parseNumero(tokens[pUnitIdx + 2]);

            // Bonificacion logic
            let esBonif = false;
            if (totalLinea < 0.01) {
                if (fullDesc.includes("*") || descuento > 0) {
                    esBonif = true;
                }
            }

            return {
                descripcion: fullDesc.replace(/^\*+/, '').trim(),
                cantidad: cant,
                precioUnitario: precioUnitario,
                descuento: descuento || 0,
                totalLinea: totalLinea,
                esBonificacion: esBonif
            };
        }

        // ─────────────────────────────────────────────
        //  HELPERS
        // ─────────────────────────────────────────────

        function parseNumero(str) {
            if (!str || typeof str !== 'string') return null;

            // Remove currency symbols and formatting commas
            let cleaned = str.replace(/[Q\$€,]/g, '').trim();
            if (cleaned === '' || cleaned === '-') return null;

            // If it contains letters (except 'e' for scientific, but not in FEL), skip it
            if (/[a-zA-Z]/.test(cleaned)) return null;

            const val = parseFloat(cleaned);
            return isNaN(val) ? null : val;
        }

        function esFormatoFecha(str) {
            if (!str) return false;
            return /\d{1,2}[-\/]\w{2,10}[-\/]\d{2,4}/.test(str) ||
                /\d{4}[-\/]\d{1,2}[-\/]\d{1,2}/.test(str);
        }

        function esAncla(str) {
            if (!str) return false;
            const anchors = ['bien', 'servicio', 'cantidad', 'precio', 'total', 'nit', 'emisor',
                'receptor', 'descripcion', 'unidad', 'medida', 'descuento', '#no',
                'gravable', 'exento', 'iva', 'impuesto', 'moneda', 'gtq', 'quetzal'];
            return anchors.includes(str.toLowerCase().trim());
        }

        function agregarAlInventario(producto, emisor, fecha, numFactura) {
            const key = producto.descripcion.toUpperCase().trim();

            if (inventario[key]) {
                inventario[key].cantidadTotal += producto.cantidad;
                inventario[key].totalPagado += producto.totalLinea;
                inventario[key].consolidado = true;
                if (producto.esBonificacion) {
                    inventario[key].cantidadBonif += producto.cantidad;
                    inventario[key].tieneBonificacion = true;
                }
                // Keep most recent data
                if (compararFechas(fecha, inventario[key].fecha) > 0) {
                    inventario[key].fecha = fecha;
                    inventario[key].numFactura = numFactura; // Keep last invoice number
                }
            } else {
                inventario[key] = {
                    emisor,
                    numFactura,
                    descripcion: producto.descripcion.trim(),
                    cantidadTotal: producto.cantidad,
                    cantidadBonif: producto.esBonificacion ? producto.cantidad : 0,
                    totalPagado: producto.totalLinea,
                    precioOriginal: producto.precioUnitario,
                    fecha: fecha,
                    consolidado: false,
                    tieneBonificacion: producto.esBonificacion,
                    esExento: producto.esExento
                };
            }
        }


        function compararFechas(fechaA, fechaB) {
            // Simple comparison - try to parse dates
            try {
                const a = new Date(fechaA);
                const b = new Date(fechaB);
                if (!isNaN(a) && !isNaN(b)) return a - b;
            } catch (e) { }
            // Fallback: string comparison
            return fechaA > fechaB ? 1 : -1;
        }

        // ─────────────────────────────────────────────
        //  DISPLAY RESULTS
        // ─────────────────────────────────────────────
        function mostrarResultados() {
            resultadoBody.innerHTML = '';
            const items = Object.values(inventario);

            if (items.length === 0) {
                resultadoBody.innerHTML = `
                    <tr><td colspan="8" class="px-6 py-20 text-center">
                        <div class="flex flex-col items-center gap-3">
                            <div class="w-14 h-14 rounded-full bg-red-500/10 flex items-center justify-center">
                                <svg class="w-7 h-7 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"/>
                                </svg>
                            </div>
                            <p class="text-red-400 font-semibold">No se detectaron productos</p>
                            <p class="text-slate-600 text-xs max-w-md">Verifica que tus archivos sean facturas FEL de Guatemala. Usa <span class="text-emerald-500">XML para datos exactos</span> o PDF como alternativa. Revisa el debug para más detalles.</p>
                        </div>
                    </td></tr>`;
                debugSection.classList.remove('hidden');
                return;
            }

            // Show buttons and stats
            btnExport.classList.remove('hidden');
            btnSaveDB.classList.remove('hidden');
            btnClear.classList.remove('hidden');
            statsRow.classList.remove('hidden');
            debugSection.classList.remove('hidden');

            // Calculate stats
            const consolidados = items.filter(i => i.consolidado).length;
            const conBonif = items.filter(i => i.tieneBonificacion).length;
            const granTotal = items.reduce((sum, i) => sum + i.totalPagado, 0);
            document.getElementById('statFacturas').textContent = totalFacturas;
            document.getElementById('statProductos').textContent = items.length;
            document.getElementById('statConsolidados').textContent = consolidados;
            document.getElementById('statBonif').textContent = conBonif;
            document.getElementById('statTotal').textContent = `Q${formatMoney(granTotal)}`;

            // Sort: by provider (emisor) first, then by date within each provider
            items.sort((a, b) => {
                // Primary: sort by provider name alphabetically
                const provComp = a.emisor.localeCompare(b.emisor, 'es', { sensitivity: 'base' });
                if (provComp !== 0) return provComp;
                // Secondary: sort by date ascending within same provider
                return compararFechas(a.fecha, b.fecha);
            });

            // Track current provider for group headers
            let currentEmisor = null;
            processedItems = [...items]; // Cache sorted items for robust detail lookups

            items.forEach((item, idx) => {
                // ── Provider group header ──
                if (item.emisor !== currentEmisor) {
                    currentEmisor = item.emisor;
                    const provItems = items.filter(i => i.emisor === currentEmisor);
                    const provTotal = provItems.reduce((sum, i) => sum + i.totalPagado, 0);
                    const provCount = provItems.length;

                    const headerRow = document.createElement('tr');
                    headerRow.className = 'row-enter';
                    headerRow.style.animationDelay = `${Math.min(idx * 30, 500)}ms`;
                    headerRow.innerHTML = `
                        <td colspan="7" class="px-5 py-3 bg-gradient-to-r from-cyan-500/10 via-transparent to-transparent border-l-4 border-cyan-400">
                            <div class="flex items-center justify-between">
                                <div class="flex items-center gap-3">
                                    <span class="text-base">🏢</span>
                                    <span class="text-sm font-bold text-cyan-300">${escapeHtml(currentEmisor)}</span>
                                    <span class="text-[10px] text-slate-500 font-mono bg-slate-800/60 px-2 py-0.5 rounded-full">${provCount} producto${provCount !== 1 ? 's' : ''}</span>
                                </div>
                                <span class="text-xs font-bold text-cyan-400 font-mono">Subtotal: Q${formatMoney(provTotal)}</span>
                            </div>
                        </td>
                    `;
                    resultadoBody.appendChild(headerRow);
                }

                const costoReal = item.cantidadTotal > 0 ? item.totalPagado / item.cantidadTotal : 0;
                const delay = Math.min(idx * 30, 500);
                let rowClass = '';
                if (item.tieneBonificacion) rowClass = 'bonif-row';
                else if (item.esExento) rowClass = 'exento-row';
                else if (item.consolidado) rowClass = 'consolidated-row';

                // Badges
                let badges = '';
                if (item.esExento) badges += `<span class="px-2 py-0.5 rounded-md text-[9px] font-black tracking-tighter badge-exento ml-2 uppercase">Exento</span>`;
                if (item.tieneBonificacion) badges += `<span class="text-base ml-1" title="Incluye ${item.cantidadBonif} unidades bonificadas (gratis)">🎁</span>`;
                if (item.consolidado) badges += `<span class="text-base ml-1" title="Consolidado de varias facturas">📦</span>`;

                let subtags = [];
                if (item.consolidado) subtags.push('<span class="text-[9px] text-blue-400/70 font-medium uppercase tracking-tighter">CONSOLIDADO</span>');
                if (item.esExento) subtags.push('<span class="text-[9px] text-emerald-400/70 font-medium uppercase tracking-tighter">IVA CERO</span>');
                if (item.tieneBonificacion) subtags.push(`<span class="text-[9px] text-purple-400/70 font-medium uppercase tracking-tighter">+${item.cantidadBonif} BONIF GRATIS</span>`);

                const tr = document.createElement('tr');
                tr.id = `row-${idx}`;
                tr.className = `${rowClass} hover:bg-white/[0.03] transition-colors row-enter border-b border-slate-800/40`;
                tr.style.animationDelay = `${delay}ms`;
                tr.innerHTML = `
                    <td class="px-5 py-3.5 text-xs text-slate-600 font-mono">${idx + 1}</td>
                    <td class="px-5 py-3.5">
                        <span class="text-[10px] text-slate-200 font-bold leading-tight block max-w-[150px] truncate" title="${escapeHtml(item.emisor)}">${escapeHtml(item.emisor)}</span>
                        <span class="text-[9px] text-slate-500 font-mono block max-w-[120px] truncate mt-0.5" title="${item.numFactura}">${item.numFactura}</span>
                        <span class="text-[9px] text-slate-500 font-mono block mt-0.5 italic">${item.fecha}</span>
                    </td>
                    <td class="px-5 py-3.5">
                        <div class="flex items-center justify-between gap-2">
                            <div class="flex items-center gap-2">
                                <span class="font-semibold text-slate-200">${escapeHtml(item.descripcion)}</span>
                                ${badges}
                            </div>
                            <button onclick="mostrarModalDesglose(${idx})" title="Desglose Manual (Surtidos)" class="px-2 py-1 rounded-lg bg-slate-800 text-amber-400 hover:bg-amber-500/20 transition-all flex items-center gap-1 border border-amber-500/30 text-[10px] font-bold">
                                ✂️ <span class="uppercase tracking-tighter">Desglosar</span>
                            </button>
                        </div>
                        ${subtags.length ? '<div class="flex gap-2 mt-0.5">' + subtags.join('') + '</div>' : ''}
                    </td>
                    <td class="px-5 py-3.5 text-center">
                        <span class="font-bold text-white bg-slate-800 px-2.5 py-1 rounded-lg text-xs">${item.cantidadTotal % 1 === 0 ? item.cantidadTotal : item.cantidadTotal.toFixed(2)}</span>
                    </td>
                    <td class="px-5 py-3.5 text-center">
                        ${item.tieneBonificacion ? `<span class="text-purple-400 font-mono text-xs font-bold">${item.cantidadBonif}</span>` : '<span class="text-slate-700">—</span>'}
                    </td>
                    <td class="px-5 py-3.5 text-right">
                        <div class="flex flex-col gap-0.5">
                            <span class="text-lime-400 font-mono text-xs font-bold">Q${formatMoney(costoReal)} <small class="text-[10px] text-slate-600 font-normal">Ud.</small></span>
                            <span class="font-bold text-emerald-400 font-mono text-xs">Q${formatMoney(item.totalPagado)}</span>
                        </div>
                        ${item.tieneBonificacion && item.precioOriginal !== costoReal ? `<span class="text-[9px] text-slate-600 line-through">Q${formatMoney(item.precioOriginal)}</span>` : ''}
                    </td>
                    <td class="px-5 py-3.5">
                        <div class="flex items-center gap-2">
                            <div class="relative flex-grow">
                                <input type="text" 
                                       id="input-assign-${idx}"
                                       onkeyup="buscarProductoAsignar(this.value, '${idx}')"
                                       placeholder="Código o nombre..."
                                       class="w-full bg-slate-900 border border-slate-700/50 rounded-lg px-3 py-1.5 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-blue-500/50 transition-all">
                                <div id="results-${idx}" class="absolute top-full left-0 right-0 z-50 mt-1 hidden max-h-40 overflow-y-auto glass border border-slate-700 rounded-lg shadow-2xl"></div>
                            </div>
                            <button onclick="mostrarModalNuevoProducto(${idx})" 
                                    class="w-8 h-8 rounded-lg bg-emerald-500/10 text-emerald-400 border border-emerald-500/30 flex items-center justify-center hover:bg-emerald-500 hover:text-white transition-all shrink-0" 
                                    title="Registrar nuevo producto">
                                ＋
                            </button>
                        </div>
                    </td>
                `;
                resultadoBody.appendChild(tr);

                // Placeholder for detail row (initially hidden)
                const detailTr = document.createElement('tr');
                detailTr.id = `detail-row-${idx}`;
                detailTr.className = 'hidden detail-assign-row';
                detailTr.innerHTML = `<td colspan="7" id="detail-content-${idx}" class="px-4 py-6"></td>`;
                resultadoBody.appendChild(detailTr);

                // Auto-mapeo tras desglose (Estado-base, no índice-base)
                if (item._autoConfig && item._autoConfig.product) {
                    const prod = item._autoConfig.product;
                    const input = document.getElementById(`input-assign-${idx}`);
                    if (input) input.value = prod.CodigoInterno || prod.NombreComercial;
                    
                    const forcedLugarId = item.lugar_compra_id || item.lugarCompraId || getIdLugarByNombre(item.emisor);
                    mostrarDetalleAsignacion(idx, prod, costoReal, item.esExento, item.descripcion, forcedLugarId);
                    
                    detailTr.classList.remove('hidden');
                    delete item._autoConfig;
                } else {
                    obtenerMappingParaFila(item.descripcion, idx, costoReal, item.esExento, item.emisor);
                }
            });

            // Grand total row
            const totalRow = document.createElement('tr');
            totalRow.className = 'bg-slate-800/50 border-t-2 border-emerald-500/30';
            totalRow.innerHTML = `
                <td colspan="5" class="px-5 py-4 text-right text-xs uppercase tracking-widest text-slate-400 font-bold">Gran Total</td>
                <td class="px-5 py-4 text-right">
                    <span class="font-black text-emerald-400 text-base font-mono">Q${formatMoney(granTotal)}</span>
                </td>
                <td></td>
            `;
            resultadoBody.appendChild(totalRow);
        }

        function formatMoney(val) {
            return val.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
        }

        // buscarCandidatosDB removed.


        function escapeHtml(str) {
            if (!str) return '';
            const div = document.createElement('div');
            div.textContent = str;
            return div.innerHTML;
        }

        // ─────────────────────────────────────────────
        //  DEBUG LOG
        // ─────────────────────────────────────────────
        function mostrarDebug() {
            debugLog.innerHTML = '';
            debugTexts.forEach(d => {
                debugLog.innerHTML += `<div class="mb-4"><strong class="text-emerald-500">📄 ${escapeHtml(d.name)}</strong>\n`;
                debugLog.innerHTML += d.tokens.map((t, i) => `  [${i}] "${escapeHtml(t)}"`).join('\n');
                debugLog.innerHTML += '\n</div>';
            });
        }

        // ─────────────────────────────────────────────
        //  CLEAR
        // ─────────────────────────────────────────────
        function limpiarTodo() {
            inventario = {};
            totalFacturas = 0;
            debugTexts = [];
            resultadoBody.innerHTML = `
                <tr><td colspan="7" class="px-6 py-24 text-center">
                    <div class="flex flex-col items-center gap-3">
                        <div class="w-16 h-16 rounded-full bg-slate-800/50 flex items-center justify-center">
                            <svg class="w-8 h-8 text-slate-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/>
                            </svg>
                        </div>
                        <p class="text-slate-600 text-sm">Esperando documentos para analizar...</p>
                    </div>
                </td></tr>`;
            btnExport.classList.add('hidden');
            btnSaveDB.classList.add('hidden');
            btnClear.classList.add('hidden');
            statsRow.classList.add('hidden');
            debugSection.classList.add('hidden');
            debugLog.innerHTML = '';
            fileInput.value = '';
        }

        // ─────────────────────────────────────────────
        //  EXPORT TO EXCEL
        // ─────────────────────────────────────────────
        function exportarExcel() {
            const items = Object.values(inventario);
            if (items.length === 0) return;

            const data = items.map(item => {
                const costoReal = item.cantidadTotal > 0 ? item.totalPagado / item.cantidadTotal : 0;
                return {
                    'Proveedor': item.emisor,
                    'Factura #': item.numFactura,
                    'Producto': item.descripcion,
                    'Tipo': item.tieneBonificacion ? 'CON BONIF 🎁' : (item.consolidado ? 'CONSOLIDADO 📦' : 'Individual'),
                    'IVA': item.esExento ? 'EXENTO' : 'Gravable',
                    'Cant. Total': item.cantidadTotal,
                    'Bonificadas': item.cantidadBonif || 0,
                    'Costo Real U.': parseFloat(costoReal.toFixed(4)),
                    'Total Pagado': parseFloat(item.totalPagado.toFixed(2)),
                    'Fecha': item.fecha
                };
            });

            const granTotal = items.reduce((s, i) => s + i.totalPagado, 0);
            data.push({ 'Proveedor': '', 'Producto': '', 'Tipo': '', 'Cant. Total': '', 'Bonificadas': '', 'Costo Real U.': 'GRAN TOTAL:', 'Total Pagado': parseFloat(granTotal.toFixed(2)), 'Fecha': '' });

            const ws = XLSX.utils.json_to_sheet(data);
            ws['!cols'] = [{ wch: 25 }, { wch: 30 }, { wch: 16 }, { wch: 12 }, { wch: 12 }, { wch: 14 }, { wch: 14 }, { wch: 14 }];

            const wb = XLSX.utils.book_new();
            XLSX.utils.book_append_sheet(wb, ws, "Inventario Grupo Zoe");

            const today = new Date();
            const dateStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
            XLSX.writeFile(wb, `Reporte_GrupoZoe_${dateStr}.xlsx`);
        }

        async function guardarEnBD() {
            const items = Object.values(inventario);
            if (items.length === 0) {
                mostrarNotificacion('error', 'Sin datos', 'No hay productos para guardar');
                return;
            }
            // Show the libro selection modal
            mostrarModalSeleccionLibro();
        }

        // ── MODAL: Selección de Libro al Guardar ──
        async function mostrarModalSeleccionLibro() {
            // Fetch existing libros
            let librosData = [];
            try {
                const res = await fetch('api/consolidador/libro.php?action=list_libros');
                const data = await res.json();
                if (data.success) librosData = data.data;
            } catch(e) { console.error(e); }

            const modal = document.createElement('div');
            modal.id = 'modalLibroSelect';
            modal.className = 'fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm modal-overlay';
            modal.onclick = (e) => { if (e.target === modal) modal.remove(); };

            const colores = ['#10b981','#3b82f6','#a855f7','#f59e0b','#ef4444','#ec4899','#06b6d4','#84cc16'];

            const librosListHTML = librosData.length > 0 ? librosData.map(l => `
                <div class="option-card flex items-center gap-3 p-3 rounded-xl bg-slate-800/30 border border-slate-700/50 hover:border-emerald-500/40"
                     onclick="seleccionarLibroExistente(${l.id}, '${escapeHtml(l.nombre)}', this)">
                    <div class="w-8 h-8 rounded-lg flex-shrink-0 flex items-center justify-center text-sm" style="background:${l.color || '#10b981'}20; color:${l.color || '#10b981'}">📖</div>
                    <div class="flex-grow min-w-0">
                        <p class="text-sm font-bold text-slate-200 truncate">${escapeHtml(l.nombre)}</p>
                        <p class="text-[10px] text-slate-500">${l.total_hojas} hojas · Q${formatMoney(parseFloat(l.total_invertido || 0))}</p>
                    </div>
                    <div class="w-5 h-5 rounded-full border-2 border-slate-600 flex-shrink-0 libro-radio"></div>
                </div>
            `).join('') : '<p class="text-sm text-slate-600 text-center py-4">No hay libros creados aún</p>';

            modal.innerHTML = `
                <div class="glass rounded-2xl p-6 max-w-lg w-full mx-4 max-h-[85vh] overflow-y-auto animate-fade-in-up">
                    <div class="flex justify-between items-center mb-5">
                        <div>
                            <h3 class="text-lg font-bold text-white">💾 Guardar Importación</h3>
                            <p class="text-xs text-slate-500 mt-0.5">${Object.keys(inventario).length} productos listos para guardar</p>
                        </div>
                        <button onclick="document.getElementById('modalLibroSelect').remove()" class="text-slate-500 hover:text-white text-xl transition-colors">✕</button>
                    </div>

                    <!-- Opciones -->
                    <div class="space-y-3 mb-5">
                        <!-- Opción: Solo guardar sin agregar a libro -->
                        <div class="option-card p-4 rounded-xl bg-slate-800/30 border border-slate-700/50" onclick="selectSaveMode('solo', this)">
                            <div class="flex items-center gap-3">
                                <div class="w-10 h-10 rounded-xl bg-blue-500/10 flex items-center justify-center text-lg">💾</div>
                                <div>
                                    <p class="text-sm font-bold text-slate-200">Solo guardar en historial</p>
                                    <p class="text-[10px] text-slate-500">Guardar sin agregar a ningún libro</p>
                                </div>
                            </div>
                        </div>

                        <!-- Opción: Crear libro nuevo -->
                        <div class="option-card p-4 rounded-xl bg-slate-800/30 border border-slate-700/50" onclick="selectSaveMode('nuevo', this)">
                            <div class="flex items-center gap-3">
                                <div class="w-10 h-10 rounded-xl bg-emerald-500/10 flex items-center justify-center text-lg">📗</div>
                                <div>
                                    <p class="text-sm font-bold text-slate-200">Crear un Libro Nuevo</p>
                                    <p class="text-[10px] text-slate-500">Crear un libro y agregar esta importación como primera hoja</p>
                                </div>
                            </div>
                        </div>

                        <!-- Campos libro nuevo (hidden initially) -->
                        <div id="nuevoLibroFields" class="hidden pl-4 space-y-3 border-l-2 border-emerald-500/30 ml-5 animate-fade-in-up">
                            <input type="text" id="inputNuevoLibroNombre" placeholder="Nombre del libro (ej: Compras Abril 2026)"
                                class="w-full bg-slate-900/50 border border-slate-700 rounded-xl py-3 px-4 text-white text-sm placeholder-slate-500 focus:outline-none focus:border-emerald-500/50 focus:ring-4 focus:ring-emerald-500/10 transition-all">
                            <div class="flex items-center gap-2 flex-wrap">
                                <span class="text-[10px] text-slate-500 uppercase tracking-wider">Color:</span>
                                ${colores.map((c, i) => `<div class="color-swatch ${i===0?'active':''}" style="background:${c}" data-color="${c}" onclick="selectLibroColor(this, '${c}')"></div>`).join('')}
                            </div>
                        </div>

                        <!-- Opción: Agregar a existente -->
                        <div class="option-card p-4 rounded-xl bg-slate-800/30 border border-slate-700/50" onclick="selectSaveMode('existente', this)">
                            <div class="flex items-center gap-3">
                                <div class="w-10 h-10 rounded-xl bg-violet-500/10 flex items-center justify-center text-lg">📚</div>
                                <div>
                                    <p class="text-sm font-bold text-slate-200">Agregar a un Libro Existente</p>
                                    <p class="text-[10px] text-slate-500">Selecciona un libro para agregar esta importación</p>
                                </div>
                            </div>
                        </div>

                        <!-- Lista de libros existentes (hidden initially) -->
                        <div id="librosExistentesList" class="hidden pl-4 space-y-2 border-l-2 border-violet-500/30 ml-5 max-h-48 overflow-y-auto animate-fade-in-up">
                            ${librosListHTML}
                        </div>
                    </div>

                    <!-- Botón confirmar -->
                    <button id="btnConfirmGuardar" onclick="confirmarGuardado()" disabled
                        class="w-full py-3.5 rounded-xl text-sm font-bold text-white bg-gradient-to-r from-emerald-500 to-emerald-600 hover:from-emerald-400 hover:to-emerald-500 transition-all shadow-lg shadow-emerald-500/25 disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:from-emerald-500 disabled:hover:to-emerald-600">
                        Confirmar y Guardar
                    </button>
                </div>
            `;
            document.body.appendChild(modal);
        }

        // Modal state
        let _saveMode = null; // 'solo', 'nuevo', 'existente'
        let _selectedLibroId = null;
        let _selectedLibroColor = '#10b981';

        function selectSaveMode(mode, el) {
            _saveMode = mode;
            _selectedLibroId = null;

            // Reset all option cards
            document.querySelectorAll('#modalLibroSelect .option-card').forEach(c => c.classList.remove('selected'));
            el.classList.add('selected');

            // Show/hide sub-fields
            const nuevoFields = document.getElementById('nuevoLibroFields');
            const existenteList = document.getElementById('librosExistentesList');
            nuevoFields.classList.add('hidden');
            existenteList.classList.add('hidden');

            if (mode === 'nuevo') {
                nuevoFields.classList.remove('hidden');
                document.getElementById('inputNuevoLibroNombre').focus();
            } else if (mode === 'existente') {
                existenteList.classList.remove('hidden');
            }

            // Enable confirm button (unless mode=existente and no libro selected)
            document.getElementById('btnConfirmGuardar').disabled = (mode === 'existente');
        }

        function seleccionarLibroExistente(id, nombre, el) {
            _selectedLibroId = id;
            // Update radio visuals
            document.querySelectorAll('#librosExistentesList .libro-radio').forEach(r => {
                r.style.background = 'transparent';
                r.style.borderColor = '#475569';
            });
            const radio = el.querySelector('.libro-radio');
            radio.style.background = '#10b981';
            radio.style.borderColor = '#10b981';
            el.classList.add('selected');

            document.getElementById('btnConfirmGuardar').disabled = false;
        }

        function selectLibroColor(el, color) {
            _selectedLibroColor = color;
            document.querySelectorAll('#modalLibroSelect .color-swatch').forEach(s => s.classList.remove('active'));
            el.classList.add('active');
        }

        async function confirmarGuardado() {
            const items = Object.values(inventario);
            const btn = document.getElementById('btnConfirmGuardar');
            btn.innerHTML = '⏳ Guardando...';
            btn.disabled = true;

            try {
                const payload = {
                    totalFacturas: totalFacturas,
                    observaciones: '',
                    agregarAlLibro: _saveMode !== 'solo',
                    crear_libro: _saveMode === 'nuevo',
                    libro_id: _saveMode === 'existente' ? _selectedLibroId : 0,
                    nombre_libro: _saveMode === 'nuevo' ? (document.getElementById('inputNuevoLibroNombre')?.value?.trim() || '') : '',
                    productos: items.map(item => ({
                        emisor: item.emisor,
                        numFactura: item.numFactura,
                        descripcion: item.descripcion,
                        cantidadTotal: item.cantidadTotal,
                        cantidadBonif: item.cantidadBonif || 0,
                        totalPagado: item.totalPagado,
                        precioOriginal: item.precioOriginal,
                        tieneBonificacion: item.tieneBonificacion || false,
                        consolidado: item.consolidado || false,
                        esExento: item.esExento || false,
                        fecha: item.fecha
                    }))
                };

                if (_saveMode === 'nuevo' && !payload.nombre_libro) {
                    mostrarNotificacion('error', 'Falta el nombre', 'Escribe un nombre para el nuevo libro');
                    btn.innerHTML = 'Confirmar y Guardar';
                    btn.disabled = false;
                    return;
                }

                const response = await fetch('api/consolidador/guardar.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(payload)
                });
                const result = await response.json();

                if (result.success) {
                    document.getElementById('modalLibroSelect')?.remove();
                    mostrarNotificacion('success', '¡Guardado exitoso!', result.message);
                    cargarHistorial();
                } else {
                    throw new Error(result.error || 'Error desconocido');
                }
            } catch (err) {
                mostrarNotificacion('error', 'Error al guardar', err.message);
                btn.innerHTML = 'Confirmar y Guardar';
                btn.disabled = false;
            }
        }

        function mostrarNotificacion(tipo, titulo, mensaje) {
            const notif = document.getElementById('saveNotification');
            const icon = document.getElementById('saveNotifIcon');
            const titleEl = document.getElementById('saveNotifTitle');
            const msgEl = document.getElementById('saveNotifMsg');

            icon.textContent = tipo === 'success' ? '✅' : '❌';
            icon.className = `w-10 h-10 rounded-full flex items-center justify-center text-lg ${tipo === 'success' ? 'bg-emerald-500/20' : 'bg-red-500/20'}`;
            titleEl.textContent = titulo;
            msgEl.textContent = mensaje;

            notif.classList.remove('hidden');
            setTimeout(() => notif.classList.add('hidden'), 5000);
        }

        // ─────────────────────────────────────────────
        //  HISTORIAL
        // ─────────────────────────────────────────────
        async function cargarHistorial() {
            const body = document.getElementById('historialBody');
            try {
                const res = await fetch('api/consolidador/historial.php?limit=10');
                const data = await res.json();

                if (!data.success || !data.data || data.data.length === 0) {
                    body.innerHTML = '<p class="text-sm text-slate-600 text-center py-6">No hay importaciones registradas aún</p>';
                    return;
                }

                body.innerHTML = data.data.map(imp => `
                    <div class="flex items-center justify-between p-3 rounded-xl bg-slate-800/30 hover:bg-slate-800/50 transition-colors cursor-pointer group" onclick="verDetalle(${imp.id})">
                        <div class="flex items-center gap-3">
                            <div class="w-9 h-9 rounded-lg bg-blue-500/10 flex items-center justify-center text-sm">📋</div>
                            <div>
                                <p class="text-xs font-bold text-slate-300">Importación #${imp.id}</p>
                                <p class="text-[10px] text-slate-600 font-mono">${imp.fecha_importacion}</p>
                            </div>
                        </div>
                        <div class="flex items-center gap-4 text-right">
                            <div>
                                <p class="text-[10px] text-slate-500">${imp.total_productos} productos</p>
                                <p class="text-[10px] text-purple-400">${imp.total_bonificaciones || 0} bonif.</p>
                            </div>
                            <div>
                                <p class="text-xs font-bold text-emerald-400 font-mono">Q${parseFloat(imp.total_invertido).toFixed(2)}</p>
                                <p class="text-[10px] text-slate-600">${imp.total_facturas} facturas</p>
                            </div>
                            <span class="text-slate-600 group-hover:text-slate-400 transition-colors">→</span>
                        </div>
                    </div>
                `).join('');

            } catch (err) {
                body.innerHTML = `<p class="text-sm text-red-400/60 text-center py-6">Error al cargar historial: ${err.message}</p>`;
            }
        }

        let activeHistoryItems = [];

        async function verDetalle(id) {
            try {
                const res = await fetch(`api/consolidador/historial.php?id=${id}`);
                const data = await res.json();
                if (!data.success) return;

                const imp = data.data;
                const productos = imp.productos || [];
                activeHistoryItems = productos;

                const modal = document.createElement('div');
                modal.className = 'fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm';
                modal.id = `modal-history-${id}`;
                modal.onclick = (e) => { if (e.target === modal) modal.remove(); };

                modal.innerHTML = `
                    <div class="glass rounded-2xl p-5 max-w-[98%] w-full mx-4 max-h-[96vh] overflow-hidden flex flex-col animate-fade-in-up border border-white/10 shadow-2xl">
                        <div class="flex justify-between items-center mb-3 flex-shrink-0">
                            <div class="flex items-center gap-3">
                                <div class="w-10 h-10 rounded-xl bg-blue-500/10 flex items-center justify-center text-xl shadow-inner border border-white/5">📜</div>
                                <div>
                                    <h3 class="text-lg font-black text-white uppercase tracking-tight">Importación #${imp.id}</h3>
                                    <p class="text-[10px] text-slate-500 font-mono tracking-widest leading-none">${imp.fecha_importacion}</p>
                                </div>
                            </div>
                            <button onclick="this.closest('.fixed').remove()" class="w-8 h-8 rounded-full hover:bg-white/10 flex items-center justify-center text-slate-500 hover:text-white transition-all text-xl">✕</button>
                        </div>

                        <div class="grid grid-cols-3 gap-3 mb-4 flex-shrink-0">
                            <div class="bg-slate-900/60 border border-slate-700/30 rounded-2xl py-2 px-4 flex items-center justify-between shadow-lg">
                                <p class="text-[9px] text-slate-500 uppercase font-black tracking-widest">Productos</p>
                                <p class="text-xl font-black text-white leading-none">${imp.total_productos}</p>
                            </div>
                            <div class="bg-slate-900/60 border border-slate-700/30 rounded-2xl py-2 px-4 flex items-center justify-between shadow-lg">
                                <p class="text-[9px] text-slate-500 uppercase font-black tracking-widest">Bonificaciones</p>
                                <p class="text-xl font-black text-purple-400 leading-none">${imp.total_bonificaciones}</p>
                            </div>
                            <div class="bg-slate-900/60 border border-slate-700/30 rounded-2xl py-2 px-4 flex items-center justify-between shadow-lg">
                                <p class="text-[9px] text-slate-500 uppercase font-black tracking-widest">Total Inversión</p>
                                <p class="text-xl font-black text-emerald-400 font-mono leading-none">Q${formatMoney(parseFloat(imp.total_invertido))}</p>
                            </div>
                        </div>

                        <div class="flex-grow overflow-y-auto CustomScroll rounded-2xl border border-white/10 bg-slate-900/30">
                            <table class="w-full text-left border-collapse">
                                <thead class="sticky top-0 bg-slate-900/95 backdrop-blur-xl z-20 border-b border-white/10 shadow-xl">
                                    <tr>
                                        <th class="py-4 px-6 text-xs uppercase font-black text-slate-500 tracking-widest">Producto</th>
                                        <th class="py-4 px-6 text-xs uppercase font-black text-slate-500 tracking-widest">Proveedor</th>
                                        <th class="py-4 px-3 text-xs uppercase font-black text-slate-500 tracking-widest text-center">Cant.</th>
                                        <th class="py-4 px-6 text-xs uppercase font-black text-slate-500 tracking-widest text-right">Costo / Total</th>
                                        <th class="py-4 px-6 text-xs uppercase font-black text-slate-500 tracking-widest">Asignar / Código</th>
                                    </tr>
                                </thead>
                                <tbody class="divide-y divide-white/5">
                                    ${(() => {
                                        let currentProv = null;
                                        return productos.map((p, idx) => {
                                            let html = '';
                                            const prov = p.proveedor_nombre || 'S/P';
                                            
                                            if (prov !== currentProv) {
                                                currentProv = prov;
                                                const provItems = productos.filter(i => (i.proveedor_nombre || 'S/P') === currentProv);
                                                const provTotal = provItems.reduce((sum, i) => sum + parseFloat(i.total_pagado), 0);
                                                
                                                html += `
                                                    <tr class="bg-emerald-600 border-l-8 border-emerald-400">
                                                        <td colspan="5" class="px-6 py-3">
                                                            <div class="flex items-center justify-between">
                                                                <div class="flex items-center gap-4">
                                                                    <div class="w-10 h-10 rounded-xl bg-white/20 flex items-center justify-center text-xl shadow-inner border border-white/30 text-white">🏢</div>
                                                                    <div class="flex flex-col">
                                                                        <span class="text-sm font-black text-white uppercase tracking-tight">${escapeHtml(currentProv)}</span>
                                                                        <span class="text-[10px] text-emerald-100/80 font-mono italic uppercase tracking-widest">${provItems.length} registros en esta hoja</span>
                                                                    </div>
                                                                </div>
                                                                <div class="text-right">
                                                                    <p class="text-lg font-black text-white font-mono leading-none">Q${formatMoney(provTotal)}</p>
                                                                    <p class="text-[10px] text-emerald-200 uppercase font-black tracking-[0.2em] mt-1">SUBTOTAL PROVEEDOR</p>
                                                                </div>
                                                            </div>
                                                        </td>
                                                    </tr>
                                                `;
                                            }

                                            let rowClass = '';
                                            if (p.tiene_bonificacion == 1) rowClass = 'bg-purple-500/[0.05] border-l-4 border-purple-500/50';
                                            else if (p.es_exento == 1) rowClass = 'bg-amber-500/[0.05] border-l-4 border-amber-500/50';
                                            
                                            const isMapped = !!p.producto_id;
                                            const hIdx = `h-${idx}`;

                                            html += `
                                                <td class="py-6 px-6">
                                                    <div class="flex flex-col gap-2 text-wrap">
                                                        <div class="flex items-center justify-between gap-4">
                                                            <span class="text-sm font-bold text-slate-100 leading-tight">${escapeHtml(p.descripcion)}</span>
                                                            <button onclick="mostrarModalDesglose('${hIdx}')" title="Desglose Manual en Historial" class="px-2 py-1 rounded-lg bg-white/5 text-amber-500 hover:bg-amber-500/10 transition-all flex items-center gap-1 border border-amber-500/20 text-[10px] font-bold">
                                                                ✂️ <span class="uppercase tracking-tighter">Desglosar</span>
                                                            </button>
                                                        </div>
                                                        <div class="flex items-center gap-3">
                                                            ${p.es_exento == 1 ? '<span class="text-[10px] px-2 py-0.5 bg-amber-500/20 text-amber-400 rounded-md border border-amber-500/30 font-black">EXENTO</span>' : ''}
                                                            ${p.tiene_bonificacion == 1 ? '<span class="text-[10px] px-2 py-0.5 bg-purple-500/20 text-purple-400 rounded-md border border-purple-500/30 font-black">BONIFICADO</span>' : ''}
                                                            ${p.consolidado == 1 ? '<span class="text-[10px] px-2 py-0.5 bg-blue-500/20 text-blue-400 rounded-md border border-blue-500/30 font-black">CONSOLIDADO</span>' : ''}
                                                        </div>
                                                    </div>
                                                </td>
                                                <td class="py-6 px-6">
                                                    <span class="text-xs text-slate-400 font-bold uppercase block">${escapeHtml(prov)}</span>
                                                    <span class="text-[10px] text-slate-600 font-mono block mt-1" title="${p.numero_autorizacion}">${p.numero_autorizacion}</span>
                                                    <span class="text-[10px] text-slate-500 font-mono block mt-1 italic">${p.fecha_factura}</span>
                                                </td>
                                                <td class="py-6 px-3 text-center text-sm font-black text-white">${p.cantidad_total}</td>
                                                <td class="py-6 px-6 text-right">
                                                    <div class="flex flex-col gap-1">
                                                        <span class="text-xs text-lime-400 font-mono font-bold">Q${formatMoney(parseFloat(p.costo_real_unitario))} <small class="text-[10px] text-slate-500">Ud.</small></span>
                                                        <span class="text-lg font-black text-emerald-400 font-mono">Q${formatMoney(parseFloat(p.total_pagado))}</span>
                                                    </div>
                                                </td>
                                                <td class="py-6 px-6">
                                                    <div id="target-assign-${hIdx}" class="flex items-center gap-3">
                                                        ${isMapped ? `
                                                            <div class="flex items-center gap-3 px-4 py-2.5 rounded-xl bg-emerald-500/10 border border-emerald-500/20 group/tag shadow-sm">
                                                                <div class="flex flex-col">
                                                                    <span class="text-xs font-black text-emerald-400 leading-none mb-1 tracking-wider">${p.CodigoInterno}</span>
                                                                    <span class="text-[11px] text-emerald-500/70 font-bold truncate max-w-[250px] uppercase">${escapeHtml(p.maestro_nombre)}</span>
                                                                </div>
                                                                <button onclick="desvincularProducto('${escapeHtml(p.descripcion)}', 'h-${hIdx}')" 
                                                                        title="Desvincular producto"
                                                                        class="w-8 h-8 rounded-full bg-red-500/10 text-red-400 flex items-center justify-center opacity-0 group-hover/tag:opacity-100 transition-all hover:bg-red-500 hover:text-white">✕</button>
                                                            </div>
                                                        ` : `
                                                            <div class="flex items-center gap-3 w-full">
                                                                <div class="relative flex-grow">
                                                                    <input type="text" 
                                                                           id="input-assign-${hIdx}"
                                                                           onkeyup="buscarProductoAsignar(this.value, '${hIdx}')"
                                                                           placeholder="Vincular con catálogo..."
                                                                           class="w-full bg-slate-900/80 border border-slate-700/50 rounded-xl px-4 py-3 text-sm text-white placeholder-slate-600 focus:outline-none focus:border-emerald-500/50 focus:ring-4 focus:ring-emerald-500/10 transition-all shadow-inner">
                                                                    <div id="results-${hIdx}" class="absolute top-full left-0 right-0 z-50 mt-2 hidden max-h-60 overflow-y-auto glass border border-slate-700 shadow-2xl rounded-xl"></div>
                                                                </div>
                                                                <button onclick="mostrarModalNuevoProducto('${hIdx}')" 
                                                                        class="w-11 h-11 rounded-xl bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 flex items-center justify-center hover:bg-emerald-500 hover:text-white transition-all shadow-lg active:scale-95">＋</button>
                                                            </div>
                                                        `}
                                                    </div>
                                                </td>
                                            </tr>
                                            <tr id="detail-row-${hIdx}" class="hidden detail-assign-row bg-slate-900/50">
                                                <td colspan="5" id="detail-content-${hIdx}" class="px-8 py-10 border-b border-white/5 animate-fade-in"></td>
                                            </tr>
                                            `;
                                            return html;
                                        }).join('');
                                    })()}
                                </tbody>
                            </table>
                        </div>
                    </div>
                `;
                document.body.appendChild(modal);
            } catch (err) {
                mostrarNotificacion('error', 'Error', err.message);
            }
        }

        // ─────────────────────────────────────────────
        //  EL LIBRO LOGIC (Multi-Book)
        // ─────────────────────────────────────────────
        let _currentLibroId = null;

        function switchTab(tab) {
            const secAnalizador = document.getElementById('sectionAnalizador');
            const secLibro = document.getElementById('sectionLibro');
            const tabA = document.getElementById('tabAnalizador');
            const tabL = document.getElementById('tabLibro');

            if (tab === 'libro') {
                secAnalizador.classList.add('hidden');
                secLibro.classList.remove('hidden');
                tabL.className = 'px-4 py-2 rounded-lg text-xs font-bold transition-all bg-emerald-500 text-white shadow-lg shadow-emerald-500/20';
                tabA.className = 'px-4 py-2 rounded-lg text-xs font-bold transition-all text-slate-400 hover:text-white hover:bg-white/5';
                volverALibros();
            } else {
                secAnalizador.classList.remove('hidden');
                secLibro.classList.add('hidden');
                tabA.className = 'px-4 py-2 rounded-lg text-xs font-bold transition-all bg-emerald-500 text-white shadow-lg shadow-emerald-500/20';
                tabL.className = 'px-4 py-2 rounded-lg text-xs font-bold transition-all text-slate-400 hover:text-white hover:bg-white/5';
            }
        }

        async function cargarLibros() {
            const grid = document.getElementById('librosGrid');
            try {
                const res = await fetch('api/consolidador/libro.php?action=list_libros');
                const data = await res.json();
                if (!data.success || data.data.length === 0) {
                    grid.innerHTML = `<div class="col-span-full glass rounded-xl p-12 text-center">
                        <p class="text-slate-500 text-lg mb-2">📚</p>
                        <p class="text-slate-500 text-sm">No hay libros creados.</p>
                        <p class="text-slate-600 text-xs mt-1">Crea uno nuevo o agrega facturas desde el Analizador.</p>
                    </div>`;
                    return;
                }

                grid.innerHTML = data.data.map(libro => {
                    const color = libro.color || '#10b981';
                    return `
                    <div class="libro-card glass rounded-xl p-5 cursor-pointer flex flex-col gap-3 group" 
                         style="--libro-color: ${color}" onclick="abrirLibro(${libro.id}, '${escapeHtml(libro.nombre)}', '${color}')">
                        <div class="flex justify-between items-start">
                            <div class="w-10 h-10 rounded-lg flex items-center justify-center text-lg transition-all"
                                 style="background:${color}15; color:${color}">📖</div>
                            <div class="flex items-center gap-2">
                                <span class="text-[10px] text-slate-600 font-mono">${libro.total_hojas} hoja${libro.total_hojas != 1 ? 's' : ''}</span>
                                <button onclick="event.stopPropagation(); eliminarLibro(${libro.id}, '${escapeHtml(libro.nombre)}')" 
                                    class="w-7 h-7 rounded-lg flex items-center justify-center text-slate-600 hover:text-red-400 hover:bg-red-500/10 transition-all opacity-0 group-hover:opacity-100" title="Eliminar libro">
                                    🗑️
                                </button>
                            </div>
                        </div>
                        <div>
                            <p class="text-sm font-bold text-slate-200 group-hover:text-white transition-colors">${escapeHtml(libro.nombre)}</p>
                            ${libro.descripcion ? `<p class="text-[10px] text-slate-500 mt-0.5">${escapeHtml(libro.descripcion)}</p>` : ''}
                        </div>
                        <div class="flex justify-between items-end mt-auto pt-3 border-t border-slate-800/50">
                            <div>
                                <p class="text-[10px] text-slate-600">Productos</p>
                                <p class="text-xs font-bold text-white">${libro.total_productos}</p>
                            </div>
                            <div class="text-right">
                                <p class="text-[10px] text-slate-600">Total</p>
                                <p class="text-xs font-bold font-mono" style="color:${color}">Q${formatMoney(parseFloat(libro.total_invertido || 0))}</p>
                            </div>
                        </div>
                    </div>`;
                }).join('');
            } catch (err) {
                grid.innerHTML = `<p class="col-span-full text-center text-red-400">Error: ${err.message}</p>`;
            }
        }

        function abrirLibro(id, nombre, color) {
            _currentLibroId = id;
            document.getElementById('librosGridView').classList.add('hidden');
            document.getElementById('libroDetailView').classList.remove('hidden');
            document.getElementById('libroDetailTitle').textContent = nombre;
            document.getElementById('libroDetailColor').style.background = color;
            cargarHojasDeLibro(id);
        }

        async function eliminarLibro(id, nombre) {
            if (!confirm(`¿Estás seguro de eliminar el libro "${nombre}"?\n\nEsto eliminará TODAS las hojas dentro de este libro. Esta acción no se puede deshacer.`)) {
                return;
            }
            try {
                const res = await fetch('api/consolidador/libro.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ action: 'delete_libro', libro_id: id })
                });
                const data = await res.json();
                if (data.success) {
                    mostrarNotificacion('success', '🗑️ Libro eliminado', `"${nombre}" fue eliminado correctamente`);
                    cargarLibros();
                } else {
                    throw new Error(data.error);
                }
            } catch (err) {
                mostrarNotificacion('error', 'Error', err.message);
            }
        }

        function volverALibros() {
            _currentLibroId = null;
            document.getElementById('libroDetailView').classList.add('hidden');
            document.getElementById('librosGridView').classList.remove('hidden');
            cargarLibros();
        }

        async function cargarHojasDeLibro(libroId) {
            const grid = document.getElementById('libroHojasGrid');
            try {
                const res = await fetch(`api/consolidador/libro.php?action=list&libro_id=${libroId}`);
                const data = await res.json();
                document.getElementById('libroDetailCount').textContent = `${data.data?.length || 0} hojas`;

                if (!data.success || data.data.length === 0) {
                    grid.innerHTML = '<div class="col-span-full glass rounded-xl p-12 text-center text-slate-600">Este libro aún no tiene hojas.</div>';
                    return;
                }

                grid.innerHTML = data.data.map(hoja => `
                    <div class="stat-card glass rounded-xl p-5 cursor-pointer flex flex-col gap-3 group" onclick="verDetalle(${hoja.importacion_id})">
                        <div class="flex justify-between items-start">
                            <div class="w-10 h-10 rounded-lg bg-emerald-500/10 flex items-center justify-center text-emerald-400 text-lg group-hover:bg-emerald-500 group-hover:text-white transition-all">📄</div>
                            <span class="text-[10px] text-slate-600 font-mono">${hoja.fecha_agregado}</span>
                        </div>
                        <div>
                            <p class="text-sm font-bold text-slate-200 group-hover:text-emerald-400 transition-colors">${escapeHtml(hoja.nombre_hoja)}</p>
                            <p class="text-[10px] text-slate-500 mt-1 uppercase">Importación #${hoja.importacion_id}</p>
                        </div>
                        <div class="flex justify-between items-end mt-2 pt-3 border-t border-slate-800/50">
                            <div>
                                <p class="text-[10px] text-slate-600">Productos</p>
                                <p class="text-xs font-bold text-white">${hoja.total_productos}</p>
                            </div>
                            <div class="text-right">
                                <p class="text-[10px] text-slate-600">Total Hoja</p>
                                <p class="text-xs font-bold text-emerald-400 font-mono">Q${formatMoney(parseFloat(hoja.total_invertido))}</p>
                            </div>
                        </div>
                    </div>
                `).join('');
            } catch (err) {
                grid.innerHTML = `<p class="col-span-full text-center text-red-400">Error: ${err.message}</p>`;
            }
        }

        // ── Modal: Crear Libro Nuevo (desde la vista de libros) ──
        function mostrarModalCrearLibro() {
            const colores = ['#10b981','#3b82f6','#a855f7','#f59e0b','#ef4444','#ec4899','#06b6d4','#84cc16'];
            let selectedColor = colores[0];

            const modal = document.createElement('div');
            modal.id = 'modalCrearLibro';
            modal.className = 'fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm modal-overlay';
            modal.onclick = (e) => { if (e.target === modal) modal.remove(); };

            modal.innerHTML = `
                <div class="glass rounded-2xl p-6 max-w-md w-full mx-4 animate-fade-in-up">
                    <div class="flex justify-between items-center mb-5">
                        <h3 class="text-lg font-bold text-white">📗 Nuevo Libro</h3>
                        <button onclick="document.getElementById('modalCrearLibro').remove()" class="text-slate-500 hover:text-white text-xl">✕</button>
                    </div>
                    <div class="space-y-4">
                        <input type="text" id="inputCrearLibroNombre" placeholder="Nombre del libro"
                            class="w-full bg-slate-900/50 border border-slate-700 rounded-xl py-3 px-4 text-white text-sm placeholder-slate-500 focus:outline-none focus:border-emerald-500/50 focus:ring-4 focus:ring-emerald-500/10 transition-all">
                        <input type="text" id="inputCrearLibroDesc" placeholder="Descripción (opcional)"
                            class="w-full bg-slate-900/50 border border-slate-700 rounded-xl py-3 px-4 text-white text-sm placeholder-slate-500 focus:outline-none focus:border-emerald-500/50 focus:ring-4 focus:ring-emerald-500/10 transition-all">
                        <div class="flex items-center gap-2 flex-wrap">
                            <span class="text-[10px] text-slate-500 uppercase tracking-wider">Color:</span>
                            ${colores.map((c, i) => `<div class="color-swatch ${i===0?'active':''}" style="background:${c}" onclick="this.parentElement.querySelectorAll('.color-swatch').forEach(s=>s.classList.remove('active'));this.classList.add('active');document.getElementById('modalCrearLibro')._color='${c}'"></div>`).join('')}
                        </div>
                        <button onclick="crearLibroDesdeModal()" class="w-full py-3 rounded-xl text-sm font-bold text-white bg-gradient-to-r from-emerald-500 to-emerald-600 hover:from-emerald-400 hover:to-emerald-500 transition-all shadow-lg shadow-emerald-500/25">
                            Crear Libro
                        </button>
                    </div>
                </div>
            `;
            document.body.appendChild(modal);
            modal._color = colores[0];
            document.getElementById('inputCrearLibroNombre').focus();
        }

        async function crearLibroDesdeModal() {
            const nombre = document.getElementById('inputCrearLibroNombre').value.trim();
            const descripcion = document.getElementById('inputCrearLibroDesc').value.trim();
            const color = document.getElementById('modalCrearLibro')._color || '#10b981';

            if (!nombre) {
                mostrarNotificacion('error', 'Falta nombre', 'Escribe un nombre para el libro');
                return;
            }

            try {
                const res = await fetch('api/consolidador/libro.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ action: 'create_libro', nombre, descripcion, color })
                });
                const data = await res.json();
                if (data.success) {
                    document.getElementById('modalCrearLibro').remove();
                    mostrarNotificacion('success', '¡Libro creado!', data.message);
                    cargarLibros();
                } else {
                    throw new Error(data.error);
                }
            } catch (err) {
                mostrarNotificacion('error', 'Error', err.message);
            }
        }

        async function buscarEnLibro() {
            const query = document.getElementById('libroSearchInput').value.trim();
            if (query.length < 2) return;

            const resCont = document.getElementById('libroSearchResults');
            const container = document.getElementById('libroSearchResultsContainer');
            
            resCont.classList.remove('hidden');
            container.innerHTML = '<div class="glass rounded-xl p-12 text-center text-slate-600">🔍 Buscando en todos los libros...</div>';

            try {
                let url = `api/libro.php?action=search&query=${encodeURIComponent(query)}`;
                if (_currentLibroId) url += `&libro_id=${_currentLibroId}`;

                const res = await fetch(url);
                const data = await res.json();

                if (!data.success || data.data.length === 0) {
                    container.innerHTML = `<div class="glass rounded-xl p-12 text-center">
                        <p class="text-red-400 font-semibold mb-1">No se encontraron coincidencias</p>
                        <p class="text-slate-600 text-xs">Intenta con otro término de búsqueda</p>
                    </div>`;
                    return;
                }

                const results = data.data;

                // ── Group by Libro → Proveedor ──
                const grouped = {};
                results.forEach(p => {
                    const libroKey = p.libro_id || 0;
                    const libroName = p.libro_nombre || 'Sin libro';
                    const libroColor = p.libro_color || '#10b981';
                    const provName = p.proveedor_nombre || 'Desconocido';

                    if (!grouped[libroKey]) {
                        grouped[libroKey] = { nombre: libroName, color: libroColor, proveedores: {}, totalItems: 0 };
                    }
                    if (!grouped[libroKey].proveedores[provName]) {
                        grouped[libroKey].proveedores[provName] = [];
                    }
                    grouped[libroKey].proveedores[provName].push(p);
                    grouped[libroKey].totalItems++;
                });

                const totalLibros = Object.keys(grouped).length;
                const totalProvs = results.reduce((set, p) => set.add(p.proveedor_nombre), new Set()).size;

                // ── Update title ──
                document.getElementById('libroSearchTitle').innerHTML = `🔍 "${escapeHtml(query)}" — <span class="text-slate-500 font-normal">${results.length} resultado${results.length !== 1 ? 's' : ''} en ${totalLibros} libro${totalLibros !== 1 ? 's' : ''}, ${totalProvs} proveedor${totalProvs !== 1 ? 'es' : ''}</span>`;

                // ── Render grouped results ──
                let html = '';

                Object.values(grouped).forEach(libro => {
                    const color = libro.color;

                    // ── Libro Header ──
                    html += `<div class="glass rounded-2xl overflow-hidden">`;
                    html += `<div class="px-5 py-3 flex items-center justify-between" style="background: linear-gradient(135deg, ${color}15, transparent); border-bottom: 1px solid ${color}30;">
                        <div class="flex items-center gap-3">
                            <div class="w-8 h-8 rounded-lg flex items-center justify-center text-sm" style="background:${color}20; color:${color}">📖</div>
                            <div>
                                <span class="text-sm font-bold text-white">${escapeHtml(libro.nombre)}</span>
                                <span class="text-[10px] text-slate-500 ml-2">${libro.totalItems} resultado${libro.totalItems !== 1 ? 's' : ''}</span>
                            </div>
                        </div>
                    </div>`;

                    // ── Per Provider inside this Libro ──
                    Object.entries(libro.proveedores).forEach(([provName, items]) => {
                        const provTotal = items.reduce((s, p) => s + parseFloat(p.total_pagado || 0), 0);
                        const hojas = [...new Set(items.map(p => p.nombre_hoja))];

                        // Provider sub-header
                        html += `<div class="px-5 py-2.5 bg-slate-900/30 border-b border-slate-800/50 flex items-center justify-between">
                            <div class="flex items-center gap-2">
                                <span class="text-[10px] text-amber-400 uppercase tracking-wider font-semibold">🏢 ${escapeHtml(provName)}</span>
                                <div class="flex gap-1 flex-wrap">
                                    ${hojas.map(h => `<span class="text-[9px] bg-emerald-500/10 text-emerald-400 px-1.5 py-0.5 rounded border border-emerald-500/20">📄 ${escapeHtml(h)}</span>`).join('')}
                                </div>
                            </div>
                            <span class="text-[10px] font-bold font-mono" style="color:${color}">Q${formatMoney(provTotal)}</span>
                        </div>`;

                        // Product rows table
                        html += `<div class="overflow-x-auto">
                            <table class="w-full text-left text-xs">
                                <thead>
                                    <tr class="border-b border-slate-800/60">
                                        <th class="px-5 py-2 text-[9px] uppercase tracking-widest text-slate-600 font-semibold">Producto</th>
                                        <th class="px-5 py-2 text-[9px] uppercase tracking-widest text-slate-600 font-semibold text-center">Factura</th>
                                        <th class="px-5 py-2 text-[9px] uppercase tracking-widest text-slate-600 font-semibold text-center">Cant.</th>
                                        <th class="px-5 py-2 text-[9px] uppercase tracking-widest text-slate-600 font-semibold text-center">Bonif.</th>
                                        <th class="px-5 py-2 text-[9px] uppercase tracking-widest text-slate-600 font-semibold text-right">Costo U.</th>
                                        <th class="px-5 py-2 text-[9px] uppercase tracking-widest text-slate-600 font-semibold text-right">Total</th>
                                        <th class="px-5 py-2 text-[9px] uppercase tracking-widest text-slate-600 font-semibold text-center">Fecha</th>
                                    </tr>
                                </thead>
                                <tbody>`;

                        items.forEach(p => {
                            const rowClass = p.tiene_bonificacion == 1 ? 'bonif-row' : (p.consolidado == 1 ? 'consolidated-row' : '');
                            let badges = '';
                            if (p.tiene_bonificacion == 1) badges += ' 🎁';
                            if (p.consolidado == 1) badges += ' 📦';

                            html += `
                                <tr class="${rowClass} hover:bg-white/[0.04] transition-colors border-b border-slate-800/30 cursor-pointer" onclick="verDetalle(${p.importacion_id})">
                                    <td class="px-5 py-2.5">
                                        <span class="font-semibold text-slate-200">${escapeHtml(p.descripcion)}</span>${badges}
                                    </td>
                                    <td class="px-5 py-2.5 text-center">
                                        <span class="text-[9px] text-slate-500 font-mono max-w-[90px] truncate block" title="${p.numero_autorizacion}">${(p.numero_autorizacion || 'S/N').substring(0, 12)}…</span>
                                    </td>
                                    <td class="px-5 py-2.5 text-center">
                                        <span class="font-bold text-white bg-slate-800 px-2 py-0.5 rounded-md text-[11px]">${p.cantidad_total}</span>
                                    </td>
                                    <td class="px-5 py-2.5 text-center text-purple-400 font-bold font-mono text-[11px]">
                                        ${p.cantidad_bonificada > 0 ? p.cantidad_bonificada : '—'}
                                    </td>
                                    <td class="px-5 py-2.5 text-right text-lime-400 font-mono text-[11px]">Q${formatMoney(parseFloat(p.costo_real_unitario))}</td>
                                    <td class="px-5 py-2.5 text-right text-emerald-400 font-bold font-mono text-[11px]">Q${formatMoney(parseFloat(p.total_pagado))}</td>
                                    <td class="px-5 py-2.5 text-center text-[10px] text-slate-600 font-mono">${p.fecha_factura || (p.fecha_importacion ? p.fecha_importacion.split(' ')[0] : '')}</td>
                                </tr>`;
                        });

                        html += `</tbody></table></div>`;
                    });

                    html += `</div>`; // close libro card
                });

                container.innerHTML = html;
            } catch (err) {
                container.innerHTML = `<div class="glass rounded-xl p-12 text-center text-red-400">Error: ${err.message}</div>`;
            }
        }

        function cerrarBusquedaLibro() {
            document.getElementById('libroSearchResults').classList.add('hidden');
            document.getElementById('libroSearchInput').value = '';
        }

        // Event listener for Esc key to close search/modals
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape') {
                cerrarBusquedaLibro();
                document.getElementById('modalLibroSelect')?.remove();
                document.getElementById('modalCrearLibro')?.remove();
            }
        });

        // Load historial and catalogs on page load
        document.addEventListener('DOMContentLoaded', () => {
            cargarHistorial();
            cargarCatalogos();
        });

        // ── Sub-Modal: Crear Nuevo Lugar de Compra ──
        function mostrarModalNuevoLugar(targetSelectId) {
            const modal = document.createElement('div');
            modal.id = 'modalNuevoLugar';
            modal.className = 'fixed inset-0 z-[70] flex items-center justify-center bg-black/80 backdrop-blur-md modal-overlay';
            modal.onclick = (e) => { if (e.target === modal) modal.remove(); };

            modal.innerHTML = `
                <div class="glass rounded-3xl p-6 max-w-sm w-full mx-4 animate-fade-in-up border border-white/10 shadow-2xl">
                    <div class="flex justify-between items-center mb-5">
                        <h3 class="text-sm font-black text-white uppercase tracking-wider">🏢 Nuevo Lugar de Compra</h3>
                        <button onclick="document.getElementById('modalNuevoLugar').remove()" class="text-slate-500 hover:text-white text-xl">✕</button>
                    </div>
                    <div class="space-y-4">
                        <div>
                            <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Nombre del Proveedor / Establecimiento</label>
                            <input type="text" id="inputNuevoLugarNombre" placeholder="ej: Droguería El Sol"
                                class="w-full bg-slate-900 border border-slate-700 rounded-xl py-3 px-4 text-white text-sm focus:outline-none focus:border-emerald-500/50 transition-all mt-1">
                        </div>
                        <button onclick="crearNuevoLugar('${targetSelectId}')" id="btnGuardarLugar" class="w-full py-3 rounded-xl text-xs font-black text-white bg-gradient-to-r from-emerald-500 to-emerald-600 hover:from-emerald-400 hover:to-emerald-500 transition-all shadow-lg shadow-emerald-500/20">
                            Guardar Establecimiento
                        </button>
                    </div>
                </div>
            `;
            document.body.appendChild(modal);
            document.getElementById('inputNuevoLugarNombre').focus();

            // Soporte para Enter
            document.getElementById('inputNuevoLugarNombre').addEventListener('keydown', (e) => {
                if (e.key === 'Enter') crearNuevoLugar(targetSelectId);
            });
        }

        async function crearNuevoLugar(targetSelectId) {
            const nombre = document.getElementById('inputNuevoLugarNombre').value.trim();
            if (!nombre) {
                mostrarNotificacion('error', 'Falta nombre', 'Escribe el nombre del lugar');
                return;
            }

            const btn = document.getElementById('btnGuardarLugar');
            btn.disabled = true;
            btn.textContent = '⏳ Guardando...';

            try {
                const res = await fetch('api/consolidador/crear_lugar.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ nombre })
                });
                const data = await res.json();
                
                if (data.success) {
                    mostrarNotificacion('success', '¡Lugar guardado!', data.message);
                    
                    // 1. Recargar el catálogo global
                    await cargarCatalogos();
                    
                    // 2. Actualizar el select que invocó el modal
                    const select = document.getElementById(targetSelectId);
                    if (select) {
                        const currentVal = data.id;
                        select.innerHTML = '<option value="">Seleccionar...</option>' + 
                            catalogos.lugares.map(l => `<option value="${l.id}" ${l.id == currentVal ? 'selected' : ''}>${escapeHtml(l.nombre)}</option>`).join('');
                    }
                    
                    document.getElementById('modalNuevoLugar').remove();
                } else {
                    throw new Error(data.error);
                }
            } catch(e) {
                mostrarNotificacion('error', 'Error', e.message);
                btn.disabled = false;
                btn.textContent = 'Guardar Establecimiento';
            }
        }

        // ─────────────────────────────────────────────
        //  INTEGRATION LOGIC: Mapping & Master Sync
        // ─────────────────────────────────────────────
        
        // ─────────────────────────────────────────────
        //  MANUAL BREAKDOWN (DESGLOSE) MODAL
        // ─────────────────────────────────────────────
        
        function mostrarModalDesglose(idx) {
            const isHistory = (typeof idx === 'string' && idx.startsWith('h-'));
            let item, currentQty;
            
            if (isHistory) {
                const rowIdx = parseInt(idx.replace('h-', ''));
                item = activeHistoryItems[rowIdx];
                currentQty = parseFloat(item.cantidad_total);
            } else {
                item = processedItems[idx];
                currentQty = parseFloat(item.cantidadTotal);
            }

            if (!item) return;

            const modal = document.createElement('div');
            modal.id = 'modalDesglose';
            modal.className = 'fixed inset-0 z-[60] flex items-center justify-center bg-black/80 backdrop-blur-md animate-fade-in';
            
            modal.innerHTML = `
                <div class="glass border border-white/10 rounded-3xl p-8 max-w-4xl w-full mx-4 max-h-[90vh] overflow-hidden flex flex-col shadow-2xl">
                    <div class="flex justify-between items-center mb-6">
                        <div class="flex items-center gap-4">
                            <div class="w-12 h-12 rounded-2xl bg-amber-500/20 flex items-center justify-center text-2xl border border-amber-500/30">✂️</div>
                            <div>
                                <h3 class="text-xl font-black text-white uppercase tracking-tight">Desglose de Producto Surtido</h3>
                                <p class="text-xs text-slate-500 font-mono truncate max-w-[400px]" title="${item.descripcion}">${item.descripcion}</p>
                            </div>
                        </div>
                        <div class="text-right">
                            <p class="text-[10px] text-slate-500 uppercase font-black tracking-widest mb-1">Cantidad Original</p>
                            <p class="text-2xl font-black text-white leading-none">${currentQty}</p>
                        </div>
                    </div>

                    <div class="flex-grow overflow-y-auto mb-6 CustomScroll rounded-2xl border border-white/5 bg-slate-900/50 p-1">
                        <table class="w-full text-left" id="tableDesglose">
                            <thead class="sticky top-0 bg-slate-800 z-10">
                                <tr>
                                    <th class="py-3 px-4 text-[10px] font-black text-slate-400 uppercase tracking-widest">Producto del Catálogo</th>
                                    <th class="py-3 px-4 text-[10px] font-black text-slate-400 uppercase tracking-widest w-32">Cantidad</th>
                                    <th class="py-3 px-4 text-center w-12 text-slate-400">✕</th>
                                </tr>
                            </thead>
                            <tbody id="tbodyDesglose" class="divide-y divide-white/5">
                                <!-- Filas de desglose dinámicas -->
                            </tbody>
                        </table>
                    </div>

                    <div class="flex items-center justify-between mt-auto">
                        <button onclick="agregarFilaDesglose()" class="flex items-center gap-2 px-4 py-2 rounded-xl bg-blue-500/10 text-blue-400 border border-blue-500/20 hover:bg-blue-500 hover:text-white transition-all text-xs font-bold">
                            <span>＋</span> Agregar Producto
                        </button>
                        
                        <div class="flex items-center gap-4">
                            <div class="text-right mr-4">
                                <p id="desgloseTotalLabel" class="text-[10px] font-black tracking-widest uppercase mb-1 ${currentQty === 0 ? 'text-emerald-400' : 'text-slate-500'}">Restante: 0</p>
                                <p id="desgloseStatus" class="text-xs font-bold font-mono text-slate-400">Suma: 0 / ${currentQty}</p>
                            </div>
                            <button onclick="document.getElementById('modalDesglose').remove()" class="px-6 py-3 rounded-xl text-xs font-bold text-slate-400 hover:text-white transition-all">Cancelar</button>
                            <button id="btnAplicarDesglose" onclick="ejecutarDesglose('${idx}', ${currentQty})" disabled
                                class="px-8 py-3 rounded-xl text-xs font-black text-white bg-emerald-500 hover:bg-emerald-400 transition-all shadow-lg shadow-emerald-500/30 disabled:opacity-30 disabled:cursor-not-allowed">
                                Aplicar Desglose
                            </button>
                        </div>
                    </div>
                </div>
            `;
            document.body.appendChild(modal);
            
            // Empezar con una fila vacía
            agregarFilaDesglose();
        }

        let filaDesgloseCounter = 0;
        function agregarFilaDesglose() {
            const tbody = document.getElementById('tbodyDesglose');
            const id = filaDesgloseCounter++;
            const tr = document.createElement('tr');
            tr.id = `row-desglose-${id}`;
            tr.className = 'group fade-in';
            tr.innerHTML = `
                <td class="py-4 px-4">
                    <div class="relative">
                        <input type="text" id="input-d-${id}" onkeyup="buscarProductoDesglose(this.value, ${id})" placeholder="Buscar código o nombre del catálogo..." 
                               class="w-full bg-slate-900/80 border border-slate-700/50 rounded-xl px-4 py-2.5 text-xs text-white focus:outline-none focus:border-blue-500/50 transition-all shadow-inner">
                        <div id="results-d-${id}" class="absolute top-full left-0 right-0 z-[70] mt-2 hidden max-h-48 overflow-y-auto glass border border-slate-700 shadow-2xl rounded-xl"></div>
                        <input type="hidden" id="pid-d-${id}" value="">
                    </div>
                </td>
                <td class="py-4 px-4">
                    <input type="number" id="qty-d-${id}" onchange="validarDesglose()" onkeyup="validarDesglose()" step="0.01" value="0"
                           class="w-full bg-slate-900/80 border border-slate-700/50 rounded-xl px-4 py-2.5 text-center text-sm font-bold text-white focus:outline-none focus:border-emerald-500/50 transition-all shadow-inner">
                </td>
                <td class="py-4 px-4 text-center">
                    <button onclick="this.closest('tr').remove(); validarDesglose();" class="text-slate-600 hover:text-red-400 transition-colors">✕</button>
                </td>
            `;
            tbody.appendChild(tr);
            document.getElementById(`input-d-${id}`).focus();
        }

        async function buscarProductoDesglose(query, rowId) {
            const resultsDiv = document.getElementById(`results-d-${rowId}`);
            if (!query || query.length < 2) {
                resultsDiv.classList.add('hidden');
                return;
            }
            try {
                const res = await fetch(`api/consolidador/buscar_productos.php?query=${encodeURIComponent(query)}`);
                const data = await res.json();
                if (data.success && data.data.length > 0) {
                    resultsDiv.innerHTML = data.data.map(p => `
                        <div class="p-3 border-b border-white/5 hover:bg-white/10 cursor-pointer transition-colors" 
                             onclick="seleccionarEnDesglose(${rowId}, ${JSON.stringify(p).replace(/"/g, '&quot;')})">
                            <p class="text-[10px] font-black text-emerald-400 leading-none mb-1">${p.CodigoInterno}</p>
                            <p class="text-[11px] text-white font-bold max-w-[300px] truncate">${escapeHtml(p.NombreComercial)}</p>
                        </div>
                    `).join('');
                    resultsDiv.classList.remove('hidden');
                }
            } catch(e) { console.error(e); }
        }

        function seleccionarEnDesglose(rowId, p) {
            document.getElementById(`input-d-${rowId}`).value = `[${p.CodigoInterno}] ${p.NombreComercial}`;
            document.getElementById(`pid-d-${rowId}`).value = p.producto_id || p.id;
            // Guardar el objeto completo para no tener que buscarlo luego
            document.getElementById(`pid-d-${rowId}`).dataset.full = JSON.stringify(p);
            document.getElementById(`results-d-${rowId}`).classList.add('hidden');
            document.getElementById(`qty-d-${rowId}`).focus();
            validarDesglose();
        }

        function validarDesglose() {
            const totalTarget = parseFloat(document.getElementById('modalDesglose')?.querySelector('p.text-2xl')?.textContent || 0);
            let suma = 0;
            let valid = true;
            
            document.querySelectorAll('#tbodyDesglose tr').forEach(tr => {
                const id = tr.id.replace('row-desglose-', '');
                const qtyVal = parseFloat(document.getElementById(`qty-d-${id}`).value || 0);
                const pid = document.getElementById(`pid-d-${id}`).value;
                suma += qtyVal;
                if (!pid || qtyVal <= 0) valid = false;
            });

            const status = document.getElementById('desgloseStatus');
            const label = document.getElementById('desgloseTotalLabel');
            const btn = document.getElementById('btnAplicarDesglose');
            
            const diff = Math.abs(suma - totalTarget);
            status.textContent = `Suma: ${suma.toFixed(2)} / ${totalTarget}`;
            
            if (diff < 0.01) {
                status.className = 'text-xs font-bold font-mono text-emerald-400';
                label.textContent = '¡Suma Correcta!';
                label.className = 'text-[10px] font-black tracking-widest uppercase mb-1 text-emerald-400';
                btn.disabled = !valid;
            } else {
                status.className = 'text-xs font-bold font-mono text-red-400';
                label.textContent = suma > totalTarget ? `Exceso: ${(suma - totalTarget).toFixed(2)}` : `Restante: ${(totalTarget - suma).toFixed(2)}`;
                label.className = 'text-[10px] font-black tracking-widest uppercase mb-1 text-red-400';
                btn.disabled = true;
            }
        }

        async function ejecutarDesglose(idx, totalQty) {
            const isHistory = (typeof idx === 'string' && idx.startsWith('h-'));
            const desgloses = [];
            
            document.querySelectorAll('#tbodyDesglose tr').forEach(tr => {
                const id = tr.id.replace('row-desglose-', '');
                const inputPid = document.getElementById(`pid-d-${id}`);
                desgloses.push({
                    producto_id: inputPid.value,
                    cantidad: parseFloat(document.getElementById(`qty-d-${id}`).value),
                    nombre: document.getElementById(`input-d-${id}`).value,
                    full_product: inputPid.dataset.full ? JSON.parse(inputPid.dataset.full) : null
                });
            });

            if (isHistory) {
                const rowIdx = parseInt(idx.replace('h-', ''));
                const item = activeHistoryItems[rowIdx];
                try {
                    const res = await fetch('api/consolidador/desglosar_lote.php', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ id_original: item.id, desgloses })
                    });
                    const data = await res.json();
                    if (data.success) {
                        mostrarNotificacion('success', 'Desglose aplicado', 'El registro se ha desglosado en el historial');
                        const modal = document.querySelector('.fixed[id^="modal-history-"]');
                        const impId = modal.id.replace('modal-history-', '');
                        modal.remove();
                        document.getElementById('modalDesglose').remove();
                        verDetalle(impId);
                    } else throw new Error(data.error);
                } catch(e) { mostrarNotificacion('error', 'Error', e.message); }
            } else {
                // Analizador (Memoria)
                const origItem = processedItems[idx];
                const key = origItem.descripcion.toUpperCase().trim();
                
                // Borrar el original de processedItems Y de inventario
                processedItems.splice(idx, 1);
                for (let k in inventario) {
                    if (inventario[k] === origItem) {
                        delete inventario[k];
                        break;
                    }
                }

                // Insertar los nuevos y marcar para auto-configuración en el render
                desgloses.forEach((d, i) => {
                    const nItem = JSON.parse(JSON.stringify(origItem));
                    const ratio = d.cantidad / totalQty;
                    nItem.cantidadTotal = d.cantidad;
                    nItem.totalPagado = origItem.totalPagado * ratio;
                    nItem.cantidadBonif = (origItem.cantidadBonif || 0) * ratio;
                    
                    // Marcar para el renderizador
                    if (d.full_product) {
                        nItem._autoConfig = { product: d.full_product };
                    }
                    
                    // Generar un nombre único para la llave del inventario (agregando espacios invisibles)
                    let uniqueKey = key;
                    while(inventario[uniqueKey]) {
                        uniqueKey += ' ';
                    }

                    inventario[uniqueKey] = nItem;
                });

                document.getElementById('modalDesglose').remove();
                mostrarResultados();
                mostrarNotificacion('success', 'Desglose aplicado', 'Se han creado las nuevas filas correctamente.');
            }
        }

        async function desglosarSurtido(idx, mappings) {
            const item = processedItems[idx];
            if (!item || !mappings || mappings.length < 2) return;

            const totalQty = item.cantidadTotal;
            const portion = totalQty / mappings.length;
            const confirmSplit = confirm(`Se detectó un surtido de ${mappings.length} productos vinculados.\n\n¿Deseas desglosar las ${totalQty} unidades automáticamente (${portion.toFixed(2)} c/u)?`);
            
            if (!confirmSplit) return;

            // El primer mapeo se queda en la fila actual
            asignarProducto(mappings[0], idx);
            item.cantidadTotal = portion;
            item.totalPagado = (item.totalPagado / totalQty) * portion;
            item.cantidadBonif = (item.cantidadBonif / totalQty) * portion;

            // Los demás crean nuevas filas
            for (let i = 1; i < mappings.length; i++) {
                const nItem = JSON.parse(JSON.stringify(item));
                const key = item.descripcion.toUpperCase().trim();
                const uniqueKey = key + ' '.repeat(processedItems.filter(it => it.descripcion.toUpperCase().trim() === key).length);
                
                inventario[uniqueKey] = nItem;
                processedItems.splice(idx + i, 0, nItem);
                
                // Asignar el producto inmediatamente
                // Nota: processedItems se actualizó, el nuevo index es idx + i
                asignarProducto(mappings[i], idx + i);
            }

            mostrarResultados();
            mostrarNotificacion('success', 'Surtido desglosado', `Se han creado ${mappings.length} filas pre-configuradas.`);
        }

        async function desvincularProducto(descripcion, idx) {
            if (!confirm(`¿Estás seguro de que deseas desvincular este producto?\n\n"${descripcion}"`)) return;

            try {
                const res = await fetch('api/consolidador/eliminar_mapping.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ descripcion })
                });
                const data = await res.json();
                
                if (data.success) {
                    mostrarNotificacion('success', 'Desvinculado', 'Se ha eliminado el mapeo correctamente');
                    
                    // Resetear la celda al estado original de búsqueda
                    buscarProductoAsignar('', idx);
                    
                    // Ocultar el panel de detalles si estaba abierto
                    const detailRow = document.getElementById(`detail-row-${idx}`);
                    if (detailRow) detailRow.classList.add('hidden');
                } else {
                    throw new Error(data.error);
                }
            } catch (err) {
                mostrarNotificacion('error', 'Error', err.message);
            }
        }

        function getIdLugarByNombre(nombre) {
            if (!nombre || !catalogos.lugares) return null;
            const normalized = nombre.toUpperCase().trim();
            // Buscar coincidencia exacta o contenida
            const found = catalogos.lugares.find(l => 
                l.nombre.toUpperCase().trim() === normalized || 
                normalized.includes(l.nombre.toUpperCase().trim()) ||
                l.nombre.toUpperCase().trim().includes(normalized)
            );
            return found ? found.id : null;
        }

        async function cargarCatalogos() {
            try {
                const res = await fetch('api/consolidador/obtener_catalogos.php');
                const data = await res.json();
                if (data.success) {
                    catalogos = data;
                }
            } catch(e) { console.error('Error cargando catálogos:', e); }
        }

        /**
         * Buscar producto en la base de datos para asignar a una fila
         * @param {string} query 
         * @param {string|number} idx - Puede ser un número (consolidador) o 'h-idx' (historial)
         */
        async function buscarProductoAsignar(query, idx) {
            const resultsDiv = document.getElementById(`results-${idx}`);
            if (!query || query.length < 2) {
                if (resultsDiv) resultsDiv.classList.add('hidden');
                
                // Si se llama buscar con query vacio y es historial, podria ser para "limpiar"
                if (!query && typeof idx === 'string' && idx.startsWith('h-')) {
                   const container = document.getElementById(`target-assign-${idx}`);
                   const rowIdx = parseInt(idx.replace('h-', ''));
                   container.innerHTML = `
                        <div class="relative flex-grow">
                            <input type="text" 
                                   id="input-assign-${idx}"
                                   onkeyup="buscarProductoAsignar(this.value, '${idx}')"
                                   placeholder="Vincular..."
                                   class="w-full bg-slate-900 border border-slate-700/50 rounded-lg px-3 py-1.5 text-[10px] text-white placeholder-slate-600 focus:outline-none focus:border-blue-500/50 transition-all">
                            <div id="results-${idx}" class="absolute top-full left-0 right-0 z-50 mt-1 hidden max-h-40 overflow-y-auto glass border border-slate-700 rounded-lg shadow-2xl"></div>
                        </div>
                        <button onclick="mostrarModalNuevoProducto('${idx}')" 
                                class="w-7 h-7 rounded-lg bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 flex items-center justify-center hover:bg-emerald-500 hover:text-white transition-all">＋</button>
                   `;
                }
                return;
            }

            try {
                const res = await fetch(`api/consolidador/buscar_productos.php?query=${encodeURIComponent(query)}`);
                const data = await res.json();
                
                if (data.success && data.data.length > 0) {
                    const html = data.data.map(p => `
                        <div class="p-3 border-b border-white/5 hover:bg-white/10 cursor-pointer transition-colors" 
                             onclick="asignarProducto(${JSON.stringify(p).replace(/"/g, '&quot;')}, '${idx}')">
                            <div class="flex justify-between items-center mb-0.5">
                                <span class="text-[10px] font-black text-emerald-400">${p.CodigoInterno}</span>
                                <span class="text-[8px] bg-emerald-500/10 text-emerald-500 px-1.5 rounded uppercase font-bold">Maestro</span>
                            </div>
                            <p class="text-[11px] text-white font-bold leading-tight">${escapeHtml(p.NombreComercial)}</p>
                        </div>
                    `).join('');
                    resultsDiv.innerHTML = html;
                    resultsDiv.classList.remove('hidden');
                } else {
                    resultsDiv.innerHTML = '<div class="p-3 text-[10px] text-slate-500 text-center">Sin resultados</div>';
                    resultsDiv.classList.remove('hidden');
                }
            } catch(e) { console.error(e); }
        }

        async function asignarProducto(p, idx) {
            // Caso 1: Historial (idx es string tipo 'h-0')
            if (typeof idx === 'string' && idx.startsWith('h-')) {
                const rowIdx = parseInt(idx.replace('h-', ''));
                const item = activeHistoryItems[rowIdx];
                if (!item) return;

                const target = document.getElementById(`target-assign-${idx}`);
                
                // Actualizar UI localmente (visual solamente)
                        target.innerHTML = `
                            <div class="flex items-center gap-3 px-4 py-2.5 rounded-xl bg-amber-500/10 border border-amber-500/20 group/tag shadow-sm">
                                <div class="flex flex-col">
                                    <span class="text-xs font-black text-amber-400 leading-none mb-1 tracking-wider">${p.CodigoInterno}</span>
                                    <span class="text-[11px] text-amber-500/70 font-bold truncate max-w-[250px] uppercase">${escapeHtml(p.NombreComercial || p.maestro_nombre)}</span>
                                </div>
                                <button onclick="desvincularProducto('${escapeHtml(item.descripcion)}', '${idx}')" 
                                        class="w-8 h-8 rounded-full bg-red-500/10 text-red-400 flex items-center justify-center transition-all hover:bg-red-500 hover:text-white">✕</button>
                            </div>
                        `;

                // Abrir panel de sincronización maestro para confirmar
                const costoInvoice = item.total_pagado / item.cantidad_total;
                mostrarDetalleAsignacion(idx, p, costoInvoice, item.es_exento == 1, item.descripcion);
                return;
            }

            // Caso 2: Analizador (idx es número)
            document.getElementById(`results-${idx}`).classList.add('hidden');
            document.getElementById(`input-assign-${idx}`).value = p.CodigoInterno || p.NombreComercial;
            
            const item = processedItems[idx];
            if (!item) {
                console.error("Item no encontrado en índice:", idx);
                return;
            }

            const descFactura = item.descripcion;
            const costoInvoice = item.totalPagado / item.cantidadTotal;
            const forcedLugarId = item.lugar_compra_id || item.lugarCompraId || getIdLugarByNombre(item.emisor);
            mostrarDetalleAsignacion(idx, p, costoInvoice, item.esExento, descFactura, forcedLugarId);
        }

        async function obtenerMappingParaFila(descripcion, idx, costoInvoice, esExento, emisor = null) {
            try {
                const res = await fetch(`api/consolidador/obtener_mapping.php?descripcion=${encodeURIComponent(descripcion)}`);
                const data = await res.json();
                
                const target = document.getElementById(`target-assign-${idx}`);
                const isHistory = (typeof idx === 'string' && idx.startsWith('h-'));

                if (data.success && data.mappings && data.mappings.length > 0) {
                    const mappings = data.mappings;
                    
                    if (mappings.length === 1) {
                        // Comportamiento normal: Un solo mapeo
                        const p = mappings[0];
                        const input = document.getElementById(`input-assign-${idx}`);
                        if (input) input.value = p.CodigoInterno || p.NombreComercial;
                        
                        const forcedLugarId = getIdLugarByNombre(emisor);
                        mostrarDetalleAsignacion(idx, p, costoInvoice, esExento, descripcion, forcedLugarId);
                    } else {
                        // Surtido detectado: Mostrar aviso y botón de desglose
                        if (target) {
                            target.innerHTML = `
                                <div class="flex items-center gap-3">
                                    <span class="px-2.5 py-1 rounded-lg bg-indigo-500/20 text-indigo-400 border border-indigo-500/30 text-[10px] font-black uppercase tracking-tighter">🧩 Surtido</span>
                                    <button onclick='desglosarSurtido(${idx}, ${JSON.stringify(mappings)})' class="px-3 py-1.5 rounded-lg bg-indigo-600 text-white text-[10px] font-bold hover:bg-indigo-500 transition-all shadow-lg active:scale-95">Desglosar Todo</button>
                                </div>
                            `;
                        }
                    }
                }
            } catch(e) { console.error(e); }
        }

        function mostrarDetalleAsignacion(idx, dbProd, costoInvoice, exentoInvoice, descFactura, forcedLugarId = null) {
            const detailRow = document.getElementById(`detail-row-${idx}`);
            const content = document.getElementById(`detail-content-${idx}`);
            
            const fBlister = parseInt(dbProd.FactorBlister || 1);
            const fCaja = parseInt(dbProd.FactorCaja || 1);
            
            const selectedLugarId = forcedLugarId || 1;
            const lugaresHtml = catalogos.lugares.map(l => `
                <option value="${l.id}" ${selectedLugarId == l.id ? 'selected' : ''}>${escapeHtml(l.nombre)}</option>
            `).join('');

            content.innerHTML = `
                <div class="grid grid-cols-1 md:grid-cols-12 gap-6 animate-fade-in-up" id="assign-container-${idx}" data-pid="${dbProd.producto_id || dbProd.id || ''}">
                    <!-- Left: Metadata & Source (3 cols) -->
                    <div class="md:col-span-3 space-y-4">
                        <div class="flex items-start gap-4">
                            <div class="w-12 h-12 rounded-xl bg-blue-500/20 flex items-center justify-center text-xl shrink-0">🔍</div>
                            <div>
                                <p class="text-sm font-black text-white leading-tight">${escapeHtml(dbProd.NombreComercial)}</p>
                                <div class="flex flex-wrap gap-1.5 mt-2">
                                    <span class="text-[10px] text-emerald-400 font-bold bg-emerald-500/10 px-2 py-0.5 rounded border border-emerald-500/20">COD: ${dbProd.CodigoInterno || 'N/A'}</span>
                                    <span class="text-[10px] text-blue-300 font-medium bg-blue-400/10 px-2 py-0.5 rounded border border-blue-500/20">${escapeHtml(dbProd.laboratorio || 'SIN LABORATORIO')}</span>
                                </div>
                            </div>
                        </div>
                        <div>
                            <div class="flex justify-between items-center mb-1">
                                <label class="block text-[9px] uppercase tracking-wider text-slate-500">Lugar de Compra / Proveedor</label>
                                <button onclick="mostrarModalNuevoLugar('lugar-${idx}')" class="text-[8px] text-blue-400 hover:text-blue-300 font-bold uppercase tracking-widest transition-colors">＋ Nuevo</button>
                            </div>
                            <select id="lugar-${idx}" class="w-full input-detail">
                                ${lugaresHtml}
                            </select>
                        </div>
                        <div class="flex items-center gap-3 bg-slate-800/40 p-3 rounded-xl border border-slate-700/30">
                            <input type="checkbox" id="exento-${idx}" ${exentoInvoice ? 'checked' : ''} class="w-4 h-4 rounded border-slate-700 bg-slate-900 text-emerald-500">
                            <label for="exento-${idx}" class="text-[11px] font-bold text-slate-300">Marcar como Exento de IVA</label>
                        </div>
                    </div>

                    <!-- Middle: Factors & Cost Preview (7 cols) -->
                    <div class="md:col-span-7 grid grid-cols-1 lg:grid-cols-2 gap-6 bg-white/[0.02] p-5 rounded-3xl border border-white/[0.05]">
                        <div class="space-y-4">
                            <p class="text-[11px] font-black text-emerald-400 uppercase tracking-widest border-b border-emerald-500/20 pb-2 mb-2 flex items-center gap-2">
                                <span>📦</span> Presentación / Factores
                            </p>
                            <div class="flex items-center gap-4">
                                <div class="flex-grow">
                                    <label class="block text-[10px] font-bold text-slate-500 mb-1.5 uppercase tracking-tighter">Unidades por Blister</label>
                                    <input type="number" id="f-blister-${idx}" value="${fBlister}" onchange="recalcularCostos('${idx}')" class="w-full input-detail">
                                </div>
                                <div class="flex-grow">
                                    <label class="block text-[10px] font-bold text-slate-500 mb-1.5 uppercase tracking-tighter">Unidades por Caja</label>
                                    <input type="number" id="f-caja-${idx}" value="${fCaja}" onchange="recalcularCostos('${idx}')" class="w-full input-detail">
                                </div>
                            </div>
                            <div class="p-4 bg-slate-950/40 rounded-2xl border border-slate-800/50 space-y-3">
                                <div class="flex justify-between items-center text-[11px]">
                                    <span class="text-slate-500 font-medium">Costo Unidad:</span>
                                    <span class="text-white font-bold font-mono" id="prev-c-u-${idx}">-</span>
                                </div>
                                <div class="flex justify-between items-center text-[11px]">
                                    <span class="text-slate-500 font-medium">Costo Blister:</span>
                                    <span class="text-white font-bold font-mono" id="prev-c-b-${idx}">-</span>
                                </div>
                                <div class="flex justify-between items-center text-[11px]">
                                    <span class="text-slate-500 font-medium">Costo Caja:</span>
                                    <span class="text-white font-bold font-mono" id="prev-c-c-${idx}">-</span>
                                </div>
                            </div>
                        </div>

                        <div class="space-y-4">
                            <p class="text-[11px] font-black text-amber-400 uppercase tracking-widest border-b border-amber-500/20 pb-2 mb-2 flex items-center gap-2">
                                <span>💰</span> Precios de Venta
                            </p>
                            <div class="grid grid-cols-2 gap-3">
                                <div>
                                    <label class="block text-[10px] font-bold text-slate-500 mb-1.5 uppercase tracking-tighter">Unidad</label>
                                    <input type="number" step="0.01" id="p-unidad-${idx}" value="${dbProd.PrecioVentaUnidad || 0}" class="w-full input-detail text-emerald-400 font-bold">
                                </div>
                                <div>
                                    <label class="block text-[10px] font-bold text-slate-500 mb-1.5 uppercase tracking-tighter">Blister</label>
                                    <input type="number" step="0.01" id="p-blister-${idx}" value="${dbProd.PrecioVentaBlister || 0}" class="w-full input-detail text-emerald-400 font-bold">
                                </div>
                                <div>
                                    <label class="block text-[10px] font-bold text-slate-500 mb-1.5 uppercase tracking-tighter">Mayorista</label>
                                    <input type="number" step="0.01" id="p-mayor-${idx}" value="${dbProd.PrecioVentaMayor || 0}" class="w-full input-detail text-emerald-400 font-bold">
                                </div>
                                <div>
                                    <label class="block text-[10px] font-bold text-slate-500 mb-1.5 uppercase tracking-tighter">Mixta</label>
                                    <input type="number" step="0.01" id="p-mixta-${idx}" value="${dbProd.PrecioVentaMixto || 0}" class="w-full input-detail text-emerald-400 font-bold">
                                </div>
                            </div>
                        </div>
                    </div>

                    <!-- Right: Actions (2 cols) -->
                    <div class="md:col-span-2 flex flex-col justify-center gap-4">
                        <button onclick="guardarAlMaestro('${idx}')" 
                                id="btn-sync-${idx}"
                                class="btn-sync w-full flex items-center justify-center gap-2">
                            <span class="text-lg">⚡</span>
                            Sincronizar Maestro
                        </button>
                        <p class="text-[10px] text-slate-500 px-2 leading-relaxed italic">
                            Actualiza costos, factores y precios en el catálogo maestro.
                        </p>
                    </div>
                </div>
            `;
            
            detailRow.classList.remove('hidden');
            recalcularCostos(idx, costoInvoice);
        }

        function recalcularCostos(idx, baseCost = null) {
            if (baseCost === null) {
                let item;
                if (typeof idx === 'string' && idx.startsWith('h-')) {
                    const rowIdx = parseInt(idx.replace('h-', ''));
                    item = activeHistoryItems[rowIdx];
                } else {
                    item = processedItems[idx];
                }
                
                if (item) {
                   const total = item.total_pagado || item.totalPagado;
                   const cant = item.cantidad_total || item.cantidadTotal;
                   baseCost = total / cant;
                } else {
                   baseCost = 0;
                }
            }

            const factorBlister = parseInt(document.getElementById(`f-blister-${idx}`).value) || 1;
            const factorCaja = parseInt(document.getElementById(`f-caja-${idx}`).value) || 1;
            
            const costUnidad = baseCost / factorCaja;
            const costBlister = costUnidad * factorBlister;
            const costCaja = baseCost;

            document.getElementById(`prev-c-u-${idx}`).textContent = `Q${formatMoney(costUnidad)}`;
            document.getElementById(`prev-c-b-${idx}`).textContent = `Q${formatMoney(costBlister)}`;
            document.getElementById(`prev-c-c-${idx}`).textContent = `Q${formatMoney(costCaja)}`;
            
            const btn = document.getElementById(`btn-sync-${idx}`);
            btn.dataset.costUnidad = costUnidad;
            btn.dataset.costBlister = costBlister;
            btn.dataset.costCaja = costCaja;
        }

        async function guardarAlMaestro(idx) {
            const btn = document.getElementById(`btn-sync-${idx}`);
            const originalHtml = btn.innerHTML;
            btn.innerHTML = '⏳ Guardando...';
            btn.disabled = true;

            const isHistory = typeof idx === 'string' && idx.startsWith('h-');
            let item;
            if (isHistory) {
                const rowIdx = parseInt(idx.replace('h-', ''));
                item = activeHistoryItems[rowIdx];
            } else {
                item = processedItems[idx];
            }

            if (!item) {
                mostrarNotificacion('error', 'Error', 'No se encontró el producto en memoria');
                btn.innerHTML = originalHtml;
                btn.disabled = false;
                return;
            }
            const desc = item.descripcion;
            const fecha = item.fecha_factura || item.fecha;
            const container = document.getElementById(`assign-container-${idx}`);
            
            const payload = {
                producto_id: container.dataset.pid,
                descripcion_factura: desc,
                lugar_compra_id: document.getElementById(`lugar-${idx}`).value,
                FactorBlister: document.getElementById(`f-blister-${idx}`).value,
                FactorCaja: document.getElementById(`f-caja-${idx}`).value,
                PrecioVentaUnidad: document.getElementById(`p-unidad-${idx}`).value,
                PrecioVentaBlister: document.getElementById(`p-blister-${idx}`).value,
                PrecioVentaMayor: document.getElementById(`p-mayor-${idx}`).value,
                PrecioVentaMixto: document.getElementById(`p-mixta-${idx}`).value,
                esExento: document.getElementById(`exento-${idx}`).checked,
                costo_unidad: btn.dataset.costUnidad,
                costo_blister: btn.dataset.costBlister,
                costo_mayor: btn.dataset.costCaja,
                fecha_factura: fecha
            };

            try {
                const res = await fetch('api/consolidador/upsert_producto_maestro.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(payload)
                });
                const data = await res.json();
                
                if (data.success) {
                    mostrarNotificacion('success', 'Éxito', 'Catálogo maestro actualizado');
                    document.getElementById(`detail-row-${idx}`).classList.add('bg-emerald-500/10');
                    btn.innerHTML = '✅ Sincronizado';
                } else {
                    throw new Error(data.error);
                }
            } catch(e) {
                mostrarNotificacion('error', 'Error', e.message);
                btn.innerHTML = originalHtml;
                btn.disabled = false;
            }
        }

        // ─────────────────────────────────────────────
        //  MODAL: NUEVO PRODUCTO (Fast Registration)
        // ─────────────────────────────────────────────
        function mostrarModalNuevoProducto(idx) {
            let item;
            const isHistory = typeof idx === 'string' && idx.startsWith('h-');
            
            if (isHistory) {
                const rowIdx = parseInt(idx.replace('h-', ''));
                item = activeHistoryItems[rowIdx];
                // Adaptar nombres de campos de historial a analizador
                if (item) {
                   item.totalPagado = parseFloat(item.total_pagado);
                   item.cantidadTotal = parseFloat(item.cantidad_total);
                   item.esExento = item.es_exento == 1;
                   item.fecha = item.fecha_factura;
                   item.emisor = item.proveedor_nombre;
                }
            } else {
                item = processedItems[idx];
            }

            if (!item) return;

            const forcedLugarId = item.lugar_compra_id || item.lugarCompraId || getIdLugarByNombre(item.emisor);
            const modal = document.createElement('div');
            modal.id = 'modalNuevoProducto';
            modal.className = 'fixed inset-0 z-[60] flex items-center justify-center bg-black/80 backdrop-blur-md modal-overlay';
            modal.onclick = (e) => { if (e.target === modal) cerrarModalNuevoProducto(); };

            const costoRealUnidad = item.cantidadTotal > 0 ? (item.totalPagado / item.cantidadTotal) : 0;
            const hoy = new Date().toISOString().split('T')[0];
            const lugaresHtml = catalogos.lugares.map(l => `<option value="${l.id}" ${forcedLugarId == l.id ? 'selected' : ''}>${escapeHtml(l.nombre)}</option>`).join('');

            modal.innerHTML = `
                <div class="glass rounded-3xl w-full max-w-4xl mx-4 overflow-hidden shadow-2xl border border-white/10 animate-fade-in-up max-h-[95vh] flex flex-col">
                    <!-- Header -->
                    <div class="bg-gradient-to-r from-slate-900 to-slate-800 px-6 py-4 flex justify-between items-center border-b border-white/5">
                        <div class="flex items-center gap-3">
                            <div class="w-10 h-10 rounded-xl bg-emerald-500 flex items-center justify-center shadow-lg shadow-emerald-500/20">
                                <span class="text-xl">＋</span>
                            </div>
                            <h2 class="text-xl font-black text-white tracking-tight uppercase">Nuevo Producto</h2>
                        </div>
                        <button onclick="cerrarModalNuevoProducto()" class="w-10 h-10 rounded-full bg-white/5 hover:bg-white/10 flex items-center justify-center text-slate-400 hover:text-white transition-all">✕</button>
                    </div>

                    <!-- Content (Scrollable) -->
                    <div class="p-6 overflow-y-auto space-y-8 CustomScroll">
                        
                        <!-- Sección 1: Información Básica -->
                        <div class="space-y-4">
                            <h3 class="text-xs font-black text-indigo-400 uppercase tracking-[0.2em] flex items-center gap-2">
                                <span class="w-5 h-5 rounded-md bg-indigo-500/20 flex items-center justify-center text-[10px]">ℹ</span> Información Básica
                            </h3>
                            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Nombre Comercial <span class="text-red-500">*</span></label>
                                    <input type="text" id="np-nombre-com" value="${escapeHtml(item.descripcion)}" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2.5 text-sm text-white focus:border-emerald-500/50 focus:ring-4 focus:ring-emerald-500/10 transition-all outline-none">
                                </div>
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Nombre Genérico <span class="text-red-500">*</span></label>
                                    <input type="text" id="np-nombre-gen" placeholder="ej: Paracetamol" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2.5 text-sm text-white focus:border-emerald-500/50 focus:ring-4 focus:ring-emerald-500/10 transition-all outline-none">
                                </div>
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Código de Barras</label>
                                    <input type="text" id="np-cod-barra" placeholder="Escanear o ingresar..." class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2.5 text-sm text-white focus:border-emerald-500/50 focus:ring-4 focus:ring-emerald-500/10 transition-all outline-none">
                                </div>
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Laboratorio <span class="text-red-500">*</span></label>
                                    <input type="text" id="np-laboratorio" placeholder="Nombre de la farmacéutica" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2.5 text-sm text-white focus:border-emerald-500/50 focus:ring-4 focus:ring-emerald-500/10 transition-all outline-none">
                                </div>
                                <div class="space-y-1.5">
                                    <div class="flex justify-between items-center ml-1">
                                        <label class="text-[10px] uppercase font-bold text-slate-500">Lugar de Compra</label>
                                        <button onclick="mostrarModalNuevoLugar('np-lugar')" class="text-[9px] text-emerald-400 hover:text-emerald-300 font-bold uppercase tracking-widest transition-colors">＋ Nuevo</button>
                                    </div>
                                    <select id="np-lugar" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2.5 text-sm text-white focus:border-emerald-500/50 transition-all outline-none">
                                        <option value="">Seleccionar...</option>
                                        ${lugaresHtml}
                                    </select>
                                </div>
                                <div class="space-y-1.5 row-span-1">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Función Médica</label>
                                    <textarea id="np-funcion" rows="1" placeholder="Descripción del uso terapéutico..." class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2.5 text-sm text-white focus:border-emerald-500/50 transition-all outline-none resize-none"></textarea>
                                </div>
                            </div>
                        </div>

                        <!-- Sección 2: Presentaciones -->
                        <div class="space-y-4">
                            <h3 class="text-xs font-black text-blue-400 uppercase tracking-[0.2em] flex items-center gap-2">
                                <span class="w-5 h-5 rounded-md bg-blue-500/20 flex items-center justify-center text-[10px]">📦</span> Presentaciones
                            </h3>
                            <div class="grid grid-cols-3 gap-4">
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Unid. por Caja</label>
                                    <input type="number" id="np-f-caja" value="1" onchange="recalcularCostosModal()" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2.5 text-sm text-white text-center">
                                </div>
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Unid. por Blister</label>
                                    <input type="number" id="np-f-blister" value="1" onchange="recalcularCostosModal()" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2.5 text-sm text-white text-center">
                                </div>
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Unidad</label>
                                    <input type="number" value="1" disabled class="w-full bg-slate-800/50 border border-slate-700/30 rounded-xl px-4 py-2.5 text-sm text-slate-500 text-center">
                                </div>
                            </div>
                        </div>

                        <!-- Sección 3: Costo de Compra -->
                        <div class="space-y-4">
                            <h3 class="text-xs font-black text-amber-400 uppercase tracking-[0.2em] flex items-center gap-2">
                                <span class="w-5 h-5 rounded-md bg-amber-500/20 flex items-center justify-center text-[10px]">Q</span> Costo de Compra
                            </h3>
                            <div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-end">
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Costo de la Presentación</label>
                                    <div class="relative">
                                        <span class="absolute left-4 top-2.5 text-slate-500 text-sm">Q</span>
                                        <input type="number" step="0.0001" id="np-costo-base" value="${costoRealUnidad.toFixed(4)}" onchange="recalcularCostosModal()" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl pl-9 pr-4 py-2.5 text-sm text-white font-mono">
                                    </div>
                                </div>
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Presentación factura</label>
                                    <select id="np-pres-factura" onchange="recalcularCostosModal()" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2.5 text-sm text-white focus:border-emerald-500/50 transition-all outline-none">
                                        <option value="unidad" selected>💊 Por Unidad</option>
                                        <option value="blister">💊 Por Blister</option>
                                        <option value="caja">📦 Por Caja</option>
                                    </select>
                                </div>
                                <div class="bg-emerald-500/5 border border-emerald-500/10 rounded-xl p-3 flex justify-between items-center">
                                    <span class="text-[10px] uppercase font-bold text-slate-500">Costo Unitario:</span>
                                    <span class="text-sm font-black text-emerald-400 font-mono" id="np-preview-cu">Q0.00</span>
                                </div>
                            </div>
                        </div>

                        <!-- Sección 4: Precios de Venta -->
                        <div class="space-y-4">
                            <h3 class="text-xs font-black text-emerald-400 uppercase tracking-[0.2em] flex items-center gap-2">
                                <span class="w-5 h-5 rounded-md bg-emerald-500/20 flex items-center justify-center text-[10px]">🏷</span> Precios de Venta
                            </h3>
                            <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Unidad</label>
                                    <div class="relative">
                                        <span class="absolute left-3 top-2 text-slate-500 text-xs">Q</span>
                                        <input type="number" id="np-v-unidad" value="0" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl pl-8 pr-3 py-2 text-sm text-white font-bold">
                                    </div>
                                </div>
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Blister</label>
                                    <div class="relative">
                                        <span class="absolute left-3 top-2 text-slate-500 text-xs">Q</span>
                                        <input type="number" id="np-v-blister" value="0" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl pl-8 pr-3 py-2 text-sm text-white font-bold">
                                    </div>
                                </div>
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Mayor</label>
                                    <div class="relative">
                                        <span class="absolute left-3 top-2 text-slate-500 text-xs">Q</span>
                                        <input type="number" id="np-v-mayor" value="0" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl pl-8 pr-3 py-2 text-sm text-white font-bold">
                                    </div>
                                </div>
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Mixto</label>
                                    <div class="relative">
                                        <span class="absolute left-3 top-2 text-slate-500 text-xs">Q</span>
                                        <input type="number" id="np-v-mixto" value="0" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl pl-8 pr-3 py-2 text-sm text-white font-bold">
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- Sección 5: Inventario -->
                        <div class="space-y-4">
                            <h3 class="text-xs font-black text-purple-400 uppercase tracking-[0.2em] flex items-center gap-2">
                                <span class="w-5 h-5 rounded-md bg-purple-500/20 flex items-center justify-center text-[10px]">🚛</span> Inventario
                            </h3>
                            <div class="grid grid-cols-2 md:grid-cols-4 gap-4 items-center">
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Fecha Vencimiento <span class="text-red-500">*</span></label>
                                    <input type="date" id="np-vencimiento" value="${hoy}" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2 text-sm text-white outline-none">
                                </div>
                                <div class="space-y-1.5">
                                    <label class="text-[10px] uppercase font-bold text-slate-500 ml-1">Existencias (Cant. Factura <span class="text-red-500">*</span>)</label>
                                    <input type="number" id="np-existencia" value="${item.cantidadTotal}" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-2 text-sm text-white text-center font-bold">
                                </div>
                                <div class="flex items-center gap-2 mt-5">
                                    <input type="checkbox" id="np-con-factura" checked class="w-4 h-4 rounded border-slate-700 bg-slate-900 text-emerald-500">
                                    <label for="np-con-factura" class="text-[11px] font-bold text-slate-400">Con Factura</label>
                                </div>
                                <div class="flex items-center gap-2 mt-5">
                                    <input type="checkbox" id="np-exento-iva" ${item.esExento ? 'checked' : ''} class="w-4 h-4 rounded border-slate-700 bg-slate-900 text-amber-500">
                                    <label for="np-exento-iva" class="text-[11px] font-bold text-slate-400">Exento IVA</label>
                                </div>
                            </div>
                        </div>

                    </div>

                    <!-- Footer / Actions -->
                    <div class="p-6 bg-slate-900/50 border-t border-white/5 flex gap-4">
                        <button onclick="cerrarModalNuevoProducto()" class="flex-grow py-3 rounded-2xl text-sm font-bold text-slate-400 bg-slate-800/50 hover:bg-slate-800 transition-all border border-slate-700/50">Cancelar</button>
                        <button id="btnRegistrarNP" onclick="guardarNuevoProducto(${idx})" class="flex-[2] py-3 rounded-2xl text-sm font-bold text-white bg-gradient-to-r from-emerald-500 to-emerald-600 hover:from-emerald-400 hover:to-emerald-500 transition-all shadow-xl shadow-emerald-500/20 active:scale-95">Registrar Producto e Inventario</button>
                    </div>
                </div>
            `;
            document.body.appendChild(modal);
            modal.dataset.idx = idx;
            recalcularCostosModal();
        }

        function recalcularCostosModal() {
            const fCaja = parseInt(document.getElementById('np-f-caja').value) || 1;
            const fBlister = parseInt(document.getElementById('np-f-blister').value) || 1;
            const valorIngresado = parseFloat(document.getElementById('np-costo-base').value) || 0;
            const presSeleccionada = document.getElementById('np-pres-factura').value;

            let cu = 0;
            if (presSeleccionada === 'unidad') {
                cu = valorIngresado;
            } else if (presSeleccionada === 'blister') {
                cu = valorIngresado / (fBlister > 0 ? fBlister : 1);
            } else if (presSeleccionada === 'caja') {
                cu = valorIngresado / (fCaja > 0 ? fCaja : 1);
            }

            document.getElementById('np-preview-cu').textContent = `Q${formatMoney(cu)}`;
        }

        function cerrarModalNuevoProducto() {
            document.getElementById('modalNuevoProducto')?.remove();
        }

        async function guardarNuevoProducto(idx) {
            const btn = document.getElementById('btnRegistrarNP');
            const originalText = btn.textContent;

            // Validaciones básicas
            const nombreCom = document.getElementById('np-nombre-com').value.trim();
            const nombreGen = document.getElementById('np-nombre-gen').value.trim();
            const lab = document.getElementById('np-laboratorio').value.trim();
            
            if (!nombreCom || !nombreGen || !lab) {
                mostrarNotificacion('error', 'Faltan campos', 'Nombre Comercial, Genérico y Laboratorio son obligatorios');
                return;
            }

            btn.textContent = '⏳ Registrando...';
            btn.disabled = true;

            const item = processedItems[idx];
            const fCaja = parseInt(document.getElementById('np-f-caja').value) || 1;
            const fBlister = parseInt(document.getElementById('np-f-blister').value) || 1;
            const costoBase = parseFloat(document.getElementById('np-costo-base').value) || 0;
            const cantFactura = parseFloat(document.getElementById('np-existencia').value) || 0;
            const cu = parseFloat(document.getElementById('np-preview-cu').textContent.replace('Q','').replace(',',''));

            const payload = {
                NombreComercial: nombreCom,
                NombreGenerico: nombreGen,
                CodigoInterno: document.getElementById('np-cod-barra').value.trim() || null, // Usamos cod barra como interno si no hay
                CodigoBarra: document.getElementById('np-cod-barra').value.trim(),
                laboratorio: lab,
                id_lugarCompra: document.getElementById('np-lugar').value,
                FuncionMedica: document.getElementById('np-funcion').value,
                FactorCaja: fCaja,
                FactorBlister: fBlister,
                CostoUnidad: cu,
                PrecioVentaUnidad: document.getElementById('np-v-unidad').value,
                PrecioVentaBlister: document.getElementById('np-v-blister').value,
                PrecioVentaMayor: document.getElementById('np-v-mayor').value,
                PrecioVentaMixto: document.getElementById('np-v-mixto').value,
                FechaVencimiento: document.getElementById('np-vencimiento').value,
                existencia: cantFactura * fCaja, // Se guarda en unidades base
                conFactura: document.getElementById('np-con-factura').checked,
                exento_iva: document.getElementById('np-exento-iva').checked,
                descripcion_factura: item.descripcion,
                fecha_factura: item.fecha
            };

            try {
                const res = await fetch('api/consolidador/registrar_producto.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(payload)
                });
                const data = await res.json();

                if (data.success) {
                    cerrarModalNuevoProducto();
                    mostrarNotificacion('success', '¡Éxito!', data.message);
                    
                    // Auto-asignar a la fila
                    const dbProd = {
                        producto_id: data.data.id,
                        CodigoInterno: data.data.CodigoInterno || data.data.lote,
                        NombreComercial: data.data.NombreComercial,
                        FactorCaja: fCaja,
                        FactorBlister: fBlister,
                        PrecioVentaUnidad: payload.PrecioVentaUnidad,
                        PrecioVentaBlister: payload.PrecioVentaBlister,
                        PrecioVentaMayor: payload.PrecioVentaMayor,
                        PrecioVentaMixto: payload.PrecioVentaMixto,
                        exento_iva: payload.exento_iva ? 1 : 0
                    };
                    
                    asignarProducto(dbProd, idx);
                } else {
                    throw new Error(data.error);
                }
            } catch (err) {
                mostrarNotificacion('error', 'Error al registrar', err.message);
                btn.textContent = originalText;
                btn.disabled = false;
            }
        }
    