/** * Newto shared theme toggle. * The initial theme is applied inline in each page's (to avoid a flash); * this file wires up the toggle button(s) marked with [data-theme-toggle]. * * Theme colors are driven by CSS custom properties that flip on * :root[data-theme="light"]. Some engines mishandle CSS transitions when the * value changes via a custom property (the transition can fail to settle), so * we suppress transitions for the duration of the switch and let the new colors * snap in cleanly. */ (function () { "use strict"; var KEY = "newto_theme"; var root = document.documentElement; // Rule that kills transitions while a switch is in progress. var killer = document.createElement("style"); killer.textContent = ".theme-switching, .theme-switching *, .theme-switching *::before, .theme-switching *::after" + "{ transition: none !important; }"; (document.head || document.documentElement).appendChild(killer); function apply(theme) { root.classList.add("theme-switching"); root.setAttribute("data-theme", theme); try { localStorage.setItem(KEY, theme); } catch (e) { /* storage unavailable (private mode) — theme still applies for this page */ } // Commit the new values while transitions are off, then re-enable them. void root.offsetWidth; requestAnimationFrame(function () { requestAnimationFrame(function () { root.classList.remove("theme-switching"); }); }); } function toggle() { apply(root.getAttribute("data-theme") === "light" ? "dark" : "light"); } function wire() { var buttons = document.querySelectorAll("[data-theme-toggle]"); for (var i = 0; i < buttons.length; i++) { buttons[i].addEventListener("click", toggle); } } if (document.readyState !== "loading") { wire(); } else { document.addEventListener("DOMContentLoaded", wire); } })();