(function () { "use strict"; const SIDEBAR_COLLAPSE_STORAGE_PREFIX = "tarot-sidebar-collapsed:v2:"; const DETAIL_COLLAPSE_STORAGE_PREFIX = "tarot-detail-collapsed:v2:"; const DEFAULT_DATASET_ENTRY_COLLAPSED = false; const DEFAULT_DATASET_DETAIL_COLLAPSED = true; const MOBILE_TOPBAR_MEDIA_QUERY = "(max-width: 900px)"; const sidebarControllers = new WeakMap(); const detailControllers = new WeakMap(); const AUTO_COLLAPSE_ENTRY_SELECTOR = [ ".planet-list-item", ".tarot-list-item", "[role='option']", ".kab-node[data-sephira]", ".kab-path-hit[data-path]", ".kab-path-tarot[data-path]", ".kab-rose-petal[data-path]", ".cube-face[role='button']", ".cube-edge-line[role='button']", ".cube-direction[role='button']", ".cube-connector[role='button']", ".cube-center[role='button']", ".kab-chip[data-path]" ].join(", "); const AUTO_COLLAPSE_IGNORE_SELECTOR = [ ".sidebar-toggle-inline", ".sidebar-popout-open", "input", "select", "textarea", "label", "form", ".dataset-search-wrap", ".alpha-text-search-controls", ".cube-rotation-controls", ".cube-rotation-btn", ".tarot-house-action-btn" ].join(", "); function loadSidebarCollapsedState(storageKey) { try { const raw = window.localStorage?.getItem(storageKey); if (raw === "1") { return true; } if (raw === "0") { return false; } return null; } catch { return null; } } function saveSidebarCollapsedState(storageKey, collapsed) { try { window.localStorage?.setItem(storageKey, collapsed ? "1" : "0"); } catch { // Ignore storage failures silently. } } function resolveLayoutTarget(target) { if (target instanceof HTMLElement) { if (target.matches(".planet-layout, .tarot-layout, .kab-layout")) { return target; } return target.closest(".planet-layout, .tarot-layout, .kab-layout"); } if (typeof target === "string" && target) { const element = document.getElementById(target); if (element instanceof HTMLElement) { if (element.matches(".planet-layout, .tarot-layout, .kab-layout")) { return element; } return element.querySelector(".planet-layout, .tarot-layout, .kab-layout") || element.closest(".planet-layout, .tarot-layout, .kab-layout"); } } return null; } function setSidebarCollapsed(target, collapsed, persist = true) { const layout = resolveLayoutTarget(target); const controller = layout ? sidebarControllers.get(layout) : null; if (!controller) { return false; } controller.applyCollapsedState(Boolean(collapsed), persist); return true; } function setDetailCollapsed(target, collapsed, persist = true) { const layout = resolveLayoutTarget(target); const controller = layout ? detailControllers.get(layout) : null; if (!controller) { return false; } controller.applyCollapsedState(Boolean(collapsed), persist); return true; } function showDetailOnly(target, persist = true) { const layout = resolveLayoutTarget(target); if (!layout) { return false; } const detailChanged = setDetailCollapsed(layout, false, persist); const sidebarChanged = setSidebarCollapsed(layout, true, persist); return detailChanged || sidebarChanged; } function showSidebarOnly(target, persist = true) { const layout = resolveLayoutTarget(target); if (!layout) { return false; } const detailChanged = setDetailCollapsed(layout, true, persist); const sidebarChanged = setSidebarCollapsed(layout, false, persist); return detailChanged || sidebarChanged; } function shouldAutoCollapseFromEvent(panel, target) { if (!(panel instanceof HTMLElement) || !(target instanceof Element) || !panel.contains(target)) { return false; } if (target.closest(AUTO_COLLAPSE_IGNORE_SELECTOR)) { return false; } return Boolean(target.closest(AUTO_COLLAPSE_ENTRY_SELECTOR)); } function scheduleAutoCollapse(layout) { if (!(layout instanceof HTMLElement)) { return; } window.requestAnimationFrame(() => { showDetailOnly(layout); }); } function initializeSidebarAutoCollapse() { const layouts = document.querySelectorAll(".planet-layout, .tarot-layout, .kab-layout"); layouts.forEach((layout) => { if (!(layout instanceof HTMLElement)) { return; } const panel = Array.from(layout.children).find((child) => ( child instanceof HTMLElement && child.matches("aside.planet-list-panel, aside.tarot-list-panel, aside.kab-tree-panel") )); if (!(panel instanceof HTMLElement) || panel.dataset.sidebarAutoCollapseReady === "1") { return; } panel.dataset.sidebarAutoCollapseReady = "1"; panel.addEventListener("click", (event) => { const target = event.target instanceof Element ? event.target : null; if (!shouldAutoCollapseFromEvent(panel, target)) { return; } scheduleAutoCollapse(layout); }); panel.addEventListener("keydown", (event) => { if (event.key !== "Enter" && event.key !== " ") { return; } const target = event.target instanceof Element ? event.target : null; if (!shouldAutoCollapseFromEvent(panel, target)) { return; } scheduleAutoCollapse(layout); }); }); } function initializeSidebarPopouts() { const layouts = document.querySelectorAll(".planet-layout, .tarot-layout, .kab-layout"); layouts.forEach((layout, index) => { if (!(layout instanceof HTMLElement)) { return; } const panel = Array.from(layout.children).find((child) => ( child instanceof HTMLElement && child.matches("aside.planet-list-panel, aside.tarot-list-panel, aside.kab-tree-panel") )); if (!(panel instanceof HTMLElement) || panel.dataset.sidebarPopoutReady === "1") { return; } const header = panel.querySelector(".planet-list-header, .tarot-list-header"); if (!(header instanceof HTMLElement)) { return; } panel.dataset.sidebarPopoutReady = "1"; const sectionId = layout.closest("section")?.id || `layout-${index + 1}`; const panelId = panel.id || `${sectionId}-entry-panel`; panel.id = panelId; const storageKey = `${SIDEBAR_COLLAPSE_STORAGE_PREFIX}${sectionId}`; const collapseBtn = document.createElement("button"); collapseBtn.type = "button"; collapseBtn.className = "sidebar-toggle-inline"; collapseBtn.textContent = "Hide Panel"; collapseBtn.setAttribute("aria-label", "Hide entry panel"); collapseBtn.setAttribute("aria-controls", panelId); header.appendChild(collapseBtn); const openBtn = document.createElement("button"); openBtn.type = "button"; openBtn.className = "sidebar-popout-open"; openBtn.textContent = "Show Panel"; openBtn.setAttribute("aria-label", "Show entry panel"); openBtn.setAttribute("aria-controls", panelId); openBtn.hidden = true; layout.appendChild(openBtn); const applyCollapsedState = (collapsed, persist = true) => { layout.classList.toggle("layout-sidebar-collapsed", collapsed); collapseBtn.setAttribute("aria-expanded", collapsed ? "false" : "true"); openBtn.setAttribute("aria-expanded", collapsed ? "false" : "true"); openBtn.hidden = !collapsed; if (persist) { saveSidebarCollapsedState(storageKey, collapsed); } }; sidebarControllers.set(layout, { applyCollapsedState, panel, collapseBtn, openBtn, storageKey }); collapseBtn.addEventListener("click", () => { showDetailOnly(layout); }); openBtn.addEventListener("click", () => { showSidebarOnly(layout); }); const storedCollapsed = loadSidebarCollapsedState(storageKey); applyCollapsedState(storedCollapsed == null ? DEFAULT_DATASET_ENTRY_COLLAPSED : storedCollapsed, false); }); } function initializeDetailPopouts() { const layouts = document.querySelectorAll(".planet-layout, .tarot-layout, .kab-layout"); layouts.forEach((layout, index) => { if (!(layout instanceof HTMLElement)) { return; } const detailPanel = Array.from(layout.children).find((child) => ( child instanceof HTMLElement && child.matches("section.planet-detail-panel, section.tarot-detail-panel, section.kab-detail-panel") )); if (!(detailPanel instanceof HTMLElement) || detailPanel.dataset.detailPopoutReady === "1") { return; } detailPanel.dataset.detailPopoutReady = "1"; const sectionId = layout.closest("section")?.id || `layout-${index + 1}`; const panelId = detailPanel.id || `${sectionId}-detail-panel`; detailPanel.id = panelId; const detailStorageKey = `${DETAIL_COLLAPSE_STORAGE_PREFIX}${sectionId}`; const sidebarStorageKey = `${SIDEBAR_COLLAPSE_STORAGE_PREFIX}${sectionId}`; const applyCollapsedState = (collapsed, persist = true) => { if (collapsed && layout.classList.contains("layout-sidebar-collapsed")) { const sidebarController = sidebarControllers.get(layout); if (sidebarController) { sidebarController.applyCollapsedState(false, persist); } else { layout.classList.remove("layout-sidebar-collapsed"); saveSidebarCollapsedState(sidebarStorageKey, false); } } layout.classList.toggle("layout-detail-collapsed", collapsed); detailPanel.setAttribute("aria-hidden", collapsed ? "true" : "false"); if (persist) { saveSidebarCollapsedState(detailStorageKey, collapsed); } }; detailControllers.set(layout, { applyCollapsedState, detailPanel, detailStorageKey }); const storedCollapsed = loadSidebarCollapsedState(detailStorageKey); const initialCollapsed = storedCollapsed == null ? DEFAULT_DATASET_DETAIL_COLLAPSED : storedCollapsed; applyCollapsedState(initialCollapsed, false); }); } function setTopbarDropdownOpen(dropdownEl, isOpen) { if (!(dropdownEl instanceof HTMLElement)) { return; } dropdownEl.classList.toggle("is-open", Boolean(isOpen)); const trigger = dropdownEl.querySelector("button[aria-haspopup='menu']"); if (trigger) { trigger.setAttribute("aria-expanded", isOpen ? "true" : "false"); } } function getTopbarElements() { const topbarEl = document.querySelector(".topbar"); const actionsEl = document.getElementById("topbar-actions"); const menuToggleEl = document.getElementById("topbar-menu-toggle"); return { topbarEl: topbarEl instanceof HTMLElement ? topbarEl : null, actionsEl: actionsEl instanceof HTMLElement ? actionsEl : null, menuToggleEl: menuToggleEl instanceof HTMLButtonElement ? menuToggleEl : null }; } function isMobileTopbarViewport() { return window.matchMedia(MOBILE_TOPBAR_MEDIA_QUERY).matches; } function setTopbarMenuOpen(isOpen) { const { topbarEl, menuToggleEl } = getTopbarElements(); if (!(topbarEl instanceof HTMLElement) || !(menuToggleEl instanceof HTMLButtonElement)) { return; } const nextOpen = Boolean(isOpen); topbarEl.classList.toggle("is-menu-open", nextOpen); menuToggleEl.setAttribute("aria-expanded", nextOpen ? "true" : "false"); menuToggleEl.textContent = nextOpen ? "Close" : "Menu"; menuToggleEl.setAttribute("aria-label", nextOpen ? "Close navigation menu" : "Open navigation menu"); if (!nextOpen) { closeTopbarDropdowns(); } } function bindTopbarMobileMenu() { const { topbarEl, actionsEl, menuToggleEl } = getTopbarElements(); if (!(topbarEl instanceof HTMLElement) || !(actionsEl instanceof HTMLElement) || !(menuToggleEl instanceof HTMLButtonElement)) { return; } if (menuToggleEl.dataset.mobileMenuReady === "1") { return; } menuToggleEl.dataset.mobileMenuReady = "1"; setTopbarMenuOpen(false); menuToggleEl.addEventListener("click", (event) => { event.stopPropagation(); const nextOpen = !topbarEl.classList.contains("is-menu-open"); setTopbarMenuOpen(nextOpen); }); actionsEl.addEventListener("click", (event) => { const button = event.target instanceof Element ? event.target.closest("button") : null; if (!(button instanceof HTMLButtonElement)) { return; } const isDropdownTrigger = button.getAttribute("aria-haspopup") === "menu"; const isMenuItem = button.getAttribute("role") === "menuitem"; if (!isDropdownTrigger || isMenuItem) { window.requestAnimationFrame(() => { if (isMobileTopbarViewport()) { setTopbarMenuOpen(false); } }); } }); document.addEventListener("click", (event) => { const clickTarget = event.target; if (!isMobileTopbarViewport()) { return; } if (clickTarget instanceof Node && topbarEl.contains(clickTarget)) { return; } setTopbarMenuOpen(false); }); window.addEventListener("resize", () => { if (!isMobileTopbarViewport()) { setTopbarMenuOpen(false); } }); document.addEventListener("keydown", (event) => { if (event.key === "Escape") { setTopbarMenuOpen(false); } }); } function closeTopbarDropdowns(exceptEl = null) { const topbarDropdownEls = Array.from(document.querySelectorAll(".topbar-dropdown")); topbarDropdownEls.forEach((dropdownEl) => { if (exceptEl && dropdownEl === exceptEl) { return; } setTopbarDropdownOpen(dropdownEl, false); }); } function bindTopbarDropdownInteractions() { const topbarDropdownEls = Array.from(document.querySelectorAll(".topbar-dropdown")); if (!topbarDropdownEls.length) { return; } topbarDropdownEls.forEach((dropdownEl) => { const trigger = dropdownEl.querySelector("button[aria-haspopup='menu']"); if (!(trigger instanceof HTMLElement)) { return; } setTopbarDropdownOpen(dropdownEl, false); dropdownEl.addEventListener("mouseenter", () => { if (isMobileTopbarViewport()) { return; } setTopbarDropdownOpen(dropdownEl, true); }); dropdownEl.addEventListener("mouseleave", () => { if (isMobileTopbarViewport()) { return; } setTopbarDropdownOpen(dropdownEl, false); }); dropdownEl.addEventListener("focusout", (event) => { const nextTarget = event.relatedTarget; if (!(nextTarget instanceof Node) || !dropdownEl.contains(nextTarget)) { setTopbarDropdownOpen(dropdownEl, false); } }); trigger.addEventListener("click", (event) => { event.stopPropagation(); const nextOpen = !dropdownEl.classList.contains("is-open"); closeTopbarDropdowns(dropdownEl); setTopbarDropdownOpen(dropdownEl, nextOpen); }); const menuItems = dropdownEl.querySelectorAll(".topbar-dropdown-menu [role='menuitem']"); menuItems.forEach((menuItem) => { menuItem.addEventListener("click", () => { closeTopbarDropdowns(); }); }); }); document.addEventListener("click", (event) => { const clickTarget = event.target; if (clickTarget instanceof Node && topbarDropdownEls.some((dropdownEl) => dropdownEl.contains(clickTarget))) { return; } closeTopbarDropdowns(); }); document.addEventListener("keydown", (event) => { if (event.key === "Escape") { closeTopbarDropdowns(); } }); } function init() { initializeSidebarPopouts(); initializeDetailPopouts(); initializeSidebarAutoCollapse(); bindTopbarMobileMenu(); bindTopbarDropdownInteractions(); } window.TarotChromeUi = { ...(window.TarotChromeUi || {}), init, initializeSidebarPopouts, initializeDetailPopouts, initializeSidebarAutoCollapse, bindTopbarMobileMenu, setSidebarCollapsed, setDetailCollapsed, showDetailOnly, showSidebarOnly, setTopbarMenuOpen, setTopbarDropdownOpen, closeTopbarDropdowns, bindTopbarDropdownInteractions }; })();