Deploy from Lumerel

This commit is contained in:
Lumerel Deploy
2026-02-20 21:19:32 +00:00
commit 6c5549c030
5 changed files with 832 additions and 0 deletions

156
main.js Normal file
View File

@@ -0,0 +1,156 @@
/**
* 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:
*
* <spline-viewer
* url="https://prod.spline.design/YOUR_SCENE_ID/scene.splinecode"
* events-target="global"
* ></spline-viewer>
*
* ── 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 <spline-viewer> web component is already loaded via CDN
* in the <head> 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 <spline-viewer>.
* @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 <spline-viewer> 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;'
);