Deploy from Lumerel

This commit is contained in:
Lumerel Deploy
2026-02-20 20:52:05 +00:00
commit f0f80697e7
5 changed files with 827 additions and 0 deletions

164
main.js Normal file
View File

@@ -0,0 +1,164 @@
/**
* Lumerel — 3D Homepage
* main.js
*
* Handles:
* - Spline 3D scene loading & pointer-events toggle
* - Navbar scroll behaviour (frosted glass on scroll)
* - Video autoplay fallback (iOS / autoplay-blocked browsers)
* - Waitlist button click handlers
* - Global helpers exposed on window.Lumerel
*/
/* ── Spline Integration ────────────────────────────────────────────
*
* WHEN YOUR SPLINE SCENE IS READY:
*
* 1. Open index.html and replace the .hero__3d-placeholder div
* with a <spline-viewer> element:
*
* <spline-viewer
* url="https://prod.spline.design/YOUR_SCENE_ID/scene.splinecode"
* events-target="global"
* ></spline-viewer>
*
* 2. To allow mouse/touch interaction on the 3D scene, call:
* window.Lumerel.enableSpline()
*
* 3. Optionally use the @splinetool/runtime package directly:
*
* import { Application } from '@splinetool/runtime';
* const app = new Application(canvas);
* app.load('https://prod.spline.design/YOUR_SCENE_ID/scene.splinecode');
*
* ──────────────────────────────────────────────────────────────── */
const splineLayer = document.getElementById('spline-layer');
/**
* Enable pointer events on the 3D layer so Spline scenes
* can receive mouse/touch input.
* Call this AFTER your Spline scene has loaded.
*/
function enableSpline() {
if (splineLayer) {
splineLayer.style.pointerEvents = 'auto';
console.log('[Lumerel] Spline pointer events ENABLED.');
}
}
/**
* Disable pointer events on the 3D layer (default state).
* Ensures all UI elements (buttons, links) remain fully clickable.
*/
function disableSpline() {
if (splineLayer) {
splineLayer.style.pointerEvents = 'none';
console.log('[Lumerel] Spline pointer events DISABLED.');
}
}
// Listen for the spline-viewer web component ready event
if (splineLayer) {
const viewer = splineLayer.querySelector('spline-viewer');
if (viewer) {
viewer.addEventListener('load', () => {
console.log('[Lumerel] Spline scene loaded.');
// Uncomment to auto-enable 3D interactivity once scene loads:
// enableSpline();
});
}
}
/* ── Navbar Scroll Effect ──────────────────────────────────────────
Adds a frosted-glass background when the user scrolls down.
──────────────────────────────────────────────────────────────── */
const navbar = document.querySelector('.navbar');
function handleNavbarScroll() {
if (!navbar) return;
if (window.scrollY > 20) {
navbar.style.background = 'rgba(0, 0, 0, 0.55)';
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', handleNavbarScroll, { passive: true });
handleNavbarScroll(); // run immediately on load
/* ── Video Autoplay Fallback ───────────────────────────────────────
Gracefully handles browsers that block autoplay or fail to
load the background video.
──────────────────────────────────────────────────────────────── */
const heroVideo = document.querySelector('.hero__video');
if (heroVideo) {
// Error: video failed to load — show a subtle gradient fallback
heroVideo.addEventListener('error', () => {
console.warn('[Lumerel] Background video failed to load — using fallback gradient.');
const videoWrap = document.querySelector('.hero__video-wrap');
if (videoWrap) {
videoWrap.style.background = 'radial-gradient(ellipse at 60% 40%, #0d0d1a 0%, #000 70%)';
}
});
// iOS Safari: resume playback after first user interaction
document.addEventListener('touchstart', () => {
if (heroVideo.paused) {
heroVideo.play().catch(() => {});
}
}, { once: true });
}
/* ── Waitlist Button Handlers ──────────────────────────────────────
Replace the console.log below with your modal / form logic.
──────────────────────────────────────────────────────────────── */
const waitlistBtns = document.querySelectorAll('.js-waitlist');
waitlistBtns.forEach((btn) => {
btn.addEventListener('click', () => {
console.log('[Lumerel] Waitlist button clicked — wire up your modal or form here.');
// Example: open a modal
// document.getElementById('waitlist-modal').classList.add('is-open');
});
});
/* ── Global API ────────────────────────────────────────────────────
Exposed on window.Lumerel for easy access from the browser
console or other scripts.
──────────────────────────────────────────────────────────────── */
window.Lumerel = {
enableSpline,
disableSpline,
/**
* Swap out the placeholder orbs for a real Spline scene at runtime.
* @param {string} sceneUrl - The Spline scene URL (.splinecode)
*/
loadSplineScene(sceneUrl) {
if (!splineLayer) return;
// Remove placeholder
const placeholder = splineLayer.querySelector('.hero__3d-placeholder');
if (placeholder) placeholder.remove();
// Create and append <spline-viewer>
const viewer = document.createElement('spline-viewer');
viewer.setAttribute('url', sceneUrl);
viewer.setAttribute('events-target', 'global');
splineLayer.appendChild(viewer);
viewer.addEventListener('load', () => {
console.log('[Lumerel] Spline scene loaded via loadSplineScene().');
});
console.log(`[Lumerel] Loading Spline scene: ${sceneUrl}`);
},
};
console.log('[Lumerel] main.js loaded. Use window.Lumerel to control 3D layer.');