diff --git a/static/css/main.css b/static/css/main.css index 58bbac7..1fa210a 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -491,6 +491,13 @@ iconify-icon { 100% { transform: rotate(360deg); } } +/* Zoom Wrapper - wraps cv-container for zoom functionality */ +.zoom-wrapper { + transform-origin: top center; /* Scale from top center */ + transition: transform 0.08s linear; /* Smooth zoom response */ + will-change: transform; /* Optimize for transforms */ +} + /* Main CV Container */ .cv-container { width: 100%; @@ -498,9 +505,6 @@ iconify-icon { margin: 0 auto; padding: 20px 0 0 0; /* Top padding to prevent sticky action bar overlap */ display: block; /* Changed from flex */ - transform-origin: top center; /* Scale from top center - container stays anchored at top */ - transition: transform 0.08s linear; /* Smooth, immediate zoom response */ - will-change: transform; /* Hint browser to optimize for transforms */ } /* Clean theme - no sidebars, centered content */ @@ -1700,9 +1704,6 @@ a:focus { padding: 20px 0; margin: 0; grid-column: 1 / -1; /* Span all columns */ - transform-origin: top center; /* Scale from top center - footer stays anchored at top */ - transition: transform 0.08s linear; /* Smooth, immediate zoom response */ - will-change: transform; /* Hint browser to optimize for transforms */ } .footer-content { @@ -2578,8 +2579,8 @@ html { position: fixed; bottom: 2rem; right: 2rem; - width: 50px; - height: 50px; + width: 35px; /* Smaller default size */ + height: 35px; background: var(--black-bar); color: white; border: none; @@ -2596,7 +2597,7 @@ html { .back-to-top:hover { opacity: 1; - transform: translateY(-3px); + transform: translateY(-3px) scale(1.43); /* Grow to ~50px on hover */ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); background: #3a3a3a; } diff --git a/static/js/main.js b/static/js/main.js index fecbeab..905c7b3 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -273,9 +273,9 @@ function initZoomControl() { const slider = document.getElementById('zoom-slider'); const resetBtn = document.getElementById('zoom-reset'); - const cvPaper = document.querySelector('.cv-paper'); + const zoomWrapper = document.getElementById('zoom-wrapper'); - if (!slider || !cvPaper) return; + if (!slider || !zoomWrapper) return; // On mobile, always use 100% zoom (zoom control is hidden anyway) if (isMobileView()) { @@ -347,20 +347,15 @@ * @param {boolean} saveToStorage - Whether to persist to localStorage */ function applyZoom(zoomValue, saveToStorage = true) { - const cvContainer = document.querySelector('.cv-container'); - const cvFooter = document.querySelector('.cv-footer'); - if (!cvContainer) return; + const zoomWrapper = document.getElementById('zoom-wrapper'); + if (!zoomWrapper) return; // Convert percentage to scale factor (100 = 1.0, 150 = 1.5, etc.) const scale = zoomValue / 100; requestAnimationFrame(() => { - // Use transform: scale() for true visual zoom without constraints - // This allows zoom to extend beyond viewport at >100% - cvContainer.style.transform = `scale(${scale})`; - if (cvFooter) { - cvFooter.style.transform = `scale(${scale})`; - } + // Apply zoom to wrapper - footer adjusts naturally below it + zoomWrapper.style.transform = `scale(${scale})`; // Update display updateZoomDisplay(zoomValue); diff --git a/templates/index.html b/templates/index.html index bc64f88..02bdb38 100644 --- a/templates/index.html +++ b/templates/index.html @@ -344,8 +344,10 @@ - -
+ +
+ +
-
+ +