2026-03-07 01:09:00 -08:00
( function ( ) {
const { resolveTarotCardImage , getTarotCardDisplayName , getTarotCardSearchAliases } = window . TarotCardImages || { } ;
2026-03-07 05:17:50 -08:00
const tarotHouseUi = window . TarotHouseUi || { } ;
const tarotRelationsUi = window . TarotRelationsUi || { } ;
2026-03-07 13:38:13 -08:00
const tarotCardDerivations = window . TarotCardDerivations || { } ;
const tarotDetailUi = window . TarotDetailUi || { } ;
const tarotRelationDisplay = window . TarotRelationDisplay || { } ;
2026-03-07 01:09:00 -08:00
const state = {
initialized : false ,
cards : [ ] ,
filteredCards : [ ] ,
searchQuery : "" ,
selectedCardId : "" ,
magickDataset : null ,
referenceData : null ,
monthRefsByCardId : new Map ( ) ,
courtCardByDecanId : new Map ( )
} ;
const TAROT _TRUMP _NUMBER _BY _NAME = {
"the fool" : 0 ,
fool : 0 ,
"the magus" : 1 ,
magus : 1 ,
magician : 1 ,
"the high priestess" : 2 ,
"high priestess" : 2 ,
"the empress" : 3 ,
empress : 3 ,
"the emperor" : 4 ,
emperor : 4 ,
"the hierophant" : 5 ,
hierophant : 5 ,
"the lovers" : 6 ,
lovers : 6 ,
"the chariot" : 7 ,
chariot : 7 ,
strength : 8 ,
lust : 8 ,
"the hermit" : 9 ,
hermit : 9 ,
fortune : 10 ,
"wheel of fortune" : 10 ,
justice : 11 ,
"the hanged man" : 12 ,
"hanged man" : 12 ,
death : 13 ,
temperance : 14 ,
art : 14 ,
"the devil" : 15 ,
devil : 15 ,
"the tower" : 16 ,
tower : 16 ,
"the star" : 17 ,
star : 17 ,
"the moon" : 18 ,
moon : 18 ,
"the sun" : 19 ,
sun : 19 ,
aeon : 20 ,
judgement : 20 ,
judgment : 20 ,
universe : 21 ,
world : 21 ,
"the world" : 21
} ;
const MINOR _NUMBER _WORD _BY _VALUE = {
1 : "ace" ,
2 : "two" ,
3 : "three" ,
4 : "four" ,
5 : "five" ,
6 : "six" ,
7 : "seven" ,
8 : "eight" ,
9 : "nine" ,
10 : "ten"
} ;
const HEBREW _LETTER _ALIASES = {
aleph : "alef" ,
alef : "alef" ,
heh : "he" ,
he : "he" ,
beth : "bet" ,
bet : "bet" ,
cheth : "het" ,
chet : "het" ,
kaph : "kaf" ,
kaf : "kaf" ,
peh : "pe" ,
tzaddi : "tsadi" ,
tzadi : "tsadi" ,
tsadi : "tsadi" ,
qoph : "qof" ,
qof : "qof" ,
taw : "tav" ,
tau : "tav"
} ;
const CUBE _MOTHER _CONNECTOR _BY _LETTER = {
alef : { connectorId : "above-below" , connectorName : "Above ↔ Below" } ,
mem : { connectorId : "east-west" , connectorName : "East ↔ West" } ,
shin : { connectorId : "south-north" , connectorName : "South ↔ North" }
} ;
const ELEMENT _NAME _BY _ID = {
water : "Water" ,
fire : "Fire" ,
air : "Air" ,
earth : "Earth"
} ;
const ELEMENT _HEBREW _LETTER _BY _ID = {
fire : "Yod" ,
water : "Heh" ,
air : "Vav" ,
earth : "Heh"
} ;
const ELEMENT _HEBREW _CHAR _BY _ID = {
fire : "י " ,
water : "ה" ,
air : "ו " ,
earth : "ה"
} ;
const HEBREW _LETTER _ID _BY _TETRAGRAMMATON _LETTER = {
yod : "yod" ,
heh : "he" ,
vav : "vav"
} ;
const ACE _ELEMENT _BY _CARD _NAME = {
"ace of cups" : "water" ,
"ace of wands" : "fire" ,
"ace of swords" : "air" ,
"ace of disks" : "earth"
} ;
const COURT _ELEMENT _BY _RANK = {
knight : "fire" ,
queen : "water" ,
prince : "air" ,
princess : "earth"
} ;
const SUIT _ELEMENT _BY _SUIT = {
wands : "fire" ,
cups : "water" ,
swords : "air" ,
disks : "earth"
} ;
const MINOR _RANK _NUMBER _BY _NAME = {
ace : 1 ,
two : 2 ,
three : 3 ,
four : 4 ,
five : 5 ,
six : 6 ,
seven : 7 ,
eight : 8 ,
nine : 9 ,
ten : 10
} ;
const SMALL _CARD _SIGN _BY _MODALITY _AND _SUIT = {
cardinal : {
wands : "aries" ,
cups : "cancer" ,
swords : "libra" ,
disks : "capricorn"
} ,
fixed : {
wands : "leo" ,
cups : "scorpio" ,
swords : "aquarius" ,
disks : "taurus"
} ,
mutable : {
wands : "sagittarius" ,
cups : "pisces" ,
swords : "gemini" ,
disks : "virgo"
}
} ;
function slugify ( value ) {
return String ( value || "" )
. trim ( )
. toLowerCase ( )
. replace ( /[^a-z0-9]+/g , "-" )
. replace ( /(^-|-$)/g , "" ) ;
}
function cardId ( card ) {
const suitPart = card . suit ? ` - ${ slugify ( card . suit ) } ` : "" ;
return ` ${ slugify ( card . arcana ) } ${ suitPart } - ${ slugify ( card . name ) } ` ;
}
function getElements ( ) {
return {
tarotCardListEl : document . getElementById ( "tarot-card-list" ) ,
tarotSearchInputEl : document . getElementById ( "tarot-search-input" ) ,
tarotSearchClearEl : document . getElementById ( "tarot-search-clear" ) ,
tarotCountEl : document . getElementById ( "tarot-card-count" ) ,
tarotDetailImageEl : document . getElementById ( "tarot-detail-image" ) ,
tarotDetailNameEl : document . getElementById ( "tarot-detail-name" ) ,
tarotDetailTypeEl : document . getElementById ( "tarot-detail-type" ) ,
tarotDetailSummaryEl : document . getElementById ( "tarot-detail-summary" ) ,
tarotDetailUprightEl : document . getElementById ( "tarot-detail-upright" ) ,
tarotDetailReversedEl : document . getElementById ( "tarot-detail-reversed" ) ,
tarotMetaMeaningCardEl : document . getElementById ( "tarot-meta-meaning-card" ) ,
tarotDetailMeaningEl : document . getElementById ( "tarot-detail-meaning" ) ,
tarotDetailKeywordsEl : document . getElementById ( "tarot-detail-keywords" ) ,
tarotMetaPlanetCardEl : document . getElementById ( "tarot-meta-planet-card" ) ,
tarotMetaElementCardEl : document . getElementById ( "tarot-meta-element-card" ) ,
tarotMetaTetragrammatonCardEl : document . getElementById ( "tarot-meta-tetragrammaton-card" ) ,
tarotMetaZodiacCardEl : document . getElementById ( "tarot-meta-zodiac-card" ) ,
tarotMetaCourtDateCardEl : document . getElementById ( "tarot-meta-courtdate-card" ) ,
tarotMetaHebrewCardEl : document . getElementById ( "tarot-meta-hebrew-card" ) ,
tarotMetaCubeCardEl : document . getElementById ( "tarot-meta-cube-card" ) ,
tarotMetaCalendarCardEl : document . getElementById ( "tarot-meta-calendar-card" ) ,
tarotDetailPlanetEl : document . getElementById ( "tarot-detail-planet" ) ,
tarotDetailElementEl : document . getElementById ( "tarot-detail-element" ) ,
tarotDetailTetragrammatonEl : document . getElementById ( "tarot-detail-tetragrammaton" ) ,
tarotDetailZodiacEl : document . getElementById ( "tarot-detail-zodiac" ) ,
tarotDetailCourtDateEl : document . getElementById ( "tarot-detail-courtdate" ) ,
tarotDetailHebrewEl : document . getElementById ( "tarot-detail-hebrew" ) ,
tarotDetailCubeEl : document . getElementById ( "tarot-detail-cube" ) ,
tarotDetailCalendarEl : document . getElementById ( "tarot-detail-calendar" ) ,
tarotKabPathEl : document . getElementById ( "tarot-kab-path" ) ,
tarotHouseOfCardsEl : document . getElementById ( "tarot-house-of-cards" )
} ;
}
function normalizeRelationId ( value ) {
return String ( value || "" )
. trim ( )
. toLowerCase ( )
. replace ( /[^a-z0-9]+/g , "-" )
. replace ( /(^-|-$)/g , "" ) ;
}
2026-03-07 13:38:13 -08:00
if ( typeof tarotRelationDisplay . createTarotRelationDisplay !== "function" ) {
throw new Error ( "TarotRelationDisplay.createTarotRelationDisplay is unavailable. Ensure app/ui-tarot-relation-display.js loads before app/ui-tarot.js." ) ;
}
if ( typeof tarotCardDerivations . createTarotCardDerivations !== "function" ) {
throw new Error ( "TarotCardDerivations.createTarotCardDerivations is unavailable. Ensure app/ui-tarot-card-derivations.js loads before app/ui-tarot.js." ) ;
}
if ( typeof tarotDetailUi . createTarotDetailRenderer !== "function" ) {
throw new Error ( "TarotDetailUi.createTarotDetailRenderer is unavailable. Ensure app/ui-tarot-detail.js loads before app/ui-tarot.js." ) ;
}
const tarotCardDerivationsUi = tarotCardDerivations . createTarotCardDerivations ( {
normalizeRelationId ,
normalizeTarotCardLookupName ,
toTitleCase ,
getReferenceData : ( ) => state . referenceData ,
ELEMENT _NAME _BY _ID ,
ELEMENT _HEBREW _LETTER _BY _ID ,
ELEMENT _HEBREW _CHAR _BY _ID ,
HEBREW _LETTER _ID _BY _TETRAGRAMMATON _LETTER ,
ACE _ELEMENT _BY _CARD _NAME ,
COURT _ELEMENT _BY _RANK ,
MINOR _RANK _NUMBER _BY _NAME ,
SMALL _CARD _SIGN _BY _MODALITY _AND _SUIT ,
MINOR _PLURAL _BY _RANK
} ) ;
const tarotRelationDisplayUi = tarotRelationDisplay . createTarotRelationDisplay ( {
normalizeRelationId
} ) ;
const tarotDetailRenderer = tarotDetailUi . createTarotDetailRenderer ( {
getMonthRefsByCardId : ( ) => state . monthRefsByCardId ,
getMagickDataset : ( ) => state . magickDataset ,
resolveTarotCardImage ,
getDisplayCardName ,
buildTypeLabel ,
clearChildren ,
normalizeRelationObject ,
buildElementRelationsForCard ,
buildTetragrammatonRelationsForCard ,
buildSmallCardRulershipRelation ,
buildSmallCardCourtLinkRelations ,
buildCubeRelationsForCard ,
parseMonthDayToken ,
createRelationListItem ,
findSephirahForMinorCard
} ) ;
2026-03-07 01:09:00 -08:00
function normalizeSearchValue ( value ) {
return String ( value || "" ) . trim ( ) . toLowerCase ( ) ;
}
function normalizeTarotName ( value ) {
return String ( value || "" )
. trim ( )
. toLowerCase ( )
. replace ( /\s+/g , " " ) ;
}
function normalizeTarotCardLookupName ( value ) {
const text = normalizeTarotName ( value )
. replace ( /\b(pentacles?|coins?)\b/g , "disks" ) ;
const match = text . match ( /^(\d{1,2})\s+of\s+(.+)$/i ) ;
if ( ! match ) {
return text ;
}
const numeric = Number ( match [ 1 ] ) ;
const suit = String ( match [ 2 ] || "" ) . trim ( ) ;
const rankWord = MINOR _NUMBER _WORD _BY _VALUE [ numeric ] ;
if ( ! rankWord || ! suit ) {
return text ;
}
return ` ${ rankWord } of ${ suit } ` ;
}
function getDisplayCardName ( cardOrName , trumpNumber ) {
const cardName = typeof cardOrName === "object"
? String ( cardOrName ? . name || "" )
: String ( cardOrName || "" ) ;
const resolvedTrumpNumber = typeof cardOrName === "object"
? cardOrName ? . number
: trumpNumber ;
if ( typeof getTarotCardDisplayName === "function" ) {
const display = String ( getTarotCardDisplayName ( cardName , { trumpNumber : resolvedTrumpNumber } ) || "" ) . trim ( ) ;
if ( display ) {
return display ;
}
}
return cardName . trim ( ) ;
}
function toTitleCase ( value ) {
return String ( value || "" )
. split ( " " )
. filter ( Boolean )
. map ( ( part ) => part . charAt ( 0 ) . toUpperCase ( ) + part . slice ( 1 ) )
. join ( " " ) ;
}
function buildElementRelationsForCard ( card , baseElementRelations = [ ] ) {
2026-03-07 13:38:13 -08:00
return tarotCardDerivationsUi . buildElementRelationsForCard ( card , baseElementRelations ) ;
2026-03-07 01:09:00 -08:00
}
function buildTetragrammatonRelationsForCard ( card ) {
2026-03-07 13:38:13 -08:00
return tarotCardDerivationsUi . buildTetragrammatonRelationsForCard ( card ) ;
2026-03-07 01:09:00 -08:00
}
function buildSmallCardRulershipRelation ( card ) {
2026-03-07 13:38:13 -08:00
return tarotCardDerivationsUi . buildSmallCardRulershipRelation ( card ) ;
2026-03-07 01:09:00 -08:00
}
function buildCourtCardByDecanId ( cards ) {
2026-03-07 05:17:50 -08:00
if ( typeof tarotRelationsUi . buildCourtCardByDecanId !== "function" ) {
return new Map ( ) ;
}
return tarotRelationsUi . buildCourtCardByDecanId ( cards ) ;
2026-03-07 01:09:00 -08:00
}
function buildSmallCardCourtLinkRelations ( card , relations ) {
2026-03-07 05:17:50 -08:00
if ( typeof tarotRelationsUi . buildSmallCardCourtLinkRelations !== "function" ) {
2026-03-07 01:09:00 -08:00
return [ ] ;
}
2026-03-07 05:17:50 -08:00
return tarotRelationsUi . buildSmallCardCourtLinkRelations ( card , relations , state . courtCardByDecanId ) ;
2026-03-07 01:09:00 -08:00
}
function parseMonthDayToken ( value ) {
2026-03-07 05:17:50 -08:00
if ( typeof tarotRelationsUi . parseMonthDayToken !== "function" ) {
2026-03-07 01:09:00 -08:00
return null ;
}
2026-03-07 05:17:50 -08:00
return tarotRelationsUi . parseMonthDayToken ( value ) ;
2026-03-07 01:09:00 -08:00
}
function buildMonthReferencesByCard ( referenceData , cards ) {
2026-03-07 05:17:50 -08:00
if ( typeof tarotRelationsUi . buildMonthReferencesByCard !== "function" ) {
return new Map ( ) ;
2026-03-07 01:09:00 -08:00
}
2026-03-07 05:17:50 -08:00
return tarotRelationsUi . buildMonthReferencesByCard ( referenceData , cards ) ;
2026-03-07 01:09:00 -08:00
}
function relationToSearchText ( relation ) {
if ( ! relation ) {
return "" ;
}
if ( typeof relation === "string" ) {
return relation ;
}
const relationParts = [
relation . label ,
relation . type ,
relation . id ,
relation . data && typeof relation . data === "object"
? Object . values ( relation . data ) . join ( " " )
: ""
] ;
return relationParts . filter ( Boolean ) . join ( " " ) ;
}
function buildCardSearchText ( card ) {
const displayName = getDisplayCardName ( card ) ;
const tarotAliases = typeof getTarotCardSearchAliases === "function"
? getTarotCardSearchAliases ( card ? . name , { trumpNumber : card ? . number } )
: [ ] ;
const parts = [
card . name ,
displayName ,
card . arcana ,
card . rank ,
card . suit ,
card . summary ,
... tarotAliases ,
... ( Array . isArray ( card . keywords ) ? card . keywords : [ ] ) ,
... ( Array . isArray ( card . relations ) ? card . relations . map ( relationToSearchText ) : [ ] )
] ;
return normalizeSearchValue ( parts . join ( " " ) ) ;
}
function applySearchFilter ( elements ) {
const query = normalizeSearchValue ( state . searchQuery ) ;
state . filteredCards = query
? state . cards . filter ( ( card ) => buildCardSearchText ( card ) . includes ( query ) )
: [ ... state . cards ] ;
if ( elements ? . tarotSearchClearEl ) {
elements . tarotSearchClearEl . disabled = ! query ;
}
renderList ( elements ) ;
if ( ! state . filteredCards . some ( ( card ) => card . id === state . selectedCardId ) ) {
if ( state . filteredCards . length > 0 ) {
selectCardById ( state . filteredCards [ 0 ] . id , elements ) ;
}
return ;
}
updateListSelection ( elements ) ;
}
function clearChildren ( element ) {
if ( element ) {
element . replaceChildren ( ) ;
}
}
function updateHouseSelection ( elements ) {
2026-03-07 05:17:50 -08:00
tarotHouseUi . updateSelection ? . ( elements ) ;
2026-03-07 01:09:00 -08:00
}
function renderHouseOfCards ( elements ) {
2026-03-07 05:17:50 -08:00
tarotHouseUi . render ? . ( elements ) ;
2026-03-07 01:09:00 -08:00
}
function buildTypeLabel ( card ) {
2026-03-07 13:38:13 -08:00
return tarotCardDerivationsUi . buildTypeLabel ( card ) ;
2026-03-07 01:09:00 -08:00
}
const MINOR _PLURAL _BY _RANK = {
ace : "aces" ,
two : "twos" ,
three : "threes" ,
four : "fours" ,
five : "fives" ,
six : "sixes" ,
seven : "sevens" ,
eight : "eights" ,
nine : "nines" ,
ten : "tens"
} ;
function findSephirahForMinorCard ( card , kabTree ) {
2026-03-07 13:38:13 -08:00
return tarotCardDerivationsUi . findSephirahForMinorCard ( card , kabTree ) ;
2026-03-07 01:09:00 -08:00
}
function formatRelation ( relation ) {
2026-03-07 13:38:13 -08:00
return tarotRelationDisplayUi . formatRelation ( relation ) ;
2026-03-07 01:09:00 -08:00
}
function relationKey ( relation , index ) {
2026-03-07 13:38:13 -08:00
return tarotRelationDisplayUi . relationKey ( relation , index ) ;
2026-03-07 01:09:00 -08:00
}
function normalizeRelationObject ( relation , index ) {
2026-03-07 13:38:13 -08:00
return tarotRelationDisplayUi . normalizeRelationObject ( relation , index ) ;
2026-03-07 01:09:00 -08:00
}
function formatRelationDataLines ( relation ) {
2026-03-07 13:38:13 -08:00
return tarotRelationDisplayUi . formatRelationDataLines ( relation ) ;
2026-03-07 01:09:00 -08:00
}
2026-03-07 05:17:50 -08:00
function buildCubeRelationsForCard ( card ) {
if ( typeof tarotRelationsUi . buildCubeRelationsForCard !== "function" ) {
2026-03-07 01:09:00 -08:00
return [ ] ;
}
2026-03-07 05:17:50 -08:00
return tarotRelationsUi . buildCubeRelationsForCard ( card , state . magickDataset ) ;
2026-03-07 01:09:00 -08:00
}
// Returns nav dispatch config for relations that have a corresponding section,
// null for informational-only relations.
function getRelationNavTarget ( relation ) {
2026-03-07 13:38:13 -08:00
return tarotRelationDisplayUi . getRelationNavTarget ( relation ) ;
2026-03-07 01:09:00 -08:00
}
function createRelationListItem ( relation ) {
2026-03-07 13:38:13 -08:00
return tarotRelationDisplayUi . createRelationListItem ( relation ) ;
2026-03-07 01:09:00 -08:00
}
function renderStaticRelationGroup ( targetEl , cardEl , relations ) {
2026-03-07 13:38:13 -08:00
tarotDetailRenderer . renderStaticRelationGroup ( targetEl , cardEl , relations ) ;
2026-03-07 01:09:00 -08:00
}
function renderDetail ( card , elements ) {
2026-03-07 13:38:13 -08:00
tarotDetailRenderer . renderDetail ( card , elements ) ;
2026-03-07 01:09:00 -08:00
}
function updateListSelection ( elements ) {
if ( ! elements ? . tarotCardListEl ) {
return ;
}
const buttons = elements . tarotCardListEl . querySelectorAll ( ".tarot-list-item" ) ;
buttons . forEach ( ( button ) => {
const isSelected = button . dataset . cardId === state . selectedCardId ;
button . classList . toggle ( "is-selected" , isSelected ) ;
button . setAttribute ( "aria-selected" , isSelected ? "true" : "false" ) ;
} ) ;
}
function selectCardById ( cardIdToSelect , elements ) {
const card = state . cards . find ( ( entry ) => entry . id === cardIdToSelect ) ;
if ( ! card ) {
return ;
}
state . selectedCardId = card . id ;
updateListSelection ( elements ) ;
updateHouseSelection ( elements ) ;
renderDetail ( card , elements ) ;
}
function renderList ( elements ) {
if ( ! elements ? . tarotCardListEl ) {
return ;
}
clearChildren ( elements . tarotCardListEl ) ;
state . filteredCards . forEach ( ( card ) => {
const cardDisplayName = getDisplayCardName ( card ) ;
const button = document . createElement ( "button" ) ;
button . type = "button" ;
button . className = "tarot-list-item" ;
button . dataset . cardId = card . id ;
button . setAttribute ( "role" , "option" ) ;
const nameEl = document . createElement ( "span" ) ;
nameEl . className = "tarot-list-name" ;
nameEl . textContent = cardDisplayName || card . name ;
const metaEl = document . createElement ( "span" ) ;
metaEl . className = "tarot-list-meta" ;
metaEl . textContent = buildTypeLabel ( card ) ;
button . append ( nameEl , metaEl ) ;
elements . tarotCardListEl . appendChild ( button ) ;
} ) ;
if ( elements . tarotCountEl ) {
elements . tarotCountEl . textContent = state . searchQuery
? ` ${ state . filteredCards . length } of ${ state . cards . length } cards `
: ` ${ state . cards . length } cards ` ;
}
}
function ensureTarotSection ( referenceData , magickDataset = null ) {
state . referenceData = referenceData || state . referenceData ;
if ( magickDataset ) {
state . magickDataset = magickDataset ;
}
2026-03-07 05:17:50 -08:00
tarotHouseUi . init ? . ( {
resolveTarotCardImage ,
getDisplayCardName ,
clearChildren ,
normalizeTarotCardLookupName ,
selectCardById ,
getCards : ( ) => state . cards ,
getSelectedCardId : ( ) => state . selectedCardId
} ) ;
2026-03-07 01:09:00 -08:00
const elements = getElements ( ) ;
if ( state . initialized ) {
state . monthRefsByCardId = buildMonthReferencesByCard ( referenceData , state . cards ) ;
state . courtCardByDecanId = buildCourtCardByDecanId ( state . cards ) ;
renderHouseOfCards ( elements ) ;
if ( state . selectedCardId ) {
const selected = state . cards . find ( ( card ) => card . id === state . selectedCardId ) ;
if ( selected ) {
renderDetail ( selected , elements ) ;
}
}
return ;
}
if ( ! elements . tarotCardListEl || ! elements . tarotDetailNameEl ) {
return ;
}
const databaseBuilder = window . TarotCardDatabase ? . buildTarotDatabase ;
if ( typeof databaseBuilder !== "function" ) {
return ;
}
const cards = databaseBuilder ( referenceData , magickDataset ) . map ( ( card ) => ( {
... card ,
id : cardId ( card )
} ) ) ;
state . cards = cards ;
state . monthRefsByCardId = buildMonthReferencesByCard ( referenceData , cards ) ;
state . courtCardByDecanId = buildCourtCardByDecanId ( cards ) ;
state . filteredCards = [ ... cards ] ;
renderList ( elements ) ;
renderHouseOfCards ( elements ) ;
if ( cards . length > 0 ) {
selectCardById ( cards [ 0 ] . id , elements ) ;
}
elements . tarotCardListEl . addEventListener ( "click" , ( event ) => {
const target = event . target ;
if ( ! ( target instanceof Node ) ) {
return ;
}
const button = target instanceof Element
? target . closest ( ".tarot-list-item" )
: null ;
if ( ! ( button instanceof HTMLButtonElement ) ) {
return ;
}
const selectedId = button . dataset . cardId ;
if ( ! selectedId ) {
return ;
}
selectCardById ( selectedId , elements ) ;
} ) ;
if ( elements . tarotSearchInputEl ) {
elements . tarotSearchInputEl . addEventListener ( "input" , ( ) => {
state . searchQuery = elements . tarotSearchInputEl . value || "" ;
applySearchFilter ( elements ) ;
} ) ;
}
if ( elements . tarotSearchClearEl && elements . tarotSearchInputEl ) {
elements . tarotSearchClearEl . addEventListener ( "click" , ( ) => {
elements . tarotSearchInputEl . value = "" ;
state . searchQuery = "" ;
applySearchFilter ( elements ) ;
elements . tarotSearchInputEl . focus ( ) ;
} ) ;
}
if ( elements . tarotDetailImageEl ) {
elements . tarotDetailImageEl . addEventListener ( "click" , ( ) => {
const src = elements . tarotDetailImageEl . getAttribute ( "src" ) || "" ;
if ( ! src || elements . tarotDetailImageEl . style . display === "none" ) {
return ;
}
2026-03-07 05:17:50 -08:00
window . TarotUiLightbox ? . open ? . ( src , elements . tarotDetailImageEl . alt || "Tarot card enlarged image" ) ;
2026-03-07 01:09:00 -08:00
} ) ;
}
state . initialized = true ;
}
function selectCardByTrump ( trumpNumber ) {
if ( ! state . initialized ) return ;
const el = getElements ( ) ;
const card = state . cards . find ( c => c . arcana === "Major" && c . number === trumpNumber ) ;
if ( ! card ) return ;
selectCardById ( card . id , el ) ;
const listItem = el . tarotCardListEl ? . querySelector ( ` [data-card-id=" ${ card . id } "] ` ) ;
listItem ? . scrollIntoView ( { block : "nearest" } ) ;
}
function selectCardByName ( name ) {
if ( ! state . initialized ) return ;
const el = getElements ( ) ;
const needle = normalizeTarotCardLookupName ( name ) ;
const card = state . cards . find ( ( entry ) => normalizeTarotCardLookupName ( entry . name ) === needle ) ;
if ( ! card ) return ;
selectCardById ( card . id , el ) ;
el . tarotCardListEl
? . querySelector ( ` [data-card-id=" ${ card . id } "] ` )
? . scrollIntoView ( { block : "nearest" } ) ;
}
window . TarotSectionUi = {
ensureTarotSection ,
selectCardByTrump ,
selectCardByName ,
getCards : ( ) => state . cards
} ;
} ) ( ) ;