// ─── Theme Management ─── let currentTheme = 'dark'; function toggleTheme() { currentTheme = currentTheme === 'dark' ? 'light' : 'dark'; const html = document.documentElement; // Set theme attribute — CSS variables handle the rest html.setAttribute('data-theme', currentTheme); if (currentTheme === 'light') { document.body.classList.remove('dark'); } else { document.body.classList.add('dark'); } // Override Gradio internal CSS variables const root = document.documentElement; const isLight = currentTheme === 'light'; const vars = isLight ? { '--body-background-fill': '#f8fafc', '--block-background-fill': '#ffffff', '--block-border-color': '#e2e8f0', '--block-label-text-color': '#475569', '--block-title-text-color': '#0f172a', '--input-background-fill': '#f1f5f9', '--input-border-color': '#cbd5e1', '--body-text-color': '#0f172a', '--neutral-100': '#f1f5f9', '--neutral-200': '#e2e8f0', '--neutral-300': '#cbd5e1', '--neutral-400': '#94a3b8', '--neutral-500': '#64748b', '--neutral-600': '#475569', '--neutral-700': '#334155', '--neutral-800': '#1e293b', '--neutral-900': '#0f172a', } : { '--body-background-fill': '#0a0a0c', '--block-background-fill': '#111827', '--block-border-color': '#374151', '--block-label-text-color': '#9ca3af', '--block-title-text-color': '#ffffff', '--input-background-fill': '#1f2937', '--input-border-color': '#374151', '--body-text-color': '#ffffff', '--neutral-100': '#1f2937', '--neutral-200': '#374151', '--neutral-300': '#4b5563', '--neutral-400': '#6b7280', '--neutral-500': '#9ca3af', '--neutral-600': '#d1d5db', '--neutral-700': '#e5e7eb', '--neutral-800': '#f3f4f6', '--neutral-900': '#ffffff', }; // Apply Gradio vars to all containers document.querySelectorAll('.gradio-container').forEach(el => { Object.entries(vars).forEach(([k, v]) => el.style.setProperty(k, v)); el.style.background = isLight ? '#f8fafc' : '#0a0a0c'; el.style.color = isLight ? '#0f172a' : '#ffffff'; }); // Force Gradio block/form/panel backgrounds const bgColor = isLight ? '#ffffff' : '#111827'; const borderColor = isLight ? '#e2e8f0' : '#374151'; const textColor = isLight ? '#0f172a' : '#ffffff'; const subTextColor = isLight ? '#475569' : '#9ca3af'; const inputBg = isLight ? '#f1f5f9' : '#1f2937'; document.querySelectorAll('.block, .form, .panel').forEach(el => { el.style.backgroundColor = bgColor; el.style.borderColor = borderColor; }); document.querySelectorAll('input, textarea, select').forEach(el => { if (!el.closest('.glass-input-wrapper')) { el.style.backgroundColor = inputBg; el.style.borderColor = borderColor; } el.style.color = textColor; }); document.querySelectorAll('label, .label-wrap, .block-label').forEach(el => { if (!el.closest('.header-banner') && !el.closest('.glass-input-wrapper')) { el.style.color = subTextColor; } }); // Update toggle button icon const btn = document.getElementById('theme-toggle'); if (btn) { btn.innerHTML = currentTheme === 'dark' ? '☀️' : '🌙'; btn.title = currentTheme === 'dark' ? 'Cambiar a modo claro' : 'Cambiar a modo oscuro'; } // Save preference try { localStorage.setItem('letxipu-theme', currentTheme); } catch(e) {} } // Initialize theme on load (respect saved preference) document.addEventListener('DOMContentLoaded', function() { try { var saved = localStorage.getItem('letxipu-theme'); if (saved === 'light') { currentTheme = 'dark'; // will be toggled to light toggleTheme(); return; } } catch(e) {} document.body.classList.add('dark'); document.documentElement.setAttribute('data-theme', 'dark'); }); window._copyCitation = function(btn, citeText) { navigator.clipboard.writeText(citeText).then(function() { var originalHtml = btn.innerHTML; btn.innerHTML = '✅ Copiado'; btn.style.color = '#10b981'; btn.style.borderColor = 'rgba(16,185,129,0.3)'; setTimeout(function() { btn.innerHTML = originalHtml; btn.style.color = 'var(--foreground, #fff)'; btn.style.borderColor = 'var(--border, rgba(255,255,255,0.1))'; }, 2000); }); }; // ─── Citation Floating Card (Global) ─── window.showCiteCard = function(el) { var b64 = el.getAttribute('data-cite-b64'); var raw = el.getAttribute('data-cite'); if (!b64 && !raw) return; var data; try { if (b64) { var decoded = decodeURIComponent(escape(atob(b64))); data = JSON.parse(decoded); } else { data = JSON.parse(raw.replace(/"/g,'"').replace(/'/g,"'")); } } catch(e) { console.error('CiteCard parse error', e); return; } var card = document.getElementById('cite-card-global'); var overlay = document.getElementById('cite-card-overlay-global'); if (!card) { overlay = document.createElement('div'); overlay.id = 'cite-card-overlay-global'; overlay.style.cssText = 'display:none;position:fixed;top:0;left:0;width:100%;height:100%;z-index:999998;background:transparent;'; overlay.addEventListener('click', function(){ window.closeCiteCard(); }); document.body.appendChild(overlay); card = document.createElement('div'); card.id = 'cite-card-global'; card.style.cssText = 'display:none;position:fixed;z-index:999999;width:340px;max-width:90vw;background:var(--popup-bg, rgba(17,24,39,0.95));backdrop-filter:blur(10px);border:1px solid var(--popup-border, rgba(139,92,246,0.3));border-radius:12px;box-shadow:0 20px 60px rgba(0,0,0,0.5),0 0 30px rgba(139,92,246,0.1);font-family:Inter,sans-serif;transition:opacity 0.2s ease,transform 0.2s ease;opacity:0;transform:translateY(8px);color:var(--foreground, #fff);display:flex;flex-direction:column;'; card.innerHTML = '
'; document.body.appendChild(card); // Setup dragging var isDragging = false; var dragOffset = {x: 0, y: 0}; document.addEventListener('mousemove', function(e) { if (isDragging && card) { card.style.left = (e.clientX - dragOffset.x) + 'px'; card.style.top = (e.clientY - dragOffset.y) + 'px'; card.style.transform = 'none'; // Clear animation transform } }); document.addEventListener('mouseup', function(e) { isDragging = false; }); window._startCardDrag = function(e) { isDragging = true; var rect = card.getBoundingClientRect(); dragOffset.x = e.clientX - rect.left; dragOffset.y = e.clientY - rect.top; e.preventDefault(); }; } overlay = document.getElementById('cite-card-overlay-global'); var content = document.getElementById('cite-card-content-global'); var doi = data.DOI || data.doi || ''; var pdfUrl = data.pdf_url || data.PDF || ''; var title = data['Título'] || data.title || 'Sin título'; var authors = data['Autores'] || data.authors || 'Autor desconocido'; var year = data['Año'] || data.year || '?'; var source = data['Fuente'] || data.source || 'Desconocido'; var abstract = data['Abstract'] || data.abstract || ''; // Icon SVGs var iconMove = ''; var iconX = ''; var iconMsg = ''; var iconDl = ''; var iconQuote = ''; var iconLang = ''; var iconBranch = ''; var iconExt = ''; var iconSearch = ''; // Header var headerHtml = '
' + '
' + iconMove + 'CITAR' + '
' + '' + '
'; var authorStr = Array.isArray(authors) ? authors.join(', ') : authors; var firstAuthor = Array.isArray(authors) ? authors[0] : authors.split(",")[0]; // Compute source URL and button styling var sourceUrl = data.url || data.URL || ''; if (!sourceUrl && doi) sourceUrl = 'https://doi.org/' + doi; if (!sourceUrl) sourceUrl = '#'; var sourceBtnText = 'Ver fuente'; var sourceBtnColor = '#a78bfa'; var sourceBtnBg = 'rgba(139,92,246,0.1)'; var sourceBtnBorder = 'rgba(139,92,246,0.3)'; var sourceBtnIcon = iconExt; if (source.toLowerCase().includes('pubmed')) { sourceBtnText = 'PubMed'; sourceBtnColor = '#22c55e'; sourceBtnBg = 'rgba(34,197,94,0.1)'; sourceBtnBorder = 'rgba(34,197,94,0.3)'; sourceBtnIcon = iconSearch; } else if (source.toLowerCase().includes('semantic')) { sourceBtnText = 'Semantic Scholar'; sourceBtnColor = '#3b82f6'; sourceBtnBg = 'rgba(59,130,246,0.1)'; sourceBtnBorder = 'rgba(59,130,246,0.3)'; sourceBtnIcon = iconSearch; } else if (source.toLowerCase().includes('crossref')) { sourceBtnText = 'Crossref'; sourceBtnColor = '#f59e0b'; sourceBtnBg = 'rgba(245,158,11,0.1)'; sourceBtnBorder = 'rgba(245,158,11,0.3)'; sourceBtnIcon = iconSearch; } else if (source.toLowerCase().includes('openalex')) { sourceBtnText = 'OpenAlex'; sourceBtnColor = '#ec4899'; sourceBtnBg = 'rgba(236,72,153,0.1)'; sourceBtnBorder = 'rgba(236,72,153,0.3)'; sourceBtnIcon = iconSearch; } else if (doi) { sourceBtnText = 'DOI'; sourceBtnColor = '#06b6d4'; sourceBtnBg = 'rgba(6,182,212,0.1)'; sourceBtnBorder = 'rgba(6,182,212,0.3)'; sourceBtnIcon = iconExt; } var citeString = firstAuthor + " et al. (" + year + "). " + title + ". " + sourceUrl; var escapedCiteString = citeString.replace(/'/g, "\\'").replace(/"/g, """).replace(/\n/g, " ").replace(/\r/g, ""); // Buttons var actionBtnsHtml = '
' + '' + (pdfUrl ? '' + iconDl + ' Descargar' + '' : '') + '' + '' + '' + '
'; // Abstract box var abstractHtml = ''; if (abstract) { abstractHtml = '
' + abstract + '
'; } var bodyHtml = '
' + '
' + title + '
' + actionBtnsHtml + '
' + authorStr + ' | ' + year + '
' + abstractHtml + '
' + '' + sourceBtnIcon + sourceBtnText + '' + '
' + '
'; content.innerHTML = headerHtml + bodyHtml; // Centering Logic var rect = el.getBoundingClientRect(); var cardW = 340; var left = rect.left + rect.width/2 - cardW/2; if (left < 10) left = 10; if (left + cardW > window.innerWidth - 10) left = window.innerWidth - cardW - 10; // Position slightly offset from cursor or element var top = rect.bottom + 10; if (top + 400 > window.innerHeight) { top = window.innerHeight - 410; if (top < 10) top = 10; } card.style.left = left + 'px'; card.style.top = top + 'px'; overlay.style.display = 'block'; card.style.display = 'flex'; setTimeout(function(){ card.style.opacity='1'; card.style.transform='translateY(0)'; }, 10); }; window.closeCiteCard = function() { var card = document.getElementById('cite-card-global'); var overlay = document.getElementById('cite-card-overlay-global'); if (card) { card.style.opacity = '0'; card.style.transform = 'translateY(8px)'; setTimeout(function(){ card.style.display='none'; if(overlay) overlay.style.display='none'; }, 200); } }; // Event Delegation for Cite Links (Fix for Gradio 6 removing inline onclick handlers) document.addEventListener('click', function(e) { const citeLink = e.target.closest('.cite-link'); if (citeLink) { e.preventDefault(); window.showCiteCard(citeLink); return; } // Check for close button if (e.target.closest('.close-cite-btn')) { e.preventDefault(); window.closeCiteCard(); } }); // References Pagination Logic window.initRefsPagination = function() { var container = document.getElementById('refs-container'); if (!container) return; var items = Array.from(container.querySelectorAll('.ref-item')); var filterCb = document.getElementById('refs-filter-cited'); var citedFilter = filterCb ? filterCb.checked : false; var visibleItems = items.filter(function(item) { if (citedFilter && item.getAttribute('data-cited') !== 'true') return false; return true; }); var perPage = 10; var totalPages = Math.ceil(visibleItems.length / perPage); var currentPage = parseInt(container.getAttribute('data-page')) || 1; if (currentPage > totalPages && totalPages > 0) currentPage = totalPages; if (currentPage < 1) currentPage = 1; items.forEach(function(item) { item.style.display = 'none'; }); var start = (currentPage - 1) * perPage; var end = start + perPage; for (var i = start; i < end && i < visibleItems.length; i++) { visibleItems[i].style.display = 'flex'; } var pagContainer = document.getElementById('refs-pagination'); if (pagContainer) { pagContainer.innerHTML = ''; if (totalPages > 1) { var createBtn = function(text, page, disabled, active) { var b = document.createElement('button'); b.innerHTML = text; b.style.cssText = 'padding: 6px 14px; margin: 0 2px; border: 1px solid var(--border, #374151); background: ' + (active ? 'var(--accent, #8b5cf6)' : 'transparent') + '; color: ' + (active ? '#fff' : 'var(--foreground, #d1d5db)') + '; border-radius: 6px; cursor: ' + (disabled ? 'default' : 'pointer') + '; opacity: ' + (disabled ? '0.5' : '1') + '; font-size: 13px; font-weight: 600; transition: all 0.2s;'; if (!disabled && !active) { b.onmouseover = function() { b.style.background = 'rgba(139,92,246,0.15)'; }; b.onmouseout = function() { b.style.background = 'transparent'; }; b.onclick = function() { container.setAttribute('data-page', page); window.initRefsPagination(); // Scroll to top of container smoothly var y = container.getBoundingClientRect().top + window.scrollY - 100; window.scrollTo({top: y, behavior: 'smooth'}); }; } return b; }; pagContainer.appendChild(createBtn('Anterior', currentPage - 1, currentPage === 1, false)); var startP = Math.max(1, currentPage - 2); var endP = Math.min(totalPages, startP + 4); if (endP - startP < 4) startP = Math.max(1, endP - 4); for (var p = startP; p <= endP; p++) { pagContainer.appendChild(createBtn(p, p, false, p === currentPage)); } pagContainer.appendChild(createBtn('Siguiente', currentPage + 1, currentPage === totalPages, false)); } } var stats = document.getElementById('refs-stats'); if (stats) stats.innerHTML = 'Mostrando ' + (visibleItems.length > 0 ? start + 1 : 0) + ' - ' + Math.min(end, visibleItems.length) + ' de ' + visibleItems.length + ' referencias'; }; // Make Headers Collapsible window.makeHeadersCollapsible = function() { var container = document.getElementById('report-content'); if (!container) return; // Prevent double processing if (container.getAttribute('data-collapsible-processed') === 'true') return; container.setAttribute('data-collapsible-processed', 'true'); var headers = Array.from(container.querySelectorAll('h1, h2, h3, h4, h5, h6')); if (headers.length === 0) return; headers.forEach(function(h) { if (h.parentElement && h.parentElement.tagName.toLowerCase() === 'summary') return; var details = document.createElement('details'); details.open = true; // Open by default as requested var summary = document.createElement('summary'); summary.innerHTML = h.innerHTML; summary.className = h.className; h.parentNode.insertBefore(details, h); details.appendChild(summary); var headerLevel = parseInt(h.tagName[1]); var next = h.nextSibling; while (next) { var current = next; next = next.nextSibling; if (current.nodeType === 1 && current.tagName.match(/^H[1-6]$/i)) { var currentLevel = parseInt(current.tagName[1]); if (currentLevel <= headerLevel) { break; } } details.appendChild(current); } h.remove(); }); }; // MathJax Loading window.MathJax = { tex: { inlineMath: [['$','$'], ['\\\\(','\\\\)']], displayMath: [['$$','$$'], ['\\\\[','\\\\]']] }, options: { skipHtmlTags: ['script','noscript','style','textarea','pre','code'] } }; const script = document.createElement('script'); script.src = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"; script.async = true; document.head.appendChild(script);