update lots of reader fixes

This commit is contained in:
2026-07-23 00:15:21 -07:00
parent 88aaab2e00
commit c6b95e23c7
10 changed files with 510 additions and 150 deletions
+8 -1
View File
@@ -44,6 +44,7 @@ const tarotSectionEl = document.getElementById("tarot-section");
const tarotFrameSectionEl = document.getElementById("tarot-frame-section");
const tarotHouseSectionEl = document.getElementById("tarot-house-section");
const astronomySectionEl = document.getElementById("astronomy-section");
const skySectionEl = document.getElementById("sky-section");
const natalSectionEl = document.getElementById("natal-section");
const planetSectionEl = document.getElementById("planet-section");
const cyclesSectionEl = document.getElementById("cycles-section");
@@ -96,6 +97,7 @@ const openNumbersEl = document.getElementById("open-numbers");
const openNumbersBrowseEl = document.getElementById("open-numbers-browse");
const openNumbersTheoryEl = document.getElementById("open-numbers-theory");
const openZodiacEl = document.getElementById("open-zodiac");
const openSkyEl = document.getElementById("open-sky");
const openNatalEl = document.getElementById("open-natal");
const openQuizEl = document.getElementById("open-quiz");
const openGodsEl = document.getElementById("open-gods");
@@ -104,6 +106,7 @@ const latEl = document.getElementById("lat");
const lngEl = document.getElementById("lng");
const nowSkyLayerEl = document.getElementById("now-sky-layer");
const nowPanelEl = document.getElementById("now-panel");
const homeWelcomeEl = document.getElementById("home-welcome");
const nowOverlayToggleEl = document.getElementById("now-overlay-toggle");
const connectionGateEl = document.getElementById("connection-gate");
const connectionGateBaseUrlEl = document.getElementById("connection-gate-base-url");
@@ -281,7 +284,7 @@ appRuntime.init?.({
calendarVisualsUi,
homeUi,
hasTarotAccess: () => hasTarotFeatureAccess(),
shouldPollNow: () => (sectionStateUi.getActiveSection?.() || "home") === "home" && document.hidden !== true,
shouldPollNow: () => (sectionStateUi.getActiveSection?.() || "home") === "sky" && document.hidden !== true,
nowPollIntervalMs: 5 * 60 * 1000,
onStatus: (text) => setStatus(text),
services: {
@@ -554,6 +557,7 @@ sectionStateUi.init?.({
calendarEl,
monthStripEl,
nowPanelEl,
homeWelcomeEl,
settingsSectionEl,
timelineSectionEl,
calendarSectionEl,
@@ -564,6 +568,7 @@ sectionStateUi.init?.({
tarotFrameSectionEl,
tarotHouseSectionEl,
astronomySectionEl,
skySectionEl,
natalSectionEl,
planetSectionEl,
cyclesSectionEl,
@@ -615,6 +620,7 @@ sectionStateUi.init?.({
openNumbersBrowseEl,
openNumbersTheoryEl,
openZodiacEl,
openSkyEl,
openNatalEl,
openQuizEl,
openGodsEl,
@@ -739,6 +745,7 @@ navigationUi.init?.({
openNumbersBrowseEl,
openNumbersTheoryEl,
openZodiacEl,
openSkyEl,
openNatalEl,
openQuizEl,
openGodsEl,
+11
View File
@@ -126,11 +126,20 @@
function syncNowTickerState() {
if (config.shouldPollNow?.() === false) {
stopNowTicker();
config.homeUi?.clearNowSkyBackground?.();
return;
}
if (!nowInterval && referenceData && currentGeo) {
startNowTicker();
return;
}
if (nowInterval && referenceData && currentGeo) {
const now = new Date();
config.homeUi?.syncNowPanelTheme?.(now);
void config.services.updateNowPanel?.(referenceData, currentGeo, config.nowElements, currentTimeFormat);
config.calendarVisualsUi?.applyDynamicNowIndicatorVisual?.(now);
}
}
@@ -144,8 +153,10 @@
try {
const tarotAccessEnabled = config.hasTarotAccess?.() === true;
currentGeo = parseGeoInput();
if (config.shouldPollNow?.()) {
config.homeUi?.syncNowPanelTheme?.(new Date());
config.homeUi?.syncNowSkyBackground?.(currentGeo);
}
if (!referenceData || !magickDataset) {
setStatus(tarotAccessEnabled
+11 -3
View File
@@ -133,18 +133,26 @@
: undefined;
}
async function fetchJson(path) {
async function fetchJson(path, { timeoutMs = 30000 } = {}) {
if (!path) {
throw new Error("API connection is not configured.");
}
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(path, {
headers: buildRequestHeaders()
headers: buildRequestHeaders(),
signal: controller.signal
});
if (!response.ok) {
throw new Error(`Failed to load ${path} (${response.status})`);
}
return response.json();
} finally {
clearTimeout(timeoutId);
}
}
function buildObjectPath(target, pathParts, value) {
@@ -240,7 +248,7 @@
}
const activeSection = String(window.TarotSectionStateUi?.getActiveSection?.() || "home").trim();
return activeSection === "home";
return activeSection === "home" || activeSection === "sky";
}
function toApiAssetUrl(assetPath) {
+87
View File
@@ -5902,6 +5902,60 @@
font-size: 26px;
}
.alpha-text-settings-popover {
position: absolute;
top: 100%;
right: 0;
z-index: 100;
min-width: 280px;
max-width: 380px;
margin-top: 6px;
}
.alpha-text-settings-popover[hidden] {
display: none;
}
.alpha-text-settings-popover-inner {
background: #1a1a26;
border: 1px solid #3f3f46;
border-radius: 10px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
overflow: hidden;
}
.alpha-text-settings-popover-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 14px;
border-bottom: 1px solid #27272a;
color: #e4e4e7;
font-size: 13px;
}
.alpha-text-settings-close {
background: none;
border: none;
color: #a1a1aa;
font-size: 18px;
cursor: pointer;
padding: 2px 6px;
line-height: 1;
}
.alpha-text-settings-close:hover {
color: #e4e4e7;
}
.alpha-text-settings-popover .alpha-text-reader-toggle-list {
padding: 10px 14px;
}
.alpha-text-settings-popover .alpha-text-reader-toggle {
padding: 4px 0;
}
.alpha-text-search-controls--detail {
padding: 14px;
border: 1px solid #2f2f39;
@@ -6032,6 +6086,20 @@
display: none !important;
}
.planet-layout.alpha-text-global-search-only > .planet-detail-panel {
display: grid !important;
grid-template-rows: 1fr !important;
min-height: 0 !important;
overflow: auto !important;
}
.planet-layout.alpha-text-global-search-only .alpha-text-detail-body {
display: block !important;
min-height: 120px !important;
visibility: visible !important;
opacity: 1 !important;
}
@media (max-width: 1040px) {
.alpha-text-heading-tools {
grid-template-columns: 1fr;
@@ -6257,6 +6325,25 @@
box-shadow: inset 0 0 0 1px rgba(165, 180, 252, 0.22);
}
.alpha-text-verse.is-highlighted-fresh {
animation: alpha-text-verse-pulse 2.5s ease-out;
}
@keyframes alpha-text-verse-pulse {
0% {
background: rgba(99, 102, 241, 0.35);
box-shadow: inset 0 0 0 2px rgba(165, 180, 252, 0.5), 0 0 24px rgba(99, 102, 241, 0.3);
}
60% {
background: rgba(99, 102, 241, 0.2);
box-shadow: inset 0 0 0 1px rgba(165, 180, 252, 0.3), 0 0 8px rgba(99, 102, 241, 0.1);
}
100% {
background: rgba(67, 56, 202, 0.18);
box-shadow: inset 0 0 0 1px rgba(165, 180, 252, 0.22);
}
}
.alpha-text-verse:first-child {
border-top: none;
padding-top: 0;
+206 -21
View File
@@ -85,6 +85,7 @@
searchError: "",
searchRequestId: 0,
highlightedVerseId: "",
highlightedVerseFresh: false,
displayPreferencesBySource: {},
showVerseHeads: readStoredBoolean(STORAGE_KEYS.showVerseHeads, true),
showSourceOverview: readStoredBoolean(STORAGE_KEYS.showSourceOverview, true),
@@ -125,6 +126,8 @@
let showExtraCardEl;
let readerFontSizeSelectEl;
let exportButtonEl;
let settingsBtnEl;
let settingsPopoverEl;
let lexiconPopupEl;
let lexiconPopupTitleEl;
let lexiconPopupSubtitleEl;
@@ -132,6 +135,15 @@
let lexiconPopupCloseEl;
let lexiconReturnFocusEl = null;
let searchTimer = null;
function debounceRunSearch(scope) {
clearTimeout(searchTimer);
searchTimer = setTimeout(() => {
void runSearch(scope);
}, 300);
}
function normalizeId(value) {
return String(value || "")
.trim()
@@ -155,6 +167,8 @@
showExtraCardEl = document.getElementById("alpha-text-show-extra-card");
readerFontSizeSelectEl = document.getElementById("alpha-text-font-size-select");
exportButtonEl = document.querySelector("#alphabet-text-section .detail-export-btn");
settingsBtnEl = document.getElementById("alpha-text-settings-btn");
settingsPopoverEl = document.getElementById("alpha-text-settings-popover");
translationSelectEl = document.getElementById("alpha-text-translation-select");
translationControlEl = translationSelectEl?.closest?.(".alpha-text-control") || null;
compareSelectEl = document.getElementById("alpha-text-compare-select");
@@ -757,7 +771,9 @@
input.value = "";
}
state.searchQuery = "";
const keepQuery = preserveHighlight && state.searchQuery ? state.searchQuery : "";
state.searchQuery = preserveHighlight ? keepQuery : "";
state.searchResults = null;
state.searchLoading = false;
state.searchError = "";
@@ -766,8 +782,6 @@
if (!preserveHighlight) {
state.highlightedVerseId = "";
}
updateSearchControls();
}
function getSourceDisplayCapabilities(source, passage) {
@@ -1924,10 +1938,34 @@
return null;
}
const card = createCard("Search Results");
const payload = state.searchResults;
const totalMatches = Number(payload?.totalMatches) || 0;
const scopeLabel = state.activeSearchScope === "global"
? "all texts"
: (state.searchResults?.scope?.source?.title || getSelectedSource()?.title || "current source");
: (payload?.scope?.source?.title || getSelectedSource()?.title || "current source");
const card = createCard("Search Results");
const diagnostic = document.createElement("div");
diagnostic.className = "alpha-text-search-diagnostic";
diagnostic.style.cssText = "padding:12px 16px;border:2px solid #ef4444;border-radius:8px;margin-bottom:12px;font-size:13px;line-height:1.6;color:#fca5a5;background:#1a0a0a";
const lines = [
`<strong>Query:</strong> <em>"${state.searchQuery || "--"}"</em>`,
`<strong>Scope:</strong> ${scopeLabel}`,
state.searchLoading
? `<strong>Status:</strong> Searching...`
: state.searchError
? `<strong>Status:</strong> <span style="color:#f87171">Error: ${state.searchError}</span>`
: totalMatches > 0
? `<strong>Status:</strong> Found <strong>${totalMatches}</strong> match${totalMatches !== 1 ? "es" : ""}${payload?.truncated ? ` (showing ${payload.resultCount})` : ""}`
: `<strong>Status:</strong> No matches found`,
payload ? `<strong>API Response:</strong> totalMatches=${totalMatches} resultCount=${payload.resultCount} truncated=${payload.truncated} results.length=${Array.isArray(payload.results) ? payload.results.length : "N/A"}` : "",
``
].filter(Boolean);
diagnostic.innerHTML = lines.join("<br>");
card.appendChild(diagnostic);
const summary = document.createElement("p");
summary.className = "alpha-text-search-summary";
@@ -1957,12 +1995,19 @@
return card;
}
const payload = state.searchResults;
const totalMatches = Number(payload?.totalMatches) || 0;
const truncatedNote = payload?.truncated ? ` Showing the first ${payload.resultCount} results.` : "";
summary.textContent = `${totalMatches} matches in ${scopeLabel}.${truncatedNote}`;
summary.textContent = "";
card.append(summary, actions);
if (state.searchLoading) {
card.appendChild(createEmptyMessage("Searching..."));
return card;
}
if (state.searchError) {
card.appendChild(createEmptyMessage(state.searchError));
return card;
}
if (!Array.isArray(payload?.results) || !payload.results.length) {
card.appendChild(createEmptyMessage(`No matches found for \"${state.searchQuery}\".`));
return card;
@@ -2027,7 +2072,18 @@
const globalSearchOnlyMode = isGlobalSearchOnlyMode();
setGlobalSearchHeadingMode(globalSearchOnlyMode);
if (!source || !work || !section) {
if (!detailBodyEl) {
return;
}
if (!globalSearchOnlyMode && (!source || !work || !section)) {
if (state.searchQuery) {
const fallbackCard = createCard("Search");
fallbackCard.appendChild(createEmptyMessage(`Searching for "${state.searchQuery}"...`));
detailBodyEl.replaceChildren();
detailBodyEl.appendChild(fallbackCard);
return;
}
renderPlaceholder("Text Reader", "Select a source to begin", "Choose a text source and section from the left panel.");
renderLexiconPopup();
return;
@@ -2047,11 +2103,99 @@
return;
}
detailBodyEl.replaceChildren();
if (globalSearchOnlyMode) {
const existing = document.getElementById("alpha-text-search-overlay");
if (existing) {
existing.remove();
}
if (!state.searchResults && !state.searchError && state.searchLoading) {
return;
}
const banner = document.createElement("div");
banner.id = "alpha-text-search-overlay";
banner.style.cssText = "position:fixed;inset:0;z-index:9999;background:#0c0c12;overflow:auto;padding:24px";
const header = document.createElement("div");
header.style.cssText = "margin-bottom:16px;display:flex;align-items:center;justify-content:space-between";
const title = document.createElement("h2");
title.style.cssText = "color:#e4e4e7;margin:0;font-size:20px";
title.textContent = state.searchQuery ? `Search: "${state.searchQuery}"` : "Search Results";
const closeBtn = document.createElement("button");
closeBtn.type = "button";
closeBtn.textContent = "✕ Close";
closeBtn.style.cssText = "padding:8px 16px;border:1px solid #3f3f46;border-radius:6px;background:#18181b;color:#d4d4d8;cursor:pointer";
closeBtn.addEventListener("click", () => {
banner.remove();
clearTimeout(searchTimer);
clearSearchState();
clearScopedSearch("global");
clearScopedSearch("source");
state.searchRequestId += 1;
setGlobalSearchHeadingMode(false);
void loadSelectedPassage();
});
header.append(title, closeBtn);
const content = document.createElement("div");
if (state.searchLoading) {
content.textContent = "Searching...";
content.style.cssText = "color:#a1a1aa;padding:24px;text-align:center";
} else if (state.searchError) {
content.textContent = state.searchError;
content.style.cssText = "color:#f87171;padding:24px";
} else if (state.searchResults) {
const p = state.searchResults;
const summary = document.createElement("p");
summary.style.cssText = "color:#a1a1aa;margin:0 0 16px";
const matchCount = p.truncated ? p.resultCount : p.totalMatches;
summary.textContent = `${matchCount}${p.truncated ? "+" : ""} match${matchCount !== 1 ? "es" : ""}`;
content.appendChild(summary);
if (Array.isArray(p.results)) {
p.results.forEach((r) => {
const btn = document.createElement("button");
btn.type = "button";
const isActive = normalizeId(r?.sourceId) === normalizeId(state.selectedSourceId)
&& normalizeId(r?.workId) === normalizeId(state.selectedWorkId)
&& normalizeId(r?.sectionId) === normalizeId(state.selectedSectionId)
&& normalizeId(r?.verseId) === normalizeId(state.highlightedVerseId);
btn.style.cssText = "display:block;width:100%;text-align:left;padding:10px 14px;margin-bottom:8px;border:2px solid "
+ (isActive ? "#818cf8" : "#3f3f46")
+ ";border-radius:8px;background:" + (isActive ? "rgba(99,102,241,0.15)" : "#18181b")
+ ";color:#d4d4d8;cursor:pointer";
const refEl = document.createElement("strong");
refEl.textContent = r.reference || "";
btn.appendChild(refEl);
btn.appendChild(document.createElement("br"));
const previewEl = document.createElement("small");
appendHighlightedText(previewEl, (r.preview || "").slice(0, 200), state.searchQuery);
btn.appendChild(previewEl);
btn.addEventListener("click", () => {
state.highlightedVerseFresh = true;
banner.remove();
void openSearchResult(r);
});
content.appendChild(btn);
});
}
} else {
content.textContent = "No results.";
content.style.cssText = "color:#a1a1aa;padding:24px";
}
banner.append(header, content);
document.body.appendChild(banner);
return;
}
const searchCard = createSearchCard();
if (searchCard) {
if (searchCard && (globalSearchOnlyMode || state.searchLoading)) {
detailBodyEl.replaceChildren();
detailBodyEl.appendChild(searchCard);
return;
}
if (globalSearchOnlyMode) {
@@ -2059,6 +2203,8 @@
return;
}
detailBodyEl.replaceChildren();
if (!state.currentPassage) {
const loadingCard = createCard("Text Reader");
loadingCard.appendChild(createEmptyMessage("Loading section…"));
@@ -2160,7 +2306,19 @@
renderDetail();
if (state.highlightedVerseId) {
requestAnimationFrame(scrollHighlightedVerseIntoView);
requestAnimationFrame(() => {
scrollHighlightedVerseIntoView();
if (state.highlightedVerseFresh) {
const verseEl = detailBodyEl?.querySelector?.(".alpha-text-verse.is-highlighted");
if (verseEl instanceof HTMLElement) {
verseEl.classList.add("is-highlighted-fresh");
setTimeout(() => {
verseEl.classList.remove("is-highlighted-fresh");
}, 2600);
}
state.highlightedVerseFresh = false;
}
});
}
}
@@ -2185,15 +2343,13 @@
updateSearchControls();
if (!query) {
clearSearchState();
state.searchLoading = false;
state.searchError = `Search query is empty (scope: ${normalizedScope}, input: ${getSearchInput(normalizedScope) ? "found" : "missing"}, stored: "${getStoredSearchQuery(normalizedScope) || "none"}")`;
state.searchResults = null;
renderDetail();
return;
}
if (normalizedScope === "global" || normalizedScope === "source") {
showDetailOnlyMode();
}
const requestId = state.searchRequestId + 1;
state.searchRequestId = requestId;
state.searchLoading = true;
@@ -2242,7 +2398,7 @@
showDetailOnlyMode();
await loadSelectedPassage();
clearActiveSearchUi({ preserveHighlight: true });
renderDetail();
updateSearchControls();
}
function bindControls() {
@@ -2253,7 +2409,7 @@
if (globalSearchFormEl instanceof HTMLFormElement) {
globalSearchFormEl.addEventListener("submit", (event) => {
event.preventDefault();
void runSearch("global");
debounceRunSearch("global");
});
}
@@ -2278,7 +2434,7 @@
if (localSearchFormEl instanceof HTMLFormElement) {
localSearchFormEl.addEventListener("submit", (event) => {
event.preventDefault();
void runSearch("source");
void debounceRunSearch("source");
});
}
@@ -2441,6 +2597,35 @@
});
}
if (settingsBtnEl instanceof HTMLButtonElement && settingsPopoverEl instanceof HTMLElement) {
settingsBtnEl.addEventListener("click", () => {
const isOpen = settingsPopoverEl.hidden === false;
settingsPopoverEl.hidden = isOpen;
settingsBtnEl.setAttribute("aria-expanded", isOpen ? "false" : "true");
});
const closeBtn = settingsPopoverEl.querySelector(".alpha-text-settings-close");
if (closeBtn instanceof HTMLButtonElement) {
closeBtn.addEventListener("click", () => {
settingsPopoverEl.hidden = true;
settingsBtnEl.setAttribute("aria-expanded", "false");
});
}
document.addEventListener("click", (event) => {
if (settingsPopoverEl.hidden) {
return;
}
const target = event.target;
if (target instanceof Node) {
if (!settingsPopoverEl.contains(target) && target !== settingsBtnEl) {
settingsPopoverEl.hidden = true;
settingsBtnEl.setAttribute("aria-expanded", "false");
}
}
});
}
state.initialized = true;
}
+72 -35
View File
@@ -488,62 +488,99 @@
throw new Error("Detail pane is not ready to export.");
}
exportClone.querySelectorAll(".detail-pane-export-controls").forEach((node) => node.remove());
exportClone.querySelectorAll(".detail-sequence-btn:not(.detail-export-btn)").forEach((node) => { node.style.display = "none"; });
exportClone.querySelectorAll(".detail-sequence-position").forEach((node) => { node.style.display = "none"; });
exportClone.querySelectorAll(".alpha-text-reader-nav-btn").forEach((node) => { node.style.display = "none"; });
exportClone.querySelectorAll(".alpha-text-reader-panel").forEach((node) => { node.style.display = "none"; });
const exportStripSelectors = [
".detail-sequence-nav",
".detail-pane-export-controls",
".alpha-text-reader-nav-btn",
".alpha-text-reader-panel",
".alpha-text-heading-tools",
".alpha-text-search-controls",
".alpha-text-controls--heading",
".alpha-text-reader-toggle-control",
".alpha-text-compare-toggle",
".alpha-text-translation-select",
".alpha-text-compare-select",
".alpha-text-work-select",
".alpha-text-section-select",
".planet-detail-summary"
];
const contentWidth = Math.max(
320,
Math.ceil(detailPanel.clientWidth || detailPanel.getBoundingClientRect().width || 0)
);
const contentHeight = Math.max(
240,
Math.ceil(detailPanel.scrollHeight || detailPanel.getBoundingClientRect().height || 0)
);
exportStripSelectors.forEach((selector) => {
exportClone.querySelectorAll(selector).forEach((node) => node.remove());
});
exportClone.querySelectorAll("*").forEach((node) => {
if (node instanceof HTMLElement && node.hidden) {
node.remove();
}
});
exportClone.style.position = "fixed";
exportClone.style.left = "-100000px";
exportClone.style.top = "0";
exportClone.style.visibility = "hidden";
exportClone.style.width = "max-content";
exportClone.style.maxWidth = "900px";
exportClone.style.minWidth = "280px";
exportClone.style.height = "auto";
exportClone.style.overflow = "visible";
exportClone.style.padding = "24px";
exportClone.style.boxSizing = "border-box";
document.body.appendChild(exportClone);
const measureWidth = Math.ceil(exportClone.getBoundingClientRect().width || 280);
document.body.removeChild(exportClone);
exportClone.style.position = "";
exportClone.style.left = "";
exportClone.style.top = "";
exportClone.style.visibility = "";
sandboxEl = document.createElement("div");
sandboxEl.style.position = "fixed";
sandboxEl.style.left = "-100000px";
sandboxEl.style.top = "0";
sandboxEl.style.width = `${contentWidth}px`;
sandboxEl.style.height = `${contentHeight}px`;
sandboxEl.style.overflow = "hidden";
sandboxEl.style.pointerEvents = "none";
sandboxEl.style.opacity = "0";
exportClone.style.width = `${contentWidth}px`;
exportClone.style.minWidth = `${contentWidth}px`;
exportClone.style.maxWidth = `${contentWidth}px`;
exportClone.style.height = `${contentHeight}px`;
exportClone.style.minHeight = `${contentHeight}px`;
exportClone.style.maxHeight = `${contentHeight}px`;
exportClone.style.width = `${measureWidth}px`;
exportClone.style.minWidth = "";
exportClone.style.maxWidth = "";
exportClone.style.height = "auto";
exportClone.style.minHeight = "";
exportClone.style.maxHeight = "";
exportClone.style.overflow = "visible";
exportClone.style.padding = "24px";
exportClone.style.boxSizing = "border-box";
sandboxEl.appendChild(exportClone);
document.body.appendChild(sandboxEl);
const exportScale = Math.max(2, Math.min(2.5, Number(window.devicePixelRatio) || 1));
const exportScale = 2;
const canvas = await html2canvas(exportClone, {
backgroundColor: null,
backgroundColor: "#0c0c12",
scale: exportScale,
useCORS: true,
allowTaint: false,
logging: false,
width: contentWidth,
height: contentHeight,
windowWidth: contentWidth,
windowHeight: contentHeight,
scrollX: 0,
scrollY: 0,
imageTimeout: 12000,
onclone(clonedDocument) {
clonedDocument.querySelectorAll(".detail-pane-export-controls").forEach((node) => node.remove());
clonedDocument.querySelectorAll(".detail-sequence-btn:not(.detail-export-btn)").forEach((node) => { node.style.display = "none"; });
clonedDocument.querySelectorAll(".detail-sequence-position").forEach((node) => { node.style.display = "none"; });
clonedDocument.querySelectorAll(".alpha-text-reader-nav-btn").forEach((node) => { node.style.display = "none"; });
clonedDocument.querySelectorAll(".alpha-text-reader-panel").forEach((node) => { node.style.display = "none"; });
clonedDocument.querySelectorAll(
".detail-sequence-nav, .detail-pane-export-controls, .alpha-text-reader-nav-btn, .alpha-text-reader-panel, .alpha-text-heading-tools, .alpha-text-search-controls, .alpha-text-controls--heading, .alpha-text-reader-toggle-control, .alpha-text-compare-toggle, .planet-detail-summary"
).forEach((node) => node.remove());
clonedDocument.querySelectorAll("*").forEach((node) => {
if (node instanceof HTMLElement && node.hidden) {
node.remove();
}
});
const detailClone = clonedDocument.querySelector(".planet-detail-panel, .tarot-detail-panel, .kab-detail-panel");
if (detailClone instanceof HTMLElement) {
detailClone.style.padding = "24px";
detailClone.style.boxSizing = "border-box";
detailClone.style.width = "max-content";
detailClone.style.maxWidth = "900px";
detailClone.style.minWidth = "280px";
}
}
});
+3 -2
View File
@@ -81,7 +81,7 @@
return;
}
nowSkyLayerEl.removeAttribute("src");
nowSkyLayerEl.src = "about:blank";
lastNowSkyGeoKey = "";
lastNowSkySourceUrl = "";
}
@@ -164,6 +164,7 @@
...(window.TarotHomeUi || {}),
init,
syncNowSkyBackground,
syncNowPanelTheme
syncNowPanelTheme,
clearNowSkyBackground
};
})();
+4
View File
@@ -249,6 +249,10 @@
setActiveSection(getActiveSection() === "zodiac" ? "home" : "zodiac");
});
bindClick(elements.openSkyEl, () => {
setActiveSection(getActiveSection() === "sky" ? "home" : "sky");
});
bindClick(elements.openNatalEl, () => {
setActiveSection(getActiveSection() === "natal" ? "home" : "natal");
});
+6 -3
View File
@@ -15,6 +15,7 @@
"astronomy",
"planets",
"cycles",
"sky",
"natal",
"elements",
"iching",
@@ -78,7 +79,6 @@
requestAnimationFrame(() => {
config.calendar?.render?.();
config.calendarVisualsUi?.updateMonthStrip?.();
config.homeUi?.syncNowPanelTheme?.(new Date());
});
}
@@ -116,11 +116,12 @@
const isTarotHouseOpen = activeSection === "tarot-house";
const isTarotMenuOpen = isTarotOpen || isTarotFrameOpen || isTarotHouseOpen;
const isAstronomyOpen = activeSection === "astronomy";
const isSkyOpen = activeSection === "sky";
const isPlanetOpen = activeSection === "planets";
const isCyclesOpen = activeSection === "cycles";
const isNatalOpen = activeSection === "natal";
const isZodiacOpen = activeSection === "zodiac";
const isAstronomyMenuOpen = isAstronomyOpen || isPlanetOpen || isCyclesOpen || isZodiacOpen || isNatalOpen;
const isAstronomyMenuOpen = isAstronomyOpen || isPlanetOpen || isCyclesOpen || isZodiacOpen || isNatalOpen || isSkyOpen;
const isElementsOpen = activeSection === "elements";
const isIChingOpen = activeSection === "iching";
const isKabbalahOpen = activeSection === "kabbalah";
@@ -149,6 +150,7 @@
setHidden(elements.tarotFrameSectionEl, !isTarotFrameOpen);
setHidden(elements.tarotHouseSectionEl, !isTarotHouseOpen);
setHidden(elements.astronomySectionEl, !isAstronomyOpen);
setHidden(elements.skySectionEl, !isSkyOpen);
setHidden(elements.planetSectionEl, !isPlanetOpen);
setHidden(elements.cyclesSectionEl, !isCyclesOpen);
setHidden(elements.natalSectionEl, !isNatalOpen);
@@ -168,7 +170,8 @@
setHidden(elements.quizSectionEl, !isQuizOpen);
setHidden(elements.godsSectionEl, !isGodsOpen);
setHidden(elements.enochianSectionEl, !isEnochianOpen);
setHidden(elements.nowPanelEl, !isHomeOpen);
setHidden(elements.nowPanelEl, !isSkyOpen);
setHidden(elements.homeWelcomeEl, !isHomeOpen);
setPressed(elements.openHomeEl, isHomeOpen);
setPressed(elements.openSettingsEl, isSettingsOpen);
+94 -77
View File
@@ -39,6 +39,7 @@
<button id="open-natal" class="settings-trigger topbar-sub-trigger" type="button" role="menuitem">Natal Chart</button>
<button id="open-planets" class="settings-trigger topbar-sub-trigger" type="button" role="menuitem">Planet</button>
<button id="open-zodiac" class="settings-trigger topbar-sub-trigger" type="button" role="menuitem">Zodiac</button>
<button id="open-sky" class="settings-trigger topbar-sub-trigger" type="button" role="menuitem">Sky</button>
</div>
</div>
<div class="topbar-dropdown" aria-label="Audio menu">
@@ -776,11 +777,60 @@
</div>
</section>
<section id="sky-section" hidden>
<div id="now-panel">
<iframe id="now-sky-layer" aria-hidden="true" scrolling="no" allow="geolocation"></iframe>
<div class="now-panel-controls">
<label class="now-panel-toggle" for="now-overlay-toggle">
<input id="now-overlay-toggle" type="checkbox" checked />
<span>Show Overlay</span>
</label>
</div>
<div class="now-panel-square">
<div class="now-section now-section-hour">
<div class="now-title">Current Planetary Hour</div>
<img id="now-hour-card" class="now-card" alt="Current planetary hour card" />
<div id="now-hour" class="now-primary now-primary-hour">--</div>
<div id="now-hour-tarot" class="now-tarot">--</div>
<div class="now-countdown-row">
<span id="now-countdown" class="now-countdown-value">--</span>
<span id="now-hour-next" class="now-countdown-next">> --</span>
</div>
</div>
<div class="now-section now-section-moon">
<div class="now-title">Moon Phase</div>
<img id="now-moon-card" class="now-card" alt="Current moon phase card" />
<div id="now-moon" class="now-primary now-primary-moon">--</div>
<div id="now-moon-tarot" class="now-tarot">--</div>
<div class="now-countdown-row">
<span id="now-moon-countdown" class="now-countdown-value">--</span>
<span id="now-moon-next" class="now-countdown-next">> --</span>
</div>
</div>
<div class="now-section now-section-decan">
<div class="now-title">Current Decan (Sun)</div>
<img id="now-decan-card" class="now-card" alt="Current decan card" />
<div id="now-decan" class="now-primary now-primary-decan">--</div>
<div id="now-decan-tarot" class="now-tarot">--</div>
<div class="now-countdown-row">
<span id="now-decan-countdown" class="now-countdown-value">--</span>
<span id="now-decan-next" class="now-countdown-next">> --</span>
</div>
</div>
<div class="now-stats-section">
<div class="now-stats-title">Planet Positions</div>
<div id="now-stats-planets" class="now-stats-planets">--</div>
<div id="now-stats-sabian" class="now-stats-sabian">--</div>
</div>
</div>
</div>
</section>
<section id="astronomy-section" hidden>
<div class="kabbalah-placeholder">
<div class="kabbalah-placeholder-card">
<strong>Astronomy</strong>
<div class="planet-text">This Astronomy landing page is intentionally blank for now. Use the Astronomy menu to open Planet, Zodiac, or Natal Chart.</div>
<div class="planet-text">Use the Astronomy menu to explore Planet, Zodiac, Natal Chart, or Sky.</div>
</div>
</div>
</section>
@@ -1116,34 +1166,15 @@
<div class="detail-sequence-nav" aria-label="Browse sections">
<div class="detail-pane-export-controls">
<button type="button" class="detail-sequence-btn detail-export-btn">Export WebP</button>
<button type="button" class="detail-sequence-btn" id="alpha-text-settings-btn" aria-label="Reader settings" aria-haspopup="true" aria-expanded="false">Settings</button>
</div>
</div>
<div class="alpha-text-heading-tools">
<div class="alpha-text-controls alpha-text-controls--heading">
<label class="alpha-text-control" for="alpha-text-translation-select" hidden>
<span>Translation</span>
<select id="alpha-text-translation-select" class="alpha-text-select" aria-label="Select text translation"></select>
</label>
<div id="alpha-text-compare-toggle-control" class="alpha-text-control alpha-text-control--toggle" hidden>
<span>Compare</span>
<button id="alpha-text-compare-toggle" class="alpha-nav-btn alpha-text-compare-toggle" type="button" aria-pressed="false">Off</button>
<div id="alpha-text-settings-popover" class="alpha-text-settings-popover" hidden aria-hidden="true">
<div class="alpha-text-settings-popover-inner">
<div class="alpha-text-settings-popover-head">
<strong>Reader Settings</strong>
<button type="button" class="alpha-text-settings-close" aria-label="Close settings">×</button>
</div>
<label class="alpha-text-control" for="alpha-text-compare-select" hidden>
<span>Compare With</span>
<select id="alpha-text-compare-select" class="alpha-text-select" aria-label="Select comparison translation"></select>
</label>
<label class="alpha-text-control" for="alpha-text-work-select">
<span>Work</span>
<select id="alpha-text-work-select" class="alpha-text-select" aria-label="Select text work"></select>
</label>
<label class="alpha-text-control" for="alpha-text-section-select">
<span>Section</span>
<select id="alpha-text-section-select" class="alpha-text-select" aria-label="Select text section"></select>
</label>
</div>
<div class="alpha-text-reader-panel alpha-text-controls alpha-text-controls--heading">
<div class="alpha-text-control alpha-text-control--toggle alpha-text-reader-toggle-control">
<span>Reader</span>
<div class="alpha-text-reader-toggle-list">
<label class="alpha-text-reader-toggle" for="alpha-text-show-verse-heads">
<input id="alpha-text-show-verse-heads" type="checkbox" checked>
@@ -1180,6 +1211,30 @@
</div>
</div>
</div>
</div>
<div class="alpha-text-heading-tools">
<div class="alpha-text-controls alpha-text-controls--heading">
<label class="alpha-text-control" for="alpha-text-translation-select" hidden>
<span>Translation</span>
<select id="alpha-text-translation-select" class="alpha-text-select" aria-label="Select text translation"></select>
</label>
<div id="alpha-text-compare-toggle-control" class="alpha-text-control alpha-text-control--toggle" hidden>
<span>Compare</span>
<button id="alpha-text-compare-toggle" class="alpha-nav-btn alpha-text-compare-toggle" type="button" aria-pressed="false">Off</button>
</div>
<label class="alpha-text-control" for="alpha-text-compare-select" hidden>
<span>Compare With</span>
<select id="alpha-text-compare-select" class="alpha-text-select" aria-label="Select comparison translation"></select>
</label>
<label class="alpha-text-control" for="alpha-text-work-select">
<span>Work</span>
<select id="alpha-text-work-select" class="alpha-text-select" aria-label="Select text work"></select>
</label>
<label class="alpha-text-control" for="alpha-text-section-select">
<span>Section</span>
<select id="alpha-text-section-select" class="alpha-text-select" aria-label="Select text section"></select>
</label>
</div>
<form id="alpha-text-local-search-form" class="alpha-text-search-controls alpha-text-search-controls--detail alpha-text-search-controls--heading">
<label class="alpha-text-control" for="alpha-text-local-search-input">
<span>Search This Source</span>
@@ -1353,49 +1408,11 @@
<div id="calendar"></div>
</section>
<div id="now-panel">
<iframe id="now-sky-layer" aria-hidden="true" scrolling="no" allow="geolocation"></iframe>
<div class="now-panel-controls">
<label class="now-panel-toggle" for="now-overlay-toggle">
<input id="now-overlay-toggle" type="checkbox" checked />
<span>Show Overlay</span>
</label>
</div>
<div class="now-panel-square">
<div class="now-section now-section-hour">
<div class="now-title">Current Planetary Hour</div>
<img id="now-hour-card" class="now-card" alt="Current planetary hour card" />
<div id="now-hour" class="now-primary now-primary-hour">--</div>
<div id="now-hour-tarot" class="now-tarot">--</div>
<div class="now-countdown-row">
<span id="now-countdown" class="now-countdown-value">--</span>
<span id="now-hour-next" class="now-countdown-next">> --</span>
</div>
</div>
<div class="now-section now-section-moon">
<div class="now-title">Moon Phase</div>
<img id="now-moon-card" class="now-card" alt="Current moon phase card" />
<div id="now-moon" class="now-primary now-primary-moon">--</div>
<div id="now-moon-tarot" class="now-tarot">--</div>
<div class="now-countdown-row">
<span id="now-moon-countdown" class="now-countdown-value">--</span>
<span id="now-moon-next" class="now-countdown-next">> --</span>
</div>
</div>
<div class="now-section now-section-decan">
<div class="now-title">Current Decan (Sun)</div>
<img id="now-decan-card" class="now-card" alt="Current decan card" />
<div id="now-decan" class="now-primary now-primary-decan">--</div>
<div id="now-decan-tarot" class="now-tarot">--</div>
<div class="now-countdown-row">
<span id="now-decan-countdown" class="now-countdown-value">--</span>
<span id="now-decan-next" class="now-countdown-next">> --</span>
</div>
</div>
<div class="now-stats-section">
<div class="now-stats-title">Planet Positions</div>
<div id="now-stats-planets" class="now-stats-planets">--</div>
<div id="now-stats-sabian" class="now-stats-sabian">--</div>
<div id="home-welcome">
<div class="kabbalah-placeholder" style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center">
<div class="kabbalah-placeholder-card">
<strong>Welcome to TaroTime</strong>
<div class="planet-text">Select a section from the top menu, or visit <strong>Astronomy &gt; Sky</strong> for the live sky view.</div>
</div>
</div>
</div>
@@ -1405,7 +1422,7 @@
<script src="node_modules/html2canvas/dist/html2canvas.min.js"></script>
<script src="app/astro-calcs.js"></script>
<script src="app/app-config.js?v=20260529-access-gating-01"></script>
<script src="app/data-service.js?v=20260601-now-polling-03"></script>
<script src="app/data-service.js?v=20260722-fetch-timeout"></script>
<script src="app/calendar-events.js"></script>
<script src="app/card-images.js?v=20260527-tarot-deck-gallery-01"></script>
<script src="app/ui-tarot-lightbox.js?v=20260608-tarot-lightbox-mobile-help-04"></script>
@@ -1453,7 +1470,7 @@
<script src="app/ui-alphabet-detail.js?v=20260531-greek-gematria-04"></script>
<script src="app/ui-alphabet-kabbalah.js"></script>
<script src="app/ui-alphabet.js?v=20260424-detail-inline-links-02"></script>
<script src="app/ui-alphabet-text.js?v=20260720-reader-extra"></script>
<script src="app/ui-alphabet-text.js?v=20260723-word-highlight"></script>
<script src="app/ui-zodiac-references.js"></script>
<script src="app/ui-zodiac.js?v=20260529-access-gating-02"></script>
<script src="app/ui-quiz-bank-builtins-domains.js"></script>
@@ -1471,14 +1488,14 @@
<script src="app/ui-tarot-spread.js"></script>
<script src="app/ui-tarot-frame.js?v=20260424-frame-export-01"></script>
<script src="app/ui-settings.js?v=20260603-detail-text-scale-01"></script>
<script src="app/ui-chrome.js?v=20260720-export-reader-panel"></script>
<script src="app/ui-navigation.js?v=20260628-numbers-theory-nav-02"></script>
<script src="app/ui-chrome.js?v=20260721-export-polish"></script>
<script src="app/ui-navigation.js?v=20260721-sky-nav"></script>
<script src="app/ui-calendar-formatting.js?v=20260307b"></script>
<script src="app/ui-calendar-visuals.js?v=20260307b"></script>
<script src="app/ui-home-calendar.js?v=20260415-stellarium-toggle-01"></script>
<script src="app/ui-section-state.js?v=20260531-now-polling-02"></script>
<script src="app/app-runtime.js?v=20260531-now-polling-02"></script>
<script src="app.js?v=20260628-numbers-theory-nav-02"></script>
<script src="app/ui-home-calendar.js?v=20260722-sky-lifecycle"></script>
<script src="app/ui-section-state.js?v=20260721-sky-section"></script>
<script src="app/app-runtime.js?v=20260722-sky-cleanup"></script>
<script src="app.js?v=20260721-sky-section"></script>
<script src="app/navigation-detail-test-harness.js?v=20260401-universal-detail-02"></script>
</body>
</html>