Spaces:
Running
Running
Ctrl+K
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>AI Quote Generator | Animated Background</title> <!-- Tailwind CSS CDN --> <script src="https://cdn.tailwindcss.com"></script> <style> /* * Custom Keyframes for the background animation. * This defines the diagonal movement of the lines. */
@keyframes
move-lines { 0% { transform: translateY(-100%) rotate(45deg); opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { transform: translateY(100vh) rotate(45deg); opacity: 0; } } /* * Utility class to apply the animation. * This makes it easy to add the animation to our dynamically generated lines. */ .animate-move-lines { animation: move-lines linear infinite; } </style> </head> <body class="bg-black font-sans"> <!-- Main container for the animation. - relative: Establishes a positioning context for the absolute-positioned lines. - h-screen, w-full: Makes the container take up the full viewport. - overflow-hidden: Hides the parts of the lines that go outside the container. --> <div id="animation-container" class="relative h-screen w-full overflow-hidden"> <!-- A subtle static grid in the background to add depth --> <div class="absolute inset-0 z-0 bg-[radial-gradient(#1a1a1a_1px,transparent_1px)] [background-size:16px_16px]"></div> <!-- Lines are dynamically inserted here by the script --> <!-- Content Area - This sits on top of the animation. It contains the UI for the Gemini-powered quote generator. --> <div class="relative z-20 flex h-full flex-col items-center justify-center text-center p-4"> <div id="content-container" class="bg-black/60 p-6 sm:p-8 rounded-2xl backdrop-blur-md shadow-2xl max-w-2xl w-full border border-white/10 transition-all duration-500"> <!-- Title for the generated content --> <h2 id="generated-title" class="text-white text-2xl md:text-3xl font-bold mb-3 transition-colors duration-500"> AI Quote Generator </h2> <!-- Display area for the generated quote or messages --> <div id="generated-content-wrapper" class="min-h-[8rem] flex items-center justify-center"> <p id="generated-content" class="text-gray-300 text-lg md:text-xl transition-opacity duration-500"> Enter a topic below and our AI will generate an inspiring quote for you. </p> <!-- Loading Spinner --> <div id="loader" class="hidden" role="status"> <svg aria-hidden="true" class="w-8 h-8 text-gray-200 animate-spin dark:text-gray-600 fill-amber-500" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/> <path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0492C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/> </svg> <span class="sr-only">Loading...</span> </div> </div> <!-- Input field and button for user interaction --> <div class="mt-6 flex flex-col sm:flex-row gap-3 w-full"> <input id="topic-input" type="text" placeholder="e.g., 'creativity', 'space', 'courage'" class="flex-grow bg-gray-900/50 border border-gray-600 text-white placeholder-gray-400 text-sm rounded-lg focus:ring-amber-500 focus:border-amber-500 block w-full p-2.5 transition-all"> <button id="generate-btn" class="bg-amber-500 hover:bg-amber-600 text-black font-bold py-2.5 px-6 rounded-lg transition-all duration-300 disabled:bg-gray-500 disabled:cursor-not-allowed"> β¨ Generate Quote </button> </div> </div> </div> </div> <script> // --- SCRIPT 1: DYNAMICALLY CREATE ANIMATED LINES --- const container = document.getElementById('animation-container'); const numberOfLines = 40; // Increased for more density for (let i = 0; i < numberOfLines; i++) { const line = document.createElement('div'); const isBrightLine = Math.random() > 0.3; // 70% chance of being a bright amber line // Common styles for all lines line.classList.add( 'absolute', 'h-[600px]', // Increased height for a better gradient effect 'rounded-full', 'opacity-0', 'animate-move-lines', 'bg-gradient-to-t' // All lines are gradients now ); // --- NEW: Logic to create different types of lines --- if (isBrightLine) { // Style for BRIGHT AMBER lines (the main streaks) line.classList.add( 'w-[3px]', 'from-transparent', 'via-amber-400', 'to-transparent', 'z-10' // Place these on top ); line.style.boxShadow = '0 0 12px #f59e0b, 0 0 24px #f59e0b'; line.style.animationDuration = `${Math.random() * 3 + 4}s`; // Faster: 4s-7s } else { // Style for FAINTER BLUE lines (the background details) line.classList.add( 'w-[1px]', 'from-transparent', 'via-blue-400', 'to-transparent', 'z-0' // Place these behind ); line.style.boxShadow = '0 0 8px #3b82f6'; line.style.animationDuration = `${Math.random() * 5 + 6}s`; // Slower: 6s-11s } // --- Randomize position and animation delay for all lines --- line.style.left = `${Math.random() * 150 - 25}%`; // Wider spawn area line.style.animationDelay = `${Math.random() * 10}s`; // Wider delay range container.appendChild(line); } // --- SCRIPT 2: GEMINI API INTEGRATION FOR QUOTE GENERATION --- const generateBtn = document.getElementById('generate-btn'); const topicInput = document.getElementById('topic-input'); const generatedContent = document.getElementById('generated-content'); const generatedTitle = document.getElementById('generated-title'); const loader = document.getElementById('loader'); generateBtn.addEventListener('click', async () => { const topic = topicInput.value.trim(); if (!topic) { generatedContent.textContent = 'Please enter a topic first.'; return; } loader.classList.remove('hidden'); generatedContent.classList.add('hidden'); generateBtn.disabled = true; topicInput.disabled = true; generatedTitle.textContent = `Generating a quote about "${topic}"...`; try { const prompt = `Generate a short, powerful, and inspiring quote about "${topic}". The quote should be one or two sentences long. Do not include quotation marks or any attribution like who said it. Just provide the quote itself.`; let chatHistory = [{ role: "user", parts: [{ text: prompt }] }]; const payload = { contents: chatHistory }; const apiKey = ""; const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`API error: ${response.statusText}`); } const result = await response.json(); if (result.candidates && result.candidates[0]?.content?.parts?.[0]) { const text = result.candidates[0].content.parts[0].text; const capitalizedTopic = topic.charAt(0).toUpperCase() + topic.slice(1); generatedTitle.textContent = `An Inspiring Quote About ${capitalizedTopic}`; generatedContent.textContent = text.trim(); } else { throw new Error("No content generated. The response format might be invalid."); } } catch (error) { console.error("Error calling Gemini API:", error); generatedTitle.textContent = "An Error Occurred"; generatedContent.textContent = "Could not generate a quote. Please check the browser console for details and try again later."; } finally { loader.classList.add('hidden'); generatedContent.classList.remove('hidden'); generateBtn.disabled = false; topicInput.disabled = false; } }); topicInput.addEventListener('keyup', (event) => { if (event.key === 'Enter') { event.preventDefault(); generateBtn.click(); } }); </script> </body> </html> - Initial Deployment
01cf310
verified