File size: 5,518 Bytes
ec18068
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// --- 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 = '<span class="status-text">Connecting to local GPU...</span><div class="loading-spinner"></div>';
    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); 
}