1// Vanilla theme toggle for static pages â matches the React-rendered version on the home page. 2// Apply persisted theme synchronously (before paint) to avoid a light/dark flash. 3(function () { 4 try { 5 var stored = localStorage.getItem("csvtd-theme"); 6 var prefersDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; 7 var theme = stored || (prefersDark ? "dark" : "light"); 8 document.documentElement.setAttribute("data-theme", theme); 9 } catch (e) { /* localStorage may be blocked */ } 10 11 function moonSvg() { 12 return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>'; 13 } 14 function sunSvg() { 15 return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>'; 16 } 17 18 function attach() { 19 // Static pages carry TWO hooks (desktop nav-links + the mobile nav-menu 20 // panel) â wire every slot and keep their icons/labels in sync. 21 var slots = document.querySelectorAll("[data-theme-toggle]"); 22 if (!slots.length) return; 23 var buttons = []; 24 25 function render() { 26 var theme = document.documentElement.getAttribute("data-theme") || "light"; 27 for (var i = 0; i < buttons.length; i++) { 28 buttons[i].innerHTML = theme === "dark" ? sunSvg() : moonSvg(); 29 buttons[i].setAttribute("aria-label", "Switch to " + (theme === "dark" ? "light" : "dark") + " mode"); 30 buttons[i].setAttribute("title", "Switch to " + (theme === "dark" ? "light" : "dark") + " mode"); 31 } 32 } 33 34 function toggle() { 35 var current = document.documentElement.getAttribute("data-theme") || "light"; 36 var next = current === "dark" ? "light" : "dark"; 37 document.documentElement.setAttribute("data-theme", next);
38 try { localStorage.setItem("csvtd-theme", next); } catch (e) {} 39 render(); 40 } 41 42 for (var i = 0; i < slots.length; i++) { 43 var btn = document.createElement("button"); 44 btn.className = "theme-toggle"; 45 btn.addEventListener("click", toggle); 46 buttons.push(btn); 47 slots[i].appendChild(btn); 48 } 49 50 render(); 51 } 52 53 if (document.readyState === "loading") { 54 document.addEventListener("DOMContentLoaded", attach); 55 } else { 56 attach(); 57 } 58 59 // Tapping a link inside the mobile <details> menu closes it (matters for 60 // same-page # anchors, which don't navigate and would leave it open). 61 document.addEventListener("click", function (e) { 62 var a = e.target && e.target.closest && e.target.closest(".nav-menu-panel a"); 63 if (!a) return; 64 var d = a.closest("details.nav-menu"); 65 if (d) d.open = false; 66 }); 67})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.