| 1 | // Theme: runs synchronously in <head> so the stored choice applies before |
| 2 | // first paint. "auto" follows the OS; the server default comes from |
| 3 | // data-default-theme (ui.theme). |
| 4 | (function () { |
| 5 | "use strict"; |
| 6 | var KEY = "ferrenium-theme"; |
| 7 | var root = document.documentElement; |
| 8 | var fallback = root.getAttribute("data-default-theme") || "auto"; |
| 9 | var current = fallback; |
| 10 | |
| 11 | try { |
| 12 | current = localStorage.getItem(KEY) || fallback; |
| 13 | } catch (e) {} |
| 14 | |
| 15 | function apply(choice) { |
| 16 | current = choice; |
| 17 | if (choice === "light" || choice === "dark") { |
| 18 | root.setAttribute("data-theme", choice); |
| 19 | } else { |
| 20 | root.removeAttribute("data-theme"); |
| 21 | } |
| 22 | var buttons = document.querySelectorAll("[data-theme-choice]"); |
| 23 | for (var i = 0; i < buttons.length; i++) { |
| 24 | var on = buttons[i].getAttribute("data-theme-choice") === choice; |
| 25 | buttons[i].setAttribute("aria-pressed", on ? "true" : "false"); |
| 26 | } |
| 27 | } |
| 28 | |
| 29 | root.classList.add("js"); |
| 30 | apply(current); |
| 31 | |
| 32 | document.addEventListener("DOMContentLoaded", function () { |
| 33 | apply(current); |
| 34 | document.addEventListener("click", function (event) { |
| 35 | var button = event.target.closest && event.target.closest("[data-theme-choice]"); |
| 36 | if (!button) return; |
| 37 | var choice = button.getAttribute("data-theme-choice"); |
| 38 | try { |
| 39 | if (choice === fallback) localStorage.removeItem(KEY); |
| 40 | else localStorage.setItem(KEY, choice); |
| 41 | } catch (e) {} |
| 42 | apply(choice); |
| 43 | }); |
| 44 | }); |
| 45 | })(); |