(() => { const getSceneById = (scenes, sceneId) => { if (!Array.isArray(scenes)) return null; return scenes.find((candidate) => candidate.id === sceneId) || null; }; const getSceneIdFromUrl = (scenes) => { if (!Array.isArray(scenes)) return null; try { const params = new URLSearchParams(window.location.search); const urlScene = params.get("scene"); return getSceneById(scenes, urlScene) ? urlScene : null; } catch (err) { return null; } }; const setSceneIdInUrl = (sceneId) => { if (!sceneId) return; try { const url = new URL(window.location.href); url.searchParams.set("scene", sceneId); history.replaceState({}, "", `${url.pathname}${url.search}${url.hash}`); } catch (err) { // ignore history failures (blocked or unsupported) } }; const getNextSceneId = (scenes, order, currentScene) => { if (!Array.isArray(scenes)) return null; const ordered = Array.isArray(order) ? order : []; const currentId = currentScene?.id; const orderedExisting = ordered.filter((id) => scenes.some((s) => s.id === id), ); if (orderedExisting.length > 0 && currentId) { const idx = orderedExisting.indexOf(currentId); if (idx >= 0 && idx < orderedExisting.length - 1) { return orderedExisting[idx + 1]; } if (idx === orderedExisting.length - 1) { return orderedExisting[0]; } } const fallbackIdx = scenes.findIndex((s) => s.id === currentId); if (fallbackIdx >= 0 && fallbackIdx < scenes.length - 1) { return scenes[fallbackIdx + 1].id; } return scenes[0]?.id || null; }; window.PhysilinksSceneRegistry = { getSceneById, getSceneIdFromUrl, setSceneIdInUrl, getNextSceneId, }; })();