(function () { "use strict"; const HOUSE_MINOR_NUMBER_BANDS = [ [2, 3, 4], [5, 6, 7], [8, 9, 10], [2, 3, 4], [5, 6, 7], [8, 9, 10] ]; const HOUSE_LEFT_SUITS = ["Wands", "Disks", "Swords", "Cups", "Wands", "Disks"]; const HOUSE_RIGHT_SUITS = ["Swords", "Cups", "Wands", "Disks", "Swords", "Cups"]; const HOUSE_MIDDLE_SUITS = ["Wands", "Cups", "Swords", "Disks"]; const HOUSE_MIDDLE_RANKS = ["Ace", "Knight", "Queen", "Prince", "Princess"]; const HOUSE_TRUMP_ROWS = [ [0], [20, 21, 12], [19, 10, 2, 1, 3, 16], [18, 17, 15, 14, 13, 9, 8, 7, 6, 5, 4], [11] ]; const config = { resolveTarotCardImage: null, getDisplayCardName: (card) => card?.name || "", clearChildren: () => {}, normalizeTarotCardLookupName: (value) => String(value || "").trim().toLowerCase(), selectCardById: () => {}, getCards: () => [], getSelectedCardId: () => "" }; function init(nextConfig = {}) { Object.assign(config, nextConfig || {}); } function getCardLookupMap(cards) { const lookup = new Map(); (Array.isArray(cards) ? cards : []).forEach((card) => { const key = config.normalizeTarotCardLookupName(card?.name); if (key) { lookup.set(key, card); } }); return lookup; } function buildMinorCardName(rankNumber, suit) { const number = Number(rankNumber); const suitName = String(suit || "").trim(); const rankName = ({ 1: "Ace", 2: "Two", 3: "Three", 4: "Four", 5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine", 10: "Ten" })[number]; if (!rankName || !suitName) { return ""; } return `${rankName} of ${suitName}`; } function buildCourtCardName(rank, suit) { const rankName = String(rank || "").trim(); const suitName = String(suit || "").trim(); if (!rankName || !suitName) { return ""; } return `${rankName} of ${suitName}`; } function findCardByLookupName(cardLookupMap, cardName) { const key = config.normalizeTarotCardLookupName(cardName); if (!key) { return null; } return cardLookupMap.get(key) || null; } function findMajorCardByTrumpNumber(cards, trumpNumber) { const target = Number(trumpNumber); if (!Number.isFinite(target)) { return null; } return (Array.isArray(cards) ? cards : []).find((card) => card?.arcana === "Major" && Number(card?.number) === target) || null; } function createHouseCardButton(card, elements) { const button = document.createElement("button"); button.type = "button"; button.className = "tarot-house-card-btn"; if (!card) { button.disabled = true; const fallback = document.createElement("span"); fallback.className = "tarot-house-card-fallback"; fallback.textContent = "Missing"; button.appendChild(fallback); return button; } const cardDisplayName = config.getDisplayCardName(card); button.title = cardDisplayName || card.name; button.setAttribute("aria-label", cardDisplayName || card.name); button.dataset.houseCardId = card.id; const imageUrl = typeof config.resolveTarotCardImage === "function" ? config.resolveTarotCardImage(card.name) : null; if (imageUrl) { const image = document.createElement("img"); image.className = "tarot-house-card-image"; image.src = imageUrl; image.alt = cardDisplayName || card.name; button.appendChild(image); } else { const fallback = document.createElement("span"); fallback.className = "tarot-house-card-fallback"; fallback.textContent = cardDisplayName || card.name; button.appendChild(fallback); } button.addEventListener("click", () => { config.selectCardById(card.id, elements); elements?.tarotCardListEl ?.querySelector(`[data-card-id="${card.id}"]`) ?.scrollIntoView({ block: "nearest" }); }); return button; } function updateSelection(elements) { if (!elements?.tarotHouseOfCardsEl) { return; } const selectedCardId = config.getSelectedCardId(); const buttons = elements.tarotHouseOfCardsEl.querySelectorAll(".tarot-house-card-btn[data-house-card-id]"); buttons.forEach((button) => { const isSelected = button.dataset.houseCardId === selectedCardId; button.classList.toggle("is-selected", isSelected); button.setAttribute("aria-current", isSelected ? "true" : "false"); }); } function appendHouseMinorRow(columnEl, cardLookupMap, numbers, suit, elements) { const rowEl = document.createElement("div"); rowEl.className = "tarot-house-row"; numbers.forEach((rankNumber) => { const cardName = buildMinorCardName(rankNumber, suit); const card = findCardByLookupName(cardLookupMap, cardName); rowEl.appendChild(createHouseCardButton(card, elements)); }); columnEl.appendChild(rowEl); } function appendHouseCourtRow(columnEl, cardLookupMap, rank, elements) { const rowEl = document.createElement("div"); rowEl.className = "tarot-house-row"; HOUSE_MIDDLE_SUITS.forEach((suit) => { const cardName = buildCourtCardName(rank, suit); const card = findCardByLookupName(cardLookupMap, cardName); rowEl.appendChild(createHouseCardButton(card, elements)); }); columnEl.appendChild(rowEl); } function appendHouseTrumpRow(containerEl, trumpNumbers, elements, cards) { const rowEl = document.createElement("div"); rowEl.className = "tarot-house-trump-row"; (trumpNumbers || []).forEach((trumpNumber) => { const card = findMajorCardByTrumpNumber(cards, trumpNumber); rowEl.appendChild(createHouseCardButton(card, elements)); }); containerEl.appendChild(rowEl); } function render(elements) { if (!elements?.tarotHouseOfCardsEl) { return; } const cards = config.getCards(); config.clearChildren(elements.tarotHouseOfCardsEl); const cardLookupMap = getCardLookupMap(cards); const trumpSectionEl = document.createElement("div"); trumpSectionEl.className = "tarot-house-trumps"; HOUSE_TRUMP_ROWS.forEach((trumpRow) => { appendHouseTrumpRow(trumpSectionEl, trumpRow, elements, cards); }); const bottomGridEl = document.createElement("div"); bottomGridEl.className = "tarot-house-bottom-grid"; const leftColumnEl = document.createElement("div"); leftColumnEl.className = "tarot-house-column"; HOUSE_MINOR_NUMBER_BANDS.forEach((numbers, rowIndex) => { appendHouseMinorRow(leftColumnEl, cardLookupMap, numbers, HOUSE_LEFT_SUITS[rowIndex], elements); }); const middleColumnEl = document.createElement("div"); middleColumnEl.className = "tarot-house-column"; HOUSE_MIDDLE_RANKS.forEach((rank) => { appendHouseCourtRow(middleColumnEl, cardLookupMap, rank, elements); }); const rightColumnEl = document.createElement("div"); rightColumnEl.className = "tarot-house-column"; HOUSE_MINOR_NUMBER_BANDS.forEach((numbers, rowIndex) => { appendHouseMinorRow(rightColumnEl, cardLookupMap, numbers, HOUSE_RIGHT_SUITS[rowIndex], elements); }); bottomGridEl.append(leftColumnEl, middleColumnEl, rightColumnEl); elements.tarotHouseOfCardsEl.append(trumpSectionEl, bottomGridEl); updateSelection(elements); } window.TarotHouseUi = { init, render, updateSelection }; })();