// --- CONFIGURATION & STATE --- const config = { localApiUrl: localStorage.getItem('motif_api_url') || null, }; // --- DOM ELEMENTS --- const modal = document.getElementById('guide-modal'); const showGuideBtn = document.getElementById('show-guide'); const closeModalBtn = document.querySelector('.close-modal'); const saveConnectionBtn = document.getElementById('save-connection'); const apiUrlInput = document.getElementById('api-url'); const navItems = document.querySelectorAll('.nav-item'); const sections = document.querySelectorAll('main section'); // --- STARTUP BEHAVIOR --- document.addEventListener('DOMContentLoaded', () => { // 1. Mandatory Setup Guide - Show popup if no API is saved if (!config.localApiUrl) { openModal(); } else { apiUrlInput.value = config.localApiUrl; } // 2. Initialize Cool Cursor Trail Effect initializeCursorTrail(); }); // --- UI / NAVIGATION HANDLERS --- navItems.forEach(item => { item.addEventListener('click', (e) => { // Handle Sidebar active state navItems.forEach(nav => nav.classList.remove('active')); item.classList.add('active'); // Handle Main Section visibility (Scrolling effect control) const targetSectionId = item.getAttribute('data-target'); sections.forEach(sec => sec.classList.remove('active-section')); document.getElementById(targetSectionId).classList.add('active-section'); }); }); // --- MODAL / CONNECTION GUIDE LOGIC --- function openModal() { modal.classList.add('active-modal'); } function closeModal() { modal.classList.remove('active-modal'); } showGuideBtn.addEventListener('click', openModal); closeModalBtn.addEventListener('click', closeModal); modal.addEventListener('click', (e) => { // Close if clicking overlay area outside the content box if (e.target === modal) closeModal(); }); saveConnectionBtn.addEventListener('click', () => { const enteredUrl = apiUrlInput.value.trim(); if (enteredUrl) { localStorage.setItem('motif_api_url', enteredUrl); config.localApiUrl = enteredUrl; closeModal(); alert(`Setup Complete! 🦄 Portal connected to backend at: ${enteredUrl}`); } else { alert('Please enter your local API address (e.g., http://localhost:7860)'); } }); // --- COOL MOUSE EFFECTS (PASTEL CURSOR TRAIL) --- function initializeCursorTrail() { const trailContainer = document.getElementById('cursor-trail'); const dots = []; const numDots = 12; // Create dots with alternating pastel colors for (let i = 0; i < numDots; i++) { const dot = document.createElement('div'); dot.className = 'trail-dot'; dot.style.backgroundColor = getPastelColor(i); trailContainer.appendChild(dot); dots.push({ element: dot, x: 0, y: 0 }); } let mouseX = 0, mouseY = 0; window.addEventListener('mousemove', (e) => { mouseX = e.clientX; mouseY = e.clientY; }); // Animation loop for dots lagging smoothly behind cursor function animateTrail() { let x = mouseX; let y = mouseY; dots.forEach((dot, index) => { const nextDot = dots[index + 1] || dots[0]; dot.x = x; dot.y = y; dot.element.style.left = x + 'px'; dot.element.style.top = y + 'px'; dot.element.style.opacity = 1 - (index / numDots); // Trail fades out // Apply smooth lag effect x += (nextDot.x - x) * 0.3; y += (nextDot.y - y) * 0.3; }); requestAnimationFrame(animateTrail); } animateTrail(); } function getPastelColor(index) { const colors = ['#ffe6d9', '#d6eaff', '#fbe0e6', '#e1f7f1']; // Peach, Blue, Pink, Mint return colors[index % colors.length]; } // --- GENERATION LOGIC (CONNECTION PLACEHOLDER) --- const generateButtons = document.querySelectorAll('.generate-btn'); generateButtons.forEach(btn => { btn.addEventListener('click', handleGeneration); }); async function handleGeneration(e) { if (!config.localApiUrl) { alert("Wait! 🛑 To keep this portal unlimited and free, you must connect to your own powerful local computer first. Click 'Connection Guide'."); openModal(); return; } const outputArea = document.getElementById('video-output'); // Add loading animation and swell effect outputArea.innerHTML = 'Connecting to local GPU...
'; outputArea.closest('.animated-frame').classList.add('generating-active'); // PLACEHOLDER GENERATION SIMULATION // In a real application, you would send a POST request to ${config.localApiUrl} here. console.log(`Sending generation request to local backend: ${config.localApiUrl}`); // Simulate backend processing time (4 seconds) setTimeout(() => { outputArea.innerHTML = ''; // Clear status spinner // Use placeholder output from model card const video = document.createElement('video'); video.src = 'https://huggingface.co/Motif-Technologies/Motif-Video-2B/resolve/main/assets/banner.mp4'; video.autoplay = true; video.loop = true; video.controls = true; video.style.width = '100%'; outputArea.appendChild(video); outputArea.closest('.animated-frame').classList.remove('generating-active'); }, 4000); }