let questions = null; // Auto-detect API base URL const getApiBase = () => { const protocol = window.location.protocol; const hostname = window.location.hostname; // If running on localhost, assume backend is on port 3001 if (hostname === "localhost" || hostname === "127.0.0.1") { return `${protocol}//${hostname}:3001`; } // For production, assume backend is on same origin return "https://fizika-backend.schmelczer.dev"; }; const API_BASE = getApiBase(); // Fetch the question bank from the backend, which is the single source of // truth. Cached after the first successful load. const ensureQuestionsLoaded = async () => { if (questions !== null) return questions; const response = await fetch(`${API_BASE}/api/fizika`); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } questions = await response.json(); return questions; }; const escapeHtml = (value) => String(value).replace( /[&<>"']/g, (ch) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'", })[ch], ); // Question text is trusted but contains light markup (, ,
) and // pre-encoded entities. Escape everything first, then restore only that // allowlist, so any other injected markup (e.g.