See More

${lang === 'en' ? p.en : p.es}`).join(''); /* Barras de idioma */ const langBars = SHOW.languages ? `

${t('about.langs_label')}
${LANGUAGES.map(l => `
${l.name}
${l.level} `).join('')} ` : ''; /* Sidebar */ const { links } = PROFILE; const sidebarRows = [ { key: t('sidebar.location'), val: PROFILE.location_full }, { key: t('sidebar.availability'), val: PROFILE.is_available ? `${t('sidebar.available_yes')}` : (lang === 'en' ? 'Not available' : 'No disponible') }, { key: t('sidebar.mode'), val: lang === 'en' ? PROFILE.work_mode_en : PROFILE.work_mode_es }, { key: t('sidebar.education'), val: lang === 'en' ? PROFILE.education_en : PROFILE.education_es }, links.github ? { key: 'GitHub', val: `${GITHUB_USER} ↗` } : null, links.linkedin ? { key: 'LinkedIn', val: `${PROFILE.name_full.split(' ').slice(0,2).join(' ')} ↗` } : null, links.email ? { key: 'Email', val: `${links.email}` } : null, links.phone ? { key: t('sidebar.phone'), val: `${PROFILE.links.phone_display}` } : null, links.cv ? { key: 'CV', val: `Descargar ↗` } : null, ].filter(Boolean); const sidebarHtml = sidebarRows.map(r => `
${r.key} ${r.val} `).join(''); target.innerHTML = `
${t('about.label')}

${t('about.title_pre')} ${t('about.title_hl')}
${paragraphs} ${langBars}
${sidebarHtml} `; if (SHOW.languages) langBarObs.observe(target.querySelector('.lang-rows')); observeAll(target); } /* ──────────────────────────────────────────────────── CONTACTO ──────────────────────────────────────────────────── */ function renderContact() { const target = document.getElementById('contactSection'); if (!SHOW.contact) { target.remove(); return; } const { links } = PROFILE; const cards = [ links.email ? { href: `mailto:${links.email}`, icon: '✉️', label: 'Email', val: links.email } : null, links.github ? { href: links.github, icon: '⌥', label: 'GitHub', val: GITHUB_USER, ext: true } : null, links.linkedin ? { href: links.linkedin, icon: 'in', label: 'LinkedIn', val: PROFILE.name_full.split(' ').slice(0,2).join(' '), ext: true } : null, links.phone ? { href: `tel:${links.phone}`, icon: '📱', label: 'WhatsApp', val: links.phone_display } : null, links.cv ? { href: links.cv, icon: '📄', label: 'CV', val: lang === 'en' ? 'Download ↗' : 'Descargar ↗', ext: true } : null, ].filter(Boolean); const cardsHtml = cards.map(c => `
${t('contact.label')}

${t('contact.title')}

${t('contact.sub')}

${cardsHtml} `; } /* ──────────────────────────────────────────────────── FOOTER ──────────────────────────────────────────────────── */ function renderFooter() { const footer = document.getElementById('siteFooter'); footer.innerHTML = `

© ${PROFILE.year} ${PROFILE.name_full} ${PROFILE.links.github ? `${PROFILE.links.github.replace('https://', '')} ↗` : ''}`; } /* ──────────────────────────────────────────────────── ORQUESTADOR PRINCIPAL ──────────────────────────────────────────────────── */ function renderAll() { /* Metadatos de página */ document.getElementById('pageTitle').textContent = `${PROFILE.name_line1} ${PROFILE.name_line2} · Data Scientist`; document.getElementById('metaDesc').content = `${PROFILE.name_full} — Data Scientist & ML Engineer. Portafolio de proyectos de ciencia de datos, machine learning y analítica.`; renderNav(); renderHero(); renderStats(); renderProjectsShell(); /* crea el shell; luego renderPinned y loadExtraFromGitHub llenan los grids */ renderSkills(); renderExperience(); renderCertifications(); renderAbout(); renderContact(); renderFooter(); observeAll(); /* observa todos los .reveal que existan en este momento */ } function refreshContent() { /* Actualiza solo las partes que dependen del idioma, sin desmontar/remontar secciones (evita reflows grandes) */ renderNav(); renderHero(); renderStats(); renderProjectsShell(); renderSkills(); renderExperience(); renderCertifications(); renderAbout(); renderContact(); renderFooter(); observeAll(); renderPinned(); loadExtraFromGitHub(); } /* ──────────────────────────────────────────────────── CAMBIO DE IDIOMA ──────────────────────────────────────────────────── */ function applyLang(l) { lang = l; document.documentElement.lang = l; document.getElementById('btn-es').classList.toggle('active', l === 'es'); document.getElementById('btn-en').classList.toggle('active', l === 'en'); document.getElementById('btn-es').setAttribute('aria-pressed', l === 'es'); document.getElementById('btn-en').setAttribute('aria-pressed', l === 'en'); refreshContent(); } document.getElementById('btn-es').addEventListener('click', () => applyLang('es')); document.getElementById('btn-en').addEventListener('click', () => applyLang('en')); /* ──────────────────────────────────────────────────── INIT ──────────────────────────────────────────────────── */ function detectLang() { return (navigator.language || 'es').toLowerCase().startsWith('es') ? 'es' : 'en'; } lang = detectLang(); document.getElementById('btn-' + lang).classList.add('active'); document.getElementById('btn-' + lang).setAttribute('aria-pressed', 'true'); renderAll(); renderPinned(); loadExtraFromGitHub();