/** * Lumerel — 3D Homepage · main.js * * Responsibilities: * 1. Spline 3D scene pointer-events toggle + runtime loader * 2. Navbar scroll backdrop blur * 3. Background video autoplay fallback (iOS Safari) * 4. Waitlist button click hooks * 5. Public API exposed on window.Lumerel */ /* ── 1. Spline / 3D Layer Integration ───────────────────────────── * * When your Spline scene is ready, choose one of three methods: * * ── Method A (HTML — recommended) ───────────────────────────────── * Open index.html → find #spline-layer → delete .spline-placeholder * → paste in: * * * * ── Method B (JavaScript runtime) ───────────────────────────────── * Call from console or your code: * window.Lumerel.loadSplineScene('https://prod.spline.design/…') * * ── Method C (Interactive scenes) ───────────────────────────────── * After scene loads, enable pointer events: * window.Lumerel.enableSpline() * * The web component is already loaded via CDN * in the of index.html — no extra imports needed. * ─────────────────────────────────────────────────────────────────── */ const splineLayer = document.getElementById('spline-layer'); /** Allow pointer events on the 3D layer (for interactive Spline scenes). */ function enableSpline() { if (splineLayer) splineLayer.style.pointerEvents = 'auto'; } /** Block pointer events on the 3D layer (default — keeps UI clickable). */ function disableSpline() { if (splineLayer) splineLayer.style.pointerEvents = 'none'; } /** * Programmatically load a Spline scene URL at runtime. * Removes the placeholder orbs and inserts a . * @param {string} url - The full Spline scene URL * @param {boolean} [interactive=false] - Enable pointer events for interactive scenes */ function loadSplineScene(url, interactive = false) { if (!splineLayer) return; // Remove placeholder if present const placeholder = splineLayer.querySelector('.spline-placeholder'); if (placeholder) placeholder.remove(); // Create and configure the viewer const viewer = document.createElement('spline-viewer'); viewer.setAttribute('url', url); viewer.setAttribute('events-target', 'global'); viewer.style.cssText = 'width:100%;height:100%;display:block;'; viewer.addEventListener('load', () => { console.log('[Lumerel] ✓ Spline scene loaded:', url); if (interactive) enableSpline(); }); splineLayer.appendChild(viewer); console.log('[Lumerel] Loading Spline scene…'); } // Auto-detect if a was placed directly in index.html if (splineLayer) { const viewer = splineLayer.querySelector('spline-viewer'); if (viewer) { viewer.addEventListener('load', () => { console.log('[Lumerel] ✓ Spline scene loaded.'); // Uncomment to enable 3D mouse interaction after scene loads: // enableSpline(); }); } } /* ── 2. Navbar Scroll Backdrop ──────────────────────────────────── */ const navbar = document.getElementById('navbar'); function updateNavbar() { if (!navbar) return; if (window.scrollY > 24) { navbar.style.background = 'rgba(0, 0, 0, 0.45)'; navbar.style.backdropFilter = 'blur(16px)'; navbar.style.webkitBackdropFilter = 'blur(16px)'; } else { navbar.style.background = 'transparent'; navbar.style.backdropFilter = 'none'; navbar.style.webkitBackdropFilter = 'none'; } } window.addEventListener('scroll', updateNavbar, { passive: true }); updateNavbar(); // run once on load /* ── 3. Background Video Fallback ───────────────────────────────── */ const heroVideo = document.querySelector('.hero__video'); if (heroVideo) { // Gradient fallback if video fails to load heroVideo.addEventListener('error', () => { console.warn('[Lumerel] Background video failed — using gradient fallback.'); const wrap = document.querySelector('.hero__video-wrap'); if (wrap) { wrap.style.background = 'radial-gradient(ellipse at 60% 30%, #1a0a2e 0%, #000000 70%)'; } }); // iOS Safari sometimes needs a manual play() call const playPromise = heroVideo.play(); if (playPromise !== undefined) { playPromise.catch(() => { // Autoplay blocked — video stays paused (expected on some browsers) console.info('[Lumerel] Video autoplay blocked by browser policy.'); }); } } /* ── 4. Waitlist Button Hooks ───────────────────────────────────── */ document.querySelectorAll('.pill-btn').forEach((btn) => { btn.addEventListener('click', () => { // TODO: Replace with your actual waitlist modal / form / redirect console.log('[Lumerel] Join Waitlist clicked — wire up your form here.'); // Example: window.location.href = 'https://your-waitlist.com'; // Example: document.getElementById('waitlist-modal').showModal(); }); }); /* ── 5. Public API ──────────────────────────────────────────────── */ window.Lumerel = { /** Load a Spline scene programmatically */ loadSplineScene, /** Enable pointer events on the 3D layer (for interactive Spline scenes) */ enableSpline, /** Disable pointer events on the 3D layer (restore default) */ disableSpline, }; console.log( '%c LUMEREL %c 3D Homepage ready. Use window.Lumerel.loadSplineScene(url) to add your 3D scene.', 'background:#fff;color:#000;font-weight:700;padding:2px 6px;border-radius:3px;', 'color:#aaa;font-weight:400;' );