updated tarot frame for mobile and desktop usability
This commit is contained in:
+7
-2
@@ -378,9 +378,14 @@
|
||||
}));
|
||||
}
|
||||
|
||||
async function loadGematriaWordsByValue(value) {
|
||||
async function loadGematriaWordsByValue(value, options = {}) {
|
||||
const ciphers = Array.isArray(options?.ciphers)
|
||||
? options.ciphers.map((cipherId) => String(cipherId || "").trim()).filter(Boolean).join(",")
|
||||
: String(options?.ciphers || "").trim();
|
||||
|
||||
return fetchJson(buildApiUrl("/api/v1/gematria/words", {
|
||||
value
|
||||
value,
|
||||
ciphers
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
+140
-11
@@ -907,6 +907,30 @@
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tarot-frame-selection-chip {
|
||||
padding: 10px 14px;
|
||||
border: 1px solid rgba(56, 189, 248, 0.55);
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(180deg, rgba(8, 47, 73, 0.96), rgba(12, 74, 110, 0.98));
|
||||
color: #e0f2fe;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.02em;
|
||||
box-shadow: 0 10px 24px rgba(2, 132, 199, 0.18);
|
||||
}
|
||||
|
||||
.tarot-frame-selection-chip:hover,
|
||||
.tarot-frame-selection-chip:focus-visible {
|
||||
border-color: rgba(125, 211, 252, 0.92);
|
||||
background: linear-gradient(180deg, rgba(12, 74, 110, 0.98), rgba(14, 116, 144, 1));
|
||||
color: #f0f9ff;
|
||||
}
|
||||
|
||||
.tarot-frame-selection-chip[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.tarot-frame-layout-panel {
|
||||
position: absolute;
|
||||
top: calc(100% + 10px);
|
||||
@@ -1681,7 +1705,8 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.tarot-frame-card-insert-menu {
|
||||
.tarot-frame-card-insert-menu,
|
||||
.tarot-frame-card-action-menu {
|
||||
position: fixed;
|
||||
z-index: 41;
|
||||
width: min(240px, calc(100vw - 24px));
|
||||
@@ -1696,11 +1721,13 @@
|
||||
box-shadow: 0 24px 70px rgba(0, 0, 0, 0.42);
|
||||
}
|
||||
|
||||
.tarot-frame-card-insert-menu[hidden] {
|
||||
.tarot-frame-card-insert-menu[hidden],
|
||||
.tarot-frame-card-action-menu[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.tarot-frame-card-insert-menu-item {
|
||||
.tarot-frame-card-insert-menu-item,
|
||||
.tarot-frame-card-action-menu-item {
|
||||
padding: 11px 12px;
|
||||
border: 1px solid rgba(99, 102, 241, 0.22);
|
||||
border-radius: 12px;
|
||||
@@ -1713,7 +1740,9 @@
|
||||
}
|
||||
|
||||
.tarot-frame-card-insert-menu-item:hover,
|
||||
.tarot-frame-card-insert-menu-item:focus-visible {
|
||||
.tarot-frame-card-insert-menu-item:focus-visible,
|
||||
.tarot-frame-card-action-menu-item:hover,
|
||||
.tarot-frame-card-action-menu-item:focus-visible {
|
||||
border-color: rgba(165, 180, 252, 0.9);
|
||||
background: rgba(49, 46, 129, 0.34);
|
||||
color: #f8fafc;
|
||||
@@ -2052,6 +2081,11 @@
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.tarot-frame-slot.is-selected {
|
||||
box-shadow: 0 0 0 2px #38bdf8, 0 0 0 6px rgba(56, 189, 248, 0.2);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.tarot-frame-slot.is-drag-source {
|
||||
opacity: 0.42;
|
||||
}
|
||||
@@ -2072,6 +2106,8 @@
|
||||
}
|
||||
|
||||
.tarot-frame-card {
|
||||
--frame-card-rotation: 0deg;
|
||||
--frame-card-hover-lift: 0px;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
padding: 0;
|
||||
@@ -2086,6 +2122,12 @@
|
||||
user-select: none;
|
||||
touch-action: none;
|
||||
-webkit-touch-callout: none;
|
||||
transform: translateY(var(--frame-card-hover-lift)) rotate(var(--frame-card-rotation));
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
.tarot-frame-card.is-flipped {
|
||||
--frame-card-rotation: 180deg;
|
||||
}
|
||||
|
||||
.tarot-frame-card.is-empty {
|
||||
@@ -2096,13 +2138,18 @@
|
||||
}
|
||||
|
||||
.tarot-frame-card:hover {
|
||||
transform: translateY(-2px);
|
||||
--frame-card-hover-lift: -2px;
|
||||
filter: drop-shadow(0 10px 18px rgba(15, 23, 42, 0.38));
|
||||
}
|
||||
|
||||
.tarot-frame-card.is-selected {
|
||||
filter: drop-shadow(0 12px 20px rgba(14, 165, 233, 0.34));
|
||||
}
|
||||
|
||||
.tarot-frame-card.is-empty:hover {
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
--frame-card-hover-lift: 0px;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
@@ -2112,6 +2159,7 @@
|
||||
}
|
||||
|
||||
.tarot-frame-card:hover {
|
||||
--frame-card-hover-lift: 0px;
|
||||
transform: none;
|
||||
filter: none;
|
||||
}
|
||||
@@ -2288,6 +2336,28 @@
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.tarot-frame-drag-ghost.is-flipped {
|
||||
transform: translate(-50%, -50%) rotate(180deg);
|
||||
}
|
||||
|
||||
.tarot-frame-drag-ghost-count {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
min-width: 26px;
|
||||
height: 26px;
|
||||
padding: 0 8px;
|
||||
border-radius: 999px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
background: rgba(56, 189, 248, 0.94);
|
||||
color: #082f49;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
box-shadow: 0 8px 20px rgba(2, 132, 199, 0.34);
|
||||
}
|
||||
|
||||
.tarot-frame-drag-ghost img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -2410,6 +2480,13 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tarot-frame-selection-chip {
|
||||
order: -1;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tarot-frame-settings-panel {
|
||||
left: 0;
|
||||
right: auto;
|
||||
@@ -2430,8 +2507,8 @@
|
||||
}
|
||||
|
||||
.tarot-frame-card-badge {
|
||||
font-size: 7px;
|
||||
padding: 3px 4px;
|
||||
font-size: 11px;
|
||||
padding: 4px 5px;
|
||||
}
|
||||
|
||||
.tarot-frame-card-text-face {
|
||||
@@ -4227,6 +4304,56 @@
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.alpha-gematria-cipher[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-ciphers {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-ciphers[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-cipher-option {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid #3f3f46;
|
||||
border-radius: 999px;
|
||||
background: #101018;
|
||||
color: #d4d4d8;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-cipher-option:has(input:checked) {
|
||||
border-color: #6366f1;
|
||||
background: #1c1b35;
|
||||
color: #eef2ff;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-cipher-option input {
|
||||
margin: 0;
|
||||
accent-color: #818cf8;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-cipher-name {
|
||||
font-size: 12px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.alpha-gematria-reverse-cipher-hint {
|
||||
color: #a1a1aa;
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.alpha-gematria-input {
|
||||
min-height: 54px;
|
||||
resize: vertical;
|
||||
@@ -4330,15 +4457,17 @@
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.alpha-gematria-controls.is-input-priority-mode,
|
||||
.alpha-gematria-controls:has(.alpha-gematria-cipher:disabled) {
|
||||
.alpha-gematria-controls.is-input-priority-mode {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.alpha-gematria-controls.is-input-priority-mode .alpha-gematria-field-cipher,
|
||||
.alpha-gematria-controls:has(.alpha-gematria-cipher:disabled) .alpha-gematria-field-cipher {
|
||||
.alpha-gematria-controls.is-input-priority-mode .alpha-gematria-field-cipher {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alpha-gematria-controls.is-reverse-cipher-mode {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.alpha-tabs {
|
||||
|
||||
+144
-13
@@ -12,7 +12,9 @@
|
||||
modeEls: [],
|
||||
matchesEl: null,
|
||||
inputLabelEl: null,
|
||||
cipherLabelEl: null
|
||||
cipherLabelEl: null,
|
||||
reverseCiphersEl: null,
|
||||
reverseCipherHintEl: null
|
||||
})
|
||||
};
|
||||
|
||||
@@ -23,6 +25,7 @@
|
||||
activeCipherId: "",
|
||||
forwardInputText: "",
|
||||
reverseInputText: "",
|
||||
reverseSelectedCipherIds: null,
|
||||
anagramInputText: "",
|
||||
dictionaryInputText: "",
|
||||
activeMode: "forward",
|
||||
@@ -52,7 +55,9 @@
|
||||
modeEls: [],
|
||||
matchesEl: null,
|
||||
inputLabelEl: null,
|
||||
cipherLabelEl: null
|
||||
cipherLabelEl: null,
|
||||
reverseCiphersEl: null,
|
||||
reverseCipherHintEl: null
|
||||
};
|
||||
}
|
||||
|
||||
@@ -273,6 +278,80 @@
|
||||
return ciphers.find((cipher) => cipher.id === selectedId) || ciphers[0];
|
||||
}
|
||||
|
||||
function getGematriaCiphers() {
|
||||
const db = state.db || getFallbackGematriaDb();
|
||||
return Array.isArray(db.ciphers) ? db.ciphers : [];
|
||||
}
|
||||
|
||||
function normalizeSelectedReverseCipherIds(rawCipherIds) {
|
||||
const ciphers = getGematriaCiphers();
|
||||
const requestedIds = Array.isArray(rawCipherIds)
|
||||
? rawCipherIds.map((cipherId) => String(cipherId || "").trim()).filter(Boolean)
|
||||
: [];
|
||||
const requestedIdSet = new Set(requestedIds);
|
||||
|
||||
return ciphers
|
||||
.map((cipher) => cipher.id)
|
||||
.filter((cipherId) => requestedIdSet.has(cipherId));
|
||||
}
|
||||
|
||||
function getDefaultReverseCipherIds() {
|
||||
const activeCipher = getActiveGematriaCipher();
|
||||
if (activeCipher?.id) {
|
||||
return [activeCipher.id];
|
||||
}
|
||||
|
||||
const firstCipher = getGematriaCiphers()[0];
|
||||
return firstCipher?.id ? [firstCipher.id] : [];
|
||||
}
|
||||
|
||||
function getSelectedReverseCipherIds() {
|
||||
if (state.reverseSelectedCipherIds === null) {
|
||||
return getDefaultReverseCipherIds();
|
||||
}
|
||||
|
||||
return normalizeSelectedReverseCipherIds(state.reverseSelectedCipherIds);
|
||||
}
|
||||
|
||||
function setSelectedReverseCipherIds(rawCipherIds) {
|
||||
state.reverseSelectedCipherIds = normalizeSelectedReverseCipherIds(rawCipherIds);
|
||||
}
|
||||
|
||||
function renderReverseCipherOptions() {
|
||||
const { reverseCiphersEl } = getElements();
|
||||
if (!reverseCiphersEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ciphers = getGematriaCiphers();
|
||||
const selectedCipherIds = new Set(getSelectedReverseCipherIds());
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
ciphers.forEach((cipher) => {
|
||||
const optionEl = document.createElement("label");
|
||||
optionEl.className = "alpha-gematria-reverse-cipher-option";
|
||||
|
||||
const checkboxEl = document.createElement("input");
|
||||
checkboxEl.type = "checkbox";
|
||||
checkboxEl.value = cipher.id;
|
||||
checkboxEl.checked = selectedCipherIds.has(cipher.id);
|
||||
checkboxEl.setAttribute("aria-label", cipher.name);
|
||||
optionEl.appendChild(checkboxEl);
|
||||
|
||||
const textEl = document.createElement("span");
|
||||
textEl.className = "alpha-gematria-reverse-cipher-name";
|
||||
textEl.textContent = cipher.name;
|
||||
if (cipher.description) {
|
||||
textEl.title = cipher.description;
|
||||
}
|
||||
optionEl.appendChild(textEl);
|
||||
|
||||
fragment.appendChild(optionEl);
|
||||
});
|
||||
|
||||
reverseCiphersEl.replaceChildren(fragment);
|
||||
}
|
||||
|
||||
function renderGematriaCipherOptions() {
|
||||
const { cipherEl } = getElements();
|
||||
if (!cipherEl) {
|
||||
@@ -296,6 +375,14 @@
|
||||
const activeCipher = getActiveGematriaCipher();
|
||||
state.activeCipherId = activeCipher?.id || "";
|
||||
cipherEl.value = state.activeCipherId;
|
||||
|
||||
if (state.reverseSelectedCipherIds === null) {
|
||||
state.reverseSelectedCipherIds = getDefaultReverseCipherIds();
|
||||
} else {
|
||||
state.reverseSelectedCipherIds = normalizeSelectedReverseCipherIds(state.reverseSelectedCipherIds);
|
||||
}
|
||||
|
||||
renderReverseCipherOptions();
|
||||
}
|
||||
|
||||
function setMatchesMessage(matchesEl, message) {
|
||||
@@ -332,12 +419,14 @@
|
||||
modeEls,
|
||||
matchesEl,
|
||||
inputLabelEl,
|
||||
cipherLabelEl
|
||||
cipherLabelEl,
|
||||
reverseCiphersEl,
|
||||
reverseCipherHintEl
|
||||
} = getElements();
|
||||
|
||||
const reverseMode = isReverseMode();
|
||||
const anagramMode = isAnagramMode();
|
||||
const dictionaryMode = isDictionaryMode();
|
||||
const dictionaryMode = isDictionaryMode();
|
||||
const radioEls = getModeElements(modeEls);
|
||||
|
||||
radioEls.forEach((element) => {
|
||||
@@ -351,16 +440,32 @@
|
||||
}
|
||||
|
||||
if (cipherLabelEl) {
|
||||
cipherLabelEl.textContent = (reverseMode || anagramMode || dictionaryMode) ? "Cipher (not used in this mode)" : "Cipher";
|
||||
cipherLabelEl.textContent = reverseMode
|
||||
? "Ciphers"
|
||||
: ((anagramMode || dictionaryMode) ? "Cipher (not used in this mode)" : "Cipher");
|
||||
}
|
||||
|
||||
if (cipherEl) {
|
||||
const disableCipher = reverseMode || anagramMode || dictionaryMode;
|
||||
const hideCipherField = anagramMode || dictionaryMode;
|
||||
cipherEl.disabled = disableCipher;
|
||||
cipherEl.hidden = reverseMode;
|
||||
const cipherFieldEl = cipherEl.closest(".alpha-gematria-field");
|
||||
const controlsEl = cipherEl.closest(".alpha-gematria-controls");
|
||||
cipherFieldEl?.classList.toggle("is-disabled", disableCipher);
|
||||
controlsEl?.classList.toggle("is-input-priority-mode", disableCipher);
|
||||
cipherFieldEl?.classList.toggle("is-disabled", hideCipherField);
|
||||
controlsEl?.classList.toggle("is-input-priority-mode", hideCipherField);
|
||||
controlsEl?.classList.toggle("is-reverse-cipher-mode", reverseMode);
|
||||
}
|
||||
|
||||
if (reverseCiphersEl) {
|
||||
if (reverseMode) {
|
||||
renderReverseCipherOptions();
|
||||
}
|
||||
reverseCiphersEl.hidden = !reverseMode;
|
||||
}
|
||||
|
||||
if (reverseCipherHintEl) {
|
||||
reverseCipherHintEl.hidden = !reverseMode;
|
||||
}
|
||||
|
||||
if (inputEl) {
|
||||
@@ -400,12 +505,15 @@
|
||||
}
|
||||
|
||||
async function loadReverseLookup(value) {
|
||||
const cacheKey = String(value);
|
||||
const selectedCipherIds = getSelectedReverseCipherIds();
|
||||
const cacheKey = `${String(value)}::${selectedCipherIds.join(",")}`;
|
||||
if (state.reverseLookupCache.has(cacheKey)) {
|
||||
return state.reverseLookupCache.get(cacheKey);
|
||||
}
|
||||
|
||||
const payload = await window.TarotDataService?.loadGematriaWordsByValue?.(value);
|
||||
const payload = await window.TarotDataService?.loadGematriaWordsByValue?.(value, {
|
||||
ciphers: selectedCipherIds
|
||||
});
|
||||
state.reverseLookupCache.set(cacheKey, payload);
|
||||
return payload;
|
||||
}
|
||||
@@ -493,7 +601,7 @@
|
||||
.map((cipher) => `${String(cipher?.name || cipher?.id || "Unknown")} ${formatCount(cipher?.count)}`)
|
||||
.join(" · ");
|
||||
|
||||
breakdownEl.textContent = `Found ${formatCount(displayCount)} matches across ${formatCount(displayCipherCount)} ciphers.${topCipherSummary ? ` Top ciphers: ${topCipherSummary}.` : ""}${displayCount > visibleMatches.length ? ` Showing first ${formatCount(visibleMatches.length)}.` : ""}`;
|
||||
breakdownEl.textContent = `Found ${formatCount(displayCount)} matches across ${formatCount(displayCipherCount)} selected ciphers.${topCipherSummary ? ` Top ciphers: ${topCipherSummary}.` : ""}${displayCount > visibleMatches.length ? ` Showing first ${formatCount(visibleMatches.length)}.` : ""}`;
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
visibleMatches.forEach((match) => {
|
||||
@@ -546,11 +654,20 @@
|
||||
}
|
||||
|
||||
const rawValue = state.reverseInputText;
|
||||
const selectedCipherIds = getSelectedReverseCipherIds();
|
||||
if (!String(rawValue || "").trim()) {
|
||||
resultEl.textContent = "Value: --";
|
||||
breakdownEl.textContent = "Enter a whole number to find words across all available ciphers.";
|
||||
breakdownEl.textContent = "Enter a whole number and choose one or more ciphers to narrow reverse matches.";
|
||||
matchesEl.hidden = false;
|
||||
setMatchesMessage(matchesEl, "Reverse lookup searches the API-backed gematria word index.");
|
||||
setMatchesMessage(matchesEl, "Reverse lookup searches the API-backed gematria word index using the selected ciphers only.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedCipherIds.length) {
|
||||
resultEl.textContent = "Value: --";
|
||||
breakdownEl.textContent = "Choose at least one cipher before running reverse lookup.";
|
||||
matchesEl.hidden = false;
|
||||
setMatchesMessage(matchesEl, "Select one or more ciphers to limit reverse gematria matches.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -865,7 +982,7 @@
|
||||
}
|
||||
|
||||
function bindGematriaListeners() {
|
||||
const { cipherEl, inputEl, modeEls } = getElements();
|
||||
const { cipherEl, inputEl, modeEls, reverseCiphersEl } = getElements();
|
||||
if (state.listenersBound || !cipherEl || !inputEl) {
|
||||
return;
|
||||
}
|
||||
@@ -900,6 +1017,20 @@
|
||||
});
|
||||
});
|
||||
|
||||
reverseCiphersEl?.addEventListener("change", (event) => {
|
||||
const target = event.target;
|
||||
if (!(target instanceof HTMLInputElement) || target.type !== "checkbox") {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextSelectedCipherIds = Array.from(reverseCiphersEl.querySelectorAll("input[type='checkbox']:checked"))
|
||||
.map((element) => String(element.value || "").trim())
|
||||
.filter(Boolean);
|
||||
setSelectedReverseCipherIds(nextSelectedCipherIds);
|
||||
renderReverseCipherOptions();
|
||||
renderGematriaResult();
|
||||
});
|
||||
|
||||
state.listenersBound = true;
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -53,6 +53,7 @@
|
||||
let searchInputEl, searchClearEl, typeFilterEl;
|
||||
let gematriaCipherEl, gematriaInputEl, gematriaResultEl, gematriaBreakdownEl;
|
||||
let gematriaModeEls, gematriaMatchesEl, gematriaInputLabelEl, gematriaCipherLabelEl;
|
||||
let gematriaReverseCiphersEl, gematriaReverseCipherHintEl;
|
||||
|
||||
function getElements() {
|
||||
listEl = document.getElementById("alpha-letter-list");
|
||||
@@ -77,6 +78,8 @@
|
||||
gematriaMatchesEl = document.getElementById("alpha-gematria-matches");
|
||||
gematriaInputLabelEl = document.getElementById("alpha-gematria-input-label");
|
||||
gematriaCipherLabelEl = document.getElementById("alpha-gematria-cipher-label");
|
||||
gematriaReverseCiphersEl = document.getElementById("alpha-gematria-reverse-ciphers");
|
||||
gematriaReverseCipherHintEl = document.getElementById("alpha-gematria-reverse-cipher-hint");
|
||||
}
|
||||
|
||||
function getGematriaElements() {
|
||||
@@ -89,7 +92,9 @@
|
||||
modeEls: gematriaModeEls,
|
||||
matchesEl: gematriaMatchesEl,
|
||||
inputLabelEl: gematriaInputLabelEl,
|
||||
cipherLabelEl: gematriaCipherLabelEl
|
||||
cipherLabelEl: gematriaCipherLabelEl,
|
||||
reverseCiphersEl: gematriaReverseCiphersEl,
|
||||
reverseCipherHintEl: gematriaReverseCipherHintEl
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+911
-69
File diff suppressed because it is too large
Load Diff
+9
-6
@@ -16,7 +16,7 @@
|
||||
<link rel="stylesheet" href="node_modules/@fontsource/amiri/arabic-400.css">
|
||||
<link rel="stylesheet" href="node_modules/@fontsource/amiri/arabic-700.css">
|
||||
<link rel="stylesheet" href="node_modules/@fontsource/noto-naskh-arabic/arabic-400.css">
|
||||
<link rel="stylesheet" href="app/styles.css?v=20260407-frame-custom-color-exact-01">
|
||||
<link rel="stylesheet" href="app/styles.css?v=20260408-frame-flip-04">
|
||||
</head>
|
||||
<body>
|
||||
<div class="topbar">
|
||||
@@ -313,9 +313,10 @@
|
||||
<div class="tarot-frame-header">
|
||||
<div>
|
||||
<h2 class="tarot-frame-title">Tarot Frame</h2>
|
||||
<p class="tarot-frame-copy">Arrange all 78 tarot cards inside one master 14x14 grid, then switch between the Frames and House of Cards presets without leaving the page. On touch screens, use two fingers to pan around the board; on desktop, trackpad scroll and middle-mouse drag both pan the grid. Use Full Screen when you want an uncluttered board view for panning and placement.</p>
|
||||
<p class="tarot-frame-copy">Arrange all 78 tarot cards inside one master 14x14 grid, then switch between the Frames and House of Cards presets without leaving the page. On desktop, Ctrl/Cmd-click builds a multi-card selection and dragging any selected card moves the whole group. On touch screens, long-press a card and choose Select Multiple, then drag any selected card to move the set; two-finger pan still moves around the board. Use Full Screen when you want an uncluttered board view for panning and placement.</p>
|
||||
</div>
|
||||
<div class="tarot-frame-actions">
|
||||
<button id="tarot-frame-selection-chip" class="tarot-frame-selection-chip" type="button" hidden>0 Selected</button>
|
||||
<button id="tarot-frame-pan-toggle" class="tarot-frame-action-btn" type="button" aria-pressed="false">Pan Grid</button>
|
||||
<button id="tarot-frame-focus-toggle" class="tarot-frame-action-btn" type="button" aria-pressed="false">Full Screen</button>
|
||||
<button id="tarot-frame-settings-toggle" class="tarot-frame-action-btn tarot-frame-settings-toggle" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="tarot-frame-settings-panel">Settings</button>
|
||||
@@ -805,10 +806,12 @@
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="alpha-gematria-controls">
|
||||
<label class="alpha-gematria-field alpha-gematria-field-cipher" for="alpha-gematria-cipher">
|
||||
<div class="alpha-gematria-field alpha-gematria-field-cipher">
|
||||
<span id="alpha-gematria-cipher-label">Cipher</span>
|
||||
<select id="alpha-gematria-cipher" class="alpha-gematria-cipher" aria-label="Gematria cipher"></select>
|
||||
</label>
|
||||
<select id="alpha-gematria-cipher" class="alpha-gematria-cipher" aria-label="Gematria cipher"></select>
|
||||
<div id="alpha-gematria-reverse-ciphers" class="alpha-gematria-reverse-ciphers" role="group" aria-label="Reverse lookup ciphers" hidden></div>
|
||||
<div id="alpha-gematria-reverse-cipher-hint" class="alpha-gematria-reverse-cipher-hint" hidden>Select one or more ciphers to narrow reverse lookup results.</div>
|
||||
</div>
|
||||
<label class="alpha-gematria-field" for="alpha-gematria-input">
|
||||
<span id="alpha-gematria-input-label">Text</span>
|
||||
<textarea id="alpha-gematria-input" class="alpha-gematria-input" placeholder="Type or paste text"></textarea>
|
||||
@@ -1195,7 +1198,7 @@
|
||||
<script src="app/ui-numbers-detail.js"></script>
|
||||
<script src="app/ui-numbers.js"></script>
|
||||
<script src="app/ui-tarot-spread.js"></script>
|
||||
<script src="app/ui-tarot-frame.js?v=20260407-frame-custom-color-exact-01"></script>
|
||||
<script src="app/ui-tarot-frame.js?v=20260408-frame-flip-04"></script>
|
||||
<script src="app/ui-settings.js?v=20260309-gate"></script>
|
||||
<script src="app/ui-chrome.js?v=20260328-topbar-settings-01"></script>
|
||||
<script src="app/ui-navigation.js?v=20260401-tarot-frame-01"></script>
|
||||
|
||||
Reference in New Issue
Block a user