(() => { const create = () => { const sceneEl = document.getElementById("scene-wrapper"); const activeColorEl = document.getElementById("active-color"); const chainLenEl = document.getElementById("chain-length"); const spawnRateEl = document.getElementById("spawn-rate"); const minLinkEl = document.getElementById("min-link"); const paletteLegendEl = document.getElementById("palette-legend"); const scoreEl = document.getElementById("score"); const highScoreEl = document.getElementById("high-score"); const sceneSelectEl = document.getElementById("scene-select"); const gameOverEl = document.getElementById("game-over"); const finalScoreEl = document.getElementById("final-score"); const restartBtn = document.getElementById("restart-btn"); const pauseBtn = document.getElementById("pause-btn"); const pauseOverlay = document.getElementById("pause-overlay"); const goalLabelEl = document.getElementById("goal-label"); const goalProgressEl = document.getElementById("goal-progress"); const winEl = document.getElementById("win-overlay"); const winMessageEl = document.getElementById("win-message"); const winNextBtn = document.getElementById("win-next"); const winRestartBtn = document.getElementById("win-restart"); const handlers = { onPauseToggle: null, onRestart: null, onSceneChange: null, onWinNext: null, }; if (pauseBtn) { pauseBtn.addEventListener("click", () => { if (handlers.onPauseToggle) handlers.onPauseToggle(); }); } if (restartBtn) { restartBtn.addEventListener("click", () => { if (handlers.onRestart) handlers.onRestart(); }); } if (sceneSelectEl) { sceneSelectEl.addEventListener("change", (e) => { if (handlers.onSceneChange) handlers.onSceneChange(e.target.value); }); } if (winNextBtn) { winNextBtn.addEventListener("click", () => { if (handlers.onWinNext) handlers.onWinNext(); }); } if (winRestartBtn) { winRestartBtn.addEventListener("click", () => { if (handlers.onRestart) handlers.onRestart(); }); } window.addEventListener("keydown", (e) => { if (e.key === "Escape" && handlers.onPauseToggle) { handlers.onPauseToggle(); } }); const setHandlers = (nextHandlers = {}) => { Object.assign(handlers, nextHandlers); }; const setSceneOptions = (scenes, activeId) => { if (!sceneSelectEl) return; sceneSelectEl.innerHTML = ""; scenes.forEach((scene) => { const opt = document.createElement("option"); opt.value = scene.id; opt.textContent = scene.name; sceneSelectEl.appendChild(opt); }); if (activeId) { sceneSelectEl.value = activeId; } }; const setSceneSelection = (sceneId) => { if (sceneSelectEl) { sceneSelectEl.value = sceneId; } }; const setPauseState = (paused) => { if (pauseOverlay) { pauseOverlay.classList.toggle("visible", paused); } if (pauseBtn) { pauseBtn.textContent = paused ? "Resume" : "Pause"; } }; const setGoal = ({ label, progress, colors }) => { if (goalLabelEl) { goalLabelEl.innerHTML = ""; if (Array.isArray(colors) && colors.length > 0) { colors.forEach((color) => { const swatch = document.createElement("span"); swatch.style.background = color; swatch.style.display = "inline-block"; swatch.style.width = "14px"; swatch.style.height = "14px"; swatch.style.borderRadius = "50%"; swatch.style.border = "1px solid rgba(255,255,255,0.2)"; swatch.style.marginRight = "6px"; goalLabelEl.appendChild(swatch); }); const text = document.createElement("span"); text.textContent = label || ""; goalLabelEl.appendChild(text); } else { goalLabelEl.textContent = label || "—"; } } if (goalProgressEl) goalProgressEl.style.width = `${Math.max( 0, Math.min(100, progress ?? 0), )}%`; }; const showWin = (message) => { if (winMessageEl) winMessageEl.textContent = message || "You win!"; if (winEl) winEl.classList.add("visible"); }; const hideWin = () => { if (winEl) winEl.classList.remove("visible"); }; const showGameOver = (score) => { if (finalScoreEl) finalScoreEl.textContent = score; if (gameOverEl) gameOverEl.classList.add("visible"); }; const hideGameOver = () => { if (gameOverEl) gameOverEl.classList.remove("visible"); }; const spawnScorePopup = (point, amount, color) => { if (!point || !sceneEl) return; const el = document.createElement("div"); el.className = "floating-score"; el.textContent = `+${amount}`; el.style.left = `${point.x}px`; el.style.top = `${point.y}px`; el.style.color = color || "#e0f2fe"; sceneEl.appendChild(el); setTimeout(() => el.remove(), 950); }; const updateHud = ({ spawnIntervalMs, minChain, chainLength, score, highScore, activeColor, }) => { if (spawnRateEl) spawnRateEl.textContent = `${spawnIntervalMs} ms`; if (minLinkEl) minLinkEl.textContent = minChain; if (chainLenEl) chainLenEl.textContent = chainLength; if (scoreEl) scoreEl.textContent = score; if (highScoreEl) highScoreEl.textContent = highScore; if (activeColorEl) { if (activeColor) { activeColorEl.textContent = ""; activeColorEl.style.display = "inline-block"; activeColorEl.style.width = "14px"; activeColorEl.style.height = "14px"; activeColorEl.style.borderRadius = "50%"; activeColorEl.style.background = activeColor; activeColorEl.style.border = "1px solid rgba(255,255,255,0.3)"; } else { activeColorEl.removeAttribute("style"); activeColorEl.textContent = "—"; } } }; const buildLegend = (palette) => { if (!paletteLegendEl) return; paletteLegendEl.innerHTML = ""; palette.forEach((color) => { const swatch = document.createElement("span"); swatch.style.background = color; paletteLegendEl.appendChild(swatch); }); }; return { sceneEl, updateHud, buildLegend, spawnScorePopup, setPauseState, showGameOver, hideGameOver, showWin, hideWin, setSceneOptions, setSceneSelection, setHandlers, setGoal, }; }; window.PhysilinksUI = { create }; })();