/* Brain of Reese — brand layer (phase 39). * * One env var (BOR_APP_NAME) drives the display name everywhere. This * small CLASSIC script is the single owner of the resolution — it is not * a module, so its top level runs at parse time: window.BOR_BRAND is * readable from the first line of the page's module scripts (modules * execute after parsing, so a module could not guarantee this). * * Contract (phase 39 locked decisions — A11 no CDN, runtime fetch): * • window.BOR_BRAND = "Brain of Reese" synchronously — the default * name renders immediately, no blank flash; * • fetch("/api/config", { cache: "no-store" }) — on success with a * non-empty app_name, window.BOR_BRAND is updated and the name is * applied to the DOM: * 1. document.title — global replace of the literal; * 2. every .brand-text node — a name starting "Brain of " keeps * the current look (Brain of rest), any other * name renders plain (no bold); the name is HTML-escaped (an * operator-controlled string must not inject markup); * 3. a TreeWalker over the document's text nodes — the literal is * replaced (the index empty-state h1 "Hey! I'm Brain of * Reese." and any other prose); script/style text nodes are * skipped so page source is never mutated; * 4. an attribute pass — the aria-label / placeholder / meta * content attributes containing the literal (the #messages * aria-label, the input label, the meta descriptions). * • fetch failure / empty name → the default stays + console.warn * (the loadHealth house style: progressive enhancement, the page * never breaks). * * No-op property: with BOR_APP_NAME unset the /api/config answer IS the * literal, so every replacement below is a byte-identical no-op. */ /* The synchronous default — set BEFORE any fetch, so module scripts reading window.BOR_BRAND at evaluation time always find a value. */ window.BOR_BRAND = "Brain of Reese"; /* The literal the DOM passes replace — the default name. The page scripts' own `window.BOR_BRAND || "Brain of Reese"` fallbacks stay in sync with it. */ const BRAND_LITERAL = "Brain of Reese"; /* The name is operator-controlled: HTML-escape it before it touches innerHTML (the markdown.js escape pattern — local on purpose, no cross-module import for a 5-line helper). */ function escapeHTML(s) { return String(s).replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'", }[c])); } function applyBrand() { fetch("/api/config", { cache: "no-store" }) .then((r) => (r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`)))) .then((cfg) => { const name = typeof cfg?.app_name === "string" ? cfg.app_name.trim() : ""; if (!name) return; // empty / missing: the default stands window.BOR_BRAND = name; // 1. The document title (global replace of the literal — covers // every page's static "<…> · Brain of Reese" titles). document.title = document.title.replaceAll(BRAND_LITERAL, name); // 2. The header brand on every page: a name starting "Brain of " // keeps the bold split (the current look), anything else // renders plain — the name is always escaped. for (const el of document.querySelectorAll(".brand-text")) { if (name.startsWith("Brain of ")) { const rest = name.slice("Brain of ".length); el.innerHTML = `Brain of ${escapeHTML(rest)}`; } else { el.textContent = name; } } // 3. Prose: a TreeWalker over the body's text nodes replaces the // literal (the empty-state h1, any other copy). Text nodes // inside