Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>PPT Presentation Viewer</title> | |
| <style> | |
| :root { | |
| --text-color: #111111; | |
| --secondary-text: #666666; | |
| --bg-color: #ffffff; | |
| --light-bg: #f8f8f8; | |
| --dark-bg: #111111; | |
| --border-color: #e0e0e0; | |
| --hover-color: #f0f0f0; | |
| --active-color: #000000; | |
| --shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 1px 4px rgba(0, 0, 0, 0.05), 0 2px 8px rgba(0, 0, 0, 0.05); | |
| --btn-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); | |
| --card-radius: 4px; | |
| --btn-radius: 4px; | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; | |
| } | |
| body { | |
| background-color: var(--light-bg); | |
| color: var(--text-color); | |
| line-height: 1.5; | |
| -webkit-font-smoothing: antialiased; | |
| } | |
| .container { | |
| max-width: 1800px; | |
| margin: 0 auto; | |
| padding: 24px; | |
| } | |
| header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 16px 24px; | |
| background-color: var(--dark-bg); | |
| color: white; | |
| margin-bottom: 32px; | |
| box-shadow: var(--shadow); | |
| } | |
| header h1 { | |
| font-size: 18px; | |
| font-weight: 500; | |
| letter-spacing: 0.2px; | |
| display: flex; | |
| align-items: center; | |
| } | |
| header h1 svg { | |
| margin-right: 12px; | |
| } | |
| .controls { | |
| display: flex; | |
| gap: 16px; | |
| align-items: center; | |
| } | |
| .view-controls { | |
| display: flex; | |
| background: rgba(255, 255, 255, 0.1); | |
| border-radius: var(--btn-radius); | |
| overflow: hidden; | |
| } | |
| .view-controls button { | |
| background: none; | |
| color: white; | |
| border: none; | |
| padding: 6px 12px; | |
| cursor: pointer; | |
| font-size: 13px; | |
| font-weight: 500; | |
| transition: all 0.2s ease; | |
| } | |
| .view-controls button.active { | |
| background: rgba(255, 255, 255, 0.2); | |
| } | |
| .play-button { | |
| background-color: white; | |
| color: var(--dark-bg); | |
| border: none; | |
| padding: 8px 16px; | |
| border-radius: var(--btn-radius); | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| transition: all 0.2s ease; | |
| font-weight: 500; | |
| font-size: 13px; | |
| box-shadow: var(--btn-shadow); | |
| } | |
| .play-button:hover { | |
| background-color: var(--hover-color); | |
| transform: translateY(-1px); | |
| } | |
| .play-button svg { | |
| margin-right: 8px; | |
| } | |
| /* Grid View */ | |
| .preview-container { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(480px, 1fr)); | |
| gap: 24px; | |
| margin-top: 24px; | |
| } | |
| /* Grid mode specific styles */ | |
| .preview-container:not(.list-view) .slide-frame-container { | |
| position: relative; | |
| padding-top: 56.25%; /* 16:9 Aspect Ratio */ | |
| width: 100%; | |
| overflow: hidden; | |
| } | |
| .preview-container:not(.list-view) .slide-frame { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| width: 1280px; | |
| height: 720px; | |
| border: none; | |
| transform-origin: center center; | |
| transform: translate(-50%, -50%) scale(1); | |
| } | |
| /* List View */ | |
| .preview-container.list-view { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 32px; | |
| align-items: center; | |
| } | |
| .preview-container.list-view .slide-preview { | |
| width: 1280px; | |
| height: 720px; | |
| max-width: 90vw; | |
| } | |
| .preview-container.list-view .slide-frame-container { | |
| width: 100%; | |
| height: 100%; | |
| position: relative; | |
| padding-top: 0; | |
| } | |
| .preview-container.list-view .slide-frame { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| border: none; | |
| } | |
| .slide-preview { | |
| background: var(--bg-color); | |
| border-radius: var(--card-radius); | |
| overflow: hidden; | |
| box-shadow: var(--shadow); | |
| transition: transform 0.2s ease, box-shadow 0.2s ease; | |
| cursor: pointer; | |
| position: relative; | |
| border: 1px solid var(--border-color); | |
| } | |
| .slide-preview:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 12px rgba(0, 0, 0, 0.08); | |
| } | |
| .slide-preview.active { | |
| border: 1px solid var(--active-color); | |
| } | |
| .slide-number { | |
| position: absolute; | |
| top: 12px; | |
| left: 12px; | |
| background-color: rgba(0, 0, 0, 0.7); | |
| color: white; | |
| border-radius: 50%; | |
| width: 28px; | |
| height: 28px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 12px; | |
| font-weight: 600; | |
| z-index: 2; | |
| } | |
| /* Presentation mode */ | |
| .presentation-mode { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-color: #000; | |
| z-index: 1000; | |
| display: none; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| /* Fullscreen mode adjustments */ | |
| .presentation-mode:fullscreen { | |
| width: 100vw; | |
| height: 100vh; | |
| } | |
| .presentation-mode:-webkit-full-screen { | |
| width: 100vw; | |
| height: 100vh; | |
| } | |
| .presentation-mode:-moz-full-screen { | |
| width: 100vw; | |
| height: 100vh; | |
| } | |
| .presentation-mode:-ms-fullscreen { | |
| width: 100vw; | |
| height: 100vh; | |
| } | |
| .presentation-slide { | |
| width: 1280px; | |
| height: 720px; | |
| border: none; | |
| transform-origin: center center; | |
| } | |
| .presentation-slide-container { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| flex: 1; | |
| width: 100%; | |
| padding: 20px; | |
| } | |
| .presentation-controls { | |
| height: 48px; | |
| background-color: rgba(0, 0, 0, 0.9); | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| gap: 24px; | |
| padding: 0 24px; | |
| position: relative; | |
| z-index: 1001; | |
| } | |
| .presentation-controls.fullscreen { | |
| position: fixed; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| opacity: 0; | |
| transition: opacity 0.3s ease; | |
| } | |
| .presentation-controls.fullscreen:hover, | |
| .presentation-controls.fullscreen.show { | |
| opacity: 1; | |
| } | |
| .progress-bar { | |
| flex: 1; | |
| max-width: 400px; | |
| height: 2px; | |
| background-color: rgba(255, 255, 255, 0.2); | |
| border-radius: 1px; | |
| overflow: hidden; | |
| position: relative; | |
| } | |
| .progress-fill { | |
| height: 100%; | |
| background-color: white; | |
| width: 0%; | |
| transition: width 0.3s ease; | |
| } | |
| .slide-indicators { | |
| color: white; | |
| font-size: 12px; | |
| min-width: 40px; | |
| text-align: center; | |
| } | |
| .presentation-controls button { | |
| background-color: transparent; | |
| color: white; | |
| border: none; | |
| width: 32px; | |
| height: 32px; | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| transition: background-color 0.2s ease; | |
| } | |
| .presentation-controls button:hover { | |
| background-color: rgba(255, 255, 255, 0.1); | |
| } | |
| /* Responsive adjustments */ | |
| @media (max-width: 1200px) { | |
| .preview-container:not(.list-view) { | |
| grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); | |
| } | |
| } | |
| @media (max-width: 900px) { | |
| .preview-container:not(.list-view) { | |
| grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); | |
| } | |
| } | |
| @media (max-width: 640px) { | |
| .container { | |
| padding: 16px; | |
| } | |
| .preview-container:not(.list-view) { | |
| grid-template-columns: 1fr; | |
| gap: 16px; | |
| } | |
| header { | |
| flex-direction: column; | |
| align-items: flex-start; | |
| gap: 16px; | |
| padding: 16px; | |
| } | |
| .controls { | |
| width: 100%; | |
| justify-content: space-between; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <header> | |
| <h1> | |
| Presentation Viewer | |
| </h1> | |
| <div class="controls"> | |
| <div class="view-controls"> | |
| <button id="grid-view-btn">Grid</button> | |
| <button id="list-view-btn" class="active">List</button> | |
| </div> | |
| <button id="play-button" class="play-button"> | |
| <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <polygon points="5 3 19 12 5 21 5 3"></polygon> | |
| </svg> | |
| Play Slides | |
| </button> | |
| </div> | |
| </header> | |
| <div class="preview-container list-view" id="preview-container"> | |
| <!-- Slide previews will be dynamically inserted here --> | |
| </div> | |
| </div> | |
| <div class="presentation-mode" id="presentation-mode"> | |
| <div class="presentation-slide-container"> | |
| <iframe id="presentation-slide" class="presentation-slide" src="" frameborder="0"></iframe> | |
| </div> | |
| <div class="presentation-controls"> | |
| <button id="prev-slide"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <line x1="19" y1="12" x2="5" y2="12"></line> | |
| <polyline points="12 19 5 12 12 5"></polyline> | |
| </svg> | |
| </button> | |
| <div class="progress-bar"> | |
| <div class="progress-fill" id="progress-fill"></div> | |
| </div> | |
| <div class="slide-indicators"> | |
| <span id="current-slide">1</span>/<span id="total-slides">0</span> | |
| </div> | |
| <button id="next-slide"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <line x1="5" y1="12" x2="19" y2="12"></line> | |
| <polyline points="12 5 19 12 12 19"></polyline> | |
| </svg> | |
| </button> | |
| <button id="fullscreen-toggle" title="Toggle Fullscreen"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path> | |
| </svg> | |
| </button> | |
| <button id="exit-presentation"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> | |
| <line x1="9" y1="9" x2="15" y2="15"></line> | |
| <line x1="15" y1="9" x2="9" y2="15"></line> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| // Load the slides data | |
| const slides = ["slides/slide01_titulo.html", "slides/slide02_resumen.html", "slides/slide03_modelo1.html", "slides/slide04_modelo2.html", "slides/slide05_comparativo.html", "slides/slide06_caso_ecuador.html", "slides/slide07_ecosistema_academico.html", "slides/slide08_indicadores.html", "slides/slide09_brechas_oportunidades.html", "slides/slide10_tendencias.html", "slides/slide11_csb_argentina.html", "slides/slide12_analisis_cuantitativo_v2.html", "slides/slide13_correlacion_educacion.html", "slides/slide14_modelos_comparativos.html", "slides/slide15_america_latina.html", "slides/slide16_casos_estudio_simple.html", "slides/slide17_conclusiones.html", "slides/slide18_bibliografia.html", "slides/slide19_agradecimientos.html"]; | |
| let currentSlideIndex = 0; | |
| let viewMode = 'list'; // 'grid' or 'list' | |
| // DOM elements | |
| const previewContainer = document.getElementById('preview-container'); | |
| const presentationMode = document.getElementById('presentation-mode'); | |
| const presentationSlide = document.getElementById('presentation-slide'); | |
| const playButton = document.getElementById('play-button'); | |
| const prevButton = document.getElementById('prev-slide'); | |
| const nextButton = document.getElementById('next-slide'); | |
| const exitButton = document.getElementById('exit-presentation'); | |
| const fullscreenToggle = document.getElementById('fullscreen-toggle'); | |
| const presentationControls = document.querySelector('.presentation-controls'); | |
| const progressFill = document.getElementById('progress-fill'); | |
| const currentSlideElement = document.getElementById('current-slide'); | |
| const totalSlidesElement = document.getElementById('total-slides'); | |
| const gridViewBtn = document.getElementById('grid-view-btn'); | |
| const listViewBtn = document.getElementById('list-view-btn'); | |
| // Fullscreen state | |
| let isFullscreen = false; | |
| let controlsTimeout; | |
| // Initialize the viewer | |
| function initViewer() { | |
| // Set total slides | |
| totalSlidesElement.textContent = slides.length; | |
| // Generate slide previews | |
| generatePreviews(); | |
| // Set up view mode buttons | |
| gridViewBtn.addEventListener('click', () => setViewMode('grid')); | |
| listViewBtn.addEventListener('click', () => setViewMode('list')); | |
| } | |
| // Generate slide previews | |
| function generatePreviews() { | |
| previewContainer.innerHTML = ''; | |
| slides.forEach((slide, index) => { | |
| const slidePreview = document.createElement('div'); | |
| slidePreview.className = 'slide-preview'; | |
| if (index === currentSlideIndex) { | |
| slidePreview.classList.add('active'); | |
| } | |
| slidePreview.innerHTML = ` | |
| <div class="slide-number">${index + 1}</div> | |
| <div class="slide-frame-container"> | |
| <iframe class="slide-frame" src="${slide}" frameborder="0"></iframe> | |
| </div> | |
| `; | |
| slidePreview.addEventListener('click', () => { | |
| startPresentation(index); | |
| }); | |
| previewContainer.appendChild(slidePreview); | |
| }); | |
| // Scale grid previews after generating | |
| if (viewMode === 'grid') { | |
| setTimeout(scaleGridPreviews, 100); | |
| } | |
| } | |
| // Set view mode (grid or list) | |
| function setViewMode(mode) { | |
| viewMode = mode; | |
| if (mode === 'grid') { | |
| previewContainer.classList.remove('list-view'); | |
| gridViewBtn.classList.add('active'); | |
| listViewBtn.classList.remove('active'); | |
| // Scale grid previews after mode change | |
| setTimeout(scaleGridPreviews, 100); | |
| } else { | |
| previewContainer.classList.add('list-view'); | |
| gridViewBtn.classList.remove('active'); | |
| listViewBtn.classList.add('active'); | |
| // Reset all iframe transforms for list mode | |
| resetListPreviews(); | |
| } | |
| } | |
| // Reset transforms for list mode | |
| function resetListPreviews() { | |
| const slideFrames = document.querySelectorAll('.slide-frame'); | |
| slideFrames.forEach(frame => { | |
| frame.style.transform = ''; | |
| }); | |
| } | |
| // Scale grid mode previews | |
| function scaleGridPreviews() { | |
| if (viewMode !== 'grid') return; | |
| const slideFrames = document.querySelectorAll('.preview-container:not(.list-view) .slide-frame'); | |
| slideFrames.forEach(frame => { | |
| const container = frame.closest('.slide-frame-container'); | |
| if (!container) return; | |
| const containerWidth = container.clientWidth; | |
| const containerHeight = container.clientHeight; | |
| // Calculate scale to fit 1280x720 within container | |
| const scaleX = containerWidth / 1280; | |
| const scaleY = containerHeight / 720; | |
| const scale = Math.min(scaleX, scaleY); | |
| frame.style.transform = `translate(-50%, -50%) scale(${scale})`; | |
| }); | |
| } | |
| // Start presentation mode | |
| function startPresentation(index = 0) { | |
| currentSlideIndex = index; | |
| presentationMode.style.display = 'flex'; | |
| document.body.style.overflow = 'hidden'; | |
| updateSlide(); | |
| // Auto-enter fullscreen | |
| requestFullscreen(); | |
| } | |
| // Request fullscreen | |
| function requestFullscreen() { | |
| const element = presentationMode; | |
| if (element.requestFullscreen) { | |
| element.requestFullscreen(); | |
| } else if (element.webkitRequestFullscreen) { | |
| element.webkitRequestFullscreen(); | |
| } else if (element.mozRequestFullScreen) { | |
| element.mozRequestFullScreen(); | |
| } else if (element.msRequestFullscreen) { | |
| element.msRequestFullscreen(); | |
| } | |
| } | |
| // Exit fullscreen | |
| function exitFullscreen() { | |
| if (document.exitFullscreen) { | |
| document.exitFullscreen(); | |
| } else if (document.webkitExitFullscreen) { | |
| document.webkitExitFullscreen(); | |
| } else if (document.mozCancelFullScreen) { | |
| document.mozCancelFullScreen(); | |
| } else if (document.msExitFullscreen) { | |
| document.msExitFullscreen(); | |
| } | |
| } | |
| // Toggle fullscreen | |
| function toggleFullscreen() { | |
| if (isFullscreen) { | |
| exitFullscreen(); | |
| } else { | |
| requestFullscreen(); | |
| } | |
| } | |
| // Handle fullscreen change | |
| function handleFullscreenChange() { | |
| isFullscreen = !!(document.fullscreenElement || | |
| document.webkitFullscreenElement || | |
| document.mozFullScreenElement || | |
| document.msFullscreenElement); | |
| if (isFullscreen) { | |
| presentationControls.classList.add('fullscreen'); | |
| setupControlsAutoHide(); | |
| } else { | |
| presentationControls.classList.remove('fullscreen'); | |
| clearTimeout(controlsTimeout); | |
| } | |
| // Re-scale slide when fullscreen changes | |
| setTimeout(scalePresentationSlide, 100); | |
| } | |
| // Setup auto-hide controls in fullscreen | |
| function setupControlsAutoHide() { | |
| if (!isFullscreen) return; | |
| // Show controls initially | |
| presentationControls.classList.add('show'); | |
| // Auto-hide after 3 seconds | |
| controlsTimeout = setTimeout(() => { | |
| if (isFullscreen) { | |
| presentationControls.classList.remove('show'); | |
| } | |
| }, 3000); | |
| } | |
| // Show controls temporarily | |
| function showControlsTemporarily() { | |
| if (!isFullscreen) return; | |
| presentationControls.classList.add('show'); | |
| clearTimeout(controlsTimeout); | |
| controlsTimeout = setTimeout(() => { | |
| if (isFullscreen) { | |
| presentationControls.classList.remove('show'); | |
| } | |
| }, 3000); | |
| } | |
| // Exit presentation mode | |
| function exitPresentation() { | |
| // Exit fullscreen if in fullscreen mode | |
| if (isFullscreen) { | |
| exitFullscreen(); | |
| } | |
| presentationMode.style.display = 'none'; | |
| document.body.style.overflow = 'auto'; | |
| } | |
| // Update current slide | |
| function updateSlide() { | |
| presentationSlide.src = slides[currentSlideIndex]; | |
| currentSlideElement.textContent = currentSlideIndex + 1; | |
| // Update progress bar | |
| const progress = ((currentSlideIndex + 1) / slides.length) * 100; | |
| progressFill.style.width = `${progress}%`; | |
| // Scale presentation slide to fit container | |
| scalePresentationSlide(); | |
| // Update preview highlighting | |
| document.querySelectorAll('.slide-preview').forEach((preview, index) => { | |
| if (index === currentSlideIndex) { | |
| preview.classList.add('active'); | |
| } else { | |
| preview.classList.remove('active'); | |
| } | |
| }); | |
| } | |
| // Scale presentation slide to fit container | |
| function scalePresentationSlide() { | |
| const container = document.querySelector('.presentation-slide-container'); | |
| const containerWidth = container.clientWidth - 40; // Account for padding | |
| const containerHeight = container.clientHeight - 40; | |
| // In fullscreen mode, use full viewport dimensions | |
| if (isFullscreen) { | |
| const viewportWidth = window.innerWidth; | |
| const viewportHeight = window.innerHeight - 48; // Account for controls height | |
| const scaleX = viewportWidth / 1280; | |
| const scaleY = viewportHeight / 720; | |
| const scale = Math.min(scaleX, scaleY); | |
| presentationSlide.style.transform = `scale(${scale})`; | |
| } else { | |
| // Calculate scale based on container size and slide dimensions (1280x720) | |
| const scaleX = containerWidth / 1280; | |
| const scaleY = containerHeight / 720; | |
| const scale = Math.min(scaleX, scaleY); | |
| presentationSlide.style.transform = `scale(${scale})`; | |
| } | |
| } | |
| // Go to next slide | |
| function nextSlide() { | |
| if (currentSlideIndex < slides.length - 1) { | |
| currentSlideIndex++; | |
| updateSlide(); | |
| } | |
| } | |
| // Go to previous slide | |
| function prevSlide() { | |
| if (currentSlideIndex > 0) { | |
| currentSlideIndex--; | |
| updateSlide(); | |
| } | |
| } | |
| // Event listeners | |
| playButton.addEventListener('click', () => startPresentation(0)); | |
| prevButton.addEventListener('click', () => { | |
| prevSlide(); | |
| showControlsTemporarily(); | |
| }); | |
| nextButton.addEventListener('click', () => { | |
| nextSlide(); | |
| showControlsTemporarily(); | |
| }); | |
| exitButton.addEventListener('click', exitPresentation); | |
| fullscreenToggle.addEventListener('click', () => { | |
| toggleFullscreen(); | |
| showControlsTemporarily(); | |
| }); | |
| // Fullscreen change listeners | |
| document.addEventListener('fullscreenchange', handleFullscreenChange); | |
| document.addEventListener('webkitfullscreenchange', handleFullscreenChange); | |
| document.addEventListener('mozfullscreenchange', handleFullscreenChange); | |
| document.addEventListener('MSFullscreenChange', handleFullscreenChange); | |
| // Mouse movement in fullscreen mode | |
| presentationMode.addEventListener('mousemove', showControlsTemporarily); | |
| // Keyboard navigation | |
| document.addEventListener('keydown', (e) => { | |
| if (presentationMode.style.display === 'flex') { | |
| if (e.key === 'ArrowRight' || e.key === ' ' || e.key === 'n') { | |
| nextSlide(); | |
| showControlsTemporarily(); | |
| } else if (e.key === 'ArrowLeft' || e.key === 'p') { | |
| prevSlide(); | |
| showControlsTemporarily(); | |
| } else if (e.key === 'Escape') { | |
| if (isFullscreen) { | |
| exitFullscreen(); | |
| } else { | |
| exitPresentation(); | |
| } | |
| } else if (e.key === 'f' || e.key === 'F') { | |
| toggleFullscreen(); | |
| showControlsTemporarily(); | |
| } | |
| } | |
| }); | |
| // Initialize the viewer when the page loads | |
| window.addEventListener('load', initViewer); | |
| // Handle window resize for presentation mode scaling | |
| window.addEventListener('resize', () => { | |
| if (presentationMode.style.display === 'flex') { | |
| scalePresentationSlide(); | |
| } | |
| // Also scale grid previews on resize | |
| if (viewMode === 'grid') { | |
| scaleGridPreviews(); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |