/** * ============================================================ * XENEX GLASS OS * Boot Controller * ============================================================ * * Responsibilities: * - Control boot animation timing * - Update boot status * - Respect reduced-motion preferences * - Transition cleanly to the login application * * This module does NOT: * - authenticate users * - contain passwords * - contain API secrets * - access Neon * - access S3 * - make privileged backend decisions * * Backend authority begins when the login module is loaded. */ "use strict"; /* ============================================================ CONFIGURATION ============================================================ */ const BOOT_CONFIG = Object.freeze({ /* * Short enough to feel responsive, but long enough for * the visual identity to register. */ minimumDuration: 3000, /* * Small transition period after the Xenex wordmark appears. */ transitionDuration: 900, /* * Destination module. * * This file will be created next. */ loginModule: "./login.html" }); /* ============================================================ BOOT STATE ============================================================ */ const BootState = Object.freeze({ STARTING: "starting", READY: "ready", TRANSITIONING: "transitioning", COMPLETE: "complete" }); let currentState = BootState.STARTING; /* ============================================================ DOM REFERENCES ============================================================ */ const bootRoot = document.getElementById("xenex-boot"); const bootStatus = document.getElementById("boot-status"); const transitionLayer = document.getElementById("boot-transition"); /* ============================================================ VALIDATION ============================================================ */ function validateBootDOM() { if (!bootRoot) { throw new Error( "Xenex Boot: boot root was not found." ); } if (!bootStatus) { throw new Error( "Xenex Boot: status element was not found." ); } if (!transitionLayer) { throw new Error( "Xenex Boot: transition layer was not found." ); } } /* ============================================================ STATUS ============================================================ */ function setBootStatus(message) { if (!bootStatus) { return; } bootStatus.textContent = message; } /* ============================================================ STATE ============================================================ */ function setState(nextState) { currentState = nextState; } /* ============================================================ REDUCED MOTION ============================================================ */ function prefersReducedMotion() { return window.matchMedia( "(prefers-reduced-motion: reduce)" ).matches; } /* ============================================================ TRANSITION ============================================================ */ function beginTransition() { if (currentState !== BootState.STARTING) { return; } setState(BootState.TRANSITIONING); setBootStatus( "Preparing your workspace" ); transitionLayer.classList.add( "is-active" ); /* * Allow the transition layer to cover the boot screen * before navigating to the login document. */ window.setTimeout(() => { setState(BootState.COMPLETE); window.location.replace( BOOT_CONFIG.loginModule ); }, BOOT_CONFIG.transitionDuration); } /* ============================================================ NORMAL BOOT ============================================================ */ function startNormalBoot() { const startedAt = performance.now(); setBootStatus( "Starting Xenex Glass OS" ); /* * We intentionally don't use a fixed "fake loading" * percentage. * * This is simply the visual boot stage. * * Later, real frontend initialization can register * readiness tasks here. */ window.setTimeout(() => { const elapsed = performance.now() - startedAt; const remaining = Math.max( 0, BOOT_CONFIG.minimumDuration - elapsed ); window.setTimeout(() => { setBootStatus( "Xenex Glass OS ready" ); beginTransition(); }, remaining); }, 100); } /* ============================================================ ACCESSIBILITY BOOT ============================================================ */ function startReducedMotionBoot() { setBootStatus( "Xenex Glass OS ready" ); /* * No unnecessary animation delay for users who have * requested reduced motion. */ window.setTimeout( beginTransition, 500 ); } /* ============================================================ INITIALIZATION ============================================================ */ function initializeBoot() { try { validateBootDOM(); setState(BootState.STARTING); if (prefersReducedMotion()) { startReducedMotionBoot(); } else { startNormalBoot(); } } catch (error) { /* * Do not silently fail. * * This remains a frontend boot error and does not * expose any backend information. */ console.error( "Xenex Glass OS boot error:", error ); setBootStatus( "Unable to start Xenex OS" ); } } /* ============================================================ START ============================================================ */ if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", initializeBoot, { once: true } ); } else { initializeBoot(); }