509 lines
18 KiB
JavaScript
509 lines
18 KiB
JavaScript
(function () {
|
||
"use strict";
|
||
|
||
const PLANET_ID_TO_LABEL = {
|
||
saturn: "Saturn",
|
||
jupiter: "Jupiter",
|
||
mars: "Mars",
|
||
sol: "Sol",
|
||
venus: "Venus",
|
||
mercury: "Mercury",
|
||
luna: "Luna"
|
||
};
|
||
|
||
const MINOR_RANK_BY_PLURAL = {
|
||
aces: "Ace",
|
||
twos: "Two",
|
||
threes: "Three",
|
||
fours: "Four",
|
||
fives: "Five",
|
||
sixes: "Six",
|
||
sevens: "Seven",
|
||
eights: "Eight",
|
||
nines: "Nine",
|
||
tens: "Ten"
|
||
};
|
||
|
||
const MINOR_SUITS = ["Wands", "Cups", "Swords", "Disks"];
|
||
|
||
const DEFAULT_FOUR_QABALISTIC_WORLD_LAYERS = [
|
||
{
|
||
slot: "Yod",
|
||
letterChar: "י",
|
||
hebrewToken: "yod",
|
||
world: "Atziluth",
|
||
worldLayer: "Archetypal World (God’s Will)",
|
||
worldDescription: "World of gods or specific facets or divine qualities.",
|
||
soulLayer: "Chiah",
|
||
soulTitle: "Life Force",
|
||
soulDescription: "The Chiah is the Life Force itself and our true identity as reflection of Supreme Consciousness."
|
||
},
|
||
{
|
||
slot: "Heh",
|
||
letterChar: "ה",
|
||
hebrewToken: "he",
|
||
world: "Briah",
|
||
worldLayer: "Creative World (God’s Love)",
|
||
worldDescription: "World of archangels, executors of divine qualities.",
|
||
soulLayer: "Neshamah",
|
||
soulTitle: "Soul-Intuition",
|
||
soulDescription: "The Neshamah is the part of our soul that transcends the thinking process."
|
||
},
|
||
{
|
||
slot: "Vav",
|
||
letterChar: "ו",
|
||
hebrewToken: "vav",
|
||
world: "Yetzirah",
|
||
worldLayer: "Formative World (God’s Mind)",
|
||
worldDescription: "World of angels who work under archangelic direction.",
|
||
soulLayer: "Ruach",
|
||
soulTitle: "Intellect",
|
||
soulDescription: "The Ruach is the thinking mind that often dominates attention and identity."
|
||
},
|
||
{
|
||
slot: "Heh (final)",
|
||
letterChar: "ה",
|
||
hebrewToken: "he",
|
||
world: "Assiah",
|
||
worldLayer: "Material World (God’s Creation)",
|
||
worldDescription: "World of spirits that infuse matter and energy through specialized duties.",
|
||
soulLayer: "Nephesh",
|
||
soulTitle: "Animal Soul",
|
||
soulDescription: "The Nephesh is instinctive consciousness expressed through appetite, emotion, sex drive, and survival."
|
||
}
|
||
];
|
||
|
||
function metaCard(label, value, wide) {
|
||
const card = document.createElement("div");
|
||
card.className = wide ? "planet-meta-card kab-wide-card" : "planet-meta-card";
|
||
card.innerHTML = `<strong>${label}</strong><p class="planet-text">${value || "—"}</p>`;
|
||
return card;
|
||
}
|
||
|
||
function createNavButton(label, eventName, detail) {
|
||
const btn = document.createElement("button");
|
||
btn.type = "button";
|
||
btn.className = "kab-god-link";
|
||
btn.textContent = `${label} ↗`;
|
||
btn.addEventListener("click", () => {
|
||
document.dispatchEvent(new CustomEvent(eventName, { detail }));
|
||
});
|
||
return btn;
|
||
}
|
||
|
||
function appendLinkRow(card, buttons) {
|
||
if (!buttons?.length) return;
|
||
const row = document.createElement("div");
|
||
row.className = "kab-god-links";
|
||
buttons.forEach((button) => row.appendChild(button));
|
||
card.appendChild(row);
|
||
}
|
||
|
||
function buildPlanetLuminaryCard(planetValue, context) {
|
||
const card = metaCard("Planet / Luminary", planetValue);
|
||
const planetId = context.resolvePlanetId(planetValue);
|
||
if (planetId) {
|
||
appendLinkRow(card, [
|
||
createNavButton(`View ${PLANET_ID_TO_LABEL[planetId] || planetValue} in Planets`, "nav:planet", { planetId })
|
||
]);
|
||
return card;
|
||
}
|
||
|
||
const zodiacId = context.resolveZodiacId(planetValue);
|
||
if (zodiacId) {
|
||
appendLinkRow(card, [
|
||
createNavButton(`View ${zodiacId.charAt(0).toUpperCase() + zodiacId.slice(1)} in Zodiac`, "nav:zodiac", { signId: zodiacId })
|
||
]);
|
||
}
|
||
return card;
|
||
}
|
||
|
||
function extractMinorRank(attribution) {
|
||
const match = String(attribution || "").match(/\bthe\s+4\s+(aces|twos|threes|fours|fives|sixes|sevens|eights|nines|tens)\b/i);
|
||
if (!match) return null;
|
||
return MINOR_RANK_BY_PLURAL[(match[1] || "").toLowerCase()] || null;
|
||
}
|
||
|
||
function buildMinorTarotNames(attribution) {
|
||
const rank = extractMinorRank(attribution);
|
||
if (!rank) return [];
|
||
return MINOR_SUITS.map((suit) => `${rank} of ${suit}`);
|
||
}
|
||
|
||
function buildTarotAttributionCard(attribution) {
|
||
const card = metaCard("Tarot Attribution", attribution);
|
||
const minorCards = buildMinorTarotNames(attribution);
|
||
if (minorCards.length) {
|
||
appendLinkRow(card, minorCards.map((cardName) =>
|
||
createNavButton(cardName, "nav:tarot-trump", { cardName })
|
||
));
|
||
}
|
||
return card;
|
||
}
|
||
|
||
function buildAstrologyCard(astrology, context) {
|
||
const astroText = astrology ? `${astrology.name} (${astrology.type})` : "—";
|
||
const card = metaCard("Astrology", astroText);
|
||
if (astrology?.type === "planet") {
|
||
const planetId = context.resolvePlanetId(astrology.name);
|
||
if (planetId) {
|
||
appendLinkRow(card, [
|
||
createNavButton(`View ${PLANET_ID_TO_LABEL[planetId] || astrology.name} in Planets`, "nav:planet", { planetId })
|
||
]);
|
||
}
|
||
} else if (astrology?.type === "zodiac") {
|
||
const signId = context.resolveZodiacId(astrology.name);
|
||
if (signId) {
|
||
appendLinkRow(card, [
|
||
createNavButton(`View ${signId.charAt(0).toUpperCase() + signId.slice(1)} in Zodiac`, "nav:zodiac", { signId })
|
||
]);
|
||
}
|
||
}
|
||
return card;
|
||
}
|
||
|
||
function buildConnectsCard(path, fromName, toName) {
|
||
const card = metaCard("Connects", `${fromName} → ${toName}`);
|
||
appendLinkRow(card, [
|
||
createNavButton(`View ${fromName}`, "nav:kabbalah-path", { pathNo: Number(path.connects.from) }),
|
||
createNavButton(`View ${toName}`, "nav:kabbalah-path", { pathNo: Number(path.connects.to) })
|
||
]);
|
||
return card;
|
||
}
|
||
|
||
function buildHebrewLetterCard(letter, context) {
|
||
const label = `${letter.char || ""} ${letter.transliteration || ""} — "${letter.meaning || ""}" (${letter.letterType || ""})`;
|
||
const card = metaCard("Hebrew Letter", label);
|
||
const hebrewLetterId = context.resolveHebrewLetterId(letter.transliteration || letter.char || "");
|
||
|
||
if (hebrewLetterId) {
|
||
appendLinkRow(card, [
|
||
createNavButton(`View ${letter.transliteration || letter.char || "Letter"} in Alphabet`, "nav:alphabet", {
|
||
alphabet: "hebrew",
|
||
hebrewLetterId
|
||
})
|
||
]);
|
||
}
|
||
|
||
return card;
|
||
}
|
||
|
||
function buildFourWorldsCard(tree, activeHebrewToken, context) {
|
||
const activeToken = String(activeHebrewToken || "").trim().toLowerCase();
|
||
const worldLayers = Array.isArray(context.fourWorldLayers) && context.fourWorldLayers.length
|
||
? context.fourWorldLayers
|
||
: DEFAULT_FOUR_QABALISTIC_WORLD_LAYERS;
|
||
|
||
const card = document.createElement("div");
|
||
card.className = "planet-meta-card kab-wide-card";
|
||
|
||
const title = document.createElement("strong");
|
||
title.textContent = "Four Qabalistic Worlds & Soul Layers";
|
||
card.appendChild(title);
|
||
|
||
const stack = document.createElement("div");
|
||
stack.className = "cal-item-stack";
|
||
|
||
worldLayers.forEach((layer) => {
|
||
const row = document.createElement("div");
|
||
row.className = "cal-item-row";
|
||
|
||
const isActive = Boolean(activeToken) && activeToken === String(layer.hebrewToken || "").trim().toLowerCase();
|
||
|
||
const head = document.createElement("div");
|
||
head.className = "cal-item-head";
|
||
head.innerHTML = `
|
||
<span class="cal-item-name">${layer.slot}: ${layer.letterChar} — ${layer.world}</span>
|
||
<span class="planet-list-meta">${layer.soulLayer}</span>
|
||
`;
|
||
row.appendChild(head);
|
||
|
||
const worldLine = document.createElement("div");
|
||
worldLine.className = "planet-text";
|
||
worldLine.textContent = `${layer.worldLayer} · ${layer.worldDescription}`;
|
||
row.appendChild(worldLine);
|
||
|
||
const soulLine = document.createElement("div");
|
||
soulLine.className = "planet-text";
|
||
soulLine.textContent = `${layer.soulLayer} — ${layer.soulTitle}: ${layer.soulDescription}`;
|
||
row.appendChild(soulLine);
|
||
|
||
const buttonRow = [];
|
||
const hebrewLetterId = context.resolveHebrewLetterId(layer.hebrewToken);
|
||
if (hebrewLetterId) {
|
||
buttonRow.push(
|
||
createNavButton(`View ${layer.letterChar} in Alphabet`, "nav:alphabet", {
|
||
alphabet: "hebrew",
|
||
hebrewLetterId
|
||
})
|
||
);
|
||
}
|
||
|
||
const linkedPath = context.findPathByHebrewToken(tree, layer.hebrewToken);
|
||
if (linkedPath?.pathNumber != null) {
|
||
buttonRow.push(
|
||
createNavButton(`View Path ${linkedPath.pathNumber}`, "nav:kabbalah-path", { pathNo: Number(linkedPath.pathNumber) })
|
||
);
|
||
}
|
||
|
||
appendLinkRow(row, buttonRow);
|
||
|
||
if (isActive) {
|
||
row.style.borderColor = "#818cf8";
|
||
}
|
||
|
||
stack.appendChild(row);
|
||
});
|
||
|
||
card.appendChild(stack);
|
||
return card;
|
||
}
|
||
|
||
function splitCorrespondenceNames(value) {
|
||
return String(value || "")
|
||
.split(/,|;|·|\/|\bor\b|\band\b|\+/i)
|
||
.map((item) => item.trim())
|
||
.filter(Boolean);
|
||
}
|
||
|
||
function uniqueNames(values) {
|
||
const seen = new Set();
|
||
const output = [];
|
||
values.forEach((name) => {
|
||
const key = String(name || "").toLowerCase();
|
||
if (seen.has(key)) return;
|
||
seen.add(key);
|
||
output.push(name);
|
||
});
|
||
return output;
|
||
}
|
||
|
||
function godLinksCard(label, names, pathNo, metaText) {
|
||
const card = document.createElement("div");
|
||
card.className = "planet-meta-card";
|
||
|
||
const title = document.createElement("strong");
|
||
title.textContent = label;
|
||
card.appendChild(title);
|
||
|
||
if (metaText) {
|
||
const meta = document.createElement("p");
|
||
meta.className = "planet-text kab-god-meta";
|
||
meta.textContent = metaText;
|
||
card.appendChild(meta);
|
||
}
|
||
|
||
const row = document.createElement("div");
|
||
row.className = "kab-god-links";
|
||
|
||
names.forEach((name) => {
|
||
const btn = document.createElement("button");
|
||
btn.type = "button";
|
||
btn.className = "kab-god-link";
|
||
btn.textContent = name;
|
||
btn.addEventListener("click", () => {
|
||
document.dispatchEvent(new CustomEvent("nav:gods", {
|
||
detail: { godName: name, pathNo: Number(pathNo) }
|
||
}));
|
||
});
|
||
row.appendChild(btn);
|
||
});
|
||
|
||
card.appendChild(row);
|
||
return card;
|
||
}
|
||
|
||
function appendGodsCards(pathNo, elements, godsData) {
|
||
const gd = godsData?.[String(pathNo)];
|
||
if (!gd) return;
|
||
|
||
const hasAny = gd.greek || gd.roman || gd.egyptian || gd.egyptianPractical
|
||
|| gd.elohim || gd.archangel || gd.angelicOrder;
|
||
if (!hasAny) return;
|
||
|
||
const sep = document.createElement("div");
|
||
sep.className = "planet-meta-card kab-wide-card";
|
||
sep.innerHTML = `<strong style="color:#a1a1aa;font-size:11px;text-transform:uppercase;letter-spacing:.05em">Divine Correspondences</strong>`;
|
||
elements.detailBodyEl.appendChild(sep);
|
||
|
||
const greekNames = uniqueNames(splitCorrespondenceNames(gd.greek));
|
||
const romanNames = uniqueNames(splitCorrespondenceNames(gd.roman));
|
||
const egyptNames = uniqueNames([
|
||
...splitCorrespondenceNames(gd.egyptianPractical),
|
||
...splitCorrespondenceNames(gd.egyptian)
|
||
]);
|
||
|
||
if (greekNames.length) {
|
||
elements.detailBodyEl.appendChild(godLinksCard("Greek", greekNames, pathNo));
|
||
}
|
||
if (romanNames.length) {
|
||
elements.detailBodyEl.appendChild(godLinksCard("Roman", romanNames, pathNo));
|
||
}
|
||
if (egyptNames.length) {
|
||
elements.detailBodyEl.appendChild(godLinksCard("Egyptian", egyptNames, pathNo));
|
||
}
|
||
|
||
if (gd.elohim) {
|
||
const g = gd.elohim;
|
||
const meta = `${g.hebrew}${g.meaning ? " — " + g.meaning : ""}`;
|
||
elements.detailBodyEl.appendChild(godLinksCard(
|
||
"God Name",
|
||
uniqueNames(splitCorrespondenceNames(g.transliteration)),
|
||
pathNo,
|
||
meta
|
||
));
|
||
}
|
||
if (gd.archangel) {
|
||
const a = gd.archangel;
|
||
const meta = `${a.hebrew}`;
|
||
elements.detailBodyEl.appendChild(godLinksCard(
|
||
"Archangel",
|
||
uniqueNames(splitCorrespondenceNames(a.transliteration)),
|
||
pathNo,
|
||
meta
|
||
));
|
||
}
|
||
if (gd.angelicOrder) {
|
||
const o = gd.angelicOrder;
|
||
elements.detailBodyEl.appendChild(metaCard(
|
||
"Angelic Order",
|
||
`${o.hebrew} ${o.transliteration}${o.meaning ? " — " + o.meaning : ""}`
|
||
));
|
||
}
|
||
}
|
||
|
||
function renderSephiraDetail(context) {
|
||
const { seph, tree, elements } = context;
|
||
elements.detailNameEl.textContent = `${seph.number} · ${seph.name}`;
|
||
elements.detailSubEl.textContent =
|
||
[seph.nameHebrew, seph.translation, seph.planet].filter(Boolean).join(" · ");
|
||
|
||
elements.detailBodyEl.innerHTML = "";
|
||
elements.detailBodyEl.appendChild(buildFourWorldsCard(tree, "", context));
|
||
elements.detailBodyEl.appendChild(buildPlanetLuminaryCard(seph.planet, context));
|
||
elements.detailBodyEl.appendChild(metaCard("Intelligence", seph.intelligence));
|
||
elements.detailBodyEl.appendChild(buildTarotAttributionCard(seph.tarot));
|
||
|
||
if (seph.description) {
|
||
elements.detailBodyEl.appendChild(
|
||
metaCard(seph.name, seph.description, true)
|
||
);
|
||
}
|
||
|
||
const connected = tree.paths.filter(
|
||
(entry) => entry.connects.from === seph.number || entry.connects.to === seph.number
|
||
);
|
||
if (connected.length) {
|
||
const card = document.createElement("div");
|
||
card.className = "planet-meta-card kab-wide-card";
|
||
const chips = connected.map((entry) =>
|
||
`<span class="kab-chip" data-path="${entry.pathNumber}" role="button" tabindex="0" title="Path ${entry.pathNumber}: ${entry.tarot?.card || ""}">`
|
||
+ `${entry.hebrewLetter?.char || ""} <span class="kab-chip-sub">${entry.pathNumber}</span>`
|
||
+ `</span>`
|
||
).join("");
|
||
card.innerHTML = `<strong>Connected Paths</strong><div class="kab-chips">${chips}</div>`;
|
||
elements.detailBodyEl.appendChild(card);
|
||
|
||
card.querySelectorAll(".kab-chip[data-path]").forEach((chip) => {
|
||
const handler = () => {
|
||
const path = tree.paths.find((entry) => entry.pathNumber === Number(chip.dataset.path));
|
||
if (path && typeof context.onPathSelect === "function") {
|
||
context.onPathSelect(path);
|
||
}
|
||
};
|
||
chip.addEventListener("click", handler);
|
||
chip.addEventListener("keydown", (event) => {
|
||
if (event.key === "Enter" || event.key === " ") {
|
||
event.preventDefault();
|
||
handler();
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
appendGodsCards(seph.number, elements, context.godsData);
|
||
}
|
||
|
||
function renderPathDetail(context) {
|
||
const { path, tree, elements } = context;
|
||
const letter = path.hebrewLetter || {};
|
||
const fromName = tree.sephiroth.find((entry) => entry.number === path.connects.from)?.name || path.connects.from;
|
||
const toName = tree.sephiroth.find((entry) => entry.number === path.connects.to)?.name || path.connects.to;
|
||
const astro = path.astrology ? `${path.astrology.name} (${path.astrology.type})` : "—";
|
||
const tarotStr = path.tarot?.card
|
||
? `${path.tarot.card}${path.tarot.trumpNumber != null ? " · Trump " + path.tarot.trumpNumber : ""}`
|
||
: "—";
|
||
|
||
elements.detailNameEl.textContent =
|
||
`Path ${path.pathNumber} · ${letter.char || ""} ${letter.transliteration || ""}`;
|
||
elements.detailSubEl.textContent = [path.tarot?.card, astro].filter(Boolean).join(" · ");
|
||
|
||
elements.detailBodyEl.innerHTML = "";
|
||
elements.detailBodyEl.appendChild(buildFourWorldsCard(tree, context.activeHebrewToken, context));
|
||
elements.detailBodyEl.appendChild(buildConnectsCard(path, fromName, toName));
|
||
elements.detailBodyEl.appendChild(buildHebrewLetterCard(letter, context));
|
||
elements.detailBodyEl.appendChild(buildAstrologyCard(path.astrology, context));
|
||
|
||
const tarotMetaCard = document.createElement("div");
|
||
tarotMetaCard.className = "planet-meta-card";
|
||
const tarotLabel = document.createElement("strong");
|
||
tarotLabel.textContent = "Tarot";
|
||
tarotMetaCard.appendChild(tarotLabel);
|
||
if (path.tarot?.card && path.tarot.trumpNumber != null) {
|
||
const tarotBtn = document.createElement("button");
|
||
tarotBtn.type = "button";
|
||
tarotBtn.className = "kab-tarot-link";
|
||
tarotBtn.textContent = `${path.tarot.card} · Trump ${path.tarot.trumpNumber}`;
|
||
tarotBtn.title = "Open in Tarot section";
|
||
tarotBtn.addEventListener("click", () => {
|
||
document.dispatchEvent(new CustomEvent("kab:view-trump", {
|
||
detail: { trumpNumber: path.tarot.trumpNumber }
|
||
}));
|
||
});
|
||
tarotMetaCard.appendChild(tarotBtn);
|
||
} else {
|
||
const tarotP = document.createElement("p");
|
||
tarotP.className = "planet-text";
|
||
tarotP.textContent = tarotStr || "—";
|
||
tarotMetaCard.appendChild(tarotP);
|
||
}
|
||
elements.detailBodyEl.appendChild(tarotMetaCard);
|
||
|
||
elements.detailBodyEl.appendChild(metaCard("Intelligence", path.intelligence));
|
||
elements.detailBodyEl.appendChild(metaCard("Pillar", path.pillar));
|
||
|
||
if (path.description) {
|
||
const desc = document.createElement("div");
|
||
desc.className = "planet-meta-card kab-wide-card";
|
||
desc.innerHTML =
|
||
`<strong>Path ${path.pathNumber} — Sefer Yetzirah</strong>`
|
||
+ `<p class="planet-text">${path.description.replace(/\n/g, "<br><br>")}</p>`;
|
||
elements.detailBodyEl.appendChild(desc);
|
||
}
|
||
|
||
appendGodsCards(path.pathNumber, elements, context.godsData);
|
||
}
|
||
|
||
function renderRoseLandingIntro(roseElements) {
|
||
if (!roseElements?.detailNameEl || !roseElements?.detailSubEl || !roseElements?.detailBodyEl) {
|
||
return;
|
||
}
|
||
|
||
roseElements.detailNameEl.textContent = "Rosicrucian Cross";
|
||
roseElements.detailSubEl.textContent = "Select a Hebrew letter petal to explore a Tree path";
|
||
|
||
const introCard = document.createElement("div");
|
||
introCard.className = "planet-meta-card kab-wide-card";
|
||
introCard.innerHTML = "<strong>Interactive Path Crosswalk</strong>"
|
||
+ "<p class=\"planet-text\">Each petal maps to one of the 22 Hebrew letter paths (11-32). Click any large Hebrew letter to view astrology, tarot, and path intelligence details.</p>";
|
||
|
||
roseElements.detailBodyEl.innerHTML = "";
|
||
roseElements.detailBodyEl.appendChild(introCard);
|
||
}
|
||
|
||
window.KabbalahDetailUi = {
|
||
renderSephiraDetail,
|
||
renderPathDetail,
|
||
renderRoseLandingIntro
|
||
};
|
||
})(); |