Merge remote-tracking branch 'origin/development' into upg100/merge

# Conflicts:
#	package.json
This commit is contained in:
Doxa Maps 2026-09-29 15:54:05 +00:00
commit 14096e19c2
66 changed files with 643 additions and 117 deletions

View file

@ -0,0 +1,131 @@
#!/usr/bin/env node
// check-leaf-hints — a map leaf gives the browser its origins early; a non-map leaf carries no map hint.
//
// ★ WHY. A first visit to a map leaf ran serially: leaf HTML → the bundle (250–470 KiB gz, parsed) →
// only THEN the engine (from cdn.jsdelivr.net or api.mapbox.com) → the style host → tiles → data. Four
// origins, discovered one after another, none pre-connected — the shape behind A9's 3–5 s cold map
// (_qa-cycle/03-deployment-cycle/A9-MAP-LOAD-STATIC.md). generate-tree now emits, per MAP leaf, a
// preconnect for the engine + style + data origins and (on the 'auto' leaf, which carries no engine
// <script>) a preload of the engine, so DNS/TLS and the engine start alongside the bundle.
//
// This is the two-sided guard, matching check:leaf-engine-per-provider's stance (a non-map leaf loads no
// map peer). It reads the BUILT tree's leaf pages:
// 1. every MAP leaf (one that draws tiles — its page carries an engine peer or the "auto" no-tags note)
// must carry the A9 preconnect hints;
// 2. no NON-MAP leaf (grid / card / chart-table / app-shell / composite: "NO map peer") may carry any
// map-engine hint (preconnect to an engine/style origin, or an engine preload) — dead weight that
// also implies a gate.
// A hint's origin must be one the code actually uses (library/constants/cdn.js + the MapLibre style host),
// so a stale origin cannot pass. Node only: reads files, starts nothing. Exit 0 pass/skip, 1 fail.
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { TREE_NAME } from './_tree-name.mjs'
import { CDN } from '../library/constants/cdn.js'
const REPO = resolve(dirname(fileURLToPath(import.meta.url)), '..')
const TREE = join(REPO, 'public', TREE_NAME)
if (!existsSync(TREE)) {
console.log(`LEAF-HINTS: SKIP — no tree at ${TREE} (run bun run tree first)`)
process.exit(0)
}
const ORIGIN = (u) => { try { return new URL(u).origin } catch { return '' } }
// The origins a hint may name, from the same registry the runtime reads + the MapLibre style host.
const ENGINE_ORIGINS = [ORIGIN(CDN.mapboxGlJs.url), ORIGIN(CDN.maplibreGlJs.url)]
const STYLE_ORIGINS = ['https://tiles.openfreemap.org', ORIGIN(CDN.mapboxGlJs.url)]
const MAP_ORIGINS = new Set([...ENGINE_ORIGINS, ...STYLE_ORIGINS].filter(Boolean))
const HINTS = 'A9 hints'
const ENGINE_RE = /useMapInstance|useMapProvider|mapbox-gl|maplibre-gl|window\.(?:mapboxgl|maplibregl)/
// The rule the generator applies (mapPageHtml → drawsMapInPage): a leaf gets A9 hints iff its OWN page
// loads a map engine — a real map leaf (`isMap`), OR a cap-4 `nested-elements-mfe` composite whose bundle
// mounts a map inline (`bundleLoadsEngine`) — and it is not a cap-5 `nested-mfe-spa` shell (its maps are
// iframe children). A plain non-map leaf that merely SHARES a bundle with a map leaf gets none. The gate
// reads the same authoritative facts: profile `type`/`isMap` from the manifest, and the built bundle. So
// the gate and the generator cannot drift.
const manifest = JSON.parse(readFileSync(join(TREE, 'manifest.json'), 'utf8'))
const engineBundles = new Map()
function oneBundleLoadsEngine(bundle) {
if (!engineBundles.has(bundle)) {
let hit = false
try { hit = ENGINE_RE.test(readFileSync(join(TREE, bundle, `${bundle}.js`), 'utf8')) } catch { hit = false }
engineBundles.set(bundle, hit)
}
return engineBundles.get(bundle)
}
// Element tag → owning bundle (mirrors generate-tree): a composes entry may name a child by element tag.
const elementToBundle = new Map()
for (const b of manifest.bundles || []) for (const e of (b.elements || [])) elementToBundle.set(e, b.bundle)
// This bundle OR any bundle it composes loads an engine (mirrors generate-tree's builtBundleLoadsEngine):
// catches a composite whose engine lives in a lazily-fetched child (research-map-plus-grid → doxa-research-map).
function bundleLoadsEngine(bundle, composes) {
if (oneBundleLoadsEngine(bundle)) return true
for (const c of composes || []) {
const tag = String(c).split('/').pop()
const child = elementToBundle.get(tag) || String(c).split('/')[0]
if (child && child !== bundle && oneBundleLoadsEngine(child)) return true
}
return false
}
// Expected hint state per profile, and the leaf dirs it renders to (profile page + any instance pages).
const expect = new Map() // "<bundle>/<profile>" -> boolean shouldHint
for (const b of manifest.bundles || []) {
for (const p of b.profiles || []) {
const shell = p.type === 'nested-mfe-spa'
const composite = p.type === 'nested-elements-mfe'
const shouldHint = (!!p.isMap || (composite && bundleLoadsEngine(b.bundle, b.composes))) && !shell
expect.set(`${b.bundle}/${p.profile}`, shouldHint)
}
}
// Every leaf index.html under the tree, mapped back to its "<bundle>/<profile>".
function leaves(dir, out = []) {
for (const e of readdirSync(dir)) {
const p = join(dir, e)
if (statSync(p).isDirectory()) leaves(p, out)
else if (e === 'index.html') out.push(p)
}
return out
}
// rel is "<bundle>/<profile>[/<instance>]"; the profile key is the first two segments.
const keyOf = (rel) => rel.split('/').slice(0, 2).join('/')
const fails = []
let hinted = 0
let bare = 0
let unclassified = 0
for (const file of leaves(TREE)) {
const html = readFileSync(file, 'utf8')
const rel = file.slice(TREE.length + 1)
const key = keyOf(rel)
if (!expect.has(key)) { unclassified += 1; continue } // a non-profile page (e.g. tree root) — not our subject
const shouldHint = expect.get(key)
const hasHints = html.includes(HINTS)
const preconnects = [...html.matchAll(/<link rel="preconnect" href="([^"]+)"/g)].map((m) => m[1])
const enginePreload = /<link rel="preload" as="script" href="([^"]+maplibre-gl[^"]*|[^"]+mapbox-gl[^"]*)"/.test(html)
const mapHint = preconnects.some((o) => MAP_ORIGINS.has(o)) || enginePreload
if (shouldHint) {
if (!hasHints) fails.push(`${rel}: loads a map engine in its own page but has NO A9 hints`)
else hinted += 1
for (const o of preconnects) {
if (!MAP_ORIGINS.has(o) && !/^https:\/\/[a-z0-9.-]+$/i.test(o)) fails.push(`${rel}: malformed preconnect origin ${o}`)
}
} else {
if (mapHint || hasHints) fails.push(`${rel}: does not load a map engine in its own page, yet carries a map-engine hint`)
else bare += 1
}
}
const maps = hinted, nonMaps = bare
if (maps === 0) fails.push('no map leaves found in the tree: the classifier or the tree is wrong')
if (fails.length) {
console.error(`LEAF-HINTS: FAIL — ${fails.length} problem(s)`)
for (const f of fails.slice(0, 30)) console.error(` ✗ ${f}`)
if (fails.length > 30) console.error(` … and ${fails.length - 30} more`)
process.exit(1)
}
console.log(`LEAF-HINTS: PASS — ${maps} map leaf/leaves carry engine-aware hints; ${nonMaps} non-map leaf/leaves carry none`)

View file

@ -838,8 +838,84 @@ function bundleHtml(b, index, manifest) {
* opts.tokenUrlExpr sources.json mapboxTokenUrl value (data-safe URL or global name)
* opts.bakedToken opt-in literal token baked from build-config (ladder rung 3)
*/
// The origins a map leaf touches, from the ONE registry the runtime reads (library/constants/cdn.js)
// plus useMapInstance's MapLibre style host. Origins only (preconnect wants an origin, not a file).
const ORIGIN = (u) => { try { return new URL(u).origin } catch { return '' } }
const ENGINE_ORIGIN = { mapbox: ORIGIN(CDN.mapboxGlJs.url), maplibre: ORIGIN(CDN.maplibreGlJs.url) }
const MAPLIBRE_STYLE_ORIGIN = 'https://tiles.openfreemap.org' // useMapInstance.js OPENFREEMAP_STYLE/_DARK
/**
* Which engine a map leaf will use, decided at BUILD time from the same inputs the runtime ladder reads
* (see mapPageHtml's token block): profile-config.provider, then whether a token is derivable now — a
* baked token, or a token endpoint (tokenUrl / window.MAP_TOKEN_URL). 'auto' with no token path is
* MapLibre, keyless. The runtime can still be overridden by ?tk=/?provider=/window.MAP_PROVIDER/a stored
* token; the hint follows the build default and the report names that miss case (one unused preconnect).
*/
function engineFor({ config }) {
// CORRECTED 2026-09-29 (regions executed the shipping resolver; rega's A9NET confirmed on the wire):
// a token no longer selects Mapbox. useMapProvider's default is MapLibre unless provider is EXPLICITLY
// 'mapbox'. rega measured all 8 auto leaves — which DO carry a pray.doxa.life token endpoint — loading
// MapLibre from jsdelivr cold. So the hint's engine is Mapbox ONLY when provider:'mapbox' is set; every
// other case (auto, or provider:'maplibre') is MapLibre, regardless of any baked token / tokenUrl.
return String((config && config.provider) || '').toLowerCase().trim() === 'mapbox' ? 'mapbox' : 'maplibre'
}
/**
* Engine-aware resource hints for a map leaf's <head>. preconnect the token-implied engine origin, the
* style host and the data origin; and, ONLY for the 'auto' leaf (which emits no engine <script> today),
* preload the engine from cdn.js so it downloads alongside the bundle instead of after it. The 'maplibre'
* and 'mapbox' branches already carry a static engine tag (mapPageHtml's peerBlock / the embed snippet),
* so a preload there would double-fetch — those get preconnects only. Returns '' for a non-map leaf.
*/
function resourceHints({ isMapLibre, config, apiBaseUrl }) {
const engine = engineFor({ config })
const styleOrigin = engine === 'maplibre' ? MAPLIBRE_STYLE_ORIGIN : ENGINE_ORIGIN.mapbox
const dataOrigin = ORIGIN(apiBaseUrl) // '' when same-origin (no build apiBaseUrl): nothing to preconnect
const origins = [...new Set([ENGINE_ORIGIN[engine], styleOrigin, dataOrigin].filter(Boolean))]
const lines = origins.map((o) => ` <link rel="preconnect" href="${o}" crossorigin />`)
// Preload the engine UNLESS the leaf already emits a static engine <script>. Only a provider:'maplibre'
// leaf does (peerBlock); the 'auto' leaf and a provider:'mapbox' leaf emit no static tag (the Mapbox
// static tags were removed 2026-09-25), so both benefit from a preload. URL+integrity+crossorigin from
// cdn.js so it matches ensureEngineScript's tag exactly (a mismatched preload is not reused).
if (!isMapLibre) {
const gl = engine === 'maplibre' ? CDN.maplibreGlJs : CDN.mapboxGlJs
lines.push(` <link rel="preload" as="script" href="${gl.url}" integrity="${gl.integrity}" crossorigin="anonymous" />`)
}
return lines.length ? ` <!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->\n${lines.join('\n')}\n` : ''
}
// Does this BUILT bundle .js reference a map engine? Read from public/<tree>/<bundle>/<bundle>.js with the
// same regex the source classifier uses — the directly verifiable A9-leaf-hint signal.
function oneBundleLoadsEngine(bundleName) {
try { return MAP_ENGINE_RE.test(readFileSync(join(DEFAULT_ROOT, bundleName, `${bundleName}.js`), 'utf8')) }
catch { return false }
}
// Element tag → owning bundle, built once from the scanned bundles so a composes entry that names a
// child by its ELEMENT tag (stack-demo composes "research-dashboard-map", whose bundle is
// "research-dashboard") resolves to the right bundle, not a non-existent dir.
let ELEMENT_TO_BUNDLE = null
function setElementToBundle(bundles) {
ELEMENT_TO_BUNDLE = new Map()
for (const b of bundles) for (const e of (b.elements || [])) ELEMENT_TO_BUNDLE.set(e, b.bundle)
}
// Does a leaf's PAGE end up loading an engine? True if its own bundle does, OR any bundle it `composes`
// does — the latter catches a composite whose engine lives in a lazily-fetched child (research-map-plus-grid
// composes doxa-research-map: its own bundle has 0 engine refs, the child's has 74). A `composes` entry is
// "<bundle>/<profile>", a bare bundle, or an element TAG — resolved to a bundle via ELEMENT_TO_BUNDLE, then
// the bundle's first segment. Verifiable from built files, so the gate can mirror it. Excludes a composite
// that composes only non-maps (big-picture).
function builtBundleLoadsEngine(bundleName, composes) {
if (oneBundleLoadsEngine(bundleName)) return true
for (const c of composes || []) {
const tag = String(c).split('/').pop()
const child = (ELEMENT_TO_BUNDLE && ELEMENT_TO_BUNDLE.get(tag)) || String(c).split('/')[0]
if (child && child !== bundleName && oneBundleLoadsEngine(child)) return true
}
return false
}
function mapPageHtml(opts) {
const { title, tag, config, jsSrc, apiBaseUrl, tokenUrlExpr, bakedToken, integrity, shellTokenFree, isMap, scrollPage, isComposite } = opts
const { title, tag, config, jsSrc, apiBaseUrl, tokenUrlExpr, bakedToken, integrity, shellTokenFree, isMap, scrollPage, isComposite, bundleLoadsEngine } = opts
const apiScript = apiBaseUrl
? `\n <script>window.MAP_APP_API_URL = ${JSON.stringify(apiBaseUrl)};</script>`
: ''
@ -876,6 +952,26 @@ function mapPageHtml(opts) {
// EVERY non-map leaf (cap-4 composites + cap-1/2/3 non-map leaves), not just cap-5 shells.
const shellOnly = !!shellTokenFree || notAMap
const tokenFree = isMapLibre || shellOnly
// A9 leaf hints (dx-base/a9-leaf-hints): give the browser the map's origins BEFORE the bundle
// parses. Engine-aware, derived from the SAME inputs the runtime ladder reads (below), never
// hardcoded: preconnect the token-implied engine + the style host + the data origin, and — only
// where the leaf emits no engine <script> today (the 'auto' leaf) — preload the engine, its URL,
// integrity and crossorigin from library/constants/cdn.js so it cannot drift from the runtime tag.
// WHO GETS HINTS: any page whose OWN bundle loads a map engine — the directly verifiable signal
// (`bundleLoadsEngine`, an engine reference in the built .js), NOT the leaf's `isMap` flag. rega's A9
// net run found regions-mfe (isMap:false, 56 engine refs in its bundle) AND research-map-plus-grid
// (isMap:false, own bundle 0 refs but composes doxa-research-map, 74 refs) opening cdn.jsdelivr.net +
// tiles.openfreemap.org from the top page and getting no hints — my first cut keyed on isMap and missed
// both, the same trap check:leaf-engine-per-provider's isMap gate fell into. bundleLoadsEngine is true
// when the leaf's own bundle OR any bundle it composes loads an engine, so both composites are covered;
// a composite that composes only non-maps (big-picture) stays out. A cap-5 nested-mfe-spa shell
// (shellTokenFree) is excluded even if it references an engine: its maps render in their OWN iframe
// leaves, which carry hints. A plain non-map leaf (a list/card) can SHARE a bundle with a map leaf
// (connectivity-list rides the cities-internet bundle) — so the `isComposite &&` guard keeps the bundle
// signal from over-hinting it: the engine only mounts in-page for a real map leaf (drawsMap) or a cap-4
// composite (isComposite) that stacks a map child; a non-map, non-composite leaf never opens it.
const drawsMapInPage = (drawsMap || (isComposite && bundleLoadsEngine)) && !shellTokenFree
const hintBlock = drawsMapInPage ? resourceHints({ isMapLibre, config, apiBaseUrl }) : ''
const peerBlock = shellOnly
? `<!-- NON-MAP leaf (app-shell / composite / grid / card / chart-table): NO map peer.
This element draws no map tiles, so it needs no Mapbox/MapLibre engine and MUST NOT
@ -908,7 +1004,7 @@ function mapPageHtml(opts) {
<script>window.MAP_OWNS_PAGE = true;</script>
<title>${esc(title)}</title>
<link rel="icon" href="data:,">
${peerBlock}
${hintBlock} ${peerBlock}
<style>
${scrollPage
? `/* SCROLL-PAGE leaf (cap-4 nested-elements-mfe composite: a StackLayout scroll-stack). The DOCUMENT
@ -1182,6 +1278,8 @@ function profileHtml(b, profile, tokenUrlExpr, bakedToken) {
// Whether this leaf actually draws map tiles (computed in scanBundles → isMapLeaf). A
// non-map leaf renders token-free with no map peer; only a real map runs the token ladder.
isMap: profile.isMap,
// Whether this bundle's OWN built .js loads a map engine — the A9-leaf-hint signal (mapPageHtml).
bundleLoadsEngine: builtBundleLoadsEngine(b.bundle, b.composes),
// A cap-4 composite (nested-elements-mfe) is a StackLayout SCROLL-STACK: its leaf must let the
// DOCUMENT own the scroll (height:auto, no position:fixed) so the page grows and a reader scrolls
// PAST one section to the next. A fixed-viewport leaf traps a 100vh dashboard and nothing scrolls
@ -1216,6 +1314,8 @@ function instanceHtml(b, profile, inst, tokenUrlExpr, bakedToken) {
// Instance pages inherit the profile's map-ness: a preset of a non-map leaf is still a
// non-map (token-free, no peer); a preset of a real map still runs the token ladder.
isMap: profile.isMap,
// Same bundle as the profile page, so the same engine signal (A9-leaf-hint, mapPageHtml).
bundleLoadsEngine: builtBundleLoadsEngine(b.bundle, b.composes),
// A preset of a cap-4 composite scroll-stack is still a scroll page (see profileHtml).
scrollPage: profile.type === 'nested-elements-mfe',
})
@ -1531,6 +1631,7 @@ function readDestinations() {
}
function writeManifestAndHtml(root, bundles, tokenUrlExpr, bakedToken) {
setElementToBundle(bundles) // for builtBundleLoadsEngine's tag→bundle resolution (A9 leaf hints)
// ── DERIVE THE COMPOSITION TIER FROM THE EDGES, BEFORE ANYTHING READS THE MANIFEST ──────────
// Every consumer downstream — the gallery's capFor, the studio rail, check:composite-embed-knobs —
// trusts profile.type. Deriving here means a composite can no longer ship understated because its

View file

@ -151,6 +151,7 @@
"check:language-tree-layout": "node internal/check-language-tree-layout.mjs",
"check:layout-key-namespaced": "node plugin-designs/research-dashboard/scripts/check-layout-key-namespaced.mjs",
"check:leaf-engine-per-provider": "node internal/check-leaf-engine-per-provider.mjs",
"check:leaf-hints": "node internal/check-leaf-hints.mjs",
"check:leaf-english-leaks": "node internal/check-leaf-english-leaks.mjs",
"check:leaf-english-leaks:self-test": "node internal/check-leaf-english-leaks.mjs --self-test",
"check:leaves-mount": "node internal/check-gospel-leaves-mount.mjs",
@ -334,7 +335,7 @@
"dev": "bun x vite",
"fix:sri": "node internal/fix-sri.mjs",
"gallery": "node internal/generate-gallery.mjs",
"gates:post": "node internal/run-parallel.mjs --label=post -- check:capability-derived check:drop check:parse verify check:sri check:public-hygiene check:label-joins check:facet-cascade check:facet-one-field check:heartbeat check:kpi-unit check:composite-reg check:descriptions check:no-abs-paths check:no-codename check:dep-names check:composite-srcs check:embed-targets check:nested-token check:i18n-parity check:tabs-localized check:packets-all check:packet-strings-parity check:zone-census check:zoning-declared check:share-policy check:library-index check:csv-shape check:capability-citations check:catalog-identity check:no-orphan-gates check:quoted-scripts check:done-evidence check:script-flags check:backlog-status check:capability-exemplars check:packet-fixture check:packet-browser check:provider-switch check:locale-reachable check:url-resolver check:manifest-covers check:one-palette check:pin-dim-slider check:legend-source check:backlog-refs check:clustering-modes check:composite-embed-knobs check:composite-locale-leaks check:linked-vocabulary check:wp-embed check:dashboard-geocoder-provider check:leaf-engine-per-provider check:auto-engine check:engine-contract check:map-props-unit check:composites-mount check:composite-interop check:no-free-identifiers check:map-fly-reduced-motion check:mst-clustering check:list-prop-unit check:profiles-mount check:cdn-pins check:no-eval check:popup-escaping check:i18n-treeshake check:pinned-umd check:one-palette:self-test check:no-cross-plugin-imports check:no-cross-plugin-imports:self-test check:map-attribution check:studio-rail check:approx-pin-note check:embedder-keys check:provider-for check:legend-logical-insets check:legend-logical-insets:self-test check:optional-t-equivalence check:text-highlight check:religion-label-not-value check:i18n-stopped-scope check:no-silent-engine check:no-silent-engine:self-test check:regions-uses-library check:shadow-css-parses check:square-map-controls check:preset-config-merge check:instance-config-keys check:frozen-labels check:plural-forms check:region-fill-repaint check:region-paint-single-source check:poster-print-fallback check:posters-exportable check:country-names check:reduced-motion check:no-dead-library check:universal-props check:readme-size check:tree-relative check:snippet-engine check:snippet-engine:self-test check:embed-base check:link-coverage check:no-public-binds check:shared-reached check:tree-weight",
"gates:post": "node internal/run-parallel.mjs --label=post -- check:capability-derived check:drop check:parse verify check:sri check:public-hygiene check:label-joins check:facet-cascade check:facet-one-field check:heartbeat check:kpi-unit check:composite-reg check:descriptions check:no-abs-paths check:no-codename check:dep-names check:composite-srcs check:embed-targets check:nested-token check:i18n-parity check:tabs-localized check:packets-all check:packet-strings-parity check:zone-census check:zoning-declared check:share-policy check:library-index check:csv-shape check:capability-citations check:catalog-identity check:no-orphan-gates check:quoted-scripts check:done-evidence check:script-flags check:backlog-status check:capability-exemplars check:packet-fixture check:packet-browser check:provider-switch check:locale-reachable check:url-resolver check:manifest-covers check:one-palette check:pin-dim-slider check:legend-source check:backlog-refs check:clustering-modes check:composite-embed-knobs check:composite-locale-leaks check:linked-vocabulary check:wp-embed check:dashboard-geocoder-provider check:leaf-engine-per-provider check:auto-engine check:engine-contract check:map-props-unit check:composites-mount check:composite-interop check:no-free-identifiers check:map-fly-reduced-motion check:mst-clustering check:list-prop-unit check:profiles-mount check:cdn-pins check:no-eval check:popup-escaping check:i18n-treeshake check:pinned-umd check:one-palette:self-test check:no-cross-plugin-imports check:no-cross-plugin-imports:self-test check:map-attribution check:studio-rail check:approx-pin-note check:embedder-keys check:provider-for check:legend-logical-insets check:legend-logical-insets:self-test check:optional-t-equivalence check:text-highlight check:religion-label-not-value check:i18n-stopped-scope check:no-silent-engine check:no-silent-engine:self-test check:regions-uses-library check:shadow-css-parses check:square-map-controls check:preset-config-merge check:instance-config-keys check:frozen-labels check:plural-forms check:region-fill-repaint check:region-paint-single-source check:poster-print-fallback check:posters-exportable check:country-names check:reduced-motion check:no-dead-library check:universal-props check:readme-size check:tree-relative check:leaf-hints check:snippet-engine check:snippet-engine:self-test check:embed-base check:link-coverage check:no-public-binds check:shared-reached check:tree-weight",
"gates:pre": "node internal/run-parallel.mjs --label=pre -- check:template-literal check:mjs-parse check:sfc-parse check:tab-radius check:synced-css check:doc-scripts check:setup-order check:package-json-unique-keys check:no-repo-pb-hooks check:no-credentials-omit check:no-credentials-omit:self-test check:shadow-reduced-motion check:poster-action-print check:targets check:targets:self-test check:browser-gates-guarded check:pin-selection check:facet-shape check:hardcoded-english:self-test check:list-selection check:selector-fields check:upg-zone-joins check:gospel-set-charts check:gospel-set-fit check:describe-group check:one-scroll-container check:packet-charts check:composite-token-url check:language-tree-layout check:i18n-keys-exist check:i18n-never-translated check:packet-variants check:profile-table check:element-bootstrap check:embed-url-absolute check:frame-target check:language-tree-model check:map-menu-anchor check:selection-kinds check:tiered-points check:whiteboard-projection check:mercator-slice check:ring-vocabulary check:map-props-unit check:mobile-gating check:provide-shadowing check:legend-top-offset check:cdn-cache check:plural-forms check:select-zone-race check:script-registry check:map-control-overlap check:poster-attribution check:board-map-options check:gospel-whiteboard check:packet-map-missing-loud check:poster-layout-optin check:ported-globals-identical check:ring-bands check:packet-a1-structure check:zone-title-tier-a check:evangelical-share check:map-labels check:packet-offline check:help-reachable check:gated-not-in-tree check:window-globals-released check:legend-data-contract check:no-new-driver-references check:poster-fetch-guard check:people-group-records check:sentence-slots check:popup-href-escaped check:popup-pan-controls check:viewport-meta check:viewport-meta:self-test check:label-key-coverage check:poster-browser-equiv check:poster-render-pinned check:host-locale-fetch check:print-frame-reclaim check:click-sheet check:coverage-consistent:chained check:coverage-consistent:poison check:dashboard-filter-a11y check:filter-multivalue check:hover-channel check:kit-options-reachable check:layout-key-namespaced check:legend-mirrors check:map-unmount-race check:no-conflict-markers check:series-isolation check:snapshot-guard check:stale-sweep-claim check:surfaces-read-the-tier check:translator-contacts check:dxlife check:wall-wysiwyg check:wall-print-watch check:wall-no-bg-photos check:template-i18n check:list-pattern-doc",
"gen:iso3-to-alpha2": "node library/scripts/generate-iso3-to-alpha2.mjs",
"internet:adm1": "node plugin-designs/cities-internet/scripts/build-adm1-internet.mjs",
@ -482,6 +483,7 @@
"check:language-tree-layout": "the library language-tree layout builder (library/scripts): families packed without overlap, every roster language reachable. Headless; in gates:pre.",
"check:layout-key-namespaced": "two dashboards on one page must not share a saved layout. useDashboardLayout persists the four divider positions to localStorage, and until kit landing 2 the key was a single constant — invisible while there was exactly one dashboard, and SHARING THE ENGINE IS WHAT MAKES A SECOND ONE POSSIBLE, so SPEC-DASHBOARD-KIT section 8 named it as that landing's risk. The failure is quiet rather than loud: drag a divider in one dashboard, reload, and the other has moved. Asserts the shell passes no bare literal, EVALUATES the real expression with two different dashboard ids to prove the key varies (never a retyped copy of the rule), and that the pre-namespacing key is READ and never written — namespacing must not silently discard a reader's layout, and a migration that also deletes cannot be rolled back. Static; no DOM, no browser.",
"check:leaf-engine-per-provider": "every leaf in the manifest at ?provider=maplibre makes ZERO requests to any *.mapbox.com host and a map leaf still draws; at its default every map leaf draws with the engine it drew with before (read from the canvas that drew). --baseline <tree> compares against another tree (e.g. main). Browser gate, @browser-slot-max-hold 2700.",
"check:leaf-hints": "a map leaf gives the browser its origins early; a non-map leaf carries no map hint. generate-tree emits, per map leaf, a preconnect for the engine + style + data origins and (on the auto leaf) an engine preload from library/constants/cdn.js, so DNS/TLS and the engine start with the bundle instead of after it (A9). Two-sided: a map leaf without hints fails, a non-map leaf with an engine hint fails; a hint origin must be one the code uses. Reads the built tree; no server.",
"check:leaves-mount": "DID THE ELEMENT ACTUALLY MOUNT, on all five gospel leaves. Exists because a ReferenceError thrown during setup dies INSIDE the custom-element boundary: the page loads, every asset returns 200, pageerror fires zero times, and the element sits there with an empty shadow root. A healthy-looking dead page. This asks the cheap unambiguous question the rich gates are too slow to ask on every leaf — is anything there — in five steps that each name their own failure: tag defined, host present, shadowRoot attached, shadow root non-empty, visible text rendered. It does NOT trust the absence of console errors; zero errors is not the same as working. --poison for the negative test.",
"check:legend-data-contract": "nobody may read a key off useLegendData that it does not return. It returns items, never rows; two plugins read legend.rows anyway and JavaScript answered undefined, so the same mistake surfaced as a THROWN Export poster in countries-map (exp NE-17) and as a silently BLANK poster legend in research-map. The returned key set is read from the composable rather than restated. NOT in gates:pre yet: it still reports countries-map, which is another owner's file (exp's d6916e05e covers .rows but not the dead .build/.refresh calls). Run it directly.",
"check:legend-export-reachable": "the Export affordance must be reachable at BOTH widths. Selects a leaf row first (the control is gated on selectedNode) and opens the mobile sheet first (it starts closed). Asserts a REAL BOX, not CSS visibility — on mobile the elements report visibility:visible at 0x0. PASSES at both widths since the mobile sheet was given :export-enabled and :tabs. SKIPs when nothing is served.",

View file

@ -150,6 +150,17 @@ const band = (a) => a === 'yes' ? 'ok' : a === 'partial' ? 'mid' : a === 'no' ?
const bandLabel = (a) => t('connectivity.list.band.' + (['yes', 'partial', 'no'].includes(a) ? a : 'unknown'))
useShadowStyles(
// ★ THE LIST MUST STAY INSIDE ITS HOST BOX. This element had NO :host rule, so a custom element
// falls back to display:inline with no height of its own, and .ci below — position:absolute;inset:0
// — resolved against whatever the PARTNER page happened to have positioned. rega measured the result
// on a partner page: content painting to y=16,799, which is 16,355px BELOW a 420px host box.
// display:block gives it a box; position:relative makes that box the containing block .ci resolves
// against; height:100% lets a definite-height slot decide; min-height is the floor for an AUTO-height
// host, which grows to fit instead of collapsing to nothing. .ci already carries overflow-y:auto, so
// once it is contained the list SCROLLS inside the box rather than overflowing it — no new scroll
// container is needed, only a host for the one that is already there.
// Pattern: regions-list.vue:408, plus the position:relative that connectivity-map needed (60cb4ff18).
':host{display:block;position:relative;width:100%;height:100%;min-height:320px}' +
'.ci{position:absolute;inset:0;overflow-y:auto;padding:20px 18px 44px;background:#f6f7f9;color:#0f1419;' +
"font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif}" +
'.ci.is-dark{background:#0a1410;color:#e5e7eb}' +

View file

@ -88,6 +88,12 @@ watch(current, (t) => t && ensure(t.file), { immediate: true })
const table = computed(() => cache.value[current.value?.file] || null)
useShadowStyles(
// ★ THE TABLE MUST STAY INSIDE ITS HOST BOX — the same defect and the same fix as connectivity-list.
// With no :host rule the element is inline with no height, and .ct (position:absolute;inset:0)
// resolved against the partner page's positioned ancestor instead of this element. rega measured
// content painting to y=1,698, which is 1,254px BELOW a 420px host box.
// .ct already has overflow-y:auto, so containing it is enough to make the table scroll in the box.
':host{display:block;position:relative;width:100%;height:100%;min-height:320px}' +
'.ct{position:absolute;inset:0;overflow-y:auto;padding:18px;background:#f6f7f9;color:#0f1419;' +
"font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif}" +
'.ct.is-dark{background:#0a1410;color:#e5e7eb}' +

View file

@ -39,6 +39,7 @@ import GiDrawer from './src/components/GiDrawer.vue'
import GiTree from './src/components/GiTree.vue'
import GiResources from './src/components/GiResources.vue'
import GiCombos from './src/components/GiCombos.vue'
import { isNarrowWidth } from './src/breakpoints.js'
const T = useGiT()
const board = useBoard()
@ -76,7 +77,7 @@ board.readUrl()
// partner's address bar is never rewritten. facetKeys is explicit: its default reads nothing on a cold load.
useShareableView(bus, { mode: 'query', write: board.profileConfig.value?.urlState === 'query', facetKeys: SHARE_FACETS })
// ── responsive: one panel at a time under 760px (ResizeObserver on the shell, not @container: a
// ── responsive: one panel at a time under the shared breakpoint (ResizeObserver on the shell, not @container: a
// container query cannot target the container itself, which is unreliable inside a shadow root) ──────
const shell = ref(null)
const isNarrow = ref(false)
@ -84,7 +85,7 @@ const mobilePanel = ref('map')
let ro = null
onMounted(() => {
if (shell.value && typeof ResizeObserver !== 'undefined') {
ro = new ResizeObserver(([e]) => { isNarrow.value = e.contentRect.width < 760 })
ro = new ResizeObserver(([e]) => { isNarrow.value = isNarrowWidth(e.contentRect.width) })
ro.observe(shell.value)
}
board.load()

View file

@ -0,0 +1,18 @@
/**
* breakpoints.js — the one width at which this dashboard stops being a three-column board.
*
* ★ IT IS A CONSTANT BECAUSE IT WAS TWO NUMBERS. board.vue collapsed to a single panel below
* 760px; the set charts stacked their legend below 900px. Between those two widths the board
* still held three columns while a chart inside it had already given up on having room — at
* 768 the centre column was about 145px, so the bounded figure was crushed to 124px and the
* centered figure's own minimum made it spill UNDER the right-hand panel.
*
* Neither number was wrong on its own. The defect was that they were separate, and nothing
* connected the width at which a chart needs room to the width at which the board gives it any.
*/
export const NARROW_MAX = 900
/** True when the shell is too narrow for side panels beside the centre column. */
export function isNarrowWidth(px) {
return Number(px) < NARROW_MAX
}

View file

@ -28,6 +28,7 @@ import { layoutCenteredSet, ringTally, inwardArrow, ringRadii } from '@map/compo
import GiRingLegend from './GiRingLegend.vue'
import GiCenteredSetMap from './GiCenteredSetMap.vue'
import FullscreenButton from '@map/components/map-controls/FullscreenButton.vue'
import { NARROW_MAX } from '../breakpoints.js'
const T = useGiT()
const board = useBoardState()
@ -70,7 +71,10 @@ function applyWidth(m) {
function setLegendOpen(v) { chosen = v; legendOpen.value = v }
onMounted(() => {
try {
mq = window.matchMedia('(max-width: 900px)')
// The same width the BOARD collapses at (NARROW_MAX). If these two ever disagree again,
// the board keeps its side panels while the chart has already given up on room — which is
// exactly the 768px failure.
mq = window.matchMedia(`(max-width: ${NARROW_MAX - 1}px)`)
applyWidth(mq)
mq.addEventListener?.('change', applyWidth)
} catch (_) { /* no matchMedia: stay wide, which is the layout that always fits */ }

View file

@ -350,6 +350,21 @@ const gap = computed(() => {
const fmt = (n) => (Number(n) || 0).toLocaleString()
useShadowStyles(
// ★ STANDALONE THIS NEEDS A HOST; COMPOSED IT MUST NOT BE CLAMPED. Two facts make one rule safe:
// 1. STANDALONE (data-tables.meta.json) this mounts as its own custom element, so :host applies and
// .gt — position:absolute;inset:0 — resolves against it. Without a :host rule the element is
// inline with no height and .gt escapes to whatever the PARTNER page has positioned, the same
// defect measured in cities-internet (16,355px below a 420px box) and connectivity-map.
// 2. COMPOSED, gospel-dashboard renders <DataTables/> as an INLINE Vue component, not a custom
// element. It has no shadow host of its own there, so :host matches NOTHING and cannot reach it;
// gospel-dashboard.vue:81 keeps its '.gd-tables .gt{position:static;…}' override, which is what
// lets the stacked section take its natural height and the PAGE scroll. That override recorded a
// measured failure (docScrollHeight 900 = clientHeight 900, a wheel gesture moving 0px) and must
// keep working.
// min-height, NOT height: with no height at all, .gt's absolute inset:0 gives the table 0px in an
// AUTO-height box — it would stop escaping and become invisible instead, which is not a fix. A floor
// gives an auto host something to grow from; a definite-height slot still decides via height:100%.
':host{display:block;position:relative;width:100%;height:100%;min-height:320px}' +
'.gt{position:absolute;inset:0;overflow-y:auto;padding:18px;background:#f6f7f9;color:#0f1419;' +
"font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif}" +
'.gt.is-dark{background:#0a1410;color:#e5e7eb}' +

View file

@ -447,7 +447,8 @@ const WIDGET_CSS = `
[data-wb-icon]{display:grid;place-items:center;flex:none;color:#38bdf8}
[data-wb-icon] svg,[data-wb-chev] svg{width:20px;height:20px;display:block}
[data-wb-text]{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
[data-widget-bubble][data-listening="true"]{width:min(300px,calc(100vw - 32px))}
/* ★ WHILE RECORDING THE PILL DOES NOT BREATHE. A recording pill that changes width on every word reads as instability. width alone was not enough: the bubble is inline-flex, so it still sizes to content wherever width loses — and it carries a max-width that the <=480px query overrides, which is exactly the phone case he was looking at. Truncating the text cannot fix it either: 33 CHARACTERS is 133px of "illi" and 344px of "MMM WOW", so a character count is not a width. min-width and max-width are pinned to the same value as width so no later rule and no viewport can let it grow or shrink; the text ellipsises inside it. */
[data-widget-bubble][data-listening="true"]{width:min(300px,calc(100vw - 32px));min-width:min(300px,calc(100vw - 32px));max-width:min(300px,calc(100vw - 32px))}
[data-widget-bubble][data-listening="true"] [data-wb-text]{flex:1 1 auto}
[data-wb-dot],[data-wb-chev]{display:none;flex:none}
[data-wb-dot]{width:10px;height:10px;border-radius:50%;background:#ef4444}
@ -465,6 +466,8 @@ const WIDGET_CSS = `
[data-studio-widgets$="left"]{left:max(8px,env(safe-area-inset-left))}
[data-widget-panel]{width:calc(100vw - 16px);max-width:none;height:60vh;height:60dvh}
[data-widget-bubble]{max-width:calc(100vw - 16px)}
/* ...but a RECORDING pill keeps its fixed width on a phone too, or it grows to the viewport. */
[data-widget-bubble][data-listening="true"]{width:min(300px,calc(100vw - 16px));min-width:min(300px,calc(100vw - 16px));max-width:min(300px,calc(100vw - 16px))}
}`
const WIDGET_ICON_OPEN = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M5 10v1a7 7 0 0 0 14 0v-1"/><path d="M12 18v4"/></svg>'
const WIDGET_ICON_CLOSE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>'

View file

@ -1148,13 +1148,43 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 1
.compact .bottom .mic.sm { padding: 9px 18px; font-size: 15px; gap: 6px; border-radius: 999px; }
.compact .bottom .mic.sm:not(.on) { background: var(--accent); color: #04121c; border-color: var(--accent); }
.compact .bottom .mic.sm.on { background: var(--rec); color: #fff; border-color: var(--rec); }
.compact .notice, .compact .hint { order: 0; font-size: 12.5px; padding: 8px 10px; }
/* ★ NOTICES SIT BELOW THE DRAFT IN THE CORNER PANEL, for the same reason they do on a phone: the
panel is short, and an engine-offline notice is several lines, so above the draft it eats the room
the draft needs. This used to say `order: 0`, which SILENTLY CANCELLED the phone rule below —
`.compact .notice` is (0,2,0) and the media query's `.notice` is (0,1,0), and a media query adds no
specificity, so the more specific rule won at every width and the notice stayed on top. The phone
rule (bac2431d0, 19:59) was already there; the corner widget (4e94e9216, 21:58) overrode it two
hours later without meaning to. Ordering it here fixes the widget at EVERY width, not only under
480px, because the corner panel is short regardless of the viewport. No floor is involved: a floor
is what clipped the draft in the first place. */
.compact .notice, .compact .hint { order: 1; font-size: 12.5px; padding: 8px 10px; }
/* ★ AND THE NOTICE YIELDS. Ordering it below the draft fixes the reading order but NOT the height:
.notice is flex:0 1 auto and .compact .compose is flex:1 1 0, so the draft still gives up whatever
the notice's content asks for. rega measured the result at 375x450 — a 20px draft whose wheel moves
nothing. The engine-offline notice is the long one (apiBase, Go 1.22, the setup command), ~132px at
375 and ~179px at 390, and it is REFERENCE text: a reader needs it once, not a third of a short
panel forever. Capping it and letting it scroll gives the draft 58px at 375x450 and 124px at
390x560, measured against the 60vh panel the corner widget actually gets (plugin-studio.vue:466),
not the viewport — sizing off the viewport is what made my first estimate wrong by 58px.
Again: no floor anywhere. A floor is what clipped the draft to begin with. */
.compact .notice { max-height: 96px; overflow-y: auto; overscroll-behavior: contain; }
.compact .debug { order: 4; }
/* A phone-sized panel: less padding, and a shorter draft so it stays in view below the controls. */
@media (max-width: 480px) {
.rudder { min-height: 100%; padding: 12px; gap: 10px; }
.compose { min-height: 200px; }
.draft { min-height: 180px; }
/* ★ THE TEXT AREA GETS THE LEFTOVER SPACE AND SCROLLS. On a phone the header can take most of the panel, leaving the draft unscrollable and its
last lines unreachable. The
panel is capped at 60vh here, and a min-height on the draft cannot fix that: a MINIMUM makes
the box refuse to shrink, so whatever the header takes is pushed off the bottom and the
draft's own scrollbar never appears. Lowering it from 240 to 180 only moved the threshold.
So the column owns the height (min-height:0 is what lets a flex child shrink BELOW its
content, and is the whole fix), the draft takes what is left and scrolls inside it, and the
header gives back the space it was holding. */
.rudder { min-height: 0; height: 100%; padding: 10px; gap: 8px; display: flex; flex-direction: column; }
.compose { min-height: 0; flex: 1 1 0; display: flex; flex-direction: column; }
.draft { min-height: 0; flex: 1 1 0; overflow-y: auto; resize: none; padding: 10px; }
.top { gap: 8px; row-gap: 6px; }
.bar .name { font-size: 13px; }
.bar .status { padding: 2px 7px; font-size: 11.5px; }
/* Notices (engine offline, mic muted, …) sit below the draft here, so the draft stays in view. */
.notice, .hint { order: 1; }
.bottom { order: 2; }

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>all-people-groups · all-people-groups</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

File diff suppressed because one or more lines are too long

View file

@ -61,7 +61,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <cities-internet-map> custom element. -->
<script src="../cities-internet.js" integrity="sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+" crossorigin="anonymous"></script>
<script src="../cities-internet.js" integrity="sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>connectivity-map · cities-internet</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
@ -65,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <cities-internet-map> custom element. -->
<script src="../cities-internet.js" integrity="sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+" crossorigin="anonymous"></script>
<script src="../cities-internet.js" integrity="sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -61,7 +61,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <cities-internet-map> custom element. -->
<script src="../cities-internet.js" integrity="sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+" crossorigin="anonymous"></script>
<script src="../cities-internet.js" integrity="sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>country-map · country-map</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>countries-map · country-posters</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>country-posters-mfe · country-posters</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>default · dashboard-plus-grid</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>dashboard-plus-grid · dashboard-plus-grid</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>demo-map · demo-map</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,10 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Demo map — MapLibre (token-free) · demo-map</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<!-- MapLibre peer (token-free engine) loaded ONCE here; the custom element
uses window.maplibregl directly (same versions as @map/composables/useMapInstance). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />

View file

@ -110,7 +110,7 @@
"bundle": "cities-internet",
"scriptUrl": "./cities-internet/cities-internet.js",
"output": "dx-maps/cities-internet/cities-internet.js",
"integrity": "sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+",
"integrity": "sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E",
"elements": [
"cities-internet-map"
],
@ -129,7 +129,7 @@
"scriptUrl": "./cities-internet/cities-internet.js",
"embed": {
"iframe": "<iframe src=\"./cities-internet/connectivity-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
}
},
{
@ -145,8 +145,8 @@
"scriptUrl": "./cities-internet/cities-internet.js",
"embed": {
"iframe": "<iframe src=\"./cities-internet/connectivity-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
}
},
{
@ -162,7 +162,7 @@
"scriptUrl": "./cities-internet/cities-internet.js",
"embed": {
"iframe": "<iframe src=\"./cities-internet/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
}
}
]
@ -653,7 +653,7 @@
"bundle": "gospel-internet",
"scriptUrl": "./gospel-internet/gospel-internet.js",
"output": "dx-maps/gospel-internet/gospel-internet.js",
"integrity": "sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO",
"integrity": "sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY",
"elements": [
"gospel-internet-board"
],
@ -674,8 +674,8 @@
"scriptUrl": "./gospel-internet/gospel-internet.js",
"embed": {
"iframe": "<iframe src=\"./gospel-internet/board/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-internet/gospel-internet.js\" integrity=\"sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-internet/gospel-internet.js\" integrity=\"sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>"
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-internet/gospel-internet.js\" integrity=\"sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-internet/gospel-internet.js\" integrity=\"sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>"
},
"instances": [
{
@ -782,7 +782,7 @@
"bundle": "gospel-resources",
"scriptUrl": "./gospel-resources/gospel-resources.js",
"output": "dx-maps/gospel-resources/gospel-resources.js",
"integrity": "sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP",
"integrity": "sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi",
"elements": [
"gospel-resources-map"
],
@ -805,7 +805,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/charts/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -821,7 +821,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -837,8 +837,8 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/gospel-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -854,7 +854,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/resources-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -870,8 +870,8 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/resources-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
}
]
@ -1010,7 +1010,7 @@
"bundle": "plugin-studio",
"scriptUrl": "./plugin-studio/plugin-studio.js",
"output": "dx-maps/plugin-studio/plugin-studio.js",
"integrity": "sha384-z28lk+j2l0xxtIiyBZr6EYjWlS/10epdE9ty6TRkVfHt6UuBj2Tq+V7Gf4+neaFm",
"integrity": "sha384-6eNQ4BMIc6DDKJRaAQJzMuWWdYDN2+Ipj+RA1Q9Jxc8T2HZqr+ECC+mm63knNIL6",
"elements": [
"plugin-studio"
],
@ -1041,7 +1041,7 @@
"scriptUrl": "./plugin-studio/plugin-studio.js",
"embed": {
"iframe": "<iframe src=\"./plugin-studio/plugin-studio/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-z28lk+j2l0xxtIiyBZr6EYjWlS/10epdE9ty6TRkVfHt6UuBj2Tq+V7Gf4+neaFm\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-6eNQ4BMIc6DDKJRaAQJzMuWWdYDN2+Ipj+RA1Q9Jxc8T2HZqr+ECC+mm63knNIL6\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
},
"instances": [
{

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>research-map · doxa-research-map</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,10 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Research map — MapLibre (token-free, no search bar) · doxa-research-map</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<!-- MapLibre peer (token-free engine) loaded ONCE here; the custom element
uses window.maplibregl directly (same versions as @map/composables/useMapInstance). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Adoption Map · doxa-simple-map</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Engagement Map · doxa-simple-map</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>doxa-simple-map · doxa-simple-map</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Prayer Map · doxa-simple-map</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Gospel x Internet — the board · gospel-internet</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
@ -65,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO" crossorigin="anonymous"></script>
<script src="../../gospel-internet.js" integrity="sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>board · gospel-internet</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
@ -65,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../gospel-internet.js" integrity="sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO" crossorigin="anonymous"></script>
<script src="../gospel-internet.js" integrity="sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>India and China by state and province · gospel-internet</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
@ -65,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO" crossorigin="anonymous"></script>
<script src="../../gospel-internet.js" integrity="sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Language tree — which languages have the gospel, family by family · gospel-internet</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
@ -65,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO" crossorigin="anonymous"></script>
<script src="../../gospel-internet.js" integrity="sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Platforms — which apps would carry a resource there · gospel-internet</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
@ -65,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO" crossorigin="anonymous"></script>
<script src="../../gospel-internet.js" integrity="sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Project 700 — the list as a partner embed · gospel-internet</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
@ -65,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO" crossorigin="anonymous"></script>
<script src="../../gospel-internet.js" integrity="sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Nothing in their own language — the front door · gospel-internet</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
@ -65,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO" crossorigin="anonymous"></script>
<script src="../../gospel-internet.js" integrity="sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -61,7 +61,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
<script src="../gospel-resources.js" integrity="sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP" crossorigin="anonymous"></script>
<script src="../gospel-resources.js" integrity="sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -61,7 +61,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
<script src="../gospel-resources.js" integrity="sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP" crossorigin="anonymous"></script>
<script src="../gospel-resources.js" integrity="sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>gospel-dashboard · gospel-resources</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
@ -76,7 +81,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
<script src="../gospel-resources.js" integrity="sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP" crossorigin="anonymous"></script>
<script src="../gospel-resources.js" integrity="sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -61,7 +61,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
<script src="../gospel-resources.js" integrity="sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP" crossorigin="anonymous"></script>
<script src="../gospel-resources.js" integrity="sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>resources-map · gospel-resources</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
@ -65,7 +70,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
<script src="../gospel-resources.js" integrity="sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP" crossorigin="anonymous"></script>
<script src="../gospel-resources.js" integrity="sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -19,6 +19,6 @@
</head>
<body>
<plugin-studio tree-base="."></plugin-studio>
<script src="./plugin-studio/plugin-studio.js" integrity="sha384-z28lk+j2l0xxtIiyBZr6EYjWlS/10epdE9ty6TRkVfHt6UuBj2Tq+V7Gf4+neaFm" crossorigin="anonymous"></script>
<script src="./plugin-studio/plugin-studio.js" integrity="sha384-6eNQ4BMIc6DDKJRaAQJzMuWWdYDN2+Ipj+RA1Q9Jxc8T2HZqr+ECC+mm63knNIL6" crossorigin="anonymous"></script>
</body>
</html>

View file

@ -110,7 +110,7 @@
"bundle": "cities-internet",
"scriptUrl": "./cities-internet/cities-internet.js",
"output": "dx-maps/cities-internet/cities-internet.js",
"integrity": "sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+",
"integrity": "sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E",
"elements": [
"cities-internet-map"
],
@ -129,7 +129,7 @@
"scriptUrl": "./cities-internet/cities-internet.js",
"embed": {
"iframe": "<iframe src=\"./cities-internet/connectivity-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
}
},
{
@ -145,8 +145,8 @@
"scriptUrl": "./cities-internet/cities-internet.js",
"embed": {
"iframe": "<iframe src=\"./cities-internet/connectivity-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
}
},
{
@ -162,7 +162,7 @@
"scriptUrl": "./cities-internet/cities-internet.js",
"embed": {
"iframe": "<iframe src=\"./cities-internet/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-cgoyUdYlyo3lG3DwLcnccnrUsmsL7GXk0xMKXkhJUB3haebLwnmJ6M22Ljj0tPN+\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-GP5ug0kZWRnv91fEfY5hf1sH8nIiQf3f3VfwZHXuY2Yd34kSfb1EYJSju3uXnS3E\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
}
}
]
@ -653,7 +653,7 @@
"bundle": "gospel-internet",
"scriptUrl": "./gospel-internet/gospel-internet.js",
"output": "dx-maps/gospel-internet/gospel-internet.js",
"integrity": "sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO",
"integrity": "sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY",
"elements": [
"gospel-internet-board"
],
@ -674,8 +674,8 @@
"scriptUrl": "./gospel-internet/gospel-internet.js",
"embed": {
"iframe": "<iframe src=\"./gospel-internet/board/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-internet/gospel-internet.js\" integrity=\"sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-internet/gospel-internet.js\" integrity=\"sha384-WM1WXMNql6OFR+HuiW8Iq05DFyygqdCVmTgvZsHa2qjAC43V2QI1QrB4wwkVfXgO\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>"
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-internet/gospel-internet.js\" integrity=\"sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-internet/gospel-internet.js\" integrity=\"sha384-6AYJ02B+ScAmrqRRmVNDWbPsY+LHm0DK/GMzCCa0RIiVrORAQs2Dsg1ZWyGehHBY\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>"
},
"instances": [
{
@ -782,7 +782,7 @@
"bundle": "gospel-resources",
"scriptUrl": "./gospel-resources/gospel-resources.js",
"output": "dx-maps/gospel-resources/gospel-resources.js",
"integrity": "sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP",
"integrity": "sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi",
"elements": [
"gospel-resources-map"
],
@ -805,7 +805,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/charts/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -821,7 +821,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -837,8 +837,8 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/gospel-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -854,7 +854,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/resources-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -870,8 +870,8 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/resources-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-KYYSAq2/MhFX7P79xkNLQlMk7QIyUlP66rSURcQeQs5T7yqQMOA2G49ZSYUpUUvP\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<!-- MapLibre engine (the default), fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js\" integrity=\"sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css\" integrity=\"sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- MapLibre draws this map and needs no token. For Mapbox, paste this map's embed.scriptMapbox from manifest.json instead: it sets \"provider\":\"mapbox\" and preloads the Mapbox engine; fill \"tk\" with your token. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>",
"scriptMapbox": "<!-- Mapbox engine, fetched early -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<link rel=\"preload\" as=\"style\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css\" integrity=\"sha384-rp1X/jJ9MpWPef9OimfXhOaOc4Gzs87yQvF+ajwY6X2H4PTeHNycNlLWiWvj7ehV\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-3EkqCUfbRGV91cwUsJr8JmkeQLNJukAEPrJzztnNhRh6C86HFqtWZUfdMfHY2bIi\" crossorigin=\"anonymous\"></script>\n<!-- Mapbox draws this map: fill \"tk\" with your Mapbox token. -->\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"provider\":\"mapbox\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
}
]
@ -1010,7 +1010,7 @@
"bundle": "plugin-studio",
"scriptUrl": "./plugin-studio/plugin-studio.js",
"output": "dx-maps/plugin-studio/plugin-studio.js",
"integrity": "sha384-z28lk+j2l0xxtIiyBZr6EYjWlS/10epdE9ty6TRkVfHt6UuBj2Tq+V7Gf4+neaFm",
"integrity": "sha384-6eNQ4BMIc6DDKJRaAQJzMuWWdYDN2+Ipj+RA1Q9Jxc8T2HZqr+ECC+mm63knNIL6",
"elements": [
"plugin-studio"
],
@ -1041,7 +1041,7 @@
"scriptUrl": "./plugin-studio/plugin-studio.js",
"embed": {
"iframe": "<iframe src=\"./plugin-studio/plugin-studio/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-z28lk+j2l0xxtIiyBZr6EYjWlS/10epdE9ty6TRkVfHt6UuBj2Tq+V7Gf4+neaFm\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-6eNQ4BMIc6DDKJRaAQJzMuWWdYDN2+Ipj+RA1Q9Jxc8T2HZqr+ECC+mm63knNIL6\" crossorigin=\"anonymous\"></script>\n<!-- provider: \"maplibre\" is the default; change it to \"mapbox\" and fill tk to use Mapbox. -->\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"provider\":\"maplibre\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
},
"instances": [
{

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>upg-100-list · my-upg-100-list</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>upg-100-mfe · my-upg-100-list</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

File diff suppressed because one or more lines are too long

View file

@ -61,7 +61,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <plugin-studio> custom element. -->
<script src="../plugin-studio.js" integrity="sha384-z28lk+j2l0xxtIiyBZr6EYjWlS/10epdE9ty6TRkVfHt6UuBj2Tq+V7Gf4+neaFm" crossorigin="anonymous"></script>
<script src="../plugin-studio.js" integrity="sha384-6eNQ4BMIc6DDKJRaAQJzMuWWdYDN2+Ipj+RA1Q9Jxc8T2HZqr+ECC+mm63knNIL6" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -61,7 +61,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <plugin-studio> custom element. -->
<script src="../../plugin-studio.js" integrity="sha384-z28lk+j2l0xxtIiyBZr6EYjWlS/10epdE9ty6TRkVfHt6UuBj2Tq+V7Gf4+neaFm" crossorigin="anonymous"></script>
<script src="../../plugin-studio.js" integrity="sha384-6eNQ4BMIc6DDKJRaAQJzMuWWdYDN2+Ipj+RA1Q9Jxc8T2HZqr+ECC+mm63knNIL6" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>pplr-data-maps · pplr-data-maps</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>prayer-walk-planner · prayer-walk-planner</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>region-dashboards · regions-dashboard</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>regions-mfe · regions-dashboard</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NON-MAP leaf (app-shell / composite / grid / card / chart-table): NO map peer.
This element draws no map tiles, so it needs no Mapbox/MapLibre engine and MUST NOT
gate on a token. Any nested MAP (in a composite/shell) renders in its own iframe leaf,

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>research-dashboard · research-dashboard</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>default · research-map-plus-grid</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NON-MAP leaf (app-shell / composite / grid / card / chart-table): NO map peer.
This element draws no map tiles, so it needs no Mapbox/MapLibre engine and MUST NOT
gate on a token. Any nested MAP (in a composite/shell) renders in its own iframe leaf,

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>research-map-plus-grid · research-map-plus-grid</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NON-MAP leaf (app-shell / composite / grid / card / chart-table): NO map peer.
This element draws no map tiles, so it needs no Mapbox/MapLibre engine and MUST NOT
gate on a token. Any nested MAP (in a composite/shell) renders in its own iframe leaf,

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>stack-demo · stack-demo</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NON-MAP leaf (app-shell / composite / grid / card / chart-table): NO map peer.
This element draws no map tiles, so it needs no Mapbox/MapLibre engine and MUST NOT
gate on a token. Any nested MAP (in a composite/shell) renders in its own iframe leaf,

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>pair · stack-demo</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NON-MAP leaf (app-shell / composite / grid / card / chart-table): NO map peer.
This element draws no map tiles, so it needs no Mapbox/MapLibre engine and MUST NOT
gate on a token. Any nested MAP (in a composite/shell) renders in its own iframe leaf,

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Mobilize near neighbors · upg-neighbor</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Mobilize near neighbors · upg-neighbor</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>upg-neighbor · upg-neighbor</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Bridge-language campaigns · upg-neighbor</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>Mobilize near neighbors · upg-neighbor</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox

View file

@ -11,6 +11,11 @@
<script>window.MAP_OWNS_PAGE = true;</script>
<title>UPG Neighbors: mobilize · upg-neighbor</title>
<link rel="icon" href="data:,">
<!-- A9 hints: the map's origins, so DNS/TLS + the engine start with the bundle, not after it (dx-base/a9-leaf-hints; engine = provider or the MapLibre default). -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://tiles.openfreemap.org" crossorigin />
<link rel="preconnect" href="https://pray.doxa.life" crossorigin />
<link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js" integrity="sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp" crossorigin="anonymous" />
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox