/* eslint-disable */ /* Root app v2 — left immersive nav, no side panel. */ const { useState: useStateRoot, useEffect: useEffectRoot, useRef: useRefRoot } = React; const SCREENS = [ { idx: 0, name: "Call to action", bg: "Idle loop · immersive background" }, { idx: 1, name: "The Evolution", bg: "Background · Evolution scene" }, { idx: 2, name: "SDT Levels", bg: "Background · SDT Levels scene" }, { idx: 3, name: "Key Characteristics", bg: "Background · Key Characteristics scene" }, { idx: 4, name: "Use Cases", bg: "Background · Use Cases scene" }, { idx: 5, name: "Value & Benefits", bg: "Background · Value scene" }, { idx: 6, name: "Global Video", bg: "Background · Global Video" }, ]; // Items shown in the airy left nav — Call to action is intentionally excluded const NAV_ITEMS = SCREENS.filter((s) => s.idx !== 0); function App() { const [current, setCurrent] = useStateRoot(0); // Per-screen states managed at the root so they persist on nav const [sliderH, setSliderH] = useStateRoot(0.5); const [sliderV, setSliderV] = useStateRoot(1); // 1 = compact, 0 = exploded const [activeLayer, setActiveLayer] = useStateRoot(null); const [activeChar, setActiveChar] = useStateRoot(null); const [useCaseIndex, setUseCaseIndex] = useStateRoot(0); const [videoOpen, setVideoOpen] = useStateRoot(false); const [activeBenefit, setActiveBenefit] = useStateRoot(null); const [playerState, setPlayerState] = useStateRoot("launch"); const [transition, setTransition] = useStateRoot(null); const transitionTimerRef = useRefRoot(null); const goTo = (target) => { if (target === current) return; const diff = target - current; let kind; if (Math.abs(diff) === 1) kind = diff > 0 ? "forward" : "reverse"; else kind = "shader"; setTransition(kind); if (transitionTimerRef.current) clearTimeout(transitionTimerRef.current); transitionTimerRef.current = setTimeout(() => { setCurrent(target); // close any opened popup on screen change setVideoOpen(false); setActiveLayer(null); setActiveChar(null); setActiveBenefit(null); // reset transitory states for the target screen if (target === 6) setPlayerState("launch"); // give the overlay a beat to fade out transitionTimerRef.current = setTimeout(() => setTransition(null), 250); }, 320); }; const onBack = () => goTo(Math.max(0, current - 1)); const onNext = () => goTo(Math.min(6, current + 1)); // Auto-scale canvas to viewport const appRef = useRefRoot(null); useEffectRoot(() => { const wrap = appRef.current; if (!wrap) return; const apply = () => { const W = wrap.clientWidth; const H = wrap.clientHeight; if (W <= 0 || H <= 0) return; const targetW = 1600, targetH = 900; const scale = Math.min((W - 48) / targetW, (H - 48) / targetH); const frame = wrap.querySelector(".canvas-frame"); if (frame) frame.style.transform = `scale(${scale})`; }; requestAnimationFrame(() => requestAnimationFrame(apply)); const ro = new ResizeObserver(apply); ro.observe(wrap); window.addEventListener("resize", apply); return () => { ro.disconnect(); window.removeEventListener("resize", apply); }; }, []); const renderScreen = () => { switch (current) { case 0: return goTo(1)} />; case 1: return ; case 2: return ; case 3: return ; case 4: return ; case 5: return ; case 6: return goTo(0)} />; default: return null; } }; const immersive = current === 6 && playerState !== "launch"; const currentBg = (() => { if (current === 2) { return sliderV < 0.5 ? "Background · Levels — exploded loop" : "Background · Levels — compact loop"; } if (current === 3) { if (!activeChar) return "Background · Key Characteristics overview loop"; return `Background · Key Characteristics — ${activeChar} loop`; } return SCREENS[current].bg; })(); const frameClass = (() => { if (current === 2 && sliderV < 0.5) return "canvas-frame bg-levels-exploded"; if (current === 3 && activeChar) return `canvas-frame bg-char-${activeChar}`; return "canvas-frame"; })(); return (
{/* Immersive bg label (single corner tag — the bg pattern itself spans the full canvas) */} {!immersive &&
{currentBg}
} {/* Persistent chrome — Alstom logo (always) + discreet home (only off the call-to-action) */} {!immersive && (
ALSTOM
{current !== 0 && ( )}
)} {/* Airy left navigation — hidden on call to action and when in immersive playback */} {current !== 0 && !immersive && (
{NAV_ITEMS.map((s, i) => ( ))}
)} {/* Scene */}
{renderScreen()}
{/* Transition overlay */} {transition && (
)}
); } ReactDOM.createRoot(document.getElementById("root")).render();