2026-03-07 01:09:00 -08:00
|
|
|
(function () {
|
2026-03-07 13:38:13 -08:00
|
|
|
"use strict";
|
|
|
|
|
|
2026-03-07 01:09:00 -08:00
|
|
|
const {
|
|
|
|
|
DAY_IN_MS,
|
|
|
|
|
getDateKey,
|
|
|
|
|
getMoonPhaseName,
|
|
|
|
|
calcPlanetaryHoursForDayAndLocation
|
|
|
|
|
} = window.TarotCalc;
|
2026-03-07 13:38:13 -08:00
|
|
|
const nowUiHelpers = window.NowUiHelpers || {};
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
typeof nowUiHelpers.findNextDecanTransition !== "function"
|
|
|
|
|
|| typeof nowUiHelpers.findNextMoonPhaseTransition !== "function"
|
|
|
|
|
|| typeof nowUiHelpers.formatCountdown !== "function"
|
|
|
|
|
|| typeof nowUiHelpers.getDisplayTarotName !== "function"
|
|
|
|
|
|| typeof nowUiHelpers.setNowCardImage !== "function"
|
|
|
|
|
|| typeof nowUiHelpers.updateNowStats !== "function"
|
|
|
|
|
) {
|
|
|
|
|
throw new Error("NowUiHelpers module must load before ui-now.js");
|
|
|
|
|
}
|
2026-03-07 01:09:00 -08:00
|
|
|
|
|
|
|
|
let moonCountdownCache = null;
|
|
|
|
|
let decanCountdownCache = null;
|
|
|
|
|
|
|
|
|
|
function updateNowPanel(referenceData, geo, elements, timeFormat = "minutes") {
|
|
|
|
|
if (!referenceData || !geo || !elements) {
|
|
|
|
|
return { dayKey: getDateKey(new Date()), skyRefreshKey: "" };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const now = new Date();
|
|
|
|
|
const dayKey = getDateKey(now);
|
|
|
|
|
|
|
|
|
|
const todayHours = calcPlanetaryHoursForDayAndLocation(now, geo);
|
|
|
|
|
const yesterday = new Date(now.getTime() - DAY_IN_MS);
|
|
|
|
|
const yesterdayHours = calcPlanetaryHoursForDayAndLocation(yesterday, geo);
|
|
|
|
|
const tomorrow = new Date(now.getTime() + DAY_IN_MS);
|
|
|
|
|
const tomorrowHours = calcPlanetaryHoursForDayAndLocation(tomorrow, geo);
|
|
|
|
|
const allHours = [...yesterdayHours, ...todayHours, ...tomorrowHours].sort(
|
|
|
|
|
(a, b) => a.start.getTime() - b.start.getTime()
|
|
|
|
|
);
|
|
|
|
|
const currentHour = allHours.find((entry) => now >= entry.start && now < entry.end);
|
|
|
|
|
const currentHourSkyKey = currentHour
|
|
|
|
|
? `${currentHour.planetId}-${currentHour.start.toISOString()}`
|
|
|
|
|
: "no-hour";
|
|
|
|
|
|
|
|
|
|
if (currentHour) {
|
|
|
|
|
const planet = referenceData.planets[currentHour.planetId];
|
|
|
|
|
elements.nowHourEl.textContent = planet
|
|
|
|
|
? `${planet.symbol} ${planet.name}`
|
|
|
|
|
: currentHour.planetId;
|
|
|
|
|
if (elements.nowHourTarotEl) {
|
|
|
|
|
const hourCardName = planet?.tarot?.majorArcana || "";
|
|
|
|
|
const hourTrumpNumber = planet?.tarot?.number;
|
|
|
|
|
elements.nowHourTarotEl.textContent = hourCardName
|
2026-03-07 13:38:13 -08:00
|
|
|
? nowUiHelpers.getDisplayTarotName(hourCardName, hourTrumpNumber)
|
2026-03-07 01:09:00 -08:00
|
|
|
: "--";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const msLeft = Math.max(0, currentHour.end.getTime() - now.getTime());
|
2026-03-07 13:38:13 -08:00
|
|
|
elements.nowCountdownEl.textContent = nowUiHelpers.formatCountdown(msLeft, timeFormat);
|
2026-03-07 01:09:00 -08:00
|
|
|
|
|
|
|
|
if (elements.nowHourNextEl) {
|
|
|
|
|
const nextHour = allHours.find(
|
|
|
|
|
(entry) => entry.start.getTime() >= currentHour.end.getTime() - 1000
|
|
|
|
|
);
|
|
|
|
|
if (nextHour) {
|
|
|
|
|
const nextPlanet = referenceData.planets[nextHour.planetId];
|
|
|
|
|
elements.nowHourNextEl.textContent = nextPlanet
|
|
|
|
|
? `> ${nextPlanet.name}`
|
|
|
|
|
: `> ${nextHour.planetId}`;
|
|
|
|
|
} else {
|
|
|
|
|
elements.nowHourNextEl.textContent = "> --";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-07 13:38:13 -08:00
|
|
|
nowUiHelpers.setNowCardImage(
|
2026-03-07 01:09:00 -08:00
|
|
|
elements.nowHourCardEl,
|
|
|
|
|
planet?.tarot?.majorArcana,
|
|
|
|
|
"Current planetary hour card",
|
|
|
|
|
planet?.tarot?.number
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
elements.nowHourEl.textContent = "--";
|
|
|
|
|
elements.nowCountdownEl.textContent = "--";
|
|
|
|
|
if (elements.nowHourTarotEl) {
|
|
|
|
|
elements.nowHourTarotEl.textContent = "--";
|
|
|
|
|
}
|
|
|
|
|
if (elements.nowHourNextEl) {
|
|
|
|
|
elements.nowHourNextEl.textContent = "> --";
|
|
|
|
|
}
|
2026-03-07 13:38:13 -08:00
|
|
|
nowUiHelpers.setNowCardImage(elements.nowHourCardEl, null, "Current planetary hour card");
|
2026-03-07 01:09:00 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const moonIllum = window.SunCalc.getMoonIllumination(now);
|
|
|
|
|
const moonPhase = getMoonPhaseName(moonIllum.phase);
|
|
|
|
|
const moonTarot = referenceData.planets.luna?.tarot?.majorArcana || "The High Priestess";
|
|
|
|
|
elements.nowMoonEl.textContent = `${moonPhase} (${Math.round(moonIllum.fraction * 100)}%)`;
|
2026-03-07 13:38:13 -08:00
|
|
|
elements.nowMoonTarotEl.textContent = nowUiHelpers.getDisplayTarotName(moonTarot, referenceData.planets.luna?.tarot?.number);
|
|
|
|
|
nowUiHelpers.setNowCardImage(
|
2026-03-07 01:09:00 -08:00
|
|
|
elements.nowMoonCardEl,
|
|
|
|
|
moonTarot,
|
|
|
|
|
"Current moon phase card",
|
|
|
|
|
referenceData.planets.luna?.tarot?.number
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!moonCountdownCache || moonCountdownCache.fromPhase !== moonPhase || now >= moonCountdownCache.changeAt) {
|
2026-03-07 13:38:13 -08:00
|
|
|
moonCountdownCache = nowUiHelpers.findNextMoonPhaseTransition(now);
|
2026-03-07 01:09:00 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (elements.nowMoonCountdownEl) {
|
|
|
|
|
if (moonCountdownCache?.changeAt) {
|
|
|
|
|
const remaining = moonCountdownCache.changeAt.getTime() - now.getTime();
|
2026-03-07 13:38:13 -08:00
|
|
|
elements.nowMoonCountdownEl.textContent = nowUiHelpers.formatCountdown(remaining, timeFormat);
|
2026-03-07 01:09:00 -08:00
|
|
|
if (elements.nowMoonNextEl) {
|
|
|
|
|
elements.nowMoonNextEl.textContent = `> ${moonCountdownCache.nextPhase}`;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
elements.nowMoonCountdownEl.textContent = "--";
|
|
|
|
|
if (elements.nowMoonNextEl) {
|
|
|
|
|
elements.nowMoonNextEl.textContent = "> --";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const sunInfo = getDecanForDate(now, referenceData.signs, referenceData.decansBySign);
|
|
|
|
|
const decanSkyKey = sunInfo?.sign
|
|
|
|
|
? `${sunInfo.sign.id}-${sunInfo.decan?.index || 1}`
|
|
|
|
|
: "no-decan";
|
|
|
|
|
if (sunInfo?.sign) {
|
|
|
|
|
const signStartDate = getSignStartDate(now, sunInfo.sign);
|
|
|
|
|
const daysSinceSignStart = (now.getTime() - signStartDate.getTime()) / DAY_IN_MS;
|
|
|
|
|
const signDegree = Math.min(29.9, Math.max(0, daysSinceSignStart));
|
2026-03-07 13:38:13 -08:00
|
|
|
const signMajorName = nowUiHelpers.getDisplayTarotName(sunInfo.sign.tarot.majorArcana, sunInfo.sign.tarot.trumpNumber);
|
2026-03-07 01:09:00 -08:00
|
|
|
elements.nowDecanEl.textContent = `${sunInfo.sign.symbol} ${sunInfo.sign.name} · ${signMajorName} (${signDegree.toFixed(1)}°)`;
|
|
|
|
|
|
|
|
|
|
const currentDecanKey = `${sunInfo.sign.id}-${sunInfo.decan?.index || 1}`;
|
|
|
|
|
if (!decanCountdownCache || decanCountdownCache.key !== currentDecanKey || now >= decanCountdownCache.changeAt) {
|
2026-03-07 13:38:13 -08:00
|
|
|
decanCountdownCache = nowUiHelpers.findNextDecanTransition(now, referenceData.signs, referenceData.decansBySign);
|
2026-03-07 01:09:00 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sunInfo.decan) {
|
|
|
|
|
const decanCardName = sunInfo.decan.tarotMinorArcana;
|
2026-03-07 13:38:13 -08:00
|
|
|
elements.nowDecanTarotEl.textContent = nowUiHelpers.getDisplayTarotName(decanCardName);
|
|
|
|
|
nowUiHelpers.setNowCardImage(elements.nowDecanCardEl, sunInfo.decan.tarotMinorArcana, "Current decan card");
|
2026-03-07 01:09:00 -08:00
|
|
|
} else {
|
|
|
|
|
const signTarotName = sunInfo.sign.tarot?.majorArcana || "--";
|
|
|
|
|
elements.nowDecanTarotEl.textContent = signTarotName === "--"
|
|
|
|
|
? "--"
|
2026-03-07 13:38:13 -08:00
|
|
|
: nowUiHelpers.getDisplayTarotName(signTarotName, sunInfo.sign.tarot?.trumpNumber);
|
|
|
|
|
nowUiHelpers.setNowCardImage(
|
2026-03-07 01:09:00 -08:00
|
|
|
elements.nowDecanCardEl,
|
|
|
|
|
sunInfo.sign.tarot?.majorArcana,
|
|
|
|
|
"Current decan card",
|
|
|
|
|
sunInfo.sign.tarot?.trumpNumber
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (elements.nowDecanCountdownEl) {
|
|
|
|
|
if (decanCountdownCache?.changeAt) {
|
|
|
|
|
const remaining = decanCountdownCache.changeAt.getTime() - now.getTime();
|
2026-03-07 13:38:13 -08:00
|
|
|
elements.nowDecanCountdownEl.textContent = nowUiHelpers.formatCountdown(remaining, timeFormat);
|
2026-03-07 01:09:00 -08:00
|
|
|
if (elements.nowDecanNextEl) {
|
2026-03-07 13:38:13 -08:00
|
|
|
elements.nowDecanNextEl.textContent = `> ${nowUiHelpers.getDisplayTarotName(decanCountdownCache.nextLabel)}`;
|
2026-03-07 01:09:00 -08:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
elements.nowDecanCountdownEl.textContent = "--";
|
|
|
|
|
if (elements.nowDecanNextEl) {
|
|
|
|
|
elements.nowDecanNextEl.textContent = "> --";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
elements.nowDecanEl.textContent = "--";
|
|
|
|
|
elements.nowDecanTarotEl.textContent = "--";
|
2026-03-07 13:38:13 -08:00
|
|
|
nowUiHelpers.setNowCardImage(elements.nowDecanCardEl, null, "Current decan card");
|
2026-03-07 01:09:00 -08:00
|
|
|
if (elements.nowDecanCountdownEl) {
|
|
|
|
|
elements.nowDecanCountdownEl.textContent = "--";
|
|
|
|
|
}
|
|
|
|
|
if (elements.nowDecanNextEl) {
|
|
|
|
|
elements.nowDecanNextEl.textContent = "> --";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-07 13:38:13 -08:00
|
|
|
nowUiHelpers.updateNowStats(referenceData, elements, now);
|
2026-03-07 01:09:00 -08:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
dayKey,
|
|
|
|
|
skyRefreshKey: `${currentHourSkyKey}|${decanSkyKey}|${moonPhase}`
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window.TarotNowUi = {
|
|
|
|
|
updateNowPanel
|
|
|
|
|
};
|
|
|
|
|
})();
|