In the digital age, the design of a download button can significantly impact user experience and conversion rates. A well-crafted button not only attracts attention but also encourages users to take action.
From minimalist designs to eye-catching animations, download buttons come in various styles. Here, we explore ten exemplary download button designs that stand out for their functionality and aesthetic appeal.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Designers and developers, elevate your UI game with Subframe's drag-and-drop interface. Its intuitive, responsive canvas ensures pixel-perfect designs every time, making it a favorite among professionals.
Ready to create stunning download buttons effortlessly? Start for free today!
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Unlock the power of Subframe and design pixel-perfect UIs with ease. Whether it's a download button or a complete interface, Subframe's drag-and-drop editor ensures efficiency and precision.
Ready to elevate your design game? Start for free and create stunning UIs immediately!
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> :root { --primary: #3a36e0; --secondary: #f02e63; --dark: #151521; --light: #f4f7ff; --success: #00c16e; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background-color: #f7f9fc; padding: 20px; } .product-card { background-color: white; border-radius: 16px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08); width: 100%; max-width: 500px; overflow: hidden; transition: transform 0.3s ease; } .product-card:hover { transform: translateY(-5px); } .product-image { height: 220px; background: linear-gradient(45deg, #eef2ff, #e6eeff); display: flex; justify-content: center; align-items: center; position: relative; overflow: hidden; } .product-image svg { width: 60%; height: auto; filter: drop-shadow(0 10px 15px rgba(58, 54, 224, 0.2)); transition: transform 0.5s ease; } .product-card:hover .product-image svg { transform: scale(1.05); } .product-info { padding: 25px; } .product-title { font-size: 22px; color: var(--dark); margin-bottom: 6px; font-weight: 700; } .product-specs { display: flex; gap: 15px; margin-bottom: 20px; } .spec { display: flex; align-items: center; gap: 5px; font-size: 14px; color: #666; } .spec svg { width: 18px; height: 18px; color: var(--primary); } .product-description { color: #555; margin-bottom: 25px; font-size: 15px; line-height: 1.5; } .download-button { display: inline-flex; align-items: center; justify-content: center; gap: 10px; background-color: var(--primary); color: white; font-weight: 600; padding: 14px 30px; border-radius: 8px; cursor: pointer; transition: all 0.3s ease; border: none; position: relative; overflow: hidden; font-size: 16px; box-shadow: 0 6px 15px rgba(58, 54, 224, 0.25); } .download-button:hover { background-color: #2e2bc7; transform: translateY(-2px); box-shadow: 0 8px 20px rgba(58, 54, 224, 0.35); } .download-button:active { transform: translateY(0); box-shadow: 0 4px 10px rgba(58, 54, 224, 0.2); } .download-button .text { position: relative; z-index: 2; transition: opacity 0.3s ease; } .download-button .icon { position: relative; z-index: 2; transition: transform 0.3s ease; } .download-button:hover .icon { transform: translateY(3px); } .download-button .progress { position: absolute; left: 0; top: 0; height: 100%; width: 0; background-color: var(--secondary); z-index: 1; transition: width 0.8s cubic-bezier(0.65, 0, 0.35, 1); } .download-button.loading .text, .download-button.loading .icon { opacity: 0.7; } .download-button.loading .loader { opacity: 1; } .download-button .loader { position: absolute; z-index: 3; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; opacity: 0; transition: opacity 0.3s ease; } .download-button.success { background-color: var(--success); box-shadow: 0 6px 15px rgba(0, 193, 110, 0.25); } .download-button.success:hover { background-color: #00ad61; box-shadow: 0 8px 20px rgba(0, 193, 110, 0.35); } .file-info { margin-top: 15px; font-size: 13px; color: #777; display: flex; align-items: center; gap: 15px; } .file-info span { display: flex; align-items: center; gap: 5px; } .file-info svg { width: 15px; height: 15px; } .dot-flashing { position: relative; width: 8px; height: 8px; border-radius: 50%; background-color: white; animation: dot-flashing 1s infinite linear alternate; animation-delay: 0.5s; } .dot-flashing::before, .dot-flashing::after { content: ''; display: inline-block; position: absolute; top: 0; } .dot-flashing::before { left: -15px; width: 8px; height: 8px; border-radius: 50%; background-color: white; animation: dot-flashing 1s infinite alternate; animation-delay: 0s; } .dot-flashing::after { left: 15px; width: 8px; height: 8px; border-radius: 50%; background-color: white; animation: dot-flashing 1s infinite alternate; animation-delay: 1s; } @keyframes dot-flashing { 0% { background-color: white; } 50%, 100% { background-color: rgba(255, 255, 255, 0.4); } } @media (max-width: 480px) { .product-title { font-size: 20px; } .product-specs { flex-direction: column; gap: 8px; } .download-button { width: 100%; } } </style> </head> <body> <div class="product-card"> <div class="product-image"> <svg viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M325.8 96.7L403.8 174.7C405.4 176.3 406.2 178.5 406.2 180.8V400C406.2 417.7 391.9 432 374.2 432H137.8C120.1 432 105.8 417.7 105.8 400V112C105.8 94.3 120.1 80 137.8 80H313.8C316.1 80 318.3 80.9 319.9 82.4L325.8 96.7Z" fill="#E6EEFF"/> <path d="M326.2 96H408V179.8L326.2 96Z" fill="#BFD1FF"/> <path d="M256 240C282.5 240 304 261.5 304 288V315.8C307.4 316.6 310.7 317.8 313.8 319.4L333.8 303.4C337.1 300.6 342.4 301 345.2 304.2C348 307.5 347.6 312.8 344.4 315.6L324.4 331.6C330.8 340.7 334.7 352 334.7 364.2C334.7 394.9 309.6 420 278.9 420H233.1C202.4 420 177.3 394.9 177.3 364.2C177.3 352 181.2 340.7 187.6 331.6L167.6 315.6C164.4 312.8 164 307.5 166.8 304.2C169.6 301 174.9 300.6 178.2 303.4L198.2 319.4C201.3 317.8 204.6 316.6 208 315.8V288C208 261.5 229.5 240 256 240ZM256 256C238.3 256 224 270.3 224 288V313.4C242.1 309.2 269.9 309.2 288 313.4V288C288 270.3 273.7 256 256 256Z" fill="#3A36E0"/> <path d="M186 156C186 152.7 188.7 150 192 150H320C323.3 150 326 152.7 326 156C326 159.3 323.3 162 320 162H192C188.7 162 186 159.3 186 156Z" fill="#3A36E0"/> <path d="M186 180C186 176.7 188.7 174 192 174H293.3C296.6 174 299.3 176.7 299.3 180C299.3 183.3 296.6 186 293.3 186H192C188.7 186 186 183.3 186 180Z" fill="#BFD1FF"/> <path d="M186 204C186 200.7 188.7 198 192 198H266.7C270 198 272.7 200.7 272.7 204C272.7 207.3 270 210 266.7 210H192C188.7 210 186 207.3 186 204Z" fill="#BFD1FF"/> </svg> </div> <div class="product-info"> <h3 class="product-title">AI-Powered Smart Sensor Datasheet</h3> <div class="product-specs"> <div class="spec"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" /> </svg> <span>Rev 2.4</span> </div> <div class="spec"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /> </svg> <span>Updated May 2023</span> </div> <div class="spec"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" /> </svg> <span>3.2K views</span> </div> </div> <p class="product-description">Complete technical specifications for our latest AI-powered sensor technology. Includes wiring diagrams, power requirements, communication protocols, and integration examples for quick implementation.</p> <button class="download-button" id="downloadBtn"> <span class="progress"></span> <span class="text">Download Datasheet</span> <span class="icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="7 10 12 15 17 10"></polyline> <line x1="12" y1="15" x2="12" y2="3"></line> </svg> </span> <span class="loader"> <div class="dot-flashing"></div> </span> </button> <div class="file-info"> <span> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path> <polyline points="14 2 14 8 20 8"></polyline> <line x1="16" y1="13" x2="8" y2="13"></line> <line x1="16" y1="17" x2="8" y2="17"></line> <polyline points="10 9 9 9 8 9"></polyline> </svg> PDF Document </span> <span> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path> <polyline points="17 21 17 13 7 13 7 21"></polyline> <polyline points="7 3 7 8 15 8"></polyline> </svg> 3.2 MB </span> <span> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <polyline points="12 6 12 12 16 14"></polyline> </svg> 24 pages </span> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const downloadBtn = document.getElementById('downloadBtn'); const progressEl = downloadBtn.querySelector('.progress'); downloadBtn.addEventListener('click', function() { if (downloadBtn.classList.contains('loading') || downloadBtn.classList.contains('success')) { return; } // Add loading state downloadBtn.classList.add('loading'); // Simulate progress let progress = 0; const interval = setInterval(() => { progress += Math.random() * 15; if (progress >= 100) { progress = 100; clearInterval(interval); // Show success state setTimeout(() => { downloadBtn.classList.remove('loading'); downloadBtn.classList.add('success'); downloadBtn.querySelector('.text').textContent = 'Downloaded'; downloadBtn.querySelector('.icon').innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> `; // Reset after 3 seconds setTimeout(() => { progressEl.style.width = '0%'; downloadBtn.classList.remove('success'); downloadBtn.querySelector('.text').textContent = 'Download Datasheet'; downloadBtn.querySelector('.icon').innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="7 10 12 15 17 10"></polyline> <line x1="12" y1="15" x2="12" y2="3"></line> </svg> `; }, 3000); }, 500); } progressEl.style.width = `${progress}%`; }, 200); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Offline Tracks Download Button</title> <style> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } :root { --primary-gradient: linear-gradient(135deg, #5D5FEF, #843CF6); --primary-gradient-hover: linear-gradient(135deg, #843CF6, #5D5FEF); --secondary-gradient: linear-gradient(135deg, #1DB954, #21E065); --background-dark: #121212; --text-light: #F5F5F7; --text-secondary: #B3B3B3; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; background-color: var(--background-dark); color: var(--text-light); padding: 20px; } .container { max-width: 650px; width: 100%; padding: 30px; border-radius: 20px; background: rgba(30, 30, 30, 0.9); backdrop-filter: blur(10px); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); } .track-container { display: flex; flex-direction: column; align-items: center; gap: 30px; } .track-info { display: flex; align-items: center; width: 100%; gap: 20px; } .album-art { width: 100px; height: 100px; border-radius: 10px; object-fit: cover; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.4); flex-shrink: 0; } .track-details { flex-grow: 1; } .track-title { font-size: 24px; font-weight: 700; margin-bottom: 5px; } .artist { font-size: 16px; color: var(--text-secondary); margin-bottom: 10px; } .track-meta { display: flex; gap: 15px; color: var(--text-secondary); font-size: 14px; } .download-container { width: 100%; } .section-title { margin-bottom: 15px; font-size: 18px; font-weight: 600; } .download-button { position: relative; width: 100%; padding: 16px 24px; border-radius: 12px; background: var(--primary-gradient); border: none; color: white; font-family: 'Inter', sans-serif; font-size: 16px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 10px; transition: all 0.3s ease; overflow: hidden; z-index: 1; box-shadow: 0 5px 15px rgba(93, 95, 239, 0.3); } .download-button:before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: var(--primary-gradient-hover); opacity: 0; transition: opacity 0.3s ease; z-index: -1; } .download-button:hover:before { opacity: 1; } .download-button:hover .download-icon { transform: translateY(2px); } .download-button:hover { box-shadow: 0 8px 20px rgba(93, 95, 239, 0.5); } .download-button.is-downloaded { background: var(--secondary-gradient); box-shadow: 0 5px 15px rgba(29, 185, 84, 0.3); } .download-icon { width: 20px; height: 20px; transition: transform 0.3s ease; } .download-icon svg { width: 100%; height: 100%; } .download-icon .arrow { transition: fill 0.3s ease; } .download-button:hover .download-icon .arrow { fill: #ffffff; } .download-status { position: absolute; bottom: -30px; left: 0; width: 100%; text-align: center; font-size: 14px; color: var(--text-secondary); opacity: 0; transform: translateY(-5px); transition: all 0.3s ease; } .download-status.active { opacity: 1; transform: translateY(0); } .pulse { position: absolute; width: 100%; height: 100%; background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 70%); border-radius: 12px; transform: scale(0.9); opacity: 0; animation: pulse 2s ease-in-out infinite; } .progress-bar { position: absolute; bottom: 0; left: 0; height: 3px; width: 0%; background: rgba(255, 255, 255, 0.9); border-radius: 0 0 0 12px; transition: width 0.2s linear; } .quality-selector { display: flex; gap: 10px; margin-bottom: 20px; } .quality-option { padding: 8px 15px; border-radius: 8px; background: rgba(255, 255, 255, 0.1); color: var(--text-secondary); font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.3s ease; } .quality-option.active { background: rgba(93, 95, 239, 0.2); color: var(--text-light); } .quality-option:hover:not(.active) { background: rgba(255, 255, 255, 0.15); } @keyframes pulse { 0% { transform: scale(0.9); opacity: 0; } 50% { opacity: 0.3; } 100% { transform: scale(1.1); opacity: 0; } } @media (max-width: 600px) { .container { padding: 20px; } .track-info { flex-direction: column; text-align: center; gap: 15px; } .album-art { width: 80px; height: 80px; } .track-title { font-size: 20px; } .track-meta { justify-content: center; } } </style> </head> <body> <div class="container"> <div class="track-container"> <div class="track-info"> <img src="https://images.unsplash.com/photo-1614613535308-eb5fbd3d2c6a?q=80&w=200&auto=format&fit=crop" alt="Album art" class="album-art"> <div class="track-details"> <h1 class="track-title">Midnight Echoes</h1> <p class="artist">Lunar Waves</p> <div class="track-meta"> <span>3:42</span> <span>•</span> <span>Album: Distant Signals</span> </div> </div> </div> <div class="download-container"> <h2 class="section-title">Download for offline listening</h2> <div class="quality-selector"> <div class="quality-option" data-quality="normal">Normal</div> <div class="quality-option active" data-quality="high">High</div> <div class="quality-option" data-quality="ultra">Ultra HD</div> </div> <button class="download-button"> <div class="pulse"></div> <div class="progress-bar"></div> <span class="download-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 17V3" class="arrow" fill="transparent"/> <path d="M6 11l6 6 6-6" class="arrow" fill="transparent"/> <path d="M3 21h18"/> </svg> </span> <span class="button-text">Download Track</span> </button> <div class="download-status">Starting download...</div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const downloadButton = document.querySelector('.download-button'); const buttonText = document.querySelector('.button-text'); const downloadStatus = document.querySelector('.download-status'); const progressBar = document.querySelector('.progress-bar'); const qualityOptions = document.querySelectorAll('.quality-option'); let isDownloaded = false; let isDownloading = false; let selectedQuality = 'high'; qualityOptions.forEach(option => { option.addEventListener('click', function() { if (isDownloading || isDownloaded) return; qualityOptions.forEach(opt => opt.classList.remove('active')); this.classList.add('active'); selectedQuality = this.dataset.quality; }); }); downloadButton.addEventListener('click', function() { if (isDownloaded) { // Already downloaded showStatusMessage('Track already available offline', 2000); return; } if (isDownloading) { // Already in progress return; } // Start download simulation isDownloading = true; buttonText.textContent = 'Downloading...'; downloadStatus.textContent = 'Starting download...'; downloadStatus.classList.add('active'); // Quality affects download speed (for simulation) let duration = 3000; if (selectedQuality === 'ultra') duration = 5000; if (selectedQuality === 'normal') duration = 2000; let progress = 0; const interval = 50; const increment = interval / duration * 100; const downloadInterval = setInterval(function() { progress += increment; if (progress >= 100) { clearInterval(downloadInterval); completeDownload(); } else { updateProgress(progress); } }, interval); }); function updateProgress(progress) { progressBar.style.width = `${progress}%`; if (progress < 15) { downloadStatus.textContent = 'Starting download...'; } else if (progress < 40) { downloadStatus.textContent = `Downloading ${Math.round(progress)}%`; } else if (progress < 75) { downloadStatus.textContent = `Almost there: ${Math.round(progress)}%`; } else { downloadStatus.textContent = `Finalizing: ${Math.round(progress)}%`; } } function completeDownload() { isDownloading = false; isDownloaded = true; downloadButton.classList.add('is-downloaded'); buttonText.textContent = 'Available Offline'; // Show completion message showStatusMessage('Track downloaded successfully!', 3000); // Update download icon const downloadIcon = document.querySelector('.download-icon svg'); downloadIcon.innerHTML = ` <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path> `; } function showStatusMessage(message, duration) { downloadStatus.textContent = message; downloadStatus.classList.add('active'); setTimeout(() => { downloadStatus.classList.remove('active'); }, duration); } }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Educational Portal - Download Button</title> <style> :root { --primary-color: #a9d6e5; --secondary-color: #61a5c2; --accent-color: #2c7da0; --text-color: #014f86; --light-color: #f8f9fa; --success-color: #89c2b6; --hover-color: #468faf; --panel-color: #f0f7fa; --shadow-color: rgba(44, 125, 160, 0.15); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; } body { background-color: #f8f9fa; display: flex; justify-content: center; align-items: center; min-height: 100vh; color: var(--text-color); padding: 20px; } .portal-container { width: 100%; max-width: 650px; background-color: white; border-radius: 16px; box-shadow: 0 8px 30px var(--shadow-color); overflow: hidden; position: relative; } .header { background-color: var(--panel-color); padding: 25px 30px; border-bottom: 1px solid rgba(97, 165, 194, 0.2); } .header h1 { font-size: 24px; font-weight: 600; margin-bottom: 6px; color: var(--text-color); } .header p { color: var(--secondary-color); font-size: 15px; line-height: 1.5; } .course-materials { padding: 25px 30px; } .course-materials h2 { font-size: 18px; margin-bottom: 20px; color: var(--text-color); font-weight: 600; } .material-item { display: flex; align-items: center; justify-content: space-between; padding: 16px; background-color: var(--panel-color); border-radius: 12px; margin-bottom: 14px; transition: transform 0.2s ease, box-shadow 0.2s ease; } .material-item:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(97, 165, 194, 0.1); } .material-info { display: flex; align-items: center; flex: 1; } .material-icon { width: 42px; height: 42px; background-color: white; border-radius: 10px; display: flex; align-items: center; justify-content: center; margin-right: 16px; box-shadow: 0 2px 6px rgba(97, 165, 194, 0.1); } .material-icon svg { width: 22px; height: 22px; fill: var(--accent-color); } .material-details h3 { font-size: 16px; font-weight: 500; margin-bottom: 4px; color: var(--text-color); } .material-details p { font-size: 13px; color: var(--secondary-color); } .download-btn { position: relative; background-color: var(--primary-color); color: var(--text-color); border: none; padding: 10px 16px; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: background-color 0.3s ease, transform 0.2s ease; display: flex; align-items: center; justify-content: center; min-width: 115px; box-shadow: 0 2px 10px rgba(97, 165, 194, 0.15); } .download-btn:hover { background-color: var(--hover-color); color: white; transform: translateY(-2px); } .download-btn:active { transform: translateY(0); } .download-btn svg { margin-right: 8px; width: 16px; height: 16px; } .download-btn .checkmark { position: absolute; opacity: 0; transform: scale(0.5); transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .download-btn .download-icon { transition: opacity 0.3s ease, transform 0.3s ease; } .download-btn.success { background-color: var(--success-color); color: white; } .download-btn.success .download-icon { opacity: 0; transform: scale(0.5); } .download-btn.success .checkmark { opacity: 1; transform: scale(1); } .download-btn.success .btn-text { transform: translateX(8px); opacity: 1; } .progress-panel { margin-top: 25px; padding: 20px; background-color: var(--panel-color); border-radius: 12px; } .progress-panel h3 { font-size: 15px; font-weight: 500; margin-bottom: 10px; color: var(--text-color); } .progress-bar-container { width: 100%; height: 8px; background-color: rgba(97, 165, 194, 0.2); border-radius: 10px; overflow: hidden; } .progress-bar { height: 100%; width: 65%; background-color: var(--accent-color); border-radius: 10px; transition: width 0.5s ease; } .progress-info { display: flex; justify-content: space-between; margin-top: 8px; font-size: 13px; color: var(--secondary-color); } @media (max-width: 600px) { .material-item { flex-direction: column; align-items: flex-start; } .download-btn { margin-top: 15px; align-self: flex-end; } .material-info { width: 100%; } } .notification { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%) translateY(100px); background-color: var(--success-color); color: white; padding: 12px 20px; border-radius: 8px; box-shadow: 0 4px 15px rgba(44, 125, 160, 0.2); opacity: 0; transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.4s ease; display: flex; align-items: center; z-index: 1000; } .notification.show { transform: translateX(-50%) translateY(0); opacity: 1; } .notification svg { margin-right: 10px; width: 18px; height: 18px; } .btn-text { transition: transform 0.3s ease, opacity 0.3s ease; } </style> </head> <body> <div class="portal-container"> <div class="header"> <h1>Advanced Data Science</h1> <p>Your comprehensive guide to statistical modeling and machine learning algorithms</p> </div> <div class="course-materials"> <h2>Week 3 Materials</h2> <div class="material-item"> <div class="material-info"> <div class="material-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20M10,19L12.5,16.5L15,19V12.5H10V19Z" /> </svg> </div> <div class="material-details"> <h3>Linear Regression Analysis</h3> <p>Lecture slides and practice datasets (PDF, 12.4 MB)</p> </div> </div> <button class="download-btn" data-file="linear-regression-analysis"> <svg class="download-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" /> </svg> <svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" /> </svg> <span class="btn-text">Download</span> </button> </div> <div class="material-item"> <div class="material-info"> <div class="material-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M8,16H4V20H8V16M14,16H10V20H14V16M8,10H4V14H8V10M14,10H10V14H14V10M8,4H4V8H8V4M14,4H10V8H14V4M20,16H16V20H20V16M20,10H16V14H20V10M20,4H16V8H20V4Z" /> </svg> </div> <div class="material-details"> <h3>R Programming Tutorial</h3> <p>Hands-on exercises with sample code (ZIP, 8.7 MB)</p> </div> </div> <button class="download-btn" data-file="r-programming-tutorial"> <svg class="download-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" /> </svg> <svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" /> </svg> <span class="btn-text">Download</span> </button> </div> <div class="material-item"> <div class="material-info"> <div class="material-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M17,19H7V5H17M17,3H7A2,2 0 0,0 5,5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V5A2,2 0 0,0 17,3M15,15H9V6H15V15Z" /> </svg> </div> <div class="material-details"> <h3>Statistical Distributions Guide</h3> <p>Interactive reference material (HTML, 5.2 MB)</p> </div> </div> <button class="download-btn" data-file="statistical-distributions-guide"> <svg class="download-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" /> </svg> <svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" /> </svg> <span class="btn-text">Download</span> </button> </div> <div class="progress-panel"> <h3>Course Progress</h3> <div class="progress-bar-container"> <div class="progress-bar"></div> </div> <div class="progress-info"> <span>Week 3 of 12</span> <span>65% complete</span> </div> </div> </div> </div> <div class="notification"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" /> </svg> <span class="notification-text">Material added to downloads folder</span> </div> <script> document.addEventListener('DOMContentLoaded', function() { const downloadButtons = document.querySelectorAll('.download-btn'); const notification = document.querySelector('.notification'); const notificationText = document.querySelector('.notification-text'); const progressBar = document.querySelector('.progress-bar'); downloadButtons.forEach(button => { button.addEventListener('click', function() { const fileName = this.getAttribute('data-file'); this.classList.add('success'); // Show success notification with specific file name const materialName = this.closest('.material-item').querySelector('h3').textContent; notificationText.textContent = `${materialName} downloaded successfully`; notification.classList.add('show'); // Progress bar animation let currentWidth = parseInt(progressBar.style.width || "65"); progressBar.style.width = Math.min(currentWidth + 5, 100) + "%"; // Reset button after animation completes setTimeout(() => { this.classList.remove('success'); }, 2000); // Hide notification after delay setTimeout(() => { notification.classList.remove('show'); }, 3000); }); }); // Add subtle hover effects to material items const materialItems = document.querySelectorAll('.material-item'); materialItems.forEach(item => { item.addEventListener('mouseenter', function() { this.style.backgroundColor = '#e9f5fb'; }); item.addEventListener('mouseleave', function() { this.style.backgroundColor = var(--panel-color); }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Financial Report Dashboard</title> <style> :root { --primary: #1a1a1a; --secondary: #333333; --tertiary: #555555; --text: #f2f2f2; --accent: #4CAF50; --accent-hover: #3e8e41; --accent-secondary: #2196F3; --background: #f9f9f9; --card-bg: #ffffff; --shadow: rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { background-color: var(--background); display: flex; justify-content: center; align-items: center; height: 100vh; color: var(--primary); } .dashboard-container { width: 100%; max-width: 650px; padding: 2rem; background-color: var(--card-bg); border-radius: 12px; box-shadow: 0 12px 24px var(--shadow); overflow: hidden; } .dashboard-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; border-bottom: 1px solid rgba(0, 0, 0, 0.05); padding-bottom: 1rem; } .dashboard-title { font-size: 1.5rem; font-weight: 600; color: var(--primary); } .dashboard-logo { height: 36px; display: flex; align-items: center; } .logo-icon { width: 24px; height: 24px; margin-right: 8px; background-color: var(--primary); border-radius: 4px; display: inline-flex; align-items: center; justify-content: center; color: white; font-weight: 600; } .logo-text { font-weight: 600; letter-spacing: -0.5px; } .report-list { margin-bottom: 2rem; } .report-title { font-size: 1rem; font-weight: 500; margin-bottom: 1rem; color: var(--secondary); } .report-item { display: flex; justify-content: space-between; align-items: center; padding: 1rem; border-radius: 8px; margin-bottom: 0.75rem; background-color: rgba(0, 0, 0, 0.02); border: 1px solid rgba(0, 0, 0, 0.05); transition: all 0.2s ease; } .report-item:hover { background-color: rgba(0, 0, 0, 0.03); transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05); } .report-item-info { display: flex; flex-direction: column; } .report-item-name { font-weight: 500; margin-bottom: 0.25rem; } .report-item-meta { font-size: 0.8rem; color: var(--tertiary); display: flex; align-items: center; } .meta-dot { width: 4px; height: 4px; border-radius: 50%; background-color: var(--tertiary); margin: 0 6px; } .download-button { position: relative; background-color: var(--primary); color: var(--text); border: none; border-radius: 6px; padding: 0.6rem 1.2rem; font-size: 0.875rem; font-weight: 500; cursor: pointer; display: flex; align-items: center; justify-content: center; overflow: hidden; transition: all 0.3s ease; min-width: 120px; outline: none; } .download-button:hover { background-color: var(--secondary); transform: translateY(-1px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } .download-button:active { transform: translateY(1px); box-shadow: none; } .download-icon { margin-right: 8px; transform: translateY(0); transition: transform 0.3s ease; } .download-button:hover .download-icon { transform: translateY(2px); } .download-text { position: relative; z-index: 2; } .progress-overlay { position: absolute; top: 0; left: 0; width: 0%; height: 100%; background-color: var(--accent); z-index: 1; transition: width 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .download-complete .progress-overlay { background-color: var(--accent); } .download-icon-animated { display: none; position: absolute; z-index: 2; animation: downloadAnimation 1.5s infinite; } @keyframes downloadAnimation { 0% { transform: translateY(-10px); opacity: 0; } 50% { opacity: 1; } 100% { transform: translateY(10px); opacity: 0; } } .download-icon-check { display: none; position: relative; z-index: 2; } .download-success-text { display: none; position: relative; z-index: 2; } .report-filters { display: flex; gap: 0.75rem; margin-bottom: 1.5rem; flex-wrap: wrap; } .filter-pill { padding: 0.5rem 1rem; background-color: rgba(0, 0, 0, 0.05); border-radius: 100px; font-size: 0.8rem; font-weight: 500; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; } .filter-pill.active { background-color: var(--primary); color: var(--text); } .filter-pill:hover:not(.active) { background-color: rgba(0, 0, 0, 0.1); } .filter-dot { width: 6px; height: 6px; border-radius: 50%; margin-right: 6px; } .quarterly .filter-dot { background-color: var(--accent); } .monthly .filter-dot { background-color: var(--accent-secondary); } .annual .filter-dot { background-color: #FF5722; } .report-tag { font-size: 0.7rem; padding: 0.2rem 0.5rem; border-radius: 4px; margin-left: 0.5rem; font-weight: 600; } .tag-quarterly { background-color: rgba(76, 175, 80, 0.1); color: var(--accent); } .tag-monthly { background-color: rgba(33, 150, 243, 0.1); color: var(--accent-secondary); } .tag-annual { background-color: rgba(255, 87, 34, 0.1); color: #FF5722; } @media (max-width: 600px) { .dashboard-container { padding: 1.5rem; max-width: 100%; } .report-item { flex-direction: column; align-items: flex-start; padding: 0.75rem; } .report-item-info { margin-bottom: 1rem; width: 100%; } .download-button { width: 100%; } } .notification { position: fixed; bottom: 20px; right: 20px; background-color: var(--primary); color: var(--text); padding: 1rem; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); transform: translateY(100px); opacity: 0; transition: all 0.3s ease; display: flex; align-items: center; max-width: 300px; z-index: 10; } .notification.show { transform: translateY(0); opacity: 1; } .notification-icon { margin-right: 12px; background-color: var(--accent); width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .notification-content { flex-grow: 1; } .notification-title { font-weight: 600; margin-bottom: 4px; font-size: 0.9rem; } .notification-message { font-size: 0.8rem; opacity: 0.8; } </style> </head> <body> <div class="dashboard-container"> <div class="dashboard-header"> <div class="dashboard-title">Financial Reports</div> <div class="dashboard-logo"> <div class="logo-icon">F</div> <div class="logo-text">FinEdge</div> </div> </div> <div class="report-filters"> <div class="filter-pill active all"> <span>All Reports</span> </div> <div class="filter-pill quarterly"> <span class="filter-dot"></span> <span>Quarterly</span> </div> <div class="filter-pill monthly"> <span class="filter-dot"></span> <span>Monthly</span> </div> <div class="filter-pill annual"> <span class="filter-dot"></span> <span>Annual</span> </div> </div> <div class="report-list"> <div class="report-title">Available Reports</div> <div class="report-item" data-type="quarterly"> <div class="report-item-info"> <div class="report-item-name">Q2 2023 Financial Statement<span class="report-tag tag-quarterly">Q2</span></div> <div class="report-item-meta"> <span>Updated Jul 15, 2023</span> <span class="meta-dot"></span> <span>4.2 MB</span> </div> </div> <button class="download-button" data-report="Q2 2023 Financial Statement"> <span class="download-icon"> <svg xmlns="http://www.w3.org/2000/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="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="7 10 12 15 17 10"></polyline> <line x1="12" y1="15" x2="12" y2="3"></line> </svg> </span> <span class="download-icon-animated"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="7 13 12 18 17 13"></polyline> <line x1="12" y1="18" x2="12" y2="6"></line> </svg> </span> <span class="download-icon-check"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> </span> <span class="download-text">Download</span> <span class="download-success-text">Complete</span> <div class="progress-overlay"></div> </button> </div> <div class="report-item" data-type="monthly"> <div class="report-item-info"> <div class="report-item-name">June 2023 Cash Flow Analysis<span class="report-tag tag-monthly">Monthly</span></div> <div class="report-item-meta"> <span>Updated Jul 5, 2023</span> <span class="meta-dot"></span> <span>3.7 MB</span> </div> </div> <button class="download-button" data-report="June 2023 Cash Flow Analysis"> <span class="download-icon"> <svg xmlns="http://www.w3.org/2000/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="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="7 10 12 15 17 10"></polyline> <line x1="12" y1="15" x2="12" y2="3"></line> </svg> </span> <span class="download-icon-animated"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="7 13 12 18 17 13"></polyline> <line x1="12" y1="18" x2="12" y2="6"></line> </svg> </span> <span class="download-icon-check"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> </span> <span class="download-text">Download</span> <span class="download-success-text">Complete</span> <div class="progress-overlay"></div> </button> </div> <div class="report-item" data-type="annual"> <div class="report-item-info"> <div class="report-item-name">2022 Annual Financial Report<span class="report-tag tag-annual">Annual</span></div> <div class="report-item-meta"> <span>Updated Mar 24, 2023</span> <span class="meta-dot"></span> <span>8.5 MB</span> </div> </div> <button class="download-button" data-report="2022 Annual Financial Report"> <span class="download-icon"> <svg xmlns="http://www.w3.org/2000/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="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="7 10 12 15 17 10"></polyline> <line x1="12" y1="15" x2="12" y2="3"></line> </svg> </span> <span class="download-icon-animated"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="7 13 12 18 17 13"></polyline> <line x1="12" y1="18" x2="12" y2="6"></line> </svg> </span> <span class="download-icon-check"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> </span> <span class="download-text">Download</span> <span class="download-success-text">Complete</span> <div class="progress-overlay"></div> </button> </div> <div class="report-item" data-type="quarterly"> <div class="report-item-info"> <div class="report-item-name">Q1 2023 Balance Sheet<span class="report-tag tag-quarterly">Q1</span></div> <div class="report-item-meta"> <span>Updated Apr 10, 2023</span> <span class="meta-dot"></span> <span>3.9 MB</span> </div> </div> <button class="download-button" data-report="Q1 2023 Balance Sheet"> <span class="download-icon"> <svg xmlns="http://www.w3.org/2000/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="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="7 10 12 15 17 10"></polyline> <line x1="12" y1="15" x2="12" y2="3"></line> </svg> </span> <span class="download-icon-animated"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="7 13 12 18 17 13"></polyline> <line x1="12" y1="18" x2="12" y2="6"></line> </svg> </span> <span class="download-icon-check"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> </span> <span class="download-text">Download</span> <span class="download-success-text">Complete</span> <div class="progress-overlay"></div> </button> </div> </div> </div> <div class="notification"> <div class="notification-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="20 6 9 17 4 12"></polyline> </svg> </div> <div class="notification-content"> <div class="notification-title">Download Complete</div> <div class="notification-message">Your financial report has been successfully prepared.</div> </div> </div> <script> document.addEventListener('DOMContentLoaded', () => { const downloadButtons = document.querySelectorAll('.download-button'); const notification = document.querySelector('.notification'); const filterPills = document.querySelectorAll('.filter-pill'); const reportItems = document.querySelectorAll('.report-item'); // Handle download button clicks downloadButtons.forEach(button => { button.addEventListener('click', function() { const reportName = this.getAttribute('data-report'); // Prevent multiple clicks during download if (this.classList.contains('downloading') || this.classList.contains('download-complete')) { return; } // Start download process this.classList.add('downloading'); // Show animated icon this.querySelector('.download-icon').style.display = 'none'; this.querySelector('.download-icon-animated').style.display = 'inline-block'; // Animate progress const progressOverlay = this.querySelector('.progress-overlay'); let progress = 0; const progressInterval = setInterval(() => { progress += 5; progressOverlay.style.width = `${progress}%`; if (progress >= 100) { clearInterval(progressInterval); completeDownload(this, reportName); } }, 120); }); }); // Complete download function function completeDownload(button, reportName) { // Hide animated icon, show check icon button.querySelector('.download-icon-animated').style.display = 'none'; button.querySelector('.download-icon-check').style.display = 'inline-block'; // Update text button.querySelector('.download-text').style.display = 'none'; button.querySelector('.download-success-text').style.display = 'inline-block'; // Add completed class button.classList.remove('downloading'); button.classList.add('download-complete'); // Show notification notification.querySelector('.notification-message').textContent = `${reportName} has been successfully prepared.`; notification.classList.add('show'); // Hide notification after 4 seconds setTimeout(() => { notification.classList.remove('show'); }, 4000); // Reset button after 3 seconds setTimeout(() => { button.querySelector('.download-icon').style.display = 'inline-block'; button.querySelector('.download-icon-check').style.display = 'none'; button.querySelector('.download-text').style.display = 'inline-block'; button.querySelector('.download-success-text').style.display = 'none'; button.querySelector('.progress-overlay').style.width = '0%'; button.classList.remove('download-complete'); }, 3000); } // Handle filter pills filterPills.forEach(pill => { pill.addEventListener('click', function() { // Remove active class from all pills filterPills.forEach(p => p.classList.remove('active')); // Add active class to clicked pill this.classList.add('active'); // Filter reports const filterType = this.classList.contains('all') ? 'all' : this.classList.contains('quarterly') ? 'quarterly' : this.classList.contains('monthly') ? 'monthly' : 'annual'; reportItems.forEach(item => { if (filterType === 'all' || item.getAttribute('data-type') === filterType) { item.style.display = 'flex'; } else { item.style.display = 'none'; } }); }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> :root { --primary-color: #4a6bff; --secondary-color: #6e42ff; --accent-color: #ff4a8d; --success-color: #36d7b7; --background-color: #f8f9fc; --text-color: #2c3e50; --shadow-color: rgba(74, 107, 255, 0.25); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 700px; background-color: var(--background-color); padding: 20px; } .app-container { width: 100%; max-width: 680px; background: white; border-radius: 24px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.06); padding: 30px; position: relative; overflow: hidden; } .app-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px; } .app-title { font-size: 24px; font-weight: 700; color: var(--text-color); } .document-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; margin-bottom: 30px; } .document-card { background: white; border-radius: 16px; box-shadow: 0 6px 15px rgba(0, 0, 0, 0.03); padding: 20px; border: 1px solid #eaeef8; position: relative; transition: transform 0.2s ease, box-shadow 0.2s ease; overflow: hidden; } .document-card:hover { transform: translateY(-3px); box-shadow: 0 12px 20px rgba(0, 0, 0, 0.05); } .document-icon { display: flex; justify-content: center; align-items: center; width: 50px; height: 50px; border-radius: 12px; background: var(--primary-color); margin-bottom: 15px; color: white; font-size: 24px; } .document-icon.pdf { background: linear-gradient(135deg, #ff4a5f, #ff4a8d); } .document-icon.doc { background: linear-gradient(135deg, #4a6bff, #6e42ff); } .document-icon.xls { background: linear-gradient(135deg, #36d7b7, #2ccfb0); } .document-title { font-size: 16px; font-weight: 600; color: var(--text-color); margin-bottom: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .document-info { font-size: 13px; color: #6c7a8c; margin-bottom: 15px; } .download-button { position: relative; width: 100%; padding: 12px 15px; border-radius: 14px; border: none; background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); color: white; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; justify-content: center; align-items: center; gap: 8px; overflow: hidden; transition: transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.2s ease; box-shadow: 0 8px 16px var(--shadow-color), 0 2px 4px rgba(0, 0, 0, 0.1); } .download-button:hover { box-shadow: 0 10px 20px var(--shadow-color), 0 3px 6px rgba(0, 0, 0, 0.1); } .download-button:active { transform: scale(0.96); } .download-button .icon { font-size: 18px; margin-right: 2px; } .download-button .download-progress { position: absolute; bottom: 0; left: 0; height: 4px; background: rgba(255, 255, 255, 0.3); border-radius: 2px; width: 0%; transition: width 0.3s linear; } .download-result { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; background: var(--success-color); color: white; font-weight: 600; opacity: 0; transform: translateY(100%); transition: transform 0.2s ease, opacity 0.2s ease; } .download-button.downloaded .download-result { opacity: 1; transform: translateY(0); } .document-size { display: inline-block; padding: 4px 8px; background-color: #f0f3f9; border-radius: 8px; font-size: 12px; font-weight: 500; color: #6c7a8c; } .storage-info { margin-top: 30px; padding: 20px; background: rgba(74, 107, 255, 0.05); border-radius: 16px; display: flex; justify-content: space-between; align-items: center; } .storage-text { flex: 1; } .storage-title { font-size: 16px; font-weight: 600; color: var(--text-color); margin-bottom: 5px; } .storage-subtext { font-size: 13px; color: #6c7a8c; } .storage-bar { width: 100%; height: 8px; background: #e0e6f5; border-radius: 4px; margin-top: 12px; overflow: hidden; } .storage-progress { height: 100%; width: 65%; background: linear-gradient(to right, var(--primary-color), var(--secondary-color)); border-radius: 4px; } .storage-action { margin-left: 20px; } .manage-button { padding: 10px 16px; border-radius: 12px; border: 1px solid var(--primary-color); background: transparent; color: var(--primary-color); font-weight: 600; font-size: 14px; cursor: pointer; transition: background 0.2s ease, color 0.2s ease; } .manage-button:hover { background: rgba(74, 107, 255, 0.05); } .pulse-animation { animation: pulse 1.5s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(74, 107, 255, 0.6); } 70% { box-shadow: 0 0 0 10px rgba(74, 107, 255, 0); } 100% { box-shadow: 0 0 0 0 rgba(74, 107, 255, 0); } } .download-icon { display: inline-block; width: 18px; height: 18px; position: relative; } .download-icon:before { content: ''; position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: 2px; height: 10px; background: white; } .download-icon:after { content: ''; position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%); width: 10px; height: 10px; border: 2px solid white; border-top: none; border-left: none; transform-origin: center; transform: translateX(-50%) rotate(45deg); } .downloaded-icon { display: inline-block; width: 18px; height: 18px; position: relative; } .downloaded-icon:before { content: ''; position: absolute; top: 50%; left: 0; width: 6px; height: 2px; background: white; transform: translateY(-50%) rotate(45deg); transform-origin: left; } .downloaded-icon:after { content: ''; position: absolute; top: 50%; left: 4px; width: 12px; height: 2px; background: white; transform: translateY(-50%) rotate(-45deg); transform-origin: left; } @media (max-width: 700px) { .app-container { padding: 20px; } .document-list { grid-template-columns: 1fr; } .storage-info { flex-direction: column; } .storage-action { margin-left: 0; margin-top: 15px; width: 100%; } .manage-button { width: 100%; } } </style> </head> <body> <div class="app-container"> <div class="app-header"> <h1 class="app-title">Offline Documents</h1> </div> <div class="document-list"> <div class="document-card"> <div class="document-icon pdf">PDF</div> <h3 class="document-title">Q3 Marketing Report</h3> <p class="document-info">Last edited: Today</p> <span class="document-size">4.2 MB</span> <button class="download-button pulse-animation" id="download-btn-1"> <span class="download-icon"></span> Save Offline <div class="download-progress"></div> <div class="download-result"> <span class="downloaded-icon"></span> Available Offline </div> </button> </div> <div class="document-card"> <div class="document-icon doc">DOC</div> <h3 class="document-title">Client Proposal Draft</h3> <p class="document-info">Last edited: Yesterday</p> <span class="document-size">1.8 MB</span> <button class="download-button" id="download-btn-2"> <span class="download-icon"></span> Save Offline <div class="download-progress"></div> <div class="download-result"> <span class="downloaded-icon"></span> Available Offline </div> </button> </div> <div class="document-card"> <div class="document-icon xls">XLS</div> <h3 class="document-title">2023 Budget Forecast</h3> <p class="document-info">Last edited: 2 days ago</p> <span class="document-size">3.5 MB</span> <button class="download-button" id="download-btn-3"> <span class="download-icon"></span> Save Offline <div class="download-progress"></div> <div class="download-result"> <span class="downloaded-icon"></span> Available Offline </div> </button> </div> </div> <div class="storage-info"> <div class="storage-text"> <h3 class="storage-title">Offline Storage</h3> <p class="storage-subtext">6.5 GB used of 10 GB</p> <div class="storage-bar"> <div class="storage-progress"></div> </div> </div> <div class="storage-action"> <button class="manage-button">Manage Storage</button> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', () => { const downloadButtons = document.querySelectorAll('.download-button'); downloadButtons.forEach(button => { button.addEventListener('click', function() { if (this.classList.contains('downloaded')) { return; } // Remove pulse animation this.classList.remove('pulse-animation'); const progressBar = this.querySelector('.download-progress'); let progress = 0; // Simulate download progress const downloadInterval = setInterval(() => { progress += Math.random() * 5; if (progress >= 100) { progress = 100; clearInterval(downloadInterval); // Add small delay before showing completion setTimeout(() => { this.classList.add('downloaded'); // Show success feedback with haptic-like animation this.style.transform = 'scale(1.05)'; setTimeout(() => { this.style.transform = 'scale(1)'; }, 150); // Create ripple effect createRippleEffect(this); }, 300); } progressBar.style.width = `${progress}%`; }, 100); }); }); function createRippleEffect(button) { const ripple = document.createElement('span'); ripple.style.position = 'absolute'; ripple.style.borderRadius = '50%'; ripple.style.backgroundColor = 'rgba(255, 255, 255, 0.3)'; ripple.style.transform = 'scale(0)'; ripple.style.top = '50%'; ripple.style.left = '50%'; ripple.style.width = '150%'; ripple.style.height = '150%'; ripple.style.marginLeft = '-75%'; ripple.style.marginTop = '-75%'; ripple.style.transition = 'transform 0.6s ease-out, opacity 0.6s ease-out'; ripple.style.opacity = '1'; ripple.style.zIndex = '0'; button.appendChild(ripple); // Add small delay for the animation to kick in setTimeout(() => { ripple.style.transform = 'scale(1)'; ripple.style.opacity = '0'; // Clean up the ripple after animation setTimeout(() => { button.removeChild(ripple); }, 600); }, 10); } // Highlight the first button with pulse animation const firstButton = document.getElementById('download-btn-1'); firstButton.classList.add('pulse-animation'); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>NeonPatch Download Hub</title> <style> @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Rajdhani:wght@300;400;500;600;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } :root { --neon-blue: #00f3ff; --neon-purple: #b300ff; --neon-green: #3dff38; --dark-bg: #060818; --darker-bg: #030210; --panel-bg: rgba(18, 21, 40, 0.6); } body { font-family: 'Rajdhani', sans-serif; background: linear-gradient(135deg, var(--darker-bg), var(--dark-bg)); color: #ffffff; height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; overflow: hidden; perspective: 1000px; } .container { width: 100%; max-width: 700px; height: 100%; max-height: 700px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center; position: relative; } .grid-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: linear-gradient(to right, rgba(30, 38, 90, 0.1) 1px, transparent 1px), linear-gradient(to bottom, rgba(30, 38, 90, 0.1) 1px, transparent 1px); background-size: 30px 30px; z-index: 0; } .hub-panel { background: var(--panel-bg); border-radius: 12px; width: 90%; max-width: 550px; padding: 30px; box-shadow: 0 0 40px rgba(0, 243, 255, 0.1); border: 1px solid rgba(0, 243, 255, 0.2); backdrop-filter: blur(10px); z-index: 10; position: relative; transform-style: preserve-3d; transform: translateZ(0); transition: all 0.3s ease; } .hub-panel:before { content: ''; position: absolute; top: -2px; left: -2px; right: -2px; bottom: -2px; background: linear-gradient(45deg, var(--neon-blue), var(--neon-purple), var(--neon-green), var(--neon-blue)); border-radius: 14px; z-index: -1; opacity: 0.3; filter: blur(8px); background-size: 400%; animation: glowBorder 12s linear infinite; } @keyframes glowBorder { 0% { background-position: 0 0; } 50% { background-position: 400% 0; } 100% { background-position: 0 0; } } .hub-header { text-align: center; margin-bottom: 25px; } .hub-title { font-family: 'Orbitron', sans-serif; font-size: 28px; font-weight: 900; text-transform: uppercase; letter-spacing: 2px; color: white; margin-bottom: 10px; position: relative; display: inline-block; } .hub-title:after { content: ''; position: absolute; bottom: -8px; left: 50%; transform: translateX(-50%); width: 70%; height: 2px; background: linear-gradient(90deg, transparent, var(--neon-blue), transparent); } .patch-info { text-align: center; color: #acb5d9; font-size: 17px; line-height: 1.5; margin-bottom: 10px; } .patch-version { font-family: 'Orbitron', sans-serif; font-size: 20px; font-weight: 700; color: white; text-shadow: 0 0 10px rgba(0, 243, 255, 0.5); margin-bottom: 5px; } .patch-size { font-size: 16px; color: rgba(255, 255, 255, 0.7); margin-bottom: 20px; } .patch-features { background: rgba(8, 11, 22, 0.6); border-radius: 8px; padding: 15px; margin-bottom: 25px; border: 1px solid rgba(0, 243, 255, 0.15); } .feature-title { font-family: 'Orbitron', sans-serif; font-size: 16px; font-weight: 600; margin-bottom: 10px; color: var(--neon-blue); } .feature-list { list-style-type: none; padding-left: 5px; } .feature-list li { position: relative; padding-left: 20px; margin-bottom: 8px; font-size: 15px; line-height: 1.4; } .feature-list li:before { content: '>'; position: absolute; left: 0; color: var(--neon-purple); font-weight: bold; } .download-container { text-align: center; margin-top: 10px; } .download-btn { position: relative; font-family: 'Orbitron', sans-serif; font-size: 18px; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; color: white; background: linear-gradient(45deg, rgba(0, 243, 255, 0.2), rgba(179, 0, 255, 0.2)); border: none; border-radius: 6px; padding: 15px 35px; cursor: pointer; overflow: hidden; transition: all 0.3s ease; outline: none; box-shadow: 0 0 20px rgba(0, 243, 255, 0.2); } .download-btn:before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(45deg, var(--neon-blue), var(--neon-purple)); opacity: 0; z-index: -1; transition: opacity 0.3s ease; } .download-btn:after { content: ''; position: absolute; top: -2px; left: -2px; right: -2px; bottom: -2px; background: linear-gradient(45deg, var(--neon-blue), var(--neon-purple)); border-radius: 6px; z-index: -2; } .btn-text { position: relative; z-index: 2; display: flex; align-items: center; justify-content: center; } .btn-icon { margin-right: 10px; font-size: 20px; } .download-btn:hover { transform: translateY(-2px); box-shadow: 0 0 25px rgba(0, 243, 255, 0.4); } .download-btn:hover:before { opacity: 0.1; } .download-btn:active { transform: translateY(1px); } .secure-info { display: flex; align-items: center; justify-content: center; margin-top: 15px; color: rgba(255, 255, 255, 0.6); font-size: 14px; } .secure-icon { color: var(--neon-green); margin-right: 6px; } .progress-container { width: 100%; background: rgba(8, 11, 22, 0.6); border-radius: 20px; height: 8px; margin-top: 20px; overflow: hidden; position: relative; display: none; } .progress-bar { position: absolute; left: 0; top: 0; height: 100%; background: linear-gradient(90deg, var(--neon-blue), var(--neon-purple)); width: 0%; border-radius: 20px; transition: width 0.5s ease; background-size: 200% 100%; animation: gradientShift 2s infinite linear; } @keyframes gradientShift { 0% { background-position: 0% 0%; } 100% { background-position: 200% 0%; } } .progress-text { margin-top: 10px; font-size: 14px; color: var(--neon-blue); display: none; } .download-complete { display: none; margin-top: 15px; text-align: center; } .complete-icon { font-size: 40px; color: var(--neon-green); animation: pulse 1.5s infinite ease-in-out; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } .complete-text { font-family: 'Orbitron', sans-serif; font-size: 18px; font-weight: 600; margin-top: 10px; color: var(--neon-green); } .particles { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; z-index: 0; } .particle { position: absolute; width: 1px; height: 1px; background-color: rgba(0, 243, 255, 0.5); pointer-events: none; } @media (max-width: 600px) { .hub-panel { width: 95%; padding: 20px; } .hub-title { font-size: 24px; } .patch-info { font-size: 15px; } .patch-version { font-size: 18px; } .download-btn { padding: 12px 25px; font-size: 16px; } } /* Scan line effect */ .scan-lines { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: repeating-linear-gradient( to bottom, transparent 0px, transparent 1px, rgba(0, 0, 0, 0.1) 1px, rgba(0, 0, 0, 0.1) 2px ); pointer-events: none; z-index: 15; opacity: 0.2; } /* Glow animation */ @keyframes textGlow { 0% { text-shadow: 0 0 5px rgba(0, 243, 255, 0.5); } 50% { text-shadow: 0 0 20px rgba(0, 243, 255, 0.8), 0 0 30px rgba(0, 243, 255, 0.5); } 100% { text-shadow: 0 0 5px rgba(0, 243, 255, 0.5); } } .glow-text { animation: textGlow 2s infinite; } </style> </head> <body> <div class="particles" id="particles"></div> <div class="container"> <div class="grid-bg"></div> <div class="hub-panel" id="hub-panel"> <div class="hub-header"> <h1 class="hub-title glow-text">NeonPatch Hub</h1> <p class="patch-info">Critical performance update for CyberNova: Quantum Eclipse</p> <div class="patch-version">Patch v2.8.7_NexGen</div> <div class="patch-size">4.76 GB</div> </div> <div class="patch-features"> <div class="feature-title">PATCH HIGHLIGHTS:</div> <ul class="feature-list"> <li>Raytracing performance boost (+30% FPS on RTX series)</li> <li>Fixed Nightcity district loading glitches</li> <li>New weapon: Quantum Disruptor MK-II</li> <li>AI enemy combat behavior enhancements</li> </ul> </div> <div class="download-container"> <button class="download-btn" id="downloadBtn"> <span class="btn-text"> <span class="btn-icon">↓</span> <span>Download Patch</span> </span> </button> <div class="secure-info"> <span class="secure-icon">✓</span> <span>Verified by NovaSec | Direct from developer</span> </div> <div class="progress-container" id="progressContainer"> <div class="progress-bar" id="progressBar"></div> </div> <div class="progress-text" id="progressText">Downloading... 0%</div> <div class="download-complete" id="downloadComplete"> <div class="complete-icon">✓</div> <div class="complete-text">PATCH READY TO INSTALL</div> </div> </div> </div> <div class="scan-lines"></div> </div> <script> // Sound effects function createAudioElement(src) { const audio = new Audio(); audio.src = 'data:audio/mp3;base64,' + src; return audio; } // Base64 encoded very short sound clips const hoverSound = createAudioElement('SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4Ljc2LjEwMAAAAAAAAAAAAAAA//tQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAADpgC1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1//////////////////////////////////////////////////////////////////8AAAAATGF2YzU4LjEzAAAAAAAAAAAAAAAAJAQJJ0EAAAAAAAADJ5gxC3X///////////////8To/l/nnLvAAAAAAAAAAAAAAAB7Oj9/w4VY2FmZgAAAAAAAAAAAImxAAAAAAAAAALj9cGNiIQAAAAAAABwP//NwrADFQEFmTy4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='); const clickSound = createAudioElement('SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4Ljc2LjEwMAAAAAAAAAAAAAAA//tUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAAEAAAIoQBaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlq2tra2tra2tra2tra2tra2tra2tra2tra2tv////////////////////////////////////8AAAAATGF2YzU4LjEzAAAAAAAAAAAAAAAAJAT3J0EAAAAAAAAI4YQi1aL//////////////////+gDGfIzM/MAAAAAAAAAAAAAA765YhAAWhoUEAAGoVsXVpYFABIaFFQAAGgZLFUAAF8pGLbICJ1hhRgx6lYAAD6+2Ga1OgA0/nfAAPMAi2+pZABAoKCgwXwW+mQAECpCAAFi+C35JAHfCvnw3fIHzaF6ABQDCW6WQAQOkIABDM0qgQPiARwcfm0CBQUGERIPn5+n5+fAA+fnwD5+fB+fHx8H59nt7fn5+fDd3d/p78AAAAHF8bvt7e/B3d3fbqcnLy8nP5+t3d3/b29v5+fr5+ft7e3t7e3t7e3GX//c37w2F1b6Pjd7vd74Nfr9fr9d6+DD36979TgYMGfl5eXl5eX77e3t7e3t5/w'); const completeSound = createAudioElement('SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4Ljc2LjEwMAAAAAAAAAAAAAAA//tUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAAEAAAIHgBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCPj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4/s7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Oz///////////8AAAAATGF2YzU4LjEzAAAAAAAAAAAAAAAAJAJwJ0EAAAAAAAAIHC/FhRr//////////////////+Hw+H/MZ/MAAAAAAAAAAAAAAHC3gA1CaGFDFgdEEoA9LQSRhNgEAmhhQwQSHRAuAPSJIIwMwCYSQwoYwEDogGP8AQCAIBAAI8fBQjoEANsGBPR5iAPiKkVGAYYxfChooaLCxcPFB4oEAgVBAR4RECKgECQCJjLIkoHBwUVAPCZnPXRBEYG0RIxE1YkOGzRZkWaJLLyg0IOiwAECQgcETGQDrA8OGNOmyZM2dOPRgdQEGRQ8SNGCxYcMFmONGjBg+kG4Cio4iQJFShMnUQRQ0tSkiZMldOjMgXPGDJw3L8Spu4SESAUIf/gRQJAgEaP6jCJFkjSpkydQoECNDDnyUSM+fVRBWpTI0SFIMQ4cOPD68o4BD2j27PHjx48OGDBcsFBhgoQIGDJkwICBP/v3//+nTu3atalUq5ShQ6dOjwL7ABAgzSQA//uUZGqK9OQz2VuYMuBEIysoH3HwAAABpAAAACAAADSAAAAEYoIJBZgGigtAZQoTK3r09LFhJViBgwdQJXGiA8vASYnv4MFBb+BBgZEILggwEGEkRIm8OVOGDRtyaCvbixIkRSqoUKNKnLmBCTty3XGjxJ9CjRrVWfWfLBgxZdqjMcOCDOJLj+Lk2eNo0qXZJFnCNAoYFBaUEBIWFBIQFBYYEhQWGBYYGBIYGBwYHBggHGaJGBwiHCAgbCZEZGSJsO13jIsXIsSZEjxElySZAwiLGSY+bAkiXKlS44dOGjYwHPihS5k0de7c0dOojp07UkqXPo0af1ZcTbdw5cpViAMIUG0AwP/7lERgh/aVEuNbsfJARoRtIYO+aQAAAaQAAAAgAAA0gAAABCSBYAIUFACJBUADGbVy4eNmzBYFEEQGDhQkeAtCSWjBMmCw/8GCuA7jjyBIGFAKCgkKDAgMBgUMDzJZUoTLFgWATJkyZJVg+csW9GCRKZInUJ/QZcyZZmStasWV6wnDxgwYLmDBkwYMHB1YgBQUGBJgwbMmDJooTGSHAwxlCYwZOGTRouPBZP7DhslDhswZM47Bk8dOmMc/pIiYGJ6Tx03jnP/yh4YaOIaSYN9RM5AoSA4RWFCQwYEDVo4dWrLyB5UCBpQkYPKEihQqMOcNHDiQcUOHIJkyJEiNGTI3K5YsQhcKsImYDAxGGhhCQP/7hGQ7g/IpEuI7mFsgNoNr6D+LJoAAAGkAAAAIAAANIAAAAbIEkANgghoRNlzJkoTgYABuOGjRo9Igg4ooLEyAn7A0rLDRQxQoSIECEiECY+ZLlzZrv2jZk2aGDBx5g6kAcOHPAgMVDq5wQJKlixcuYMe8WLGPcWDDdw4c3MGTBo4dPTRcmeYnix5EiWPkmDBcbcxcuXJk3xo8sMnECJc80bYvnTpw6eYOnU/8eLHj16+MHjwrSpUsWJsuXGCQoJDXN02dN/CpMka0GDBnTZw2b+GDBf+bKlBjkxKiwoJCQkHCQgIBwcHGCQ8OCg4ODg4PCfsBPEAQK/h1G3//+05GRkYFQwPDC5//tEZFiD6WkRP9xnwAAwwmf5jHgAAAAaQAAAAgAAA0gAAABGBsZGP0///1GBwZGRj/YGB0cmBwcGBj/Yy/RkZf/7j2AgYjOp//t0ZAqP8qMSyFh/YAAAAANIOAAAAAAAA0gAAAAAAAAANIAAAAAP//43bAOoAAGAAD//luTAOoAABgAAEwASG98PP3kzF88/fyZjc43sxMgTIErLkzICIE8AQBgACEKgg0nUvkbE9zYmNzkXj6g+fjA3PL4YA8x1xVP1Og3g9D1lGqWUkr0oMkjvJFLapRKJP3/7f///1kAC1QAkfUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'); // Create particles function createParticles() { const particlesContainer = document.getElementById('particles'); const particleCount = 50; for (let i = 0; i < particleCount; i++) { const particle = document.createElement('div'); particle.classList.add('particle'); // Random positions const posX = Math.random() * 100; const posY = Math.random() * 100; particle.style.left = `${posX}%`; particle.style.top = `${posY}%`; // Random sizes const size = Math.random() * 3; particle.style.width = `${size}px`; particle.style.height = `${size}px`; // Random opacity particle.style.opacity = Math.random() * 0.5 + 0.2; // Random colors (blue, purple) const colors = ['rgba(0, 243, 255, 0.7)', 'rgba(179, 0, 255, 0.7)', 'rgba(61, 255, 56, 0.7)']; particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; // Animation const duration = Math.random() * 20 + 10; particle.style.animation = `float ${duration}s linear infinite`; particlesContainer.appendChild(particle); // Add floating animation particle.animate( [ { transform: `translate(0, 0)` }, { transform: `translate(${Math.random() * 50 - 25}px, ${Math.random() * 100 - 50}px)` }, { transform: `translate(${Math.random() * 50 - 25}px, ${Math.random() * 100 - 50}px)` }, { transform: `translate(0, 0)` } ], { duration: Math.random() * 20000 + 10000, iterations: Infinity } ); } } document.addEventListener('DOMContentLoaded', function() { createParticles(); const downloadBtn = document.getElementById('downloadBtn'); const progressContainer = document.getElementById('progressContainer'); const progressBar = document.getElementById('progressBar'); const progressText = document.getElementById('progressText'); const downloadComplete = document.getElementById('downloadComplete'); const hubPanel = document.getElementById('hub-panel'); // 3D tilt effect for panel hubPanel.addEventListener('mousemove', function(e) { const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const centerX = rect.width / 2; const centerY = rect.height / 2; const deltaX = (x - centerX) / (rect.width / 2); const deltaY = (y - centerY) / (rect.height / 2); this.style.transform = `perspective(1000px) rotateX(${-deltaY * 5}deg) rotateY(${deltaX * 5}deg) translateZ(10px)`; }); hubPanel.addEventListener('mouseleave', function() { this.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) translateZ(0)'; }); // Button hover sound downloadBtn.addEventListener('mouseenter', function() { hoverSound.currentTime = 0; hoverSound.play(); }); // Download button click downloadBtn.addEventListener('click', function() { clickSound.currentTime = 0; clickSound.play(); // Visual button feedback this.classList.add('downloading'); // Show progress elements progressContainer.style.display = 'block'; progressText.style.display = 'block'; // Hide download button this.style.opacity = '0.5'; this.disabled = true; // Simulated download progress let progress = 0; const interval = setInterval(function() { progress += Math.random() * 5; if (progress >= 100) { progress = 100; clearInterval(interval); // Show complete status after 1 second setTimeout(function() { completeSound.play(); progressContainer.style.display = 'none'; progressText.style.display = 'none'; downloadComplete.style.display = 'block'; // Reset button after 3 seconds setTimeout(function() { downloadBtn.style.opacity = '1'; downloadBtn.disabled = false; downloadBtn.classList.remove('downloading'); downloadComplete.style.display = 'none'; }, 3000); }, 1000); } progressBar.style.width = `${progress}%`; progressText.textContent = `Downloading... ${Math.floor(progress)}%`; }, 200); // Particle burst effect const particles = document.querySelectorAll('.particle'); particles.forEach(particle => { const randomX = (Math.random() - 0.5) * 200; const randomY = (Math.random() - 0.5) * 200; particle.animate( [ { transform: 'scale(1) translate(0, 0)', opacity: particle.style.opacity }, { transform: `scale(2) translate(${randomX}px, ${randomY}px)`, opacity: '0' } ], { duration: 1000, fill: 'forwards', easing: 'cubic-bezier(0.42, 0, 0.58, 1)' } ); // Restore particles after animation setTimeout(() => { particle.animate( [ { transform: `scale(0) translate(${randomX}px, ${randomY}px)`, opacity: '0' }, { transform: 'scale(1) translate(0, 0)', opacity: particle.style.opacity } ], { duration: 1000, fill: 'forwards', easing: 'cubic-bezier(0.42, 0, 0.58, 1)' } ); }, 1500); }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Editorial PDF Download Button</title> <style> @import url('https://fonts.googleapis.com/css2?family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&family=Playfair+Display:ital,wght@0,400;0,600;1,400&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Libre Baskerville', Georgia, serif; background-color: #f9f7f4; color: #333; display: flex; justify-content: center; align-items: center; min-height: 700px; padding: 30px; } .article-preview { max-width: 640px; background-color: #fff; padding: 40px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); border-radius: 2px; position: relative; } .article-meta { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; font-size: 14px; color: #666; letter-spacing: 0.5px; } .article-category { text-transform: uppercase; font-weight: 700; letter-spacing: 1px; font-size: 12px; color: #b33d3d; } .article-date { font-style: italic; } h1 { font-family: 'Playfair Display', Georgia, serif; font-size: 32px; line-height: 1.2; margin-bottom: 20px; font-weight: 600; color: #222; } .article-lead { font-size: 18px; line-height: 1.6; margin-bottom: 30px; color: #444; } .download-area { border-top: 1px solid #eee; margin-top: 30px; padding-top: 30px; display: flex; flex-direction: column; align-items: center; } .download-heading { font-size: 16px; text-align: center; margin-bottom: 20px; color: #555; font-style: italic; } .download-button { position: relative; padding: 12px 28px; background-color: #fff; color: #333; border: 1px solid #333; font-family: 'Libre Baskerville', Georgia, serif; font-size: 15px; cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; gap: 12px; margin-bottom: 20px; overflow: hidden; } .download-button::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: #b33d3d; transform: scaleX(0); transform-origin: right; transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1); z-index: -1; } .download-button:hover { color: #fff; border-color: #b33d3d; } .download-button:hover::before { transform: scaleX(1); transform-origin: left; } .download-button:active { transform: translateY(2px); } .icon { display: inline-block; transition: transform 0.3s ease; } .download-button:hover .icon { transform: translateY(3px); } .download-details { display: flex; align-items: center; gap: 15px; font-size: 13px; color: #666; } .download-detail { display: flex; align-items: center; gap: 5px; } .detail-icon { font-size: 14px; } .progress-container { display: none; width: 100%; height: 3px; background-color: #f0f0f0; margin-top: 20px; overflow: hidden; } .progress-bar { height: 100%; width: 0; background-color: #b33d3d; transition: width 0.3s ease; } .download-message { margin-top: 15px; font-size: 14px; color: #b33d3d; text-align: center; opacity: 0; transition: opacity 0.3s ease; } @media (max-width: 600px) { .article-preview { padding: 25px; } h1 { font-size: 26px; } .article-lead { font-size: 16px; } .download-button { padding: 10px 20px; font-size: 14px; } .download-details { flex-direction: column; gap: 8px; align-items: center; } } </style> </head> <body> <div class="article-preview"> <div class="article-meta"> <div class="article-category">Foreign Policy</div> <div class="article-date">October 17, 2023</div> </div> <h1>The Shifting Geopolitics of the Eastern Mediterranean: A New Era of Regional Cooperation?</h1> <p class="article-lead">This in-depth analysis examines how emerging energy interests, security concerns, and diplomatic initiatives are reshaping alliances in one of the world's most contested maritime regions.</p> <div class="download-area"> <p class="download-heading">Access our 27-page research report with expert analysis, data visualizations, and policy recommendations</p> <button class="download-button" id="pdfDownload"> <span class="icon"> <svg xmlns="http://www.w3.org/2000/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="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="7 10 12 15 17 10"></polyline> <line x1="12" y1="15" x2="12" y2="3"></line> </svg> </span> Download Full PDF Report </button> <div class="download-details"> <div class="download-detail"> <span class="detail-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path> <polyline points="14 2 14 8 20 8"></polyline> <line x1="16" y1="13" x2="8" y2="13"></line> <line x1="16" y1="17" x2="8" y2="17"></line> <polyline points="10 9 9 9 8 9"></polyline> </svg> </span> 4.2 MB PDF </div> <div class="download-detail"> <span class="detail-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <polyline points="12 6 12 12 16 14"></polyline> </svg> </span> 27 minute read </div> <div class="download-detail"> <span class="detail-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M15 7h3a5 5 0 0 1 5 5 5 5 0 0 1-5 5h-3m-6 0H6a5 5 0 0 1-5-5 5 5 0 0 1 5-5h3"></path> <line x1="8" y1="12" x2="16" y2="12"></line> </svg> </span> Cite-ready </div> </div> <div class="progress-container" id="progressContainer"> <div class="progress-bar" id="progressBar"></div> </div> <div class="download-message" id="downloadMessage">Report downloaded successfully</div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const downloadBtn = document.getElementById('pdfDownload'); const progressContainer = document.getElementById('progressContainer'); const progressBar = document.getElementById('progressBar'); const downloadMessage = document.getElementById('downloadMessage'); downloadBtn.addEventListener('click', function() { // Disable button during "download" downloadBtn.disabled = true; downloadBtn.style.opacity = '0.7'; // Show progress container progressContainer.style.display = 'block'; // Simulate progress let width = 0; const interval = setInterval(function() { if (width >= 100) { clearInterval(interval); // Show success message downloadMessage.style.opacity = '1'; // Re-enable button after "download" setTimeout(function() { downloadBtn.disabled = false; downloadBtn.style.opacity = '1'; progressContainer.style.display = 'none'; // Reset progress bar for next download progressBar.style.width = '0%'; // Hide message after 3 seconds setTimeout(function() { downloadMessage.style.opacity = '0'; }, 3000); }, 500); } else { width += Math.random() * 10; if (width > 100) width = 100; progressBar.style.width = width + '%'; } }, 150); // In a real implementation, you would trigger the actual PDF download here // For example: // window.location.href = 'path/to/your/report.pdf'; }); // Add subtle hover effect to button text downloadBtn.addEventListener('mouseover', function() { this.style.letterSpacing = '0.5px'; }); downloadBtn.addEventListener('mouseout', function() { this.style.letterSpacing = 'normal'; }); }); </script> </body> </html>
<html> <head> <style> :root { --primary: #FF6B35; /* Vibrant orange */ --secondary: #17BEBB; /* Turquoise */ --accent: #FFD166; /* Golden yellow */ --dark: #2E4057; /* Deep blue */ --light: #FFF8F0; /* Off-white */ } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Montserrat', 'Helvetica Neue', sans-serif; } body { background: linear-gradient(135deg, var(--light), #E8F4F2); display: flex; justify-content: center; align-items: center; min-height: 700px; width: 100%; color: var(--dark); overflow: hidden; } .container { width: 100%; max-width: 650px; padding: 2rem; position: relative; } .itinerary-card { background-color: white; border-radius: 20px; box-shadow: 0 15px 35px rgba(46, 64, 87, 0.1); padding: 2.5rem; position: relative; overflow: hidden; transition: all 0.3s ease; } .itinerary-card::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 8px; background: linear-gradient(90deg, var(--primary), var(--secondary)); } .card-pattern { position: absolute; bottom: 0; right: 0; width: 180px; height: 180px; opacity: 0.07; z-index: 0; } h1 { font-size: 1.8rem; margin-bottom: 0.5rem; font-weight: 700; color: var(--dark); position: relative; z-index: 1; } .subtitle { font-size: 1rem; color: #667789; margin-bottom: 2rem; font-weight: 500; position: relative; z-index: 1; } .trip-details { display: flex; flex-wrap: wrap; gap: 1.5rem; margin-bottom: 2.5rem; position: relative; z-index: 1; } .detail-item { flex: 1 1 140px; } .detail-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 1px; color: #667789; margin-bottom: 0.25rem; font-weight: 600; } .detail-value { font-size: 1rem; font-weight: 600; color: var(--dark); } .download-btn-wrapper { display: flex; justify-content: center; position: relative; z-index: 2; } .download-btn { display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, var(--primary), #FF8E63); color: white; border: none; border-radius: 50px; padding: 0.9rem 2rem; font-size: 1rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease, transform 0.15s ease; box-shadow: 0 10px 20px rgba(255, 107, 53, 0.3); position: relative; overflow: hidden; min-width: 220px; } .download-btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0) 100%); transition: all 0.6s ease; z-index: 1; } .download-btn:hover { background: linear-gradient(135deg, #FF7F4A, #FF9E73); box-shadow: 0 15px 25px rgba(255, 107, 53, 0.4); transform: translateY(-2px); } .download-btn:hover::before { left: 100%; } .download-btn:active { transform: translateY(1px); box-shadow: 0 5px 15px rgba(255, 107, 53, 0.4); } .btn-text { margin-left: 10px; position: relative; z-index: 2; } .btn-icon { position: relative; z-index: 2; } /* Animation for download feedback */ @keyframes downloadAnimation { 0% { transform: translateY(0); opacity: 1; } 50% { transform: translateY(10px); opacity: 0; } 51% { transform: translateY(-10px); opacity: 0; } 100% { transform: translateY(0); opacity: 1; } } .success-message { position: absolute; top: 2rem; left: 50%; transform: translateX(-50%); background-color: var(--secondary); color: white; padding: 0.75rem 1.5rem; border-radius: 50px; font-weight: 600; opacity: 0; transition: all 0.3s ease; box-shadow: 0 8px 15px rgba(23, 190, 187, 0.3); display: flex; align-items: center; gap: 8px; z-index: 10; } .success-message.show { opacity: 1; animation: fadeInOut 3s ease forwards; } @keyframes fadeInOut { 0% { opacity: 0; transform: translate(-50%, 10px); } 15% { opacity: 1; transform: translate(-50%, 0); } 85% { opacity: 1; transform: translate(-50%, 0); } 100% { opacity: 0; transform: translate(-50%, -10px); } } .tropical-icon { fill: var(--accent); margin-right: 5px; width: 20px; height: 20px; } .floating-elements { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; overflow: hidden; z-index: 0; } .float-item { position: absolute; width: 40px; height: 40px; opacity: 0.1; animation: float 20s linear infinite; } .float-item:nth-child(1) { top: 10%; left: 5%; animation-delay: 0s; animation-duration: 25s; } .float-item:nth-child(2) { top: 70%; left: 80%; animation-delay: 2s; animation-duration: 18s; } .float-item:nth-child(3) { top: 40%; left: 10%; animation-delay: 5s; animation-duration: 20s; } .float-item:nth-child(4) { top: 20%; left: 90%; animation-delay: 10s; animation-duration: 22s; } @keyframes float { 0% { transform: translate(0, 0) rotate(0deg); } 25% { transform: translate(100px, 50px) rotate(90deg); } 50% { transform: translate(50px, 100px) rotate(180deg); } 75% { transform: translate(-50px, 50px) rotate(270deg); } 100% { transform: translate(0, 0) rotate(360deg); } } /* Responsive adjustments */ @media (max-width: 600px) { .container { padding: 1rem; } .itinerary-card { padding: 1.5rem; } h1 { font-size: 1.5rem; } .subtitle { font-size: 0.9rem; margin-bottom: 1.5rem; } .trip-details { gap: 1rem; margin-bottom: 2rem; } .detail-item { flex: 1 1 100px; } } </style> </head> <body> <div class="container"> <div class="floating-elements"> <svg class="float-item" viewBox="0 0 24 24"> <path d="M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z" /> </svg> <svg class="float-item" viewBox="0 0 24 24"> <path d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4M7,10L12,15L17,10H7Z" /> </svg> <svg class="float-item" viewBox="0 0 24 24"> <path d="M11.19,2.25C10.93,2.25 10.67,2.31 10.42,2.4L3.06,5.45C2.04,5.87 1.55,7.04 1.97,8.05L6.93,20C7.24,20.77 7.97,21.23 8.74,21.25C9,21.25 9.27,21.22 9.53,21.1L16.9,18.05C17.65,17.74 18.11,17 18.13,16.25C18.14,16 18.09,15.71 18,15.45L13,3.5C12.71,2.73 11.97,2.26 11.19,2.25M14.67,2.25L18.12,10.6V4.25A2,2 0 0,0 16.12,2.25M20.13,3.79V12.82L22.56,6.96C22.97,5.94 22.5,4.78 21.47,4.36M11.19,4.22L16.17,16.24L8.78,19.3L3.8,7.29" /> </svg> <svg class="float-item" viewBox="0 0 24 24"> <path d="M16,5V11H21V5M10,11H15V5H10M16,18H21V12H16M10,18H15V12H10M4,18H9V12H4M4,11H9V5H4V11Z" /> </svg> </div> <div class="success-message" id="successMessage"> <svg width="20" height="20" viewBox="0 0 24 24"> <path fill="currentColor" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M11,16.5L6.5,12L7.91,10.59L11,13.67L16.59,8.09L18,9.5L11,16.5Z" /> </svg> Itinerary Downloaded Successfully! </div> <div class="itinerary-card"> <svg class="card-pattern" viewBox="0 0 100 100"> <path d="M25,60 a20,20 0 0,1 0,-40 a20,20 0 0,1 0,40 z" fill="#FF6B35" /> <path d="M75,30 a20,20 0 0,1 0,40 a20,20 0 0,1 0,-40 z" fill="#17BEBB" /> <path d="M50,90 a20,20 0 0,1 0,-40 a20,20 0 0,1 0,40 z" fill="#FFD166" /> <path d="M50,50 a20,20 0 0,1 0,-40 a20,20 0 0,1 0,40 z" fill="#2E4057" /> </svg> <h1>Bali Beaches Getaway</h1> <p class="subtitle">Your tropical escape is all set and ready to enjoy!</p> <div class="trip-details"> <div class="detail-item"> <p class="detail-label">Dates</p> <p class="detail-value">Jun 15 - Jun 28, 2023</p> </div> <div class="detail-item"> <p class="detail-label">Travelers</p> <p class="detail-value">2 Adults</p> </div> <div class="detail-item"> <p class="detail-label">Reservations</p> <p class="detail-value">5 Bookings</p> </div> <div class="detail-item"> <p class="detail-label">Booking ID</p> <p class="detail-value">BALI-23795</p> </div> </div> <div class="download-btn-wrapper"> <button class="download-btn" id="downloadBtn"> <span class="btn-icon"> <svg width="20" height="20" viewBox="0 0 24 24"> <path fill="currentColor" d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" /> </svg> </span> <span class="btn-text">Download Travel Itinerary</span> </button> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const downloadBtn = document.getElementById('downloadBtn'); const successMessage = document.getElementById('successMessage'); const btnIcon = downloadBtn.querySelector('.btn-icon'); const btnText = downloadBtn.querySelector('.btn-text'); downloadBtn.addEventListener('click', function() { // Button click effect btnIcon.style.animation = 'downloadAnimation 0.8s ease'; downloadBtn.style.pointerEvents = 'none'; downloadBtn.style.background = 'linear-gradient(135deg, #FF8E63, #FF6B35)'; // Change text and icon during download setTimeout(() => { btnText.textContent = 'Preparing Document...'; btnIcon.innerHTML = ` <svg width="20" height="20" viewBox="0 0 24 24"> <path fill="currentColor" d="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z"> <animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="1s" from="0 12 12" to="360 12 12" repeatCount="indefinite" /> </path> </svg> `; }, 300); // Simulate download complete setTimeout(() => { btnText.textContent = 'Download Complete!'; btnIcon.innerHTML = ` <svg width="20" height="20" viewBox="0 0 24 24"> <path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" /> </svg> `; downloadBtn.style.background = 'linear-gradient(135deg, #17BEBB, #4ECECA)'; downloadBtn.style.boxShadow = '0 10px 20px rgba(23, 190, 187, 0.3)'; // Show success message successMessage.classList.add('show'); // Reset button after delay setTimeout(() => { btnText.textContent = 'Download Travel Itinerary'; btnIcon.innerHTML = ` <svg width="20" height="20" viewBox="0 0 24 24"> <path fill="currentColor" d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" /> </svg> `; btnIcon.style.animation = ''; downloadBtn.style.pointerEvents = 'auto'; downloadBtn.style.background = 'linear-gradient(135deg, var(--primary), #FF8E63)'; downloadBtn.style.boxShadow = '0 10px 20px rgba(255, 107, 53, 0.3)'; // Hide success message setTimeout(() => { successMessage.classList.remove('show'); }, 1000); }, 2500); }, 2000); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Patient Records Portal</title> <style> :root { --primary: #2A6BB0; --primary-dark: #1A548B; --primary-light: #3C81CB; --secondary: #EEF4FA; --neutral: #F5F7F9; --text: #2A3542; --text-light: #6A7684; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: var(--neutral); display: flex; justify-content: center; align-items: center; min-height: 700px; color: var(--text); padding: 20px; } .portal-container { max-width: 600px; width: 100%; background-color: white; border-radius: 16px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); padding: 32px; transition: all 0.3s ease; } .portal-header { margin-bottom: 24px; text-align: center; } .portal-header h1 { font-size: 28px; margin-bottom: 8px; color: var(--primary-dark); } .portal-header p { color: var(--text-light); font-size: 16px; line-height: 1.5; } .records-section { background-color: var(--secondary); border-radius: 12px; padding: 24px; margin-bottom: 24px; } .records-meta { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; } .records-title { font-weight: 600; font-size: 18px; } .records-date { color: var(--text-light); font-size: 14px; } .records-details { display: flex; gap: 12px; margin-bottom: 16px; } .records-icon { display: flex; align-items: center; justify-content: center; width: 48px; height: 48px; background-color: rgba(42, 107, 176, 0.1); border-radius: 8px; color: var(--primary); } .records-info h3 { font-size: 16px; margin-bottom: 4px; } .records-info p { color: var(--text-light); font-size: 14px; } .security-badge { display: flex; align-items: center; gap: 8px; background-color: rgba(70, 180, 115, 0.1); color: #46B473; padding: 8px 12px; border-radius: 6px; font-size: 14px; font-weight: 500; margin-bottom: 20px; width: fit-content; } .download-button { position: relative; display: flex; align-items: center; justify-content: center; gap: 10px; padding: 16px 28px; background-color: var(--primary); color: white; border: none; border-radius: 8px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; width: 100%; overflow: hidden; } .download-button:hover { background-color: var(--primary-dark); } .download-button:focus { outline: 3px solid rgba(42, 107, 176, 0.3); } .download-button:active { transform: scale(0.98); } .download-icon { transition: all 0.3s ease; display: flex; align-items: center; } .download-button:hover .download-icon { transform: translateY(4px); } .download-progress { position: absolute; top: 0; left: 0; height: 100%; width: 0; background-color: var(--primary-dark); opacity: 0; transition: width 1s ease-in-out, opacity 0.3s ease; z-index: 1; } .download-button-text { position: relative; z-index: 2; } .download-icon { position: relative; z-index: 2; } .tooltip { position: absolute; bottom: -50px; left: 50%; transform: translateX(-50%); background-color: var(--text); color: white; padding: 8px 12px; border-radius: 6px; font-size: 14px; opacity: 0; visibility: hidden; transition: all 0.3s ease; white-space: nowrap; } .tooltip::before { content: ''; position: absolute; top: -6px; left: 50%; transform: translateX(-50%); border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 6px solid var(--text); } .download-info { margin-top: 24px; display: flex; justify-content: space-between; align-items: center; color: var(--text-light); font-size: 14px; } .privacy-note { display: flex; align-items: center; gap: 6px; } .privacy-note svg { color: var(--primary); flex-shrink: 0; } .success-message { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 20px; padding: 12px; background-color: rgba(70, 180, 115, 0.1); color: #46B473; border-radius: 8px; font-weight: 500; opacity: 0; transform: translateY(10px); transition: all 0.5s ease; display: none; } .success-message.show { opacity: 1; transform: translateY(0); display: flex; } @media (max-width: 600px) { .portal-container { padding: 20px; } .records-section { padding: 16px; } .portal-header h1 { font-size: 24px; } .download-button { padding: 14px 20px; } .download-info { flex-direction: column; gap: 10px; align-items: flex-start; } } /* Animation keyframes */ @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(42, 107, 176, 0.4); } 70% { box-shadow: 0 0 0 10px rgba(42, 107, 176, 0); } 100% { box-shadow: 0 0 0 0 rgba(42, 107, 176, 0); } } .pulse-animation { animation: pulse 2s infinite; } </style> </head> <body> <div class="portal-container"> <div class="portal-header"> <h1>Your Patient Records</h1> <p>Securely download and manage your health information in just a few clicks.</p> </div> <div class="records-section"> <div class="records-meta"> <div class="records-title">Complete Medical History</div> <div class="records-date">Last updated: May 18, 2023</div> </div> <div class="records-details"> <div class="records-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path> <rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect> <path d="M9 14h6"></path> <path d="M9 10h6"></path> <path d="M9 18h6"></path> </svg> </div> <div class="records-info"> <h3>Comprehensive Health Record</h3> <p>PDF file containing recent lab work, medications, appointments, and physician notes.</p> </div> </div> <div class="security-badge"> <svg xmlns="http://www.w3.org/2000/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="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path> </svg> HIPAA Compliant & Encrypted </div> <button id="downloadButton" class="download-button" aria-label="Download your medical records"> <div class="download-progress" id="downloadProgress"></div> <div class="download-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline points="7 10 12 15 17 10"></polyline> <line x1="12" y1="15" x2="12" y2="3"></line> </svg> </div> <span class="download-button-text">Download Health Records</span> <div class="tooltip">Press to securely download your complete records</div> </button> <div class="download-info"> <div class="privacy-note"> <svg xmlns="http://www.w3.org/2000/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="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path> <path d="M12 8v4"></path> <path d="M12 16h.01"></path> </svg> End-to-end encryption protects your data </div> <div>File size: 4.2 MB</div> </div> </div> <div id="successMessage" class="success-message"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> <polyline points="22 4 12 14.01 9 11.01"></polyline> </svg> Your records have been successfully downloaded </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const downloadButton = document.getElementById('downloadButton'); const downloadProgress = document.getElementById('downloadProgress'); const tooltip = document.querySelector('.tooltip'); const successMessage = document.getElementById('successMessage'); // Show tooltip on hover downloadButton.addEventListener('mouseenter', function() { tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; downloadButton.classList.add('pulse-animation'); }); downloadButton.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; downloadButton.classList.remove('pulse-animation'); }); // Download simulation on click downloadButton.addEventListener('click', function() { // Disable button during download downloadButton.disabled = true; // Show progress animation downloadProgress.style.opacity = '1'; // Update button text document.querySelector('.download-button-text').textContent = 'Downloading...'; // Simulate download progress let progress = 0; const interval = setInterval(function() { progress += 5; downloadProgress.style.width = progress + '%'; if (progress >= 100) { clearInterval(interval); // Reset and show success after completion setTimeout(function() { downloadProgress.style.opacity = '0'; downloadProgress.style.width = '0'; document.querySelector('.download-button-text').textContent = 'Download Health Records'; downloadButton.disabled = false; // Show success message successMessage.classList.add('show'); // Hide success message after 5 seconds setTimeout(function() { successMessage.classList.remove('show'); }, 5000); }, 500); } }, 80); }); // Keyboard accessibility for the button downloadButton.addEventListener('keydown', function(e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); downloadButton.click(); } }); // Add focus state for accessibility downloadButton.addEventListener('focus', function() { tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; }); downloadButton.addEventListener('blur', function() { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SaaS Analytics Dashboard Export Button</title> <style> :root { --primary: #4361ee; --primary-dark: #3a56d4; --secondary: #7209b7; --accent: #4cc9f0; --light: #f8f9fa; --dark: #212529; --success: #38b000; --danger: #d00000; --warning: #ffb700; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 700px; background-color: #f0f2f5; padding: 20px; } .dashboard-container { width: 100%; max-width: 660px; background-color: white; border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.06); padding: 30px; position: relative; overflow: hidden; } .dashboard-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px; } .dashboard-title { font-size: 24px; font-weight: 600; color: var(--dark); } .dashboard-subtitle { font-size: 14px; color: #6c757d; margin-top: 5px; } .metrics-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 15px; margin-bottom: 30px; } .metric-card { background-color: #f8f9fa; border-radius: 8px; padding: 15px; text-align: center; transition: transform 0.3s ease, box-shadow 0.3s ease; } .metric-card:hover { transform: translateY(-3px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08); } .metric-value { font-size: 24px; font-weight: bold; color: var(--dark); margin-bottom: 5px; } .metric-label { font-size: 12px; color: #6c757d; text-transform: uppercase; letter-spacing: 0.5px; } .chart-container { width: 100%; height: 200px; background-color: #f8f9fa; border-radius: 8px; margin-bottom: 30px; position: relative; overflow: hidden; } .chart-line { position: absolute; bottom: 0; left: 0; width: 100%; height: 60%; fill: none; stroke: var(--primary); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 1000; stroke-dashoffset: 1000; animation: drawLine 2s forwards ease-out; } @keyframes drawLine { to { stroke-dashoffset: 0; } } .data-points { position: absolute; bottom: 0; left: 0; width: 100%; height: 60%; display: flex; justify-content: space-between; padding: 0 5%; } .data-point { position: relative; width: 10px; height: 10px; background-color: var(--primary); border-radius: 50%; transform: translateY(-100px) scale(0); animation: popPoints 0.5s forwards ease-out; animation-delay: calc(var(--i) * 0.1s + 1.5s); } @keyframes popPoints { to { transform: translateY(calc(-1 * var(--y) * 1px)) scale(1); } } .export-section { display: flex; flex-direction: column; align-items: center; gap: 20px; } .export-controls { display: flex; gap: 15px; width: 100%; flex-wrap: wrap; justify-content: center; } .format-selector { position: relative; width: 140px; } .format-selector select { appearance: none; width: 100%; padding: 12px 20px; font-size: 14px; background-color: #f8f9fa; border: 2px solid #e9ecef; border-radius: 8px; color: var(--dark); cursor: pointer; transition: all 0.2s ease; } .format-selector select:focus { border-color: var(--primary); outline: none; box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.15); } .format-selector::after { content: "▼"; font-size: 10px; color: #6c757d; position: absolute; right: 15px; top: 50%; transform: translateY(-50%); pointer-events: none; } .export-button { position: relative; display: flex; align-items: center; justify-content: center; gap: 10px; padding: 12px 25px; background-color: var(--primary); color: white; border: none; border-radius: 8px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); overflow: hidden; min-width: 180px; } .export-button:hover { background-color: var(--primary-dark); transform: translateY(-2px); box-shadow: 0 5px 15px rgba(67, 97, 238, 0.3); } .export-button:active { transform: translateY(0); box-shadow: 0 2px 8px rgba(67, 97, 238, 0.3); } .export-button .icon { display: flex; align-items: center; justify-content: center; width: 20px; height: 20px; transition: all 0.3s ease; } .export-button .icon svg { width: 100%; height: 100%; transition: all 0.3s ease; } .export-button .icon .arrow { transition: transform 0.3s ease; } .export-button:hover .icon .arrow { transform: translateY(3px); } .export-button.loading { background-color: var(--primary-dark); pointer-events: none; } .export-button.loading .icon { animation: spin 1.5s infinite linear; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .export-button.success { background-color: var(--success); } .export-button.error { background-color: var(--danger); } .background-grid { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, rgba(240, 242, 245, 0.5) 1px, transparent 1px), linear-gradient(rgba(240, 242, 245, 0.5) 1px, transparent 1px); background-size: 20px 20px; z-index: -1; } .tooltip { position: absolute; background-color: var(--dark); color: white; padding: 10px 15px; border-radius: 6px; font-size: 14px; opacity: 0; visibility: hidden; transform: translateY(10px); transition: all 0.3s ease; z-index: 100; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); pointer-events: none; width: max-content; max-width: 250px; text-align: center; } .tooltip::after { content: ''; position: absolute; top: 100%; left: 50%; margin-left: -8px; width: 0; height: 0; border-left: 8px solid transparent; border-right: 8px solid transparent; border-top: 8px solid var(--dark); } .tooltip.show { opacity: 1; visibility: visible; transform: translateY(0); } .success-checkmark { width: 20px; height: 20px; stroke-dasharray: 100; stroke-dashoffset: 100; animation: drawCheck 1s forwards ease-out; } @keyframes drawCheck { to { stroke-dashoffset: 0; } } .error-exclamation { width: 20px; height: 20px; } .progress-bar { position: absolute; bottom: 0; left: 0; width: 0%; height: 3px; background-color: rgba(255, 255, 255, 0.5); transition: width 0.3s linear; } .time-range { padding: 5px 15px; background-color: #f8f9fa; border: 2px solid #e9ecef; border-radius: 8px; font-size: 14px; color: var(--dark); cursor: pointer; transition: all 0.2s ease; } .time-range:hover, .time-range.active { border-color: var(--primary); background-color: rgba(67, 97, 238, 0.05); } .time-range.active { font-weight: 600; } .geometric-shape { position: absolute; z-index: -1; opacity: 0.1; } .shape-1 { top: 20%; left: 5%; width: 80px; height: 80px; background-color: var(--primary); border-radius: 12px; transform: rotate(15deg); } .shape-2 { bottom: 15%; right: 8%; width: 60px; height: 60px; background-color: var(--secondary); border-radius: 50%; } .shape-3 { top: 10%; right: 15%; width: 50px; height: 50px; background-color: var(--accent); clip-path: polygon(50% 0%, 0% 100%, 100% 100%); } .data-details { background-color: #f8f9fa; border-radius: 8px; padding: 15px; margin-top: 20px; font-size: 14px; color: #6c757d; line-height: 1.5; text-align: center; } .data-details strong { color: var(--dark); } .notification { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%) translateY(100px); background-color: white; border-left: 4px solid var(--success); border-radius: 6px; padding: 15px 20px; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15); display: flex; align-items: center; gap: 12px; opacity: 0; transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); z-index: 1000; } .notification.show { transform: translateX(-50%) translateY(0); opacity: 1; } .notification .icon { color: var(--success); display: flex; } .notification.error { border-left-color: var(--danger); } .notification.error .icon { color: var(--danger); } .notification-message { font-size: 14px; color: var(--dark); } .notification-close { margin-left: auto; background: none; border: none; cursor: pointer; color: #6c757d; font-size: 16px; padding: 5px; } @media (max-width: 600px) { .dashboard-container { padding: 20px; } .metrics-grid { grid-template-columns: repeat(2, 1fr); } .export-controls { flex-direction: column; align-items: center; } .format-selector, .export-button { width: 100%; } .time-range { padding: 8px 10px; font-size: 12px; } } </style> </head> <body> <div class="dashboard-container"> <div class="background-grid"></div> <div class="geometric-shape shape-1"></div> <div class="geometric-shape shape-2"></div> <div class="geometric-shape shape-3"></div> <div class="dashboard-header"> <div> <h1 class="dashboard-title">Data Analytics</h1> <p class="dashboard-subtitle">KPIs and performance metrics</p> </div> <div class="time-ranges"> <button class="time-range" data-range="7">7d</button> <button class="time-range active" data-range="30">30d</button> <button class="time-range" data-range="90">90d</button> </div> </div> <div class="metrics-grid"> <div class="metric-card"> <div class="metric-value">86.2%</div> <div class="metric-label">Retention</div> </div> <div class="metric-card"> <div class="metric-value">$19.4K</div> <div class="metric-label">Revenue</div> </div> <div class="metric-card"> <div class="metric-value">3.7K</div> <div class="metric-label">New Users</div> </div> <div class="metric-card"> <div class="metric-value">24.8%</div> <div class="metric-label">Growth</div> </div> </div> <div class="chart-container"> <svg width="100%" height="100%" viewBox="0 0 600 200" preserveAspectRatio="none"> <path class="chart-line" d="M0,150 C50,100 100,160 150,120 S250,40 300,70 S400,180 450,110 S550,90 600,70"></path> </svg> <div class="data-points"> <div class="data-point" style="--y: 100; --i: 1;"></div> <div class="data-point" style="--y: 40; --i: 2;"></div> <div class="data-point" style="--y: 80; --i: 3;"></div> <div class="data-point" style="--y: 130; --i: 4;"></div> <div class="data-point" style="--y: 70; --i: 5;"></div> <div class="data-point" style="--y: 90; --i: 6;"></div> <div class="data-point" style="--y: 130; --i: 7;"></div> </div> </div> <div class="export-section"> <div class="export-controls"> <div class="format-selector"> <select id="export-format"> <option value="csv">CSV Format</option> <option value="xlsx">Excel (XLSX)</option> <option value="json">JSON Data</option> <option value="pdf">PDF Report</option> </select> </div> <button id="export-button" class="export-button"> <span class="icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> <polyline class="arrow" points="7 10 12 15 17 10"></polyline> <line class="arrow" x1="12" y1="15" x2="12" y2="3"></line> </svg> </span> <span class="button-text">Export Data</span> <div class="progress-bar"></div> </button> </div> <div class="data-details"> <strong>Analytics Data Set:</strong> Includes user engagement metrics, conversion rates, and revenue analytics from <span id="date-range">March 1 - March 30, 2023</span> </div> </div> <div id="tooltip" class="tooltip">Tip: You can export specific sections by using filters before exporting</div> <div id="notification" class="notification"> <div class="icon"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> <polyline points="22 4 12 14.01 9 11.01"></polyline> </svg> </div> <div class="notification-message">Your data has been successfully exported!</div> <button class="notification-close">×</button> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const exportButton = document.getElementById('export-button'); const exportFormat = document.getElementById('export-format'); const tooltip = document.getElementById('tooltip'); const notification = document.getElementById('notification'); const notificationClose = document.querySelector('.notification-close'); const timeRanges = document.querySelectorAll('.time-range'); const dateRangeSpan = document.getElementById('date-range'); // Show tooltip on hover exportButton.addEventListener('mouseenter', function() { tooltip.style.left = `${exportButton.offsetLeft + exportButton.offsetWidth / 2}px`; tooltip.style.top = `${exportButton.offsetTop - 10}px`; tooltip.classList.add('show'); }); exportButton.addEventListener('mouseleave', function() { tooltip.classList.remove('show'); }); // Export button functionality exportButton.addEventListener('click', function() { if (exportButton.classList.contains('loading') || exportButton.classList.contains('success') || exportButton.classList.contains('error')) { return; } // Start loading state exportButton.classList.add('loading'); const buttonText = exportButton.querySelector('.button-text'); const icon = exportButton.querySelector('.icon'); const progressBar = exportButton.querySelector('.progress-bar'); const originalText = buttonText.textContent; const originalIcon = icon.innerHTML; buttonText.textContent = 'Processing...'; icon.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <polyline points="12 6 12 12 16 14"></polyline> </svg> `; // Simulate progress let progress = 0; const progressInterval = setInterval(() => { progress += 5; progressBar.style.width = `${progress}%`; if (progress >= 100) { clearInterval(progressInterval); } }, 100); // Simulate export process setTimeout(() => { clearInterval(progressInterval); progressBar.style.width = '100%'; // Random success or failure (mostly success) const success = Math.random() > 0.15; if (success) { exportButton.classList.remove('loading'); exportButton.classList.add('success'); buttonText.textContent = 'Exported!'; icon.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="success-checkmark"> <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> <polyline points="22 4 12 14.01 9 11.01"></polyline> </svg> `; // Show success notification notification.classList.remove('error'); notification.querySelector('.notification-message').textContent = `Your data has been successfully exported as ${exportFormat.options[exportFormat.selectedIndex].text}!`; notification.classList.add('show'); // Auto hide notification after 5 seconds setTimeout(() => { notification.classList.remove('show'); }, 5000); } else { exportButton.classList.remove('loading'); exportButton.classList.add('error'); buttonText.textContent = 'Failed!'; icon.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="error-exclamation"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="8" x2="12" y2="12"></line> <line x1="12" y1="16" x2="12.01" y2="16"></line> </svg> `; // Show error notification notification.classList.add('error'); notification.querySelector('.notification-message').textContent = `Export failed. Please try again or contact support.`; notification.classList.add('show'); } // Reset button after 2 seconds setTimeout(() => { exportButton.classList.remove('success', 'error'); buttonText.textContent = originalText; icon.innerHTML = originalIcon; progressBar.style.width = '0%'; }, 2000); }, 2000); }); // Close notification notificationClose.addEventListener('click', function() { notification.classList.remove('show'); }); // Time range buttons timeRanges.forEach(btn => { btn.addEventListener('click', function() { timeRanges.forEach(b => b.classList.remove('active')); this.classList.add('active'); const range = parseInt(this.dataset.range); const today = new Date(); const startDate = new Date(); startDate.setDate(today.getDate() - range); const formatDate = (date) => { const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; return `${months[date.getMonth()]} ${date.getDate()}`; }; dateRangeSpan.textContent = `${formatDate(startDate)} - ${formatDate(today)}, ${today.getFullYear()}`; }); }); }); </script> </body> </html>