(function () { "use strict"; let initialized = false; let activeTarotSpread = null; let activeTarotSpreadDraw = []; let config = { ensureTarotSection: null, getReferenceData: () => null, getMagickDataset: () => null, getActiveSection: () => "home", setActiveSection: null }; const THREE_CARD_POSITIONS = [ { pos: "past", label: "Past" }, { pos: "present", label: "Present" }, { pos: "future", label: "Future" } ]; const CELTIC_CROSS_POSITIONS = [ { pos: "crown", label: "Crown" }, { pos: "out", label: "Outcome" }, { pos: "past", label: "Recent Past" }, { pos: "present", label: "Present" }, { pos: "near-fut", label: "Near Future" }, { pos: "hope", label: "Hopes & Fears" }, { pos: "chall", label: "Challenge" }, { pos: "env", label: "Environment" }, { pos: "found", label: "Foundation" }, { pos: "self", label: "Self" } ]; function getElements() { return { openTarotCardsEl: document.getElementById("open-tarot-cards"), openTarotSpreadEl: document.getElementById("open-tarot-spread"), tarotBrowseViewEl: document.getElementById("tarot-browse-view"), tarotSpreadViewEl: document.getElementById("tarot-spread-view"), tarotSpreadBackEl: document.getElementById("tarot-spread-back"), tarotSpreadBtnThreeEl: document.getElementById("tarot-spread-btn-three"), tarotSpreadBtnCelticEl: document.getElementById("tarot-spread-btn-celtic"), tarotSpreadRevealAllEl: document.getElementById("tarot-spread-reveal-all"), tarotSpreadRedrawEl: document.getElementById("tarot-spread-redraw"), tarotSpreadMeaningsEl: document.getElementById("tarot-spread-meanings"), tarotSpreadBoardEl: document.getElementById("tarot-spread-board") }; } function ensureTarotBrowseData() { const referenceData = typeof config.getReferenceData === "function" ? config.getReferenceData() : null; const magickDataset = typeof config.getMagickDataset === "function" ? config.getMagickDataset() : null; if (typeof config.ensureTarotSection === "function" && referenceData) { config.ensureTarotSection(referenceData, magickDataset); } } function normalizeTarotSpread(value) { return value === "celtic-cross" ? "celtic-cross" : "three-card"; } function drawNFromDeck(n) { const allCards = window.TarotSectionUi?.getCards?.() || []; if (!allCards.length) return []; const shuffled = [...allCards]; for (let index = shuffled.length - 1; index > 0; index -= 1) { const swapIndex = Math.floor(Math.random() * (index + 1)); [shuffled[index], shuffled[swapIndex]] = [shuffled[swapIndex], shuffled[index]]; } return shuffled.slice(0, n).map((card) => ({ ...card, reversed: Math.random() < 0.3 })); } function escapeHtml(value) { return String(value || "") .replace(/&/g, "&") .replace(//g, ">") .replace(/\"/g, """) .replace(/'/g, "'"); } function getSpreadPositions(spreadId) { return spreadId === "celtic-cross" ? CELTIC_CROSS_POSITIONS : THREE_CARD_POSITIONS; } function regenerateTarotSpreadDraw() { const normalizedSpread = normalizeTarotSpread(activeTarotSpread); const positions = getSpreadPositions(normalizedSpread); const cards = drawNFromDeck(positions.length); activeTarotSpreadDraw = positions.map((position, index) => ({ position, card: cards[index] || null, revealed: false })); } function renderTarotSpreadMeanings() { const { tarotSpreadMeaningsEl } = getElements(); if (!tarotSpreadMeaningsEl) { return; } if (!activeTarotSpreadDraw.length || activeTarotSpreadDraw.some((entry) => !entry.card)) { tarotSpreadMeaningsEl.innerHTML = ""; return; } const revealedEntries = activeTarotSpreadDraw.filter((entry) => entry.card && entry.revealed); if (!revealedEntries.length) { tarotSpreadMeaningsEl.innerHTML = '
Cards are face down. Click a card to reveal its meaning.
'; return; } const hiddenCount = activeTarotSpreadDraw.length - revealedEntries.length; const hiddenHintMarkup = hiddenCount > 0 ? `
${hiddenCount} card${hiddenCount === 1 ? "" : "s"} still face down.
` : ""; tarotSpreadMeaningsEl.innerHTML = revealedEntries.map((entry) => { const positionLabel = escapeHtml(entry.position.label).toUpperCase(); const card = entry.card; const cardName = escapeHtml(card.name || "Unknown Card"); const meaningText = escapeHtml(card.reversed ? (card.meanings?.reversed || card.summary || "--") : (card.meanings?.upright || card.summary || "--")); const keywords = Array.isArray(card.keywords) ? card.keywords.map((keyword) => String(keyword || "").trim()).filter(Boolean) : []; const keywordMarkup = keywords.length ? `
Keywords: ${escapeHtml(keywords.join(", "))}
` : ""; const orientationMarkup = card.reversed ? ' (Reversed)' : ""; return `
` + `
${positionLabel}: ${cardName}${orientationMarkup}
` + `
${meaningText}
` + keywordMarkup + `
`; }).join("") + hiddenHintMarkup; } function renderTarotSpread() { const { tarotSpreadBoardEl, tarotSpreadMeaningsEl, tarotSpreadRevealAllEl } = getElements(); if (!tarotSpreadBoardEl) { return; } const normalizedSpread = normalizeTarotSpread(activeTarotSpread); const isCeltic = normalizedSpread === "celtic-cross"; const cardBackImageSrc = String(window.TarotCardImages?.resolveTarotCardBackImage?.() || "").trim(); if (!activeTarotSpreadDraw.length) { regenerateTarotSpreadDraw(); } tarotSpreadBoardEl.className = `tarot-spread-board tarot-spread-board--${isCeltic ? "celtic" : "three"}`; if (!activeTarotSpreadDraw.length || activeTarotSpreadDraw.some((entry) => !entry.card)) { tarotSpreadBoardEl.innerHTML = '
Tarot deck not loaded yet - open Cards first, then return to Spread.
'; if (tarotSpreadMeaningsEl) { tarotSpreadMeaningsEl.innerHTML = ""; } if (tarotSpreadRevealAllEl) { tarotSpreadRevealAllEl.disabled = true; tarotSpreadRevealAllEl.textContent = "Reveal All"; } return; } if (tarotSpreadRevealAllEl) { const totalCards = activeTarotSpreadDraw.length; const revealedCount = activeTarotSpreadDraw.reduce((count, entry) => ( count + (entry?.card && entry.revealed ? 1 : 0) ), 0); tarotSpreadRevealAllEl.disabled = revealedCount >= totalCards; tarotSpreadRevealAllEl.textContent = revealedCount >= totalCards ? "All Revealed" : `Reveal All (${totalCards - revealedCount})`; } renderTarotSpreadMeanings(); tarotSpreadBoardEl.innerHTML = activeTarotSpreadDraw.map((entry, index) => { const position = entry.position; const card = entry.card; const imgSrc = window.TarotCardImages?.resolveTarotCardImage?.(card.name); const isRevealed = Boolean(entry.revealed); const cardBackAttr = cardBackImageSrc ? ` data-card-back-src="${escapeHtml(cardBackImageSrc)}"` : ""; const reversed = card.reversed; const wrapClass = [ "spread-card-wrap", isRevealed ? "is-revealed" : "is-facedown", (isRevealed && reversed) ? "is-reversed" : "" ].filter(Boolean).join(" "); let faceMarkup = ""; if (isRevealed) { faceMarkup = imgSrc ? `${escapeHtml(card.name)}` : `
${escapeHtml(card.name)}
`; } else if (cardBackImageSrc) { faceMarkup = 'Face-down tarot card'; } else { faceMarkup = '
CARD BACK
'; } const reversedTag = isRevealed && reversed ? 'Reversed' : ""; const buttonAriaLabel = isRevealed ? `Open ${escapeHtml(card.name)} for ${escapeHtml(position.label)} in fullscreen` : `Reveal ${escapeHtml(position.label)} card`; return `
` + `
${escapeHtml(position.label)}
` + `` + (reversedTag ? `
${reversedTag}
` : "") + `
`; }).join(""); } function applyViewState() { const { openTarotCardsEl, openTarotSpreadEl, tarotBrowseViewEl, tarotSpreadViewEl, tarotSpreadBtnThreeEl, tarotSpreadBtnCelticEl } = getElements(); const isSpreadOpen = activeTarotSpread !== null; const isCeltic = activeTarotSpread === "celtic-cross"; const isTarotActive = typeof config.getActiveSection === "function" && config.getActiveSection() === "tarot"; if (tarotBrowseViewEl) tarotBrowseViewEl.hidden = isSpreadOpen; if (tarotSpreadViewEl) tarotSpreadViewEl.hidden = !isSpreadOpen; if (tarotSpreadBtnThreeEl) tarotSpreadBtnThreeEl.classList.toggle("is-active", isSpreadOpen && !isCeltic); if (tarotSpreadBtnCelticEl) tarotSpreadBtnCelticEl.classList.toggle("is-active", isSpreadOpen && isCeltic); if (openTarotCardsEl) openTarotCardsEl.classList.toggle("is-active", isTarotActive && !isSpreadOpen); if (openTarotSpreadEl) openTarotSpreadEl.classList.toggle("is-active", isTarotActive && isSpreadOpen); } function showCardsView() { activeTarotSpread = null; activeTarotSpreadDraw = []; applyViewState(); ensureTarotBrowseData(); const detailPanelEl = document.querySelector("#tarot-browse-view .tarot-detail-panel"); if (detailPanelEl instanceof HTMLElement) { detailPanelEl.scrollTop = 0; } } function showTarotSpreadView(spreadId = "three-card") { activeTarotSpread = normalizeTarotSpread(spreadId); regenerateTarotSpreadDraw(); applyViewState(); ensureTarotBrowseData(); renderTarotSpread(); } function setSpread(spreadId, openTarotSection = false) { if (openTarotSection && typeof config.setActiveSection === "function") { config.setActiveSection("tarot"); } showTarotSpreadView(spreadId); } function revealAll() { if (!activeTarotSpreadDraw.length) { regenerateTarotSpreadDraw(); } activeTarotSpreadDraw.forEach((entry) => { if (entry?.card) { entry.revealed = true; } }); renderTarotSpread(); } function handleBoardClick(event) { const target = event.target; if (!(target instanceof Node)) { return; } const button = target instanceof Element ? target.closest(".spread-card-wrap[data-spread-index]") : null; if (!(button instanceof HTMLButtonElement)) { return; } const spreadIndex = Number(button.dataset.spreadIndex); if (!Number.isInteger(spreadIndex) || spreadIndex < 0 || spreadIndex >= activeTarotSpreadDraw.length) { return; } const spreadEntry = activeTarotSpreadDraw[spreadIndex]; if (!spreadEntry?.card) { return; } if (!spreadEntry.revealed) { spreadEntry.revealed = true; renderTarotSpread(); return; } const imageSrc = window.TarotCardImages?.resolveTarotCardImage?.(spreadEntry.card.name); if (imageSrc) { window.TarotUiLightbox?.open?.(imageSrc, `${spreadEntry.card.name} (${spreadEntry.position?.label || "Spread"})`); } } function bindEvents() { const { openTarotCardsEl, openTarotSpreadEl, tarotSpreadBackEl, tarotSpreadBtnThreeEl, tarotSpreadBtnCelticEl, tarotSpreadRevealAllEl, tarotSpreadRedrawEl, tarotSpreadBoardEl } = getElements(); if (openTarotCardsEl) { openTarotCardsEl.addEventListener("click", () => { if (typeof config.setActiveSection === "function") { config.setActiveSection("tarot"); } showCardsView(); }); } if (openTarotSpreadEl) { openTarotSpreadEl.addEventListener("click", () => { setSpread("three-card", true); }); } if (tarotSpreadBackEl) { tarotSpreadBackEl.addEventListener("click", () => { showCardsView(); }); } if (tarotSpreadBtnThreeEl) { tarotSpreadBtnThreeEl.addEventListener("click", () => { showTarotSpreadView("three-card"); }); } if (tarotSpreadBtnCelticEl) { tarotSpreadBtnCelticEl.addEventListener("click", () => { showTarotSpreadView("celtic-cross"); }); } if (tarotSpreadRedrawEl) { tarotSpreadRedrawEl.addEventListener("click", () => { regenerateTarotSpreadDraw(); renderTarotSpread(); }); } if (tarotSpreadRevealAllEl) { tarotSpreadRevealAllEl.addEventListener("click", revealAll); } if (tarotSpreadBoardEl) { tarotSpreadBoardEl.addEventListener("click", handleBoardClick); } } function handleSectionActivated() { ensureTarotBrowseData(); applyViewState(); if (activeTarotSpread !== null) { renderTarotSpread(); } } function init(nextConfig = {}) { config = { ...config, ...nextConfig }; if (initialized) { applyViewState(); return; } bindEvents(); applyViewState(); initialized = true; } window.TarotSpreadUi = { ...(window.TarotSpreadUi || {}), init, applyViewState, showCardsView, showTarotSpreadView, setSpread, handleSectionActivated, renderTarotSpread, isSpreadOpen() { return activeTarotSpread !== null; } }; })();