updating text reader - wip
This commit is contained in:
@@ -5,6 +5,12 @@
|
||||
const deckManifestCache = new Map();
|
||||
let quizCategoriesCache = null;
|
||||
const quizTemplatesCache = new Map();
|
||||
let textLibraryCache = null;
|
||||
const textSourceCache = new Map();
|
||||
const textSectionCache = new Map();
|
||||
const textLexiconCache = new Map();
|
||||
const textLexiconOccurrencesCache = new Map();
|
||||
const textSearchCache = new Map();
|
||||
|
||||
const DATA_ROOT = "data";
|
||||
const MAGICK_ROOT = DATA_ROOT;
|
||||
@@ -219,8 +225,14 @@
|
||||
magickDataCache = null;
|
||||
deckOptionsCache = null;
|
||||
quizCategoriesCache = null;
|
||||
textLibraryCache = null;
|
||||
deckManifestCache.clear();
|
||||
quizTemplatesCache.clear();
|
||||
textSourceCache.clear();
|
||||
textSectionCache.clear();
|
||||
textLexiconCache.clear();
|
||||
textLexiconOccurrencesCache.clear();
|
||||
textSearchCache.clear();
|
||||
}
|
||||
|
||||
function normalizeTarotName(value) {
|
||||
@@ -378,6 +390,127 @@
|
||||
}));
|
||||
}
|
||||
|
||||
async function loadTextLibrary(forceRefresh = false) {
|
||||
if (!forceRefresh && textLibraryCache) {
|
||||
return textLibraryCache;
|
||||
}
|
||||
|
||||
textLibraryCache = await fetchJson(buildApiUrl("/api/v1/texts"));
|
||||
return textLibraryCache;
|
||||
}
|
||||
|
||||
async function loadTextSource(sourceId, forceRefresh = false) {
|
||||
const normalizedSourceId = String(sourceId || "").trim().toLowerCase();
|
||||
if (!normalizedSourceId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!forceRefresh && textSourceCache.has(normalizedSourceId)) {
|
||||
return textSourceCache.get(normalizedSourceId);
|
||||
}
|
||||
|
||||
const payload = await fetchJson(buildApiUrl(`/api/v1/texts/${encodeURIComponent(normalizedSourceId)}`));
|
||||
textSourceCache.set(normalizedSourceId, payload);
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function loadTextSection(sourceId, workId, sectionId, forceRefresh = false) {
|
||||
const normalizedSourceId = String(sourceId || "").trim().toLowerCase();
|
||||
const normalizedWorkId = String(workId || "").trim().toLowerCase();
|
||||
const normalizedSectionId = String(sectionId || "").trim().toLowerCase();
|
||||
if (!normalizedSourceId || !normalizedWorkId || !normalizedSectionId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const cacheKey = `${normalizedSourceId}::${normalizedWorkId}::${normalizedSectionId}`;
|
||||
if (!forceRefresh && textSectionCache.has(cacheKey)) {
|
||||
return textSectionCache.get(cacheKey);
|
||||
}
|
||||
|
||||
const payload = await fetchJson(buildApiUrl(
|
||||
`/api/v1/texts/${encodeURIComponent(normalizedSourceId)}/works/${encodeURIComponent(normalizedWorkId)}/sections/${encodeURIComponent(normalizedSectionId)}`
|
||||
));
|
||||
textSectionCache.set(cacheKey, payload);
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function loadTextLexiconEntry(lexiconId, entryId, forceRefresh = false) {
|
||||
const normalizedLexiconId = String(lexiconId || "").trim().toLowerCase();
|
||||
const normalizedEntryId = String(entryId || "").trim().toUpperCase();
|
||||
if (!normalizedLexiconId || !normalizedEntryId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const cacheKey = `${normalizedLexiconId}::${normalizedEntryId}`;
|
||||
if (!forceRefresh && textLexiconCache.has(cacheKey)) {
|
||||
return textLexiconCache.get(cacheKey);
|
||||
}
|
||||
|
||||
const payload = await fetchJson(buildApiUrl(
|
||||
`/api/v1/texts/lexicons/${encodeURIComponent(normalizedLexiconId)}/entries/${encodeURIComponent(normalizedEntryId)}`
|
||||
));
|
||||
textLexiconCache.set(cacheKey, payload);
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function loadTextLexiconOccurrences(lexiconId, entryId, options = {}, forceRefresh = false) {
|
||||
const normalizedLexiconId = String(lexiconId || "").trim().toLowerCase();
|
||||
const normalizedEntryId = String(entryId || "").trim().toUpperCase();
|
||||
const normalizedLimit = Number.parseInt(options?.limit, 10);
|
||||
const limit = Number.isFinite(normalizedLimit) ? normalizedLimit : 100;
|
||||
if (!normalizedLexiconId || !normalizedEntryId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const cacheKey = `${normalizedLexiconId}::${normalizedEntryId}::${limit}`;
|
||||
if (!forceRefresh && textLexiconOccurrencesCache.has(cacheKey)) {
|
||||
return textLexiconOccurrencesCache.get(cacheKey);
|
||||
}
|
||||
|
||||
const payload = await fetchJson(buildApiUrl(
|
||||
`/api/v1/texts/lexicons/${encodeURIComponent(normalizedLexiconId)}/entries/${encodeURIComponent(normalizedEntryId)}/occurrences`,
|
||||
{ limit }
|
||||
));
|
||||
textLexiconOccurrencesCache.set(cacheKey, payload);
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function searchTextLibrary(query, options = {}, forceRefresh = false) {
|
||||
const normalizedQuery = String(query || "").trim();
|
||||
const normalizedSourceId = String(options?.sourceId || "").trim().toLowerCase();
|
||||
const normalizedLimit = Number.parseInt(options?.limit, 10);
|
||||
const limit = Number.isFinite(normalizedLimit) ? normalizedLimit : 50;
|
||||
|
||||
if (!normalizedQuery) {
|
||||
return {
|
||||
query: "",
|
||||
normalizedQuery: "",
|
||||
scope: normalizedSourceId ? { type: "source", sourceId: normalizedSourceId } : { type: "global" },
|
||||
limit,
|
||||
totalMatches: 0,
|
||||
resultCount: 0,
|
||||
truncated: false,
|
||||
results: []
|
||||
};
|
||||
}
|
||||
|
||||
const cacheKey = `${normalizedSourceId || "global"}::${limit}::${normalizedQuery.toLowerCase()}`;
|
||||
if (!forceRefresh && textSearchCache.has(cacheKey)) {
|
||||
return textSearchCache.get(cacheKey);
|
||||
}
|
||||
|
||||
const path = normalizedSourceId
|
||||
? `/api/v1/texts/${encodeURIComponent(normalizedSourceId)}/search`
|
||||
: "/api/v1/texts/search";
|
||||
|
||||
const payload = await fetchJson(buildApiUrl(path, {
|
||||
q: normalizedQuery,
|
||||
limit
|
||||
}));
|
||||
textSearchCache.set(cacheKey, payload);
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function loadDeckOptions(forceRefresh = false) {
|
||||
if (!forceRefresh && deckOptionsCache) {
|
||||
return deckOptionsCache;
|
||||
@@ -515,6 +648,12 @@
|
||||
loadReferenceData,
|
||||
loadMagickManifest,
|
||||
loadMagickDataset,
|
||||
loadTextLibrary,
|
||||
loadTextSource,
|
||||
searchTextLibrary,
|
||||
loadTextSection,
|
||||
loadTextLexiconEntry,
|
||||
loadTextLexiconOccurrences,
|
||||
probeConnection,
|
||||
pullQuizQuestion,
|
||||
pullTarotSpread,
|
||||
|
||||
538
app/styles.css
538
app/styles.css
@@ -21,7 +21,9 @@
|
||||
border-bottom: 1px solid #27272a;
|
||||
background: #18181b;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
z-index: 40;
|
||||
}
|
||||
.topbar-home-button {
|
||||
padding: 0;
|
||||
@@ -49,7 +51,12 @@
|
||||
justify-content: flex-start;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
padding-bottom: 2px;
|
||||
padding-bottom: 132px;
|
||||
margin-bottom: -130px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.topbar-actions > * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
.topbar-actions::-webkit-scrollbar {
|
||||
height: 6px;
|
||||
@@ -77,6 +84,10 @@
|
||||
.topbar-dropdown.is-open .topbar-dropdown-menu {
|
||||
display: grid;
|
||||
}
|
||||
.topbar-dropdown:hover .topbar-dropdown-menu,
|
||||
.topbar-dropdown:focus-within .topbar-dropdown-menu {
|
||||
display: grid;
|
||||
}
|
||||
.topbar-sub-trigger {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
@@ -1095,6 +1106,8 @@
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.planet-list-count {
|
||||
color: #a1a1aa;
|
||||
@@ -1144,6 +1157,10 @@
|
||||
gap: 16px;
|
||||
background: #18181b;
|
||||
}
|
||||
.planet-detail-heading {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.planet-detail-heading h2 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
@@ -1979,11 +1996,17 @@
|
||||
.sidebar-toggle-inline {
|
||||
margin-left: auto;
|
||||
align-self: center;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.detail-toggle-inline {
|
||||
margin-left: auto;
|
||||
align-self: center;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.sidebar-popout-open {
|
||||
@@ -3072,6 +3095,16 @@
|
||||
border-color: #818cf8;
|
||||
color: #e0e7ff;
|
||||
}
|
||||
.alpha-nav-btn--ghost {
|
||||
background: transparent;
|
||||
border-color: #3f3f46;
|
||||
color: #d4d4d8;
|
||||
}
|
||||
.alpha-nav-btn--ghost:hover {
|
||||
background: #18181b;
|
||||
border-color: #71717a;
|
||||
color: #fafafa;
|
||||
}
|
||||
.alpha-nav-btn.is-selected,
|
||||
.alpha-nav-btn[aria-pressed="true"] {
|
||||
background: #4338ca;
|
||||
@@ -3126,6 +3159,507 @@
|
||||
color: #a1a1aa;
|
||||
}
|
||||
|
||||
#alphabet-text-section {
|
||||
height: calc(100vh - 61px);
|
||||
background: #18181b;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#alphabet-text-section[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alpha-text-controls {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
padding: 12px;
|
||||
border-top: 1px solid #27272a;
|
||||
background: #101018;
|
||||
}
|
||||
|
||||
.alpha-text-search-controls {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.alpha-text-search-controls--sidebar {
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid #27272a;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(30, 27, 75, 0.22), rgba(16, 16, 24, 0.96));
|
||||
}
|
||||
|
||||
.alpha-text-search-controls--detail {
|
||||
padding: 14px;
|
||||
border: 1px solid #2f2f39;
|
||||
border-radius: 14px;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(24, 24, 38, 0.98), rgba(12, 12, 18, 0.98));
|
||||
box-shadow: inset 0 0 0 1px rgba(99, 102, 241, 0.08);
|
||||
}
|
||||
|
||||
.alpha-text-control {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.alpha-text-control > span {
|
||||
color: #a1a1aa;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.alpha-text-select {
|
||||
width: 100%;
|
||||
padding: 7px 8px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #3f3f46;
|
||||
background: #09090b;
|
||||
color: #f4f4f5;
|
||||
box-sizing: border-box;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.alpha-text-search-input {
|
||||
width: 100%;
|
||||
padding: 9px 10px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #4338ca;
|
||||
background: #09090b;
|
||||
color: #f4f4f5;
|
||||
box-sizing: border-box;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.alpha-text-search-input::placeholder {
|
||||
color: #71717a;
|
||||
}
|
||||
|
||||
.alpha-text-search-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.alpha-text-search-controls--sidebar .alpha-text-search-actions .alpha-nav-btn {
|
||||
flex: 1 1 0;
|
||||
min-height: 34px;
|
||||
}
|
||||
|
||||
.alpha-text-search-controls--detail .alpha-text-search-actions .alpha-nav-btn {
|
||||
min-height: 34px;
|
||||
padding-inline: 12px;
|
||||
}
|
||||
|
||||
.alpha-text-source-btn {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.alpha-text-source-meta {
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
color: #a1a1aa;
|
||||
}
|
||||
|
||||
.alpha-text-detail-body {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.alpha-text-meta-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 12px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.alpha-text-toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.alpha-text-reader {
|
||||
display: grid;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.alpha-text-search-summary {
|
||||
margin: 0 0 10px;
|
||||
color: #a1a1aa;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.alpha-text-search-results {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.alpha-text-search-result {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 1px solid #2f2f39;
|
||||
border-radius: 12px;
|
||||
background: #0c0c12;
|
||||
color: #f4f4f5;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.alpha-text-search-result:hover {
|
||||
border-color: #6366f1;
|
||||
background: #131325;
|
||||
}
|
||||
|
||||
.alpha-text-search-result.is-active {
|
||||
border-color: #a5b4fc;
|
||||
background: #1e1b4b;
|
||||
box-shadow: inset 0 0 0 1px rgba(199, 210, 254, 0.18);
|
||||
}
|
||||
|
||||
.alpha-text-search-result-head {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.alpha-text-search-reference {
|
||||
color: #eef2ff;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
.alpha-text-search-location {
|
||||
color: #a5b4fc;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
|
||||
.alpha-text-search-preview {
|
||||
margin: 0;
|
||||
color: #e4e4e7;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.alpha-text-mark {
|
||||
padding: 0 2px;
|
||||
border-radius: 4px;
|
||||
background: rgba(251, 191, 36, 0.24);
|
||||
color: #fef3c7;
|
||||
}
|
||||
|
||||
.alpha-text-mark--lexicon {
|
||||
background: rgba(129, 140, 248, 0.28);
|
||||
color: #e0e7ff;
|
||||
box-shadow: inset 0 0 0 1px rgba(165, 180, 252, 0.2);
|
||||
}
|
||||
|
||||
.alpha-text-verse {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
padding: 12px 0;
|
||||
border-top: 1px solid #27272a;
|
||||
}
|
||||
|
||||
.alpha-text-verse.is-highlighted {
|
||||
margin: 0 -12px;
|
||||
padding: 12px;
|
||||
border-radius: 12px;
|
||||
border-top-color: transparent;
|
||||
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;
|
||||
}
|
||||
|
||||
.alpha-text-verse-head {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.alpha-text-verse-reference {
|
||||
color: #c4b5fd;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
.alpha-text-verse-text {
|
||||
margin: 0;
|
||||
color: #e4e4e7;
|
||||
font-size: 15px;
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
.alpha-text-token-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.alpha-text-token {
|
||||
display: grid;
|
||||
gap: 3px;
|
||||
min-width: 96px;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid #2f2f39;
|
||||
border-radius: 10px;
|
||||
background: #0c0c12;
|
||||
color: #f4f4f5;
|
||||
text-align: left;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.alpha-text-token--interactive {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.alpha-text-token--interactive:hover {
|
||||
background: #141427;
|
||||
border-color: #6366f1;
|
||||
}
|
||||
|
||||
.alpha-text-token-gloss {
|
||||
color: #f4f4f5;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.alpha-text-token-original {
|
||||
color: #c4b5fd;
|
||||
font-size: 15px;
|
||||
font-family: var(--font-script-display);
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.alpha-text-token-strongs {
|
||||
color: #a1a1aa;
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-term {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-head {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-id {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid #4f46e5;
|
||||
border-radius: 999px;
|
||||
background: #1e1b4b;
|
||||
color: #c7d2fe;
|
||||
font-size: 11px;
|
||||
line-height: 1;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-id--button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-id--button:hover {
|
||||
background: #312e81;
|
||||
border-color: #818cf8;
|
||||
color: #e0e7ff;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-id--button[aria-expanded="true"] {
|
||||
background: #312e81;
|
||||
border-color: #a5b4fc;
|
||||
color: #eef2ff;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-hint {
|
||||
margin: 0;
|
||||
color: #a1a1aa;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-occurrences {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
padding-top: 6px;
|
||||
border-top: 1px solid #27272a;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-occurrence-list {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-occurrence {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #2f2f39;
|
||||
border-radius: 10px;
|
||||
background: #0c0c12;
|
||||
color: #f4f4f5;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-occurrence:hover {
|
||||
background: #141427;
|
||||
border-color: #6366f1;
|
||||
}
|
||||
|
||||
.alpha-text-search-preview--compact {
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 80;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 24px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-backdrop {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.68);
|
||||
-webkit-backdrop-filter: blur(4px);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-card {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: min(720px, calc(100vw - 32px));
|
||||
max-height: calc(100vh - 48px);
|
||||
overflow: auto;
|
||||
padding: 18px;
|
||||
border: 1px solid #3f3f46;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(180deg, rgba(24, 24, 27, 0.98), rgba(9, 9, 11, 0.98));
|
||||
box-shadow: 0 24px 70px rgba(0, 0, 0, 0.6);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-heading {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-heading h3 {
|
||||
margin: 0;
|
||||
color: #f4f4f5;
|
||||
font-size: 22px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-subtitle {
|
||||
margin: 0;
|
||||
color: #a1a1aa;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-close {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #3f3f46;
|
||||
border-radius: 8px;
|
||||
background: #18181b;
|
||||
color: #f4f4f5;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-close:hover {
|
||||
background: #27272a;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-body {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-body .alpha-dl {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.alpha-text-empty {
|
||||
color: #a1a1aa;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.alpha-text-meta-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.alpha-text-token {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-card {
|
||||
width: min(100vw - 20px, 100%);
|
||||
max-height: calc(100vh - 32px);
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.alpha-text-lexicon-popup-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Zodiac section ──────────────────────────────────────────────────── */
|
||||
#zodiac-section {
|
||||
height: calc(100vh - 61px);
|
||||
|
||||
1322
app/ui-alphabet-text.js
Normal file
1322
app/ui-alphabet-text.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -86,6 +86,10 @@
|
||||
setActiveSection(getActiveSection() === "alphabet-letters" ? "home" : "alphabet-letters");
|
||||
});
|
||||
|
||||
bindClick(elements.openAlphabetTextEl, () => {
|
||||
setActiveSection(getActiveSection() === "alphabet-text" ? "home" : "alphabet-text");
|
||||
});
|
||||
|
||||
bindClick(elements.openNumbersEl, () => {
|
||||
setActiveSection(getActiveSection() === "numbers" ? "home" : "numbers");
|
||||
});
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"cube",
|
||||
"alphabet",
|
||||
"alphabet-letters",
|
||||
"alphabet-text",
|
||||
"numbers",
|
||||
"zodiac",
|
||||
"quiz",
|
||||
@@ -101,7 +102,8 @@
|
||||
const isKabbalahMenuOpen = isKabbalahOpen || isKabbalahTreeOpen || isCubeOpen;
|
||||
const isAlphabetOpen = activeSection === "alphabet";
|
||||
const isAlphabetLettersOpen = activeSection === "alphabet-letters";
|
||||
const isAlphabetMenuOpen = isAlphabetOpen || isAlphabetLettersOpen;
|
||||
const isAlphabetTextOpen = activeSection === "alphabet-text";
|
||||
const isAlphabetMenuOpen = isAlphabetOpen || isAlphabetLettersOpen || isAlphabetTextOpen;
|
||||
const isNumbersOpen = activeSection === "numbers";
|
||||
const isQuizOpen = activeSection === "quiz";
|
||||
const isGodsOpen = activeSection === "gods";
|
||||
@@ -122,6 +124,7 @@
|
||||
setHidden(elements.cubeSectionEl, !isCubeOpen);
|
||||
setHidden(elements.alphabetSectionEl, !isAlphabetOpen);
|
||||
setHidden(elements.alphabetLettersSectionEl, !isAlphabetLettersOpen);
|
||||
setHidden(elements.alphabetTextSectionEl, !isAlphabetTextOpen);
|
||||
setHidden(elements.numbersSectionEl, !isNumbersOpen);
|
||||
setHidden(elements.zodiacSectionEl, !isZodiacOpen);
|
||||
setHidden(elements.quizSectionEl, !isQuizOpen);
|
||||
@@ -146,6 +149,7 @@
|
||||
toggleActive(elements.openKabbalahCubeEl, isCubeOpen);
|
||||
setPressed(elements.openAlphabetEl, isAlphabetMenuOpen);
|
||||
toggleActive(elements.openAlphabetLettersEl, isAlphabetLettersOpen);
|
||||
toggleActive(elements.openAlphabetTextEl, isAlphabetTextOpen);
|
||||
setPressed(elements.openNumbersEl, isNumbersOpen);
|
||||
toggleActive(elements.openZodiacEl, isZodiacOpen);
|
||||
toggleActive(elements.openNatalEl, isNatalOpen);
|
||||
@@ -216,6 +220,11 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAlphabetTextOpen) {
|
||||
ensure.ensureAlphabetTextSection?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNumbersOpen) {
|
||||
ensure.ensureNumbersSection?.();
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user