UNPKG

clickstyles

Version:

A collection of animated styles for buttons, CTAs, links, cards, toggles, and other interactive UI elements.

624 lines (597 loc) 26.4 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>ClickStyle Button Gallery - Modal Code View (Enhanced)</title> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link href="https://fonts.googleapis.com/css2?family=Prompt:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet" /> <script src="https://cdn.tailwindcss.com"></script> <link rel="stylesheet" href="../dist/clickstyles.min.css" /> <style> body { background: #111; color: white; padding: 2rem; display: flex; flex-direction: column; align-items: center; min-height: 100vh; font-family: 'Prompt', sans-serif; } button { outline: none; cursor: pointer; font-weight: 500; /* Default Tailwind Button Styles to make them look good without specific overrides */ @apply bg-blue-600 hover:bg-blue-700 text-white py-3 px-6 rounded-full transition-all duration-300 ease-in-out shadow-lg hover:shadow-xl focus:ring-4 focus:ring-blue-300; } /* Specific override for the cs__btn-spin-bg as it has its own styling */ .cs__btn-spin-bg { @apply bg-transparent p-0 rounded-none shadow-none hover:shadow-none focus:ring-0; /* Remove default button styles */ } /* Modal Specific Styles */ .modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.7); /* Darker overlay */ backdrop-filter: blur(8px); /* Glass effect */ -webkit-backdrop-filter: blur(8px); /* For Safari */ display: flex; justify-content: center; align-items: center; z-index: 1000; opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0.3s ease; } .modal-overlay.open { opacity: 1; visibility: visible; } .modal-content { background: rgba(30, 41, 59, 0.9); /* bg-slate-800 with slight transparency */ border-radius: 0.75rem; /* rounded-xl */ width: 90%; max-width: 800px; max-height: 90vh; /* Limit modal height */ display: flex; flex-direction: column; overflow: hidden; /* Hide scrollbar for the modal itself */ transform: translateY(-20px); opacity: 0; transition: transform 0.3s ease, opacity 0.3s ease; border: 1px solid rgba(71, 85, 105, 0.5); /* subtle border */ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.4); } .modal-overlay.open .modal-content { transform: translateY(0); opacity: 1; } .code-display { font-family: 'Fira Code', 'JetBrains Mono', monospace; font-size: 0.875rem; /* text-sm */ line-height: 1.5; color: #e2e8f0; /* text-gray-200 */ background-color: #1a202c; /* bg-gray-900 */ padding: 1rem; overflow-y: auto; /* Allow scrolling for code content */ flex-grow: 1; /* Take up remaining space */ border-radius: 0 0 0.75rem 0.75rem; /* rounded-b-xl */ } .code-display pre { margin: 0; white-space: pre-wrap; /* Forces text to wrap */ word-wrap: break-word; /* Breaks long words if needed */ line-break: anywhere; /* Allows breaking lines anywhere for maximum wrapping */ } /* Code tab styles */ .code-tabs { @apply flex bg-gray-900 px-4 pt-2 border-b border-gray-700; /* Added bottom border to tabs container */ } .code-tabs .tab-button { /* Base styles for tab buttons */ @apply bg-transparent text-gray-400 font-semibold py-2 px-4 rounded-t-lg transition-colors duration-200 border-b-2 border-transparent; /* Custom hover effect for inactive tabs */ &:not(.active-tab):hover { @apply text-white border-gray-500; } } .code-tabs .tab-button.active-tab { /* Active tab styles */ @apply bg-gray-800 text-blue-400 border-blue-500; /* Darker background, blue text, blue bottom border */ } .code-panel { display: none; padding: 1rem; /* Padding for the code content within the panel */ } .code-panel.active-panel { display: block; } .copy-code-btn { @apply absolute bottom-3 right-3 bg-blue-500 hover:bg-blue-600 text-white text-xs py-1 px-2 rounded z-20; /* Moved to bottom-right */ } /* Ensure the code display area has relative positioning for copy button absolute positioning */ .code-display > div { position: relative; height: 100%; /* Make sure panels fill height for scroll */ } </style> </head> <body class="selection:bg-blue-500 selection:text-white"> <header class="text-center mb-12"> <h1 class="text-5xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-600 mb-4"> ClickStyle Button Gallery </h1> <p class="text-xl text-gray-300"> Explore interactive buttons and grab their code instantly. </p> </header> <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-8 max-w-7xl mx-auto p-4"> <div class="flex flex-col bg-gray-800 rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300"> <div class="flex justify-center items-center p-6 min-h-[150px]"> <button class="cs__btn cs__btn-expand-reveal" data-cs-btn-suffix="More"> Discover </button> </div> <div class="p-4 border-t border-gray-700"> <button class="show-code-modal-btn bg-gray-700 hover:bg-gray-600 text-white text-sm py-2 px-4 rounded-md w-full" data-html-code='&lt;button class="cs__btn cs__btn-expand-reveal bg-blue-600 hover:bg-blue-700 text-white py-3 px-6 rounded-full transition-all duration-300 ease-in-out shadow-lg hover:shadow-xl focus:ring-4 focus:ring-blue-300" data-cs-btn-suffix="More"&gt;Discover&lt;/button&gt;' data-css-code='/* No specific custom CSS for this effect beyond base button styles provided by Tailwind and ClickStyles */ .cs__btn-expand-reveal::after { /* ClickStyle&apos;s specific CSS for this effect */ content: attr(data-cs-btn-suffix); padding-left: 0.5em; /* Example: Added for clarity */ /* ... other ClickStyle rules ... */ } .cs__btn-expand-reveal { /* Some base styles for the button itself if not covered by general rules */ display: inline-flex; align-items: center; justify-content: center; overflow: hidden; position: relative; transition: all 0.3s ease; }' data-js-code='// ClickStyles library handles the JavaScript for this effect. // Ensure you include: // &lt;script src="https://unpkg.com/gsap@3/dist/gsap.min.js"&gt;&lt;/script&gt; // &lt;script src="../dist/clickstyles.min.js"&gt;&lt;/script&gt; // The GSAP library (gsap.min.js) is required for most ClickStyles animations. // The ClickStyles library itself typically initializes effects on DOMContentLoaded.'> Show Code </button> </div> </div> <div class="flex flex-col bg-gray-800 rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300"> <div class="flex justify-center items-center p-6 min-h-[150px]"> <button class="cs__btn ca__btn-shine bg-purple-600 hover:bg-purple-700 focus:ring-purple-300"> Shine Swipe <span class="ca__btn-shine_effect"></span> </button> </div> <div class="p-4 border-t border-gray-700"> <button class="show-code-modal-btn bg-gray-700 hover:bg-gray-600 text-white text-sm py-2 px-4 rounded-md w-full" data-html-code='&lt;button class="cs__btn ca__btn-shine bg-purple-600 hover:bg-purple-700 text-white py-3 px-6 rounded-full transition-all duration-300 ease-in-out shadow-lg hover:shadow-xl focus:ring-4 focus:ring-purple-300"&gt; Shine Swipe &lt;span class="ca__btn-shine_effect"&gt;&lt;/span&gt; &lt;/button&gt;' data-css-code='/* ClickStyle&apos;s CSS for .ca__btn-shine and .ca__btn-shine_effect provides the styling for the shine. */ .ca__btn-shine { overflow: hidden; position: relative; /* ... other ClickStyle rules ... */ } .ca__btn-shine_effect { position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient( 90deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.5) 50%, rgba(255, 255, 255, 0.1) 100% ); transform: skewX(-20deg); /* Common for shine effects */ transition: transform 0.3s ease-in-out; /* ... other ClickStyle rules ... */ } .ca__btn-shine:hover .ca__btn-shine_effect { transform: translateX(200%); }' data-js-code='// ClickStyles library handles the JavaScript for this effect. // Ensure you include: // &lt;script src="https://unpkg.com/gsap@3/dist/gsap.min.js"&gt;&lt;/script&gt; // &lt;script src="../dist/clickstyles.min.js"&gt;&lt;/script&gt;'> Show Code </button> </div> </div> <div class="flex flex-col bg-gray-800 rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300"> <div class="flex justify-center items-center p-6 min-h-[150px]"> <button class="cs__btn ripple-btn bg-green-600 hover:bg-green-700 focus:ring-green-300"> Hover Me </button> </div> <div class="p-4 border-t border-gray-700"> <button class="show-code-modal-btn bg-gray-700 hover:bg-gray-600 text-white text-sm py-2 px-4 rounded-md w-full" data-html-code='&lt;button class="cs__btn ripple-btn bg-green-600 hover:bg-green-700 text-white py-3 px-6 rounded-full transition-all duration-300 ease-in-out shadow-lg hover:shadow-xl focus:ring-4 focus:ring-green-300"&gt;Hover Me&lt;/button&gt;' data-css-code='/* ClickStyle&apos;s CSS handles the ripple effect, likely using pseudo-elements and animations. */ .ripple-btn { position: relative; overflow: hidden; /* ... other ClickStyle rules ... */ } .ripple-btn .ripple-effect { position: absolute; border-radius: 50%; background: rgba(255, 255, 255, 0.4); animation: ripple-animation 0.6s linear forwards; transform: scale(0); opacity: 1; } @keyframes ripple-animation { to { transform: scale(4); opacity: 0; } }' data-js-code='// ClickStyles library handles the JavaScript for this effect, // typically adding a dynamic ripple element on click. // Ensure you include: // &lt;script src="https://unpkg.com/gsap@3/dist/gsap.min.js"&gt;&lt;/script&gt; // &lt;script src="../dist/clickstyles.min.js"&gt;&lt;/script&gt;'> Show Code </button> </div> </div> <div class="flex flex-col bg-gray-800 rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300"> <div class="flex justify-center items-center p-6 min-h-[150px]"> <button class="cs__btn cs__btn-slideIn-bounce bg-red-600 hover:bg-red-700 focus:ring-red-300"> <span>Slide In</span> </button> </div> <div class="p-4 border-t border-gray-700"> <button class="show-code-modal-btn bg-gray-700 hover:bg-gray-600 text-white text-sm py-2 px-4 rounded-md w-full" data-html-code='&lt;button class="cs__btn cs__btn-slideIn-bounce bg-red-600 hover:bg-red-700 text-white py-3 px-6 rounded-full transition-all duration-300 ease-in-out shadow-lg hover:shadow-xl focus:ring-4 focus:ring-red-300"&gt; &lt;span&gt;Slide In&lt;/span&gt; &lt;/button&gt;' data-css-code='/* ClickStyle&apos;s CSS for .cs__btn-slideIn-bounce and its span provides the animation. */ .cs__btn-slideIn-bounce span { display: block; transform: translateY(0); transition: transform 0.3s ease-out; /* ... other ClickStyle rules ... */ } .cs__btn-slideIn-bounce:hover span { animation: slideInBounce 0.6s forwards; } @keyframes slideInBounce { 0% { transform: translateY(0); } 50% { transform: translateY(-5px); } 100% { transform: translateY(0); } }' data-js-code='// ClickStyles library handles the JavaScript for this effect. // Ensure you include: // &lt;script src="https://unpkg.com/gsap@3/dist/gsap.min.js"&gt;&lt;/script&gt; // &lt;script src="../dist/clickstyles.min.js"&gt;&lt;/script&gt;'> Show Code </button> </div> </div> <div class="flex flex-col bg-gray-800 rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300"> <div class="flex justify-center items-center p-6 min-h-[150px]"> <button class="cs__btn cs__btn-press-bounce bg-yellow-500 hover:bg-yellow-600 focus:ring-yellow-300"> Press Me </button> </div> <div class="p-4 border-t border-gray-700"> <button class="show-code-modal-btn bg-gray-700 hover:bg-gray-600 text-white text-sm py-2 px-4 rounded-md w-full" data-html-code='&lt;button class="cs__btn cs__btn-press-bounce bg-yellow-500 hover:bg-yellow-600 text-white py-3 px-6 rounded-full transition-all duration-300 ease-in-out shadow-lg hover:shadow-xl focus:ring-4 focus:ring-yellow-300"&gt;Press Me&lt;/button&gt;' data-css-code='/* ClickStyle&apos;s CSS for .cs__btn-press-bounce handles the press animation. */ .cs__btn-press-bounce:active { transform: scale(0.95); /* ... other ClickStyle rules ... */ }' data-js-code='// ClickStyles library handles the JavaScript for this effect. // Ensure you include: // &lt;script src="https://unpkg.com/gsap@3/dist/gsap.min.js"&gt;&lt;/script&gt; // &lt;script src="../dist/clickstyles.min.js"&gt;&lt;/script&gt;'> Show Code </button> </div> </div> <div class="flex flex-col bg-gray-800 rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300"> <div class="flex justify-center items-center p-6 min-h-[150px]"> <button class="cs__btn cs__btn-magnetic bg-indigo-600 hover:bg-indigo-700 focus:ring-indigo-300"> Magnetic </button> </div> <div class="p-4 border-t border-gray-700"> <button class="show-code-modal-btn bg-gray-700 hover:bg-gray-600 text-white text-sm py-2 px-4 rounded-md w-full" data-html-code='&lt;button class="cs__btn cs__btn-magnetic bg-indigo-600 hover:bg-indigo-700 text-white py-3 px-6 rounded-full transition-all duration-300 ease-in-out shadow-lg hover:shadow-xl focus:ring-4 focus:ring-indigo-300"&gt;Magnetic&lt;/button&gt;' data-css-code='/* The magnetic effect is primarily JavaScript driven, potentially using CSS transforms. */ .cs__btn-magnetic { /* ... base styles ... */ transition: transform 0.1s linear; /* Smooth movement */ }' data-js-code='// ClickStyles library handles the JavaScript for the magnetic effect, // moving the button slightly based on mouse position. // Ensure you include: // &lt;script src="https://unpkg.com/gsap@3/dist/gsap.min.js"&gt;&lt;/script&gt; // &lt;script src="../dist/clickstyles.min.js"&gt;&lt;/script&gt;'> Show Code </button> </div> </div> <div class="flex flex-col bg-gray-800 rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300"> <div class="flex justify-center items-center p-6 min-h-[150px]"> <button class="cs__btn cs__btn-pulse-pop bg-pink-600 hover:bg-pink-700 focus:ring-pink-300"> Pulse Pop </button> </div> <div class="p-4 border-t border-gray-700"> <button class="show-code-modal-btn bg-gray-700 hover:bg-gray-600 text-white text-sm py-2 px-4 rounded-md w-full" data-html-code='&lt;button class="cs__btn cs__btn-pulse-pop bg-pink-600 hover:bg-pink-700 text-white py-3 px-6 rounded-full transition-all duration-300 ease-in-out shadow-lg hover:shadow-xl focus:ring-4 focus:ring-pink-300"&gt;Pulse Pop&lt;/button&gt;' data-css-code='/* ClickStyle&apos;s CSS for .cs__btn-pulse-pop handles the animation. */ .cs__btn-pulse-pop { animation: pulse-pop 1.5s infinite; /* or on hover/active */ /* ... other ClickStyle rules ... */ } @keyframes pulse-pop { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } }' data-js-code='// ClickStyles library handles the JavaScript for this effect if dynamic. // Ensure you include: // &lt;script src="https://unpkg.com/gsap@3/dist/gsap.min.js"&gt;&lt;/script&gt; // &lt;script src="../dist/clickstyles.min.js"&gt;&lt;/script&gt;'> Show Code </button> </div> </div> <div class="flex flex-col bg-gray-800 rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300"> <div class="flex justify-center items-center p-6 min-h-[150px]"> <button class="cs__btn cs__btn-shine bg-teal-600 hover:bg-teal-700 focus:ring-teal-300"> Shiny <span class="cs__shine"></span> </button> </div> <div class="p-4 border-t border-gray-700"> <button class="show-code-modal-btn bg-gray-700 hover:bg-gray-600 text-white text-sm py-2 px-4 rounded-md w-full" data-html-code='&lt;button class="cs__btn cs__btn-shine bg-teal-600 hover:bg-teal-700 text-white py-3 px-6 rounded-full transition-all duration-300 ease-in-out shadow-lg hover:shadow-xl focus:ring-4 focus:ring-teal-300"&gt; Shiny &lt;span class="cs__shine"&gt;&lt;/span&gt; &lt;/button&gt;' data-css-code='/* ClickStyle&apos;s CSS for .cs__btn-shine and .cs__shine provides the effect. */ .cs__shine { 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.4) 50%, rgba(255, 255, 255, 0) 100% ); transform: skewX(-20deg); /* ... other ClickStyle rules ... */ } .cs__btn-shine:hover .cs__shine { animation: shine-effect 0.8s forwards; } @keyframes shine-effect { to { left: 100%; } }' data-js-code='// ClickStyles library handles the JavaScript for this effect if dynamic. // Ensure you include: // &lt;script src="https://unpkg.com/gsap@3/dist/gsap.min.js"&gt;&lt;/script&gt; // &lt;script src="../dist/clickstyles.min.js"&gt;&lt;/script&gt;'> Show Code </button> </div> </div> <div class="flex flex-col bg-gray-800 rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300"> <div class="flex justify-center items-center p-6 min-h-[150px]"> <button class="cs__btn-spin-bg" data-variant="rainbow"> <span class="cs__btn-spin-bg__ring"></span> <span class="cs__btn-spin-bg__text">Spin</span> </button> </div> <div class="p-4 border-t border-gray-700"> <button class="show-code-modal-btn bg-gray-700 hover:bg-gray-600 text-white text-sm py-2 px-4 rounded-md w-full" data-html-code='&lt;button class="cs__btn-spin-bg" data-variant="rainbow"&gt; &lt;span class="cs__btn-spin-bg__ring"&gt;&lt;/span&gt; &lt;span class="cs__btn-spin-bg__text"&gt;Spin&lt;/span&gt; &lt;/button&gt;' data-css-code='/* This button&apos;s CSS is more complex, likely involving ::before/::after or multiple spans for the ring and background. */ .cs__btn-spin-bg { position: relative; overflow: hidden; /* ... other ClickStyle rules ... */ } .cs__btn-spin-bg__ring { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 150%; /* Larger to ensure it covers the button */ height: 150%; border-radius: 50%; background: conic-gradient(#ff0000, #ff7f00, #ffff00, #00ff00, #0000ff, #4b0082, #9400d3); /* Rainbow example */ animation: spin-around 5s linear infinite; z-index: 0; } .cs__btn-spin-bg__text { position: relative; z-index: 1; /* Ensure text is visible over the spinning ring */ color: white; padding: 0.75rem 1.5rem; /* Match general button padding */ border-radius: 9999px; background-color: #2d3748; /* Dark background for text */ }' data-js-code='// ClickStyles library handles the JavaScript for this effect. // Ensure you include: // &lt;script src="https://unpkg.com/gsap@3/dist/gsap.min.js"&gt;&lt;/script&gt; // &lt;script src="../dist/clickstyles.min.js"&gt;&lt;/script&gt;'> Show Code </button> </div> </div> </div> <div id="codeModal" class="modal-overlay"> <div class="modal-content"> <div class="flex justify-between items-center bg-gray-900 p-4 rounded-t-xl border-b border-gray-700"> <h2 class="text-2xl font-semibold text-gray-100">Button Code</h2> <button id="closeModal" class="text-gray-400 hover:text-white text-3xl font-bold leading-none">&times;</button> </div> <div class="code-tabs"> <button data-code-type="html" class="tab-button active-tab">HTML</button> <button data-code-type="css" class="tab-button">CSS</button> <button data-code-type="js" class="tab-button">JavaScript</button> </div> <div class="code-display relative"> <div id="htmlPanel" class="code-panel active-panel"> <pre id="htmlCodeDisplay"></pre> <button class="copy-code-btn" data-copy-target="htmlCodeDisplay">Copy HTML</button> </div> <div id="cssPanel" class="code-panel"> <pre id="cssCodeDisplay"></pre> <button class="copy-code-btn" data-copy-target="cssCodeDisplay">Copy CSS</button> </div> <div id="jsPanel" class="code-panel"> <pre id="jsCodeDisplay"></pre> <button class="copy-code-btn" data-copy-target="jsCodeDisplay">Copy JS</button> </div> </div> </div> </div> <script src="https://unpkg.com/gsap@3/dist/gsap.min.js"></script> <script src="../dist/clickstyles.min.js"></script> <script> document.addEventListener('DOMContentLoaded', () => { const showCodeModalBtns = document.querySelectorAll('.show-code-modal-btn'); const codeModal = document.getElementById('codeModal'); const closeModalBtn = document.getElementById('closeModal'); const tabButtons = document.querySelectorAll('.tab-button'); const codePanels = document.querySelectorAll('.code-panel'); const htmlCodeDisplay = document.getElementById('htmlCodeDisplay'); const cssCodeDisplay = document.getElementById('cssCodeDisplay'); const jsCodeDisplay = document.getElementById('jsCodeDisplay'); const copyCodeBtns = document.querySelectorAll('.copy-code-btn'); function openCodeModal(html, css, js) { htmlCodeDisplay.textContent = html; cssCodeDisplay.textContent = css; jsCodeDisplay.textContent = js; // Activate HTML tab by default when modal opens tabButtons.forEach(btn => btn.classList.remove('active-tab')); codePanels.forEach(panel => panel.classList.remove('active-panel')); document.querySelector('.tab-button[data-code-type="html"]').classList.add('active-tab'); document.getElementById('htmlPanel').classList.add('active-panel'); codeModal.classList.add('open'); document.body.style.overflow = 'hidden'; } function closeCodeModal() { codeModal.classList.remove('open'); document.body.style.overflow = ''; } showCodeModalBtns.forEach(button => { button.addEventListener('click', () => { const html = button.dataset.htmlCode; const css = button.dataset.cssCode; const js = button.dataset.jsCode; openCodeModal(html, css, js); }); }); closeModalBtn.addEventListener('click', closeCodeModal); codeModal.addEventListener('click', (e) => { if (e.target === codeModal) { closeCodeModal(); } }); tabButtons.forEach(button => { button.addEventListener('click', () => { const targetType = button.dataset.codeType; // Deactivate all tabs and panels tabButtons.forEach(btn => btn.classList.remove('active-tab')); codePanels.forEach(panel => panel.classList.remove('active-panel')); // Activate clicked tab and corresponding panel button.classList.add('active-tab'); document.getElementById(`${targetType}Panel`).classList.add('active-panel'); }); }); copyCodeBtns.forEach(button => { button.addEventListener('click', async () => { const targetId = button.dataset.copyTarget; const codeToCopy = document.getElementById(targetId).textContent; try { await navigator.clipboard.writeText(codeToCopy.trim()); button.textContent = 'Copied!'; setTimeout(() => { // Determine current active tab to set copy button text correctly const activeTab = document.querySelector('.tab-button.active-tab'); if (activeTab) { const type = activeTab.dataset.codeType.toUpperCase(); button.textContent = `Copy ${type}`; } else { button.textContent = 'Copy Code'; // Fallback } }, 2000); } catch (err) { console.error('Failed to copy code: ', err); alert('Failed to copy code. Please copy manually.'); } }); }); }); </script> </body> </html>