/* TuringDNA · Assistant — theme bootstrap. * * Loaded synchronously in BEFORE app.css so is set * before first paint (no flash). Mirrors the engine's inline bootstrap, but * kept as an external file because assistant.html is served as a STATIC file * (not through the nonce-injecting index route), so the site's Content-Security * -Policy — script-src 'self' 'nonce-…' — refuses un-nonced inline scripts. * A same-origin /static/ file is allowed by 'self'. Dark is the default. */ (function () { try { var t = localStorage.getItem('td-theme'); if (t !== 'light' && t !== 'dark') { t = 'dark'; } // dark by default document.documentElement.setAttribute('data-theme', t); } catch (e) { document.documentElement.setAttribute('data-theme', 'dark'); } // Embed mode (?embed=1): the panel is inside the engine's #turing view, so // its own brand header + "Engine" back-link + ambient backdrop are redundant // — hide them (CSS keys off html.asst-embed). Set pre-paint to avoid a flash. try { if (/[?&]embed=1\b/.test(location.search)) { document.documentElement.classList.add('asst-embed'); } } catch (e) {} // --vh: this document is its OWN nested browsing context (loaded in an // iframe), so its 100vh/100dvh resolve against the IFRAME's own viewport, // not the parent page's — and needs the same window.innerHeight-based fix // as the engine (see index.html's bootstrap comment). Safari 15.6.1 was // clipping the composer at the bottom of this exact panel because of it. // // The plain 'resize' listener isn't enough here: confirmed directly (this // repo's own test) that Chrome DOES fire 'resize' on an iframe's // contentWindow when the PARENT page's layout changes the iframe's box // (no top-level window resize involved) — but Safari has a long-documented // gap where it only fires 'resize' for genuine top-level window resizes, // never for parent-driven layout shifts. That leaves this iframe's --vh // stuck at whatever it measured on first paint, even after the engine's // topbar/sidebar finish laying out and the iframe's real box changes. // ResizeObserver doesn't have that gap — it fires on ANY box-size change // to the observed element, which for IS this iframe's effective // viewport, regardless of what caused the change. // // One more layer confirmed directly on real Safari 15.6.1 (not guessed): // getBoundingClientRect() already reports the CORRECT, uncut geometry at // rest — the layout is right. What's wrong is that Safari doesn't always // repaint the screen to match a `--vh` change applied via a custom // property; the stale frame stays on screen until something forces a // repaint. A user-driven scroll is exactly that kind of forcing trigger // (confirmed: scrolling makes the "hidden" content flash correctly // into view, then it reverts once scrolling settles) — so nudge a // repaint ourselves right after every --vh change instead of waiting // for the user to accidentally trigger one. try { // Nudges .asst specifically, not / — see index.html's // matching comment (transforming an ancestor of a position:fixed // element hijacks that element's containing block for a frame). // This document has no fixed-position elements at all, but staying // consistent with the targeted approach costs nothing. function nudgeRepaint() { var el = document.querySelector('.asst'); // Also bail if a nudge is already in flight — see index.html's // matching comment (overlapping calls otherwise leave the // transform stuck on permanently instead of reverting). if (!el || el.dataset.nudging) return; el.dataset.nudging = '1'; var prev = el.style.transform; el.style.transform = "translateZ(0)"; void el.offsetHeight; requestAnimationFrame(function () { el.style.transform = prev; delete el.dataset.nudging; }); } function setVH() { document.documentElement.style.setProperty('--vh', (window.innerHeight * 0.01) + 'px'); nudgeRepaint(); } setVH(); window.addEventListener('resize', setVH); if (window.ResizeObserver) { new ResizeObserver(setVH).observe(document.documentElement); } // Same reasoning as index.html: this script runs in , before // .asst exists, so the first nudgeRepaint() above is a no-op. document.addEventListener('DOMContentLoaded', nudgeRepaint); } catch (e) {} })();