Files
cv-site/templates/index.html
T
juanatsap 93b471b7e3 feat: add zoom control with accessibility and persistence
UI Components:
- Fixed bottom-center zoom slider (50%-200% range, step 5%)
- Modern glass-morphism design with gradient slider track
- Reset button with smooth rotation animation
- Real-time zoom percentage display
- Fully responsive (desktop/tablet/mobile)

Functionality:
- CSS transform-based zoom (GPU accelerated)
- localStorage persistence across sessions
- Keyboard shortcuts: Ctrl/Cmd +/-/0
- Smooth transitions with debouncing (50ms)
- Scroll position preservation during zoom
- Print mode: Temporarily resets to 100%

Accessibility (WCAG AA):
- Complete ARIA labels and live regions
- Keyboard navigation support
- Focus indicators on all interactive elements
- Screen reader compatible (announces zoom level)
- Touch-friendly (44px+ targets)

Integration:
- Follows existing toggle patterns (length, logos, theme)
- Initializes in initPreferences()
- Works with print-friendly mode
- Hidden in print (.no-print class)
- Bilingual support (English/Spanish)

Performance:
- will-change: transform for compositor layer
- Debounced slider input for smooth dragging
- requestAnimationFrame for scroll preservation
- No layout thrashing (transform-only changes)

Technical Details:
- Range: 50-200 (prevents unusability, allows 2x mag)
- Transform origin: top center (maintains alignment)
- Transition: 300ms cubic-bezier (material design)
- Storage key: 'cv-zoom'
- Default: 100% (normal view)
2025-11-12 11:00:29 +00:00

520 lines
27 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="{{if eq .Lang "es"}}es{{else}}en{{end}}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Primary Meta Tags -->
<title>{{.CV.Personal.Name}} - {{if eq .Lang "es"}}Curriculum Vitae{{else}}Curriculum Vitae{{end}}</title>
<meta name="title" content="{{.CV.Personal.Name}} - {{if eq .Lang "es"}}CV Profesional{{else}}Professional CV{{end}}">
<meta name="description" content="{{.CV.Personal.Title}} | {{if eq .Lang "es"}}18 años de experiencia en desarrollo web, SAP CDC, React, Node.js, Go, HTMX y desarrollo asistido por IA{{else}}18 years of experience in web development, SAP CDC, React, Node.js, Go, HTMX and AI-assisted development{{end}}">
<meta name="keywords" content="{{if eq .Lang "es"}}CV, Curriculum Vitae, {{.CV.Personal.Name}}, Desarrollador FullStack, SAP CDC, React, Node.js, Go, HTMX, IA, Desarrollo Web, Consultor Técnico{{else}}CV, Resume, {{.CV.Personal.Name}}, FullStack Developer, SAP CDC, React, Node.js, Go, HTMX, AI, Web Development, Technical Consultant{{end}}">
<meta name="author" content="{{.CV.Personal.Name}}">
<meta name="robots" content="index, follow">
<link rel="canonical" href="{{.CanonicalURL}}">
<!-- Hreflang tags for international SEO -->
<link rel="alternate" hreflang="en" href="{{.AlternateEN}}">
<link rel="alternate" hreflang="es" href="{{.AlternateES}}">
<link rel="alternate" hreflang="x-default" href="https://juan.andres.morenorub.io/?lang=en">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="profile">
<meta property="og:url" content="{{.CV.Personal.Website}}">
<meta property="og:title" content="{{.CV.Personal.Name}} - {{if eq .Lang "es"}}CV Profesional{{else}}Professional CV{{end}}">
<meta property="og:description" content="{{.CV.Personal.Title}} | {{if eq .Lang "es"}}Consultor Técnico Senior con 18 años de experiencia{{else}}Senior Technical Consultant with 18 years of experience{{end}}">
<meta property="og:image" content="{{.CV.Personal.Website}}/static/images/profile.jpg">
<meta property="og:locale" content="{{if eq .Lang "es"}}es_ES{{else}}en_US{{end}}">
<meta property="og:site_name" content="{{.CV.Personal.Name}}">
<meta property="profile:first_name" content="Juan Andrés">
<meta property="profile:last_name" content="Moreno Rubio">
<meta property="profile:username" content="txeo">
<!-- Social Media Card (Generic) -->
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="{{.CV.Personal.Name}} - {{if eq .Lang "es"}}CV Profesional{{else}}Professional CV{{end}}">
<meta name="twitter:description" content="{{.CV.Personal.Title}}">
<meta name="twitter:image" content="{{.CV.Personal.Website}}/static/images/profile.jpg">
<!-- HTMX Configuration -->
<meta name="htmx-config" content='{"timeout":5000,"defaultSwapStyle":"innerHTML","defaultSwapDelay":0,"defaultSettleDelay":20}'>
<!-- HTMX with SRI (Subresource Integrity) -->
<script src="https://unpkg.com/htmx.org@1.9.10"
integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC"
crossorigin="anonymous"></script>
<!-- Iconify - Load synchronously for immediate rendering -->
<script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script>
<!-- CSS -->
<link rel="stylesheet" href="/static/css/main.css">
<link rel="stylesheet" href="/static/css/logo-toggle.css">
<link rel="stylesheet" href="/static/css/print.css" media="print">
<!-- Fonts with Preload -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- Structured Data (JSON-LD) -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": "{{.CV.Personal.Name}}",
"jobTitle": "{{.CV.Personal.Title}}",
"url": "{{.CV.Personal.Website}}",
"email": "{{.CV.Personal.Email}}",
"telephone": "{{.CV.Personal.Phone}}",
"address": {
"@type": "PostalAddress",
"addressLocality": "{{.CV.Personal.Location}}"
},
"sameAs": [
"{{.CV.Personal.LinkedIn}}",
"{{.CV.Personal.GitHub}}",
"{{.CV.Personal.Domestika}}"
],
"alumniOf": {
"@type": "EducationalOrganization",
"name": "Universidad de Extremadura"
},
"knowsAbout": [
"Web Development",
"SAP Customer Data Cloud",
"React",
"Node.js",
"Go",
"HTMX",
"AI-Assisted Development",
"Full Stack Development"
],
"worksFor": {
"@type": "Organization",
"name": "Olympic Broadcasting Services"
}
}
</script>
</head>
<body>
<!-- Single Black Bar with Everything -->
<div class="action-bar no-print" role="navigation" aria-label="Language and export controls">
<div class="action-bar-content">
<!-- Left: Site Title + Hamburger Menu + Language -->
<div class="site-title">
<!-- Left group: Logo + Hamburger -->
<div class="site-title-left">
<a href="/" class="site-logo-link" id="logoLink" aria-label="Home">
<iconify-icon icon="mdi:file-account" width="24" height="24" class="site-icon"></iconify-icon>
</a>
<!-- Hamburger Menu Button -->
<button class="hamburger-btn" aria-label="Toggle navigation menu">
<iconify-icon icon="mdi:menu" width="24" height="24"></iconify-icon>
</button>
</div>
<!-- Center: Title -->
<a href="/" class="site-title-link" id="titleLink">
<iconify-icon icon="mdi:file-account" width="20" height="20" class="site-icon-mobile"></iconify-icon>
<span class="site-title-text">CV JAMR<span class="site-title-year"> - {{.CurrentYear}}</span></span>
</a>
<!-- Right: Language selector -->
<div class="language-selector">
<button class="selector-btn {{if eq .Lang "en"}}active{{end}}" data-short="EN" onclick="selectLanguage('en')" aria-label="English">
English
</button>
<button class="selector-btn {{if eq .Lang "es"}}active{{end}}" data-short="ES" onclick="selectLanguage('es')" aria-label="Español">
Español
</button>
</div>
</div>
<!-- Center: View controls with labels -->
<div class="view-controls-center">
<!-- CV Length toggle -->
<div class="selector-group">
<label class="selector-label">{{if eq .Lang "es"}}Longitud{{else}}Length{{end}}:</label>
<label class="icon-toggle">
<input type="checkbox" id="lengthToggle" onchange="toggleCVLength()">
<span class="icon-toggle-slider">
<iconify-icon icon="mdi:file-document-outline" width="16" height="16" class="icon-left"></iconify-icon>
<iconify-icon icon="mdi:file-document-multiple-outline" width="16" height="16" class="icon-right"></iconify-icon>
</span>
</label>
</div>
<!-- Logo toggle -->
<div class="selector-group">
<label class="selector-label">{{if eq .Lang "es"}}Logos{{else}}Logos{{end}}:</label>
<label class="icon-toggle">
<input type="checkbox" id="logoToggle" checked onchange="toggleLogos()">
<span class="icon-toggle-slider">
<iconify-icon icon="mdi:image-off-outline" width="16" height="16" class="icon-left"></iconify-icon>
<iconify-icon icon="mdi:image-multiple-outline" width="16" height="16" class="icon-right"></iconify-icon>
</span>
</label>
</div>
<!-- Theme toggle -->
<div class="selector-group">
<label class="selector-label">{{if eq .Lang "es"}}Vista{{else}}View{{end}}:</label>
<label class="icon-toggle">
<input type="checkbox" id="themeToggle" onchange="toggleTheme()">
<span class="icon-toggle-slider">
<iconify-icon icon="mdi:page-layout-sidebar-left" width="16" height="16" class="icon-left"></iconify-icon>
<iconify-icon icon="mdi:page-layout-body" width="16" height="16" class="icon-right"></iconify-icon>
</span>
</label>
</div>
</div>
<!-- Right: Action buttons -->
<div class="action-buttons-right">
<button
class="action-btn pdf-btn"
onclick="openPdfModal()"
aria-label="{{if eq .Lang "es"}}Descargar como PDF{{else}}Download as PDF{{end}}">
<iconify-icon icon="mdi:download" width="18" height="18"></iconify-icon>
{{if eq .Lang "es"}}Descargar como PDF{{else}}Download as PDF{{end}}
</button>
<button
class="action-btn print-btn"
onclick="printFriendly()"
aria-label="{{if eq .Lang "es"}}Imprimir amigable{{else}}Print Friendly{{end}}">
<iconify-icon icon="mdi:leaf" width="18" height="18"></iconify-icon>
{{if eq .Lang "es"}}Imprimir amigable{{else}}Print Friendly{{end}}
</button>
</div>
<span id="loading"
class="htmx-indicator"
role="status"
aria-live="polite"
aria-label="Loading">
<span class="loader"></span>
</span>
</div>
</div>
<!-- Navigation Menu (Hidden by default) -->
<nav id="navigation-menu" class="navigation-menu no-print" role="navigation" aria-label="CV sections">
<div class="menu-content">
<!-- CV Sections - Quick Navigation -->
<div class="menu-item-submenu">
<a href="#" class="menu-item has-submenu">
<iconify-icon icon="mdi:menu" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Secciones CV{{else}}CV Sections{{end}}</span>
<iconify-icon icon="mdi:chevron-right" width="16" height="16" class="submenu-arrow"></iconify-icon>
</a>
<div class="submenu-content">
<a href="#education" class="menu-item" onclick="scrollToSection('education')">
<iconify-icon icon="mdi:school" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Formación{{else}}Training{{end}}</span>
</a>
<a href="#skills" class="menu-item" onclick="scrollToSection('skills')">
<iconify-icon icon="mdi:brain" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Competencias{{else}}Skills{{end}}</span>
</a>
<a href="#experience" class="menu-item" onclick="scrollToSection('experience')">
<iconify-icon icon="mdi:office-building" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Experiencia{{else}}Experience{{end}}</span>
</a>
<a href="#awards" class="menu-item" onclick="scrollToSection('awards')">
<iconify-icon icon="mdi:trophy" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Premios y Reconocimientos{{else}}Awards{{end}}</span>
</a>
<a href="#projects" class="menu-item" onclick="scrollToSection('projects')">
<iconify-icon icon="mdi:web" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Proyectos Personales / Freelance{{else}}Personal / Freelance Projects{{end}}</span>
</a>
<a href="#courses" class="menu-item" onclick="scrollToSection('courses')">
<iconify-icon icon="mdi:school" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Cursos Realizados{{else}}Courses{{end}}</span>
</a>
<a href="#languages" class="menu-item" onclick="scrollToSection('languages')">
<iconify-icon icon="mdi:translate" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Idiomas{{else}}Languages{{end}}</span>
</a>
<a href="#references" class="menu-item" onclick="scrollToSection('references')">
<iconify-icon icon="mdi:link-variant" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Referencias{{else}}References{{end}}</span>
</a>
<a href="#other" class="menu-item" onclick="scrollToSection('other')">
<iconify-icon icon="mdi:information" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Otros{{else}}Other{{end}}</span>
</a>
</div>
</div>
<!-- Quick Actions Section -->
<div class="menu-section-wrapper">
<div class="menu-item menu-item-header">
<iconify-icon icon="mdi:cog-outline" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Acciones Rápidas{{else}}Quick Actions{{end}}</span>
</div>
<a href="#" class="menu-item menu-item-action" onclick="collapseAllSections(event)">
<iconify-icon icon="mdi:arrow-collapse-all" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Colapsar Todo{{else}}Collapse All{{end}}</span>
</a>
<a href="#" class="menu-item menu-item-action" onclick="expandAllSections(event)">
<iconify-icon icon="mdi:arrow-expand-all" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Expandir Todo{{else}}Expand All{{end}}</span>
</a>
</div>
<!-- View Controls in menu (visible only on mobile < 900px) -->
<div class="menu-controls-section">
<div class="menu-item menu-item-header">
<iconify-icon icon="mdi:tune-variant" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Controles de Vista{{else}}View Controls{{end}}</span>
</div>
<!-- CV Length toggle -->
<div class="menu-control-item">
<label class="menu-control-label">
<iconify-icon icon="mdi:file-document-outline" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Longitud{{else}}Length{{end}}</span>
</label>
<label class="icon-toggle">
<input type="checkbox" id="lengthToggleMenu" onchange="toggleCVLength()">
<span class="icon-toggle-slider">
<iconify-icon icon="mdi:file-document-outline" width="16" height="16" class="icon-left"></iconify-icon>
<iconify-icon icon="mdi:file-document-multiple-outline" width="16" height="16" class="icon-right"></iconify-icon>
</span>
</label>
</div>
<!-- Logo toggle -->
<div class="menu-control-item">
<label class="menu-control-label">
<iconify-icon icon="mdi:image-multiple-outline" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Logos{{else}}Logos{{end}}</span>
</label>
<label class="icon-toggle">
<input type="checkbox" id="logoToggleMenu" checked onchange="toggleLogos()">
<span class="icon-toggle-slider">
<iconify-icon icon="mdi:image-off-outline" width="16" height="16" class="icon-left"></iconify-icon>
<iconify-icon icon="mdi:image-multiple-outline" width="16" height="16" class="icon-right"></iconify-icon>
</span>
</label>
</div>
<!-- Theme toggle -->
<div class="menu-control-item">
<label class="menu-control-label">
<iconify-icon icon="mdi:page-layout-sidebar-left" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Vista{{else}}View{{end}}</span>
</label>
<label class="icon-toggle">
<input type="checkbox" id="themeToggleMenu" onchange="toggleTheme()">
<span class="icon-toggle-slider">
<iconify-icon icon="mdi:page-layout-sidebar-left" width="16" height="16" class="icon-left"></iconify-icon>
<iconify-icon icon="mdi:page-layout-body" width="16" height="16" class="icon-right"></iconify-icon>
</span>
</label>
</div>
</div>
<!-- Action Buttons in menu (visible only on mobile < 900px) -->
<div class="menu-actions-section">
<div class="menu-item menu-item-header">
<iconify-icon icon="mdi:lightning-bolt" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Acciones{{else}}Actions{{end}}</span>
</div>
<button class="menu-action-btn" onclick="openPdfModal()">
<iconify-icon icon="mdi:download" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Descargar como PDF{{else}}Download as PDF{{end}}</span>
</button>
<button class="menu-action-btn" onclick="printFriendly()">
<iconify-icon icon="mdi:leaf" width="20" height="20"></iconify-icon>
<span>{{if eq .Lang "es"}}Imprimir amigable{{else}}Print Friendly{{end}}</span>
</button>
</div>
</div>
</nav>
<!-- CV Content Container -->
<div class="cv-container">
<main id="cv-content"
class="cv-paper"
role="main"
aria-live="polite">
{{template "cv-content.html" .}}
</main>
</div>
<!-- Footer (hidden in print) -->
<footer class="no-print">
<p style="text-align: center; margin-bottom: 0.5rem;">
<a href="https://github.com/juanatsap/cv-site" target="_blank" rel="noopener noreferrer" class="github-repo-link" style="text-decoration: none; display: inline-flex; align-items: center; gap: 0.5rem;">
<iconify-icon icon="mdi:github" width="20" height="20"></iconify-icon>
{{if eq .Lang "es"}}Ver este proyecto en GitHub{{else}}View this project on GitHub{{end}}
</a>
</p>
<p>© {{.CV.Meta.LastUpdated}} {{.CV.Personal.Name}} |
{{if eq .Lang "es"}}Última actualización{{else}}Last updated{{end}}: {{.CV.Meta.LastUpdated}}</p>
</footer>
<!-- Error Toast -->
<div id="error-toast" class="error-toast no-print" role="alert" aria-live="assertive" style="display: none;">
<span class="error-icon">⚠️</span>
<span id="error-message"></span>
<button onclick="this.parentElement.style.display='none'" aria-label="Close error message" class="error-close">×</button>
</div>
<!-- Back to Top Button -->
<button id="back-to-top" class="back-to-top no-print" aria-label="{{if eq .Lang "es"}}Volver arriba{{else}}Back to top{{end}}" style="display: none;">
<iconify-icon icon="mdi:arrow-up" width="24" height="24"></iconify-icon>
</button>
<!-- Info Button (Bottom Left) -->
<button id="info-button" class="info-button no-print" aria-label="{{if eq .Lang "es"}}Información{{else}}Information{{end}}" onclick="openInfoModal()">
<iconify-icon icon="mdi:information-outline" width="24" height="24"></iconify-icon>
</button>
<!-- Info Modal -->
<div id="info-modal" class="info-modal no-print" onclick="closeInfoModalOnBackdrop(event)">
<div class="info-modal-content" onclick="event.stopPropagation()">
<button class="info-modal-close" onclick="closeInfoModal()" aria-label="Close">
<iconify-icon icon="mdi:close" width="24" height="24"></iconify-icon>
</button>
<div class="info-modal-header">
<h2>{{.UI.InfoModal.Title}}</h2>
<div class="info-modal-cv-title">
CV {{.CurrentYear}} JAMR -
<span class="photo-bracket-wrapper">
<img src="/static/images/profile/dni.jpeg" alt="JAMR" class="info-modal-photo">
</span>
</div>
</div>
<div class="info-modal-body">
<p class="info-modal-description">
{{.UI.InfoModal.Description}}
</p>
<div class="info-modal-tech">
<div class="info-tech-item">
<iconify-icon icon="mdi:language-go" width="32" height="32"></iconify-icon>
<span>{{.UI.InfoModal.TechStack.GoHono}}</span>
</div>
<div class="info-tech-item">
<iconify-icon icon="mdi:lightning-bolt" width="32" height="32"></iconify-icon>
<span>{{.UI.InfoModal.TechStack.HTMX}}</span>
</div>
<div class="info-tech-item">
<iconify-icon icon="mdi:language-html5" width="32" height="32"></iconify-icon>
<span>{{.UI.InfoModal.TechStack.HTML5}}</span>
</div>
<div class="info-tech-item">
<iconify-icon icon="mdi:language-css3" width="32" height="32"></iconify-icon>
<span>{{.UI.InfoModal.TechStack.CSS3}}</span>
</div>
</div>
<p class="info-modal-github-subtext">{{.UI.InfoModal.ViewSourceSubtext}}</p>
<a href="https://github.com/juanatsap/cv-site" target="_blank" rel="noopener noreferrer" class="info-modal-github">
<iconify-icon icon="mdi:github" width="24" height="24"></iconify-icon>
<span>{{.UI.InfoModal.ViewSource}}</span>
<iconify-icon icon="mdi:arrow-right" width="20" height="20"></iconify-icon>
</a>
</div>
</div>
</div>
<!-- PDF Export Modal -->
<div id="pdf-modal" class="info-modal no-print" onclick="closePdfModalOnBackdrop(event)">
<div class="info-modal-content" onclick="event.stopPropagation()">
<button class="info-modal-close" onclick="closePdfModal()" aria-label="Close">
<iconify-icon icon="mdi:close" width="24" height="24"></iconify-icon>
</button>
<div class="info-modal-header">
<div class="icon" style="font-size: 3rem; margin-bottom: 1rem;">🚧</div>
<h2>{{if eq .Lang "es"}}Exportación PDF - En Desarrollo{{else}}PDF Export - Work in Progress{{end}}</h2>
</div>
<div class="info-modal-body">
<p class="info-modal-description">
{{if eq .Lang "es"}}
La función de exportación a PDF está siendo mejorada. Por favor, usa el botón <strong>Imprimir Amigable</strong> en su lugar (Ctrl+P o Cmd+P para guardar como PDF).
{{else}}
The PDF export feature is currently being improved. Please use the <strong>Print Friendly</strong> button instead (Ctrl+P or Cmd+P to save as PDF).
{{end}}
</p>
</div>
</div>
</div>
<!-- Zoom Control (Fixed Bottom Center) -->
<div id="zoom-control" class="zoom-control no-print" role="group" aria-label="{{if eq .Lang "es"}}Control de zoom{{else}}Zoom control{{end}}">
<label for="zoom-slider" class="zoom-label">
<iconify-icon icon="mdi:magnify" width="20" height="20" aria-hidden="true"></iconify-icon>
<span class="sr-only">{{if eq .Lang "es"}}Nivel de zoom{{else}}Zoom level{{end}}</span>
</label>
<div class="zoom-slider-container">
<span class="zoom-value zoom-value-min" aria-hidden="true">50%</span>
<input
type="range"
id="zoom-slider"
class="zoom-slider"
min="50"
max="200"
step="5"
value="100"
aria-label="{{if eq .Lang "es"}}Ajustar nivel de zoom del CV{{else}}Adjust CV zoom level{{end}}"
aria-valuemin="50"
aria-valuemax="200"
aria-valuenow="100"
aria-valuetext="100%">
<span id="zoom-value-current" class="zoom-value zoom-value-current" aria-live="polite">100%</span>
<span class="zoom-value zoom-value-max" aria-hidden="true">200%</span>
</div>
<button
id="zoom-reset"
class="zoom-reset-btn"
aria-label="{{if eq .Lang "es"}}Restablecer zoom al 100%{{else}}Reset zoom to 100%{{end}}"
title="{{if eq .Lang "es"}}Restablecer{{else}}Reset{{end}}">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/>
<path d="M21 3v5h-5"/>
<path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/>
<path d="M3 21v-5h5"/>
</svg>
</button>
</div>
<!-- External JavaScript - CSP Compliant -->
<script src="/static/js/main.js"></script>
<!-- Matomo Analytics - Nonce-based CSP -->
<script nonce="{{.CSPNonce}}">
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://matomo.drolo.club/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '4']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</body>
</html>