Agamas

.jlr[data-jlr-root]{ –bg:#0f1318; –panel:#141a22; –panel2:#10151c; –text:#e9eef6; –muted:#aeb8c8; –border:rgba(233,238,246,.14); –shadow:0 18px 60px rgba(0,0,0,.35); –r:18px; –fs:18px; –zoom:1; background:transparent !important; color:var(–text); display:block; font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Arial; font-size:var(–fs); } .jlr[data-jlr-root][data-theme=”light”]{ –bg:#fff; –panel:#f2f4f7; –panel2:#fff; –text:#14161a; –muted:#5b6472; –border:rgba(20,22,26,.12); –shadow:0 18px 50px rgba(0,0,0,.12); } .jlr[data-jlr-root] *{box-sizing:border-box;} .jlr[data-jlr-root] .jlr-shell{ background:var(–bg); border:1px solid var(–border); border-radius:var(–r); box-shadow:var(–shadow); overflow:hidden; max-width:1200px; margin:18px auto; } .jlr__top{ display:flex; justify-content:space-between; align-items:center; gap:12px; padding:14px 14px 10px; background:linear-gradient(180deg, rgba(255,255,255,.04), transparent); border-bottom:1px solid var(–border); } .jlr__brand{display:flex; gap:12px; align-items:center; min-width:0;} .jlr__mark{ width:44px; height:44px; border-radius:14px; display:grid; place-items:center; background:var(–panel2); border:1px solid var(–border); letter-spacing:.12em; font-size:12px; } .jlr__title{font-weight:800;} .jlr__subtitle{color:var(–muted); font-size:12px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:60vw;} .jlr__topActions{display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end; align-items:center;} .jlr__boot{ border:1px solid var(–border); border-radius:999px; padding:6px 10px; font-size:11px; color:var(–muted); background:rgba(255,255,255,.04); } .jlr__boot–ok{ color:#7ee7a8; } .jlr__boot–bad{ color:#ffb4b4; } .jlr__btn{ border:1px solid var(–border); background:var(–text); color:var(–panel2); border-radius:999px; padding:10px 12px; cursor:pointer; font-size:13px; line-height:1; } .jlr[data-theme=”dark”] .jlr__btn{ background:var(–text); color:#0b0d10; } .jlr__btn–ghost{ background:transparent; color:var(–text); } .jlr__btn:hover{ filter:brightness(1.05); } .jlr__btn:active{ transform:translateY(1px); } .jlr__controls{ padding:12px 14px 14px; background:var(–panel); border-bottom:1px solid var(–border); } .jlr.is-controls-collapsed .jlr__controls{ display:none; } .jlr__grid{ display:grid; grid-template-columns:220px 220px 1fr 190px; gap:10px; } .jlr__grid2{ display:grid; grid-template-columns:1fr 260px auto; gap:10px; margin-top:10px; align-items:end; } .jlr__field{display:flex; flex-direction:column; gap:6px; min-width:0;} .jlr__field–grow{min-width:260px;} .jlr__field–compact{min-width:180px;} .jlr__label{font-size:11px; color:var(–muted); text-transform:uppercase; letter-spacing:.08em;} .jlr__select,.jlr__input{ width:100%; border-radius:14px; border:1px solid var(–border); background:var(–panel2); color:var(–text); padding:10px 12px; outline:none; font-size:14px; } .jlr[data-theme=”light”] .jlr__select, .jlr[data-theme=”light”] .jlr__input{ background:#fff; color:var(–text); } .jlr__input–center{text-align:center;} .jlr__pageRow{display:flex; gap:8px; align-items:center;} .jlr__pageRow .jlr__btn{padding:10px 11px;} .jlr__chip{ display:inline-flex; align-items:center; justify-content:center; padding:6px 10px; border:1px solid var(–border); border-radius:999px; background:rgba(0,0,0,.10); min-width:56px; font-size:12px; color:var(–muted); } .jlr__policy{ margin-top:10px; padding:10px 12px; border:1px solid var(–border); border-radius:14px; background:rgba(255,255,255,.04); color:var(–muted); font-size:12px; line-height:1.4; } .jlr__policyTag{ display:inline-block; margin-left:8px; padding:3px 8px; border:1px solid var(–border); border-radius:999px; font-size:11px; background:rgba(255,255,255,.04); } .jlr__status{ margin-top:10px; color:var(–muted); font-size:12px; min-height:16px; } .jlr__main{ padding:14px; } .jlr__readerHead{ display:flex; justify-content:space-between; gap:10px; align-items:center; padding:10px 12px; border:1px solid var(–border); border-radius:16px; background:rgba(255,255,255,.03); } .jlr__crumb{ color:var(–muted); font-size:12px; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } .jlr__readerBtns{ display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end; } .jlr.is-reader-mode .jlr__top, .jlr.is-reader-mode .jlr__footer, .jlr.is-reader-mode .jlr__controls, .jlr.is-reader-mode .jlr__readerHead{ display:none; } .jlr.is-reader-mode .jlr__main{ padding:0; } .jlr__viewerWrap{ display:flex; justify-content:center; padding:12px 0 0; } .jlr__viewerInner{ width:100%; max-width:1000px; } .jlr__frame{ display:block !important; width:calc(100% / var(–zoom)) !important; height:calc(min(78vh, 980px) / var(–zoom)); min-height:560px; border:1px solid var(–border); border-radius:18px; background:var(–panel2); transform:scale(var(–zoom)); transform-origin:0 0; } .jlr__fallback{ margin-top:10px; padding:10px 12px; border:1px dashed var(–border); border-radius:14px; color:var(–muted); background:rgba(255,255,255,.03); font-size:12px; } .jlr__mobileNav{ display:none; margin-top:12px; gap:10px; justify-content:space-between; } .jlr__mobileNav .jlr__btn{ flex:1; padding:14px 12px; font-size:14px; } .jlr__footer{ padding:12px 14px 14px; border-top:1px solid var(–border); background:var(–panel); display:flex; gap:10px; justify-content:space-between; flex-wrap:wrap; } .jlr__credit{display:flex; gap:10px; align-items:center; color:var(–muted); font-size:12px;} .jlr__dot{opacity:.7;} .jlr__link{color:inherit; text-decoration:underline; text-underline-offset:3px;} .jlr__diag{ color:var(–muted); font-size:11px; font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,”Liberation Mono”,monospace; white-space:pre-wrap; } @media (max-width:980px){ .jlr__grid{grid-template-columns:1fr 1fr;} .jlr__grid2{grid-template-columns:1fr 1fr;} .jlr__mobileNav{ display:flex; } .jlr__frame{ min-height:520px; height:75vh; } } @media (max-width:560px){ .jlr__grid{grid-template-columns:1fr;} .jlr__grid2{grid-template-columns:1fr;} .jlr__subtitle{max-width:72vw;} } (() => { “use strict”; const README_CDN = “https://cdn.jsdelivr.net/gh/jainqq-org/JLOR@main/README.md”; const README_RAW = “https://raw.githubusercontent.com/jainqq-org/JLOR/main/README.md”; // Built-in fallback so dropdowns NEVER empty const BUILTIN = [ { l1:”Shwetambar Agams”, l2:”Ang Agams”, title:”Acharang Sutra Part 1″, srno:”007646″, verified:true }, { l1:”Shwetambar Agams”, l2:”Ang Agams”, title:”Acharang Sutra Part 2″, srno:”007647″, verified:true }, { l1:”Shwetambar Agams”, l2:”Ang Agams”, title:”Sutrakritanga Sutra”, srno:”011060″, verified:true }, { l1:”Shwetambar Agams”, l2:”Ang Agams”, title:”Sthananga Sutra Part 1″, srno:”002905″, verified:true }, { l1:”Shwetambar Agams”, l2:”Ang Agams”, title:”Sthananga Sutra Part 2″, srno:”002906″, verified:true }, { l1:”Shwetambar Agams”, l2:”Ang Agams”, title:”Samvayang Sutra”, srno:”002488″, verified:true }, { l1:”Shwetambar Agams”, l2:”Ang Agams”, title:”Bhagavati Sutra”, srno:”002902″, verified:true }, // Examples (hidden unless AI toggle ON) { l1:”Other Texts”, l2:”AI/Unverified”, title:”Tattvartha Sutra (catalog item)”, srno:”001916″, verified:false }, { l1:”Anuyogas and Digambar Texts”, l2:”Pratham Anuyoga (Stories)”, title:”Padmapurana Part 1″, srno:”001822″, verified:false }, ]; // Storage safe wrapper const mem = Object.create(null); const store = { get(k, fb = null) { try { const v = localStorage.getItem(k); return v == null ? (k in mem ? mem[k] : fb) : v; } catch { return (k in mem ? mem[k] : fb); } }, set(k, v) { const s = String(v); mem[k] = s; try { localStorage.setItem(k, s); } catch {} } }; // Boot + handle Gutenberg rerenders const ROOT_SEL = ‘.jlr[data-jlr-root]’; const initAll = () => document.querySelectorAll(ROOT_SEL).forEach((root, idx) => initOne(root, idx)); function boot() { initAll(); const mo = new MutationObserver(() => initAll()); mo.observe(document.documentElement, { childList: true, subtree: true }); } if (document.readyState === “loading”) document.addEventListener(“DOMContentLoaded”, boot, { once: true }); else boot(); function initOne(ROOT, idx) { if (ROOT.dataset.jlrInit === “1”) return; ROOT.dataset.jlrInit = “1”; ROOT.dataset.jlrInst = ROOT.dataset.jlrInst || String(idx + 1); const inst = ROOT.dataset.jlrInst; const LS = { theme: `jlr_theme_${inst}`, font: `jlr_font_${inst}`, ai: `jlr_ai_${inst}`, last: `jlr_last_${inst}`, bm: `jlr_bm_${inst}`, readme: `jlr_readme_${inst}`, readmeAt: `jlr_readmeAt_${inst}`, }; const q = (k) => ROOT.querySelector(`[data-jlr=”${k}”]`); const els = { boot: q(“boot”), diag: q(“diag”), status: q(“status”), policyTag: q(“policyTag”), crumb: q(“crumb”), fallback: q(“fallback”), l1: q(“l1”), l2: q(“l2”), text: q(“text”), search: q(“search”), page: q(“page”), frame: q(“frame”), // Buttons panelToggle: q(“panelToggle”), theme: q(“theme”), aminus: q(“aminus”), aplus: q(“aplus”), bookmark: q(“bookmark”), share: q(“share”), open: q(“open”), load: q(“load”), prev: q(“prev”), next: q(“next”), prev2: q(“prev2”), next2: q(“next2”), aiToggle: q(“aiToggle”), aiChip: q(“aiChip”), readerMode: q(“readerMode”), }; const log = (m) => { if (els.diag) els.diag.textContent += (els.diag.textContent ? “\n” : “”) + m; }; const status = (m) => { if (els.status) els.status.textContent = m || “”; }; if (!els.l1 || !els.l2 || !els.text || !els.load || !els.aiToggle || !els.frame) { if (els.boot) { els.boot.textContent = “JS: BLOCKED”; els.boot.classList.add(“jlr__boot–bad”); } return; } if (els.boot) { els.boot.textContent = “JS: RUNNING”; els.boot.classList.add(“jlr__boot–ok”); } let catalog = […BUILTIN]; const clamp = (n, a, b) => Math.max(a, Math.min(b, n)); const exploreUrl = (srno, page) => `https://jainqq.org/explore/${srno}/${page}`; const clear = (sel) => sel.replaceChildren(); const addOpt = (sel, value, label) => { const o = document.createElement(“option”); o.value = value; o.textContent = label; sel.appendChild(o); }; const aiEnabled = () => store.get(LS.ai, “0”) === “1”; const setAI = (v) => { store.set(LS.ai, v ? “1” : “0”); els.aiToggle.setAttribute(“aria-pressed”, v ? “true” : “false”); if (els.aiChip) els.aiChip.textContent = v ? “On” : “Off”; }; const setTheme = (t) => { ROOT.dataset.theme = t; store.set(LS.theme, t); }; const setFont = (px) => { const v = Math.max(14, Math.min(24, px)); ROOT.style.setProperty(“–fs”, `${v}px`); const zoom = Math.max(0.85, Math.min(1.25, v / 18)); ROOT.style.setProperty(“–zoom”, String(zoom)); // zoom iframe too store.set(LS.font, String(v)); }; function currentItem() { const srno = els.text.value; return catalog.find(x => x.srno === srno) || null; } function applyPolicyTag(item) { if (!els.policyTag) return; if (!item) { els.policyTag.textContent = “—”; return; } els.policyTag.textContent = item.verified ? “✅ Verified (non-AI)” : “⚠ AI/Unverified”; } function filterCatalog() { const qtxt = (els.search?.value || “”).trim().toLowerCase(); const allowAI = aiEnabled(); return catalog.filter(it => { if (!allowAI && !it.verified) return false; if (qtxt && !it.title.toLowerCase().includes(qtxt)) return false; return true; }); } function buildHierarchy(items) { const h = {}; for (const it of items) { (h[it.l1] ||= {}); (h[it.l1][it.l2] ||= []).push(it); } for (const a of Object.keys(h)) { for (const b of Object.keys(h[a])) { h[a][b].sort((x,y) => (x.verified === y.verified ? x.title.localeCompare(y.title) : (x.verified ? -1 : 1))); } } return h; } function repopulate(keep = {}) { const filtered = filterCatalog(); const hier = buildHierarchy(filtered); const l1s = Object.keys(hier).sort((a,b)=>a.localeCompare(b)); clear(els.l1); (l1s.length ? l1s : [“No results”]).forEach(k => addOpt(els.l1, k === “No results” ? “” : k, k)); els.l1.value = (keep.l1 && l1s.includes(keep.l1)) ? keep.l1 : (l1s[0] || “”); const l2s = Object.keys(hier[els.l1.value] || {}).sort((a,b)=>a.localeCompare(b)); clear(els.l2); (l2s.length ? l2s : [“No results”]).forEach(k => addOpt(els.l2, k === “No results” ? “” : k, k)); els.l2.value = (keep.l2 && l2s.includes(keep.l2)) ? keep.l2 : (l2s[0] || “”); const list = hier[els.l1.value]?.[els.l2.value] || []; clear(els.text); if (!list.length) addOpt(els.text, “”, “No texts”); else list.forEach(it => addOpt(els.text, it.srno, `${it.verified ? “✅ ” : “⚠ “}${it.title}`)); els.text.value = (keep.srno && list.some(x => x.srno === keep.srno)) ? keep.srno : (list[0]?.srno || “”); applyPolicyTag(currentItem()); status(aiEnabled() ? `Showing verified + AI/unverified (${filtered.length})` : `Showing verified only (${filtered.length})`); } function encodeState(st) { return btoa(unescape(encodeURIComponent(JSON.stringify(st)))); } function decodeState(s) { return JSON.parse(decodeURIComponent(escape(atob(s)))); } function getState() { return { l1: els.l1.value, l2: els.l2.value, srno: els.text.value, page: String(parseInt(els.page?.value || “1”, 10) || 1), ai: store.get(LS.ai, “0”) }; } function setFrame(url) { els.frame.src = url; // basic iframe-block detect: if it never loads, fallback stays visible; user can Open if (els.fallback) els.fallback.hidden = true; status(“Loading…”); } function loadReader() { const item = currentItem(); if (!item || !item.srno) { status(“Select a text.”); return; } const page = clamp(parseInt(els.page?.value || “1”, 10) || 1, 1, 999999); if (els.page) els.page.value = String(page); const url = exploreUrl(item.srno, page); setFrame(url); applyPolicyTag(item); if (els.crumb) els.crumb.textContent = `${item.title} • SR ${item.srno} • Page ${page}`; status(item.verified ? “✅ Verified” : “⚠ AI/Unverified”); store.set(LS.last, JSON.stringify(getState())); } function bump(delta) { const p = clamp((parseInt(els.page?.value || “1”, 10) || 1) + delta, 1, 999999); if (els.page) els.page.value = String(p); loadReader(); } // iframe load / error hints els.frame.addEventListener(“load”, () => { status(“Loaded.”); if (els.fallback) els.fallback.hidden = true; }); // Some browsers don’t fire error reliably for iframe cross-site blocks. // We show fallback if the iframe still looks empty after a short delay. const showFallbackSoon = () => { if (!els.fallback) return; setTimeout(() => { els.fallback.hidden = false; }, 1500); }; // Event delegation so buttons never “lose” handlers on re-render ROOT.addEventListener(“click”, async (ev) => { const btn = ev.target.closest(“button[data-jlr]”); if (!btn) return; const key = btn.getAttribute(“data-jlr”); if (key === “panelToggle”) ROOT.classList.toggle(“is-controls-collapsed”); else if (key === “readerMode”) ROOT.classList.toggle(“is-reader-mode”); else if (key === “theme”) setTheme(ROOT.dataset.theme === “dark” ? “light” : “dark”); else if (key === “aminus”) setFont((parseInt(store.get(LS.font, “18”), 10) || 18) – 1); else if (key === “aplus”) setFont((parseInt(store.get(LS.font, “18”), 10) || 18) + 1); else if (key === “aiToggle”) { setAI(!aiEnabled()); repopulate({ l1: els.l1.value, l2: els.l2.value, srno: els.text.value }); } else if (key === “prev” || key === “prev2”) bump(-1); else if (key === “next” || key === “next2”) bump(1); else if (key === “load”) loadReader(); else if (key === “open”) { const url = els.frame.src || exploreUrl(currentItem()?.srno || “007646”, parseInt(els.page?.value || “1”, 10) || 1); window.open(url, “_blank”, “noopener,noreferrer”); } else if (key === “bookmark”) { store.set(LS.bm, JSON.stringify(getState())); status(“Bookmarked.”); setTimeout(() => status(“”), 900); } else if (key === “share”) { const st = getState(); const url = new URL(window.location.href); url.searchParams.set(“jlr”, encodeState(st)); const shareUrl = url.toString(); try { if (navigator.share) await navigator.share({ title: “Jain Scripture Reader”, url: shareUrl }); else if (navigator.clipboard && window.isSecureContext) await navigator.clipboard.writeText(shareUrl); else window.prompt(“Copy link:”, shareUrl); status(“Share link ready.”); setTimeout(() => status(“”), 900); } catch {} } }); ROOT.addEventListener(“change”, (ev) => { const el = ev.target.closest(“[data-jlr]”); if (!el) return; const key = el.getAttribute(“data-jlr”); if (key === “l1”) repopulate({ l1: els.l1.value }); if (key === “l2”) repopulate({ l1: els.l1.value, l2: els.l2.value }); if (key === “text”) applyPolicyTag(currentItem()); }); ROOT.addEventListener(“input”, (ev) => { const el = ev.target.closest(“[data-jlr]”); if (!el) return; const key = el.getAttribute(“data-jlr”); if (key === “search”) repopulate({ l1: els.l1.value, l2: els.l2.value, srno: els.text.value }); }); // README hydrate (no GitHub API) async function fetchWithTimeout(url, ms = 20000) { const ctrl = new AbortController(); const t = setTimeout(() => ctrl.abort(), ms); try { const r = await fetch(url, { signal: ctrl.signal, cache: “no-store” }); if (!r.ok) throw new Error(`HTTP ${r.status}`); return await r.text(); } finally { clearTimeout(t); } } function parseReadme(md) { const out = []; const lines = String(md || “”).split(/\r?\n/); let l1 = “JLOR”, l2 = “General”; for (const line of lines) { const h2 = line.match(/^##\s+(.+)\s*$/); if (h2) { l1 = h2[1].trim(); l2 = “General”; continue; } const h3 = line.match(/^###\s+(.+)\s*$/); if (h3) { l2 = h3[1].trim(); continue; } const link = line.match(/\[([^\]]+)\]\((https?:\/\/jainqq\.org\/explore\/(\d{1,6})\/1)\)/); if (!link) continue; out.push({ l1, l2, title: link[1].trim(), srno: String(link[3] || “”).padStart(6, “0”), verified: /✅\s*Verified/i.test(line) }); } const seen = new Set(); return out.filter(x => { const k = `${x.srno}|${x.title}|${x.l1}|${x.l2}|${x.verified}`; if (seen.has(k)) return false; seen.add(k); return true; }); } async function hydrateCatalog() { const cached = store.get(LS.readme, “”); const cachedAt = parseInt(store.get(LS.readmeAt, “0”), 10) || 0; const fresh = (Date.now() – cachedAt) `${it.srno}|${it.title}|${it.l1}|${it.l2}|${it.verified}`; const existing = new Set(catalog.map(key)); let added = 0; for (const it of parsed) { const k = key(it); if (!existing.has(k)) { catalog.push(it); existing.add(k); added++; } } log(`Catalog merged +${added} (total ${catalog.length})`); repopulate({ l1: els.l1.value, l2: els.l2.value, srno: els.text.value }); } // Init UI try { const savedTheme = store.get(LS.theme, null); if (savedTheme === “dark” || savedTheme === “light”) setTheme(savedTheme); else setTheme(window.matchMedia && window.matchMedia(“(prefers-color-scheme: dark)”).matches ? “dark” : “light”); setFont(parseInt(store.get(LS.font, “18”), 10) || 18); setAI(store.get(LS.ai, “0”) === “1”); // Restore state from URL > bookmark > last try { const u = new URL(window.location.href); const enc = u.searchParams.get(“jlr”); if (enc) { const st = decodeState(enc); setAI(st.ai === “1”); repopulate({ l1: st.l1, l2: st.l2, srno: st.srno }); if (els.page) els.page.value = st.page || “1”; } else { const bm = store.get(LS.bm, “”); const last = store.get(LS.last, “”); const src = bm || last; if (src) { const st = JSON.parse(src); setAI(st.ai === “1”); repopulate({ l1: st.l1, l2: st.l2, srno: st.srno }); if (els.page) els.page.value = st.page || “1”; } else { repopulate({ l1:”Shwetambar Agams”, l2:”Ang Agams”, srno:”007646″ }); } } } catch { repopulate({ l1:”Shwetambar Agams”, l2:”Ang Agams”, srno:”007646″ }); } hydrateCatalog().finally(() => { loadReader(); showFallbackSoon(); log(“Ready ✅”); }); } catch (e) { if (els.boot) { els.boot.textContent = “JS: ERROR”; els.boot.classList.add(“jlr__boot–bad”); } log(`Init error: ${String(e?.message || e)}`); } } })();
Jain Scripture Reader
JLOR Catalog • JainQQ Reader • AI list toggle
JS: STARTING…
Major Section Division Text AI / Unverified
Search titles Page
Translation Notice: AI makes mistakes and can generate misinformation. “The Seeker’s Lamp.com” and “Hochmah Media INC” are not responsible for misinformation in the AI Generated Translations. Always cross-check with trusted human editions and primary sources.

Leave a Comment