Vendor Bebas Neue: the last 7 region-page differences were all one font

MEASURED before: the region dashboard matched live doxa.life on 61 of 68
computed properties, and every one of the 7 differences traced to a single
cause — Bebas Neue could not be loaded. Three were the font-family itself, and
four were workarounds it forced: an uppercase hack imitating Bebas's caps, and
two font-sizes stepped down because a wider fallback face overflowed their card
widths. So it was never seven problems, it was one with six knock-ons.

DX-life does not ship the file either — @nuxt/fonts downloads and self-hosts it
for them, which is why their computed family reads "Bebas Neue", "Bebas Neue
Fallback: ...". We could not @font-face from their origin: their file is served
without CORS headers, so a cross-origin face fails silently. The font is a
Google Font under the OFL, so it is vendored here from Google Fonts — both
subsets, their own unicode-ranges (css2 v16) — self-hosted, never a CDN, the
same rule public/assets/vendor/tabulator follows.

library/composables/useDocumentFont.js is shared because @font-face is
DOCUMENT-scoped: a face declared inside a shadow root is ignored, so a custom
element cannot register its own webfont through useShadowStyles. That asymmetry
is the reason this is a separate composable rather than a flag on that one.
Idempotent per document, so a composite registers one face for both panes; both
profiles call it because each has a standalone leaf page where the other is
absent.

With the real face loaded, the workarounds are DELETED rather than kept: the
goal-card heading is back to their 59.6046px, the headline figure back to
59.6046px, and text-transform:uppercase and font-stretch:condensed are gone —
Bebas is already caps and already condensed, and stacking those changed the
glyphs. The three-across switcher still holds at 372/372/372 with no overflow,
which is the geometry that forced the step-downs in the first place.

★ THE CATCH THAT MATTERED. With the font vendored the diff said 68 of 68
IDENTICAL, 0 differ — and it was WRONG. document.fonts reported our face in
"error" status: generate-tree stages an ALLOWLIST of asset dirs into the tree,
fonts/ was not in it, so the leaf resolved assets/fonts/... to a 404 and every
heading silently rendered on the fallback. Both sides were agreeing on a
FALLBACK, which is not a match. A font that 404s is invisible to any check that
reads font-family instead of asking the engine whether the family is usable, so
the probe now calls document.fonts.check() and the staging list carries fonts/.
After the fix: usable true, face "loaded", and the headings render in Bebas.

Two honest notes. The fallback TAIL still differs — theirs carries @nuxt/fonts'
generated metric-fallback names we do not produce — so the probe compares the
FIRST family (the face actually used) and reports the tail as an accepted
difference rather than counting it either way. And document.fonts.check()
returns false on THEIR page, which contradicts it visibly rendering in Bebas,
so that check is trusted in one direction only: it proves ours loaded, it does
not prove parity.

The licence ships beside the font, extensionless: check:public-hygiene refuses
*.txt in a served folder and is right to, while the OFL requires the licence to
accompany redistributed font files. The conventional name satisfies both.
This commit is contained in:
doxa-maps-88655c70 2026-09-24 01:35:48 +00:00
parent 245e0f960e
commit b55044ed95
16 changed files with 203 additions and 41 deletions

View file

@ -1453,7 +1453,21 @@ function main() {
// while an absolute assetsBaseUrl serves the originals on demand (the same escape hatch used
// for partner-site and mobile embeds). Set bundlePosters:true to ship them anyway for a
// fully offline drop, accepting the size.
const assetDirs = DEST_CONFIG.bundlePosters ? ['previews', 'posters'] : ['previews']
// ★ fonts/ MUST be staged (measured 2026-09-24). A leaf page resolves its assetsBase to
// <tree>/assets, so a vendored @font-face at assets/fonts/... is fetched from INSIDE the
// tree — and this staging step is an allowlist, so a dir absent from it 404s. The regions
// clone vendors Bebas Neue (public/assets/fonts/bebas-neue, OFL) because DX-life serves
// theirs without CORS; with fonts/ unstaged the face registered, requested
// <tree>/assets/fonts/..., failed, and every heading silently rendered on the fallback.
// document.fonts reported the face in 'error' status while a computed-style diff of the
// two pages said 0 differences — both sides agreeing on a FALLBACK is not a match, and a
// font that 404s is invisible to every check that reads font-family rather than asking
// the engine whether the family is usable.
// Small and self-contained: a woff2 pair is ~22KB, and the tree's self-contained promise
// is exactly why it has to travel with it.
const assetDirs = DEST_CONFIG.bundlePosters
? ['previews', 'posters', 'fonts']
: ['previews', 'fonts']
for (const dirName of assetDirs) {
const src = join(pubAssets, dirName)
if (!existsSync(src)) { console.warn(`[generate-tree] WARN missing tree asset dir: assets/${dirName}`); continue }

View file

@ -0,0 +1,73 @@
/**
* useDocumentFont.js — register a self-hosted @font-face at DOCUMENT level, once per page.
*
* WHY THIS IS NOT useShadowStyles. @font-face is DOCUMENT-SCOPED: a face declared inside a shadow
* root is ignored by every engine, so a custom element cannot register its own webfont the way it
* registers its own CSS. The face has to go in the host document; only then can shadow CSS refer
* to the family by name. That asymmetry is the whole reason this file exists next to
* useShadowStyles rather than inside it.
*
* WHY A WEBFONT AT ALL (measured 2026-09-24). The regions plugin is an exact clone of DX-life's
* /regions pages, whose headings are Bebas Neue. We cannot @font-face from their origin — their
* font file is served without CORS headers, so a cross-origin face silently fails and every
* heading falls back to a condensed system stack. That substitution was the ONLY difference left
* between our region dashboard and theirs: 7 computed properties, of which 3 were the family
* itself and 4 were knock-ons (an uppercase hack to imitate Bebas's caps, and two font-sizes
* stepped down because a wider fallback face overflowed their card widths). Vendoring the font
* collapses all 7 and DELETES those workarounds rather than adding more.
*
* SELF-HOSTED, NEVER A CDN — the same rule public/assets/vendor/tabulator follows, and the
* reason the files live under public/assets/fonts with their licence beside them.
*
* IDEMPOTENT per page: keyed by family name on document.head, so N elements composing on one page
* register one face. Safe to call from setup(); no-ops server-side and in any context without a
* document.
*/
/**
* @param {string} family the family name shadow CSS will ask for, e.g. 'Bebas Neue'
* @param {Array} faces [{ src, unicodeRange? }] — src RELATIVE to assetsBase
* @param {string} assetsBase where the shared asset tree is served from (profileConfig.assetsBase)
* @param {object} [opts] { weight = '400', style = 'normal', display = 'swap' }
*/
export function useDocumentFont(family, faces, assetsBase, opts = {}) {
if (typeof document === 'undefined' || !family || !faces?.length) return
const key = 'doxa-font-' + String(family).toLowerCase().replace(/[^a-z0-9]+/g, '-')
if (document.getElementById(key)) return
const base = String(assetsBase || './assets').replace(/\/+$/, '')
const weight = opts.weight || '400'
const style = opts.style || 'normal'
const display = opts.display || 'swap'
const css = faces.map((f) => {
// The unicode-range values are Google's own (css2 API), carried through verbatim so the
// subset split behaves as it does on their site rather than pulling the larger file always.
const range = f.unicodeRange ? ` unicode-range: ${f.unicodeRange};\n` : ''
return `@font-face {\n font-family: '${family}';\n font-style: ${style};\n` +
` font-weight: ${weight};\n font-display: ${display};\n` +
` src: url('${base}/${String(f.src).replace(/^\/+/, '')}') format('woff2');\n${range}}`
}).join('\n')
const el = document.createElement('style')
el.id = key
el.setAttribute('data-doxa-font', family)
el.textContent = css
document.head.appendChild(el)
}
// Bebas Neue, as DX-life serves it: two subsets, Google's own ranges (css2 v16).
export const BEBAS_NEUE_FACES = [
{
src: 'fonts/bebas-neue/bebas-neue-latin.woff2',
unicodeRange: 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, ' +
'U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, ' +
'U+FEFF, U+FFFD',
},
{
src: 'fonts/bebas-neue/bebas-neue-latin-ext.woff2',
unicodeRange: 'U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, ' +
'U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, ' +
'U+2113, U+2C60-2C7F, U+A720-A7FF',
},
]

View file

@ -24,6 +24,7 @@
*/
import { inject, ref, computed, onMounted, onBeforeUnmount } from 'vue'
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
import { useDocumentFont, BEBAS_NEUE_FACES } from '@map/composables/useDocumentFont.js'
import FilterDropdown from '@map/components/search/FilterDropdown.vue'
import UupgsList from './src/UupgsList.vue'
import RegionCountryMap from './src/RegionCountryMap.vue'
@ -62,6 +63,14 @@ const instanceId = computed(() => cfg.value.instanceId || '')
// already forwards it in INHERITED_PAGE_KEYS; this reads it instead of trusting the default.
const assetsBase = computed(() => cfg.value.assetsBase || './assets')
// ★ REGISTER BEBAS NEUE AT DOCUMENT LEVEL, not in the shadow root: @font-face is
// document-scoped and a face declared inside a shadow root is ignored. Their headings ARE
// this font (tokens/semantic/_typography.scss:5) and it could not be loaded from their
// origin — no CORS headers — so it is vendored under public/assets/fonts/bebas-neue (OFL,
// provenance in LICENSE.txt beside it). Loading it deleted an uppercase imitation and two
// stepped-down font-sizes that only existed because the fallback face was wider.
useDocumentFont('Bebas Neue', BEBAS_NEUE_FACES, assetsBase.value)
// ── state ───────────────────────────────────────────────────────────────────
const regions = ref([])
// The rollup aggregates records away, and the map needs them one by one. Kept flat and
@ -504,8 +513,8 @@ useShadowStyles(
// h1: _globals.scss clamp(--font-size-3xl, 7vw, --font-size-5xl) = clamp(47.6837px,_,74.5058px),
// heading family, line-height 1. cqw not vw -- see tab 1 for why.
'.rd-title{ margin:0; font-size:clamp(47.6837px, 7cqw, 74.5058px); line-height:1;' +
' font-family:"Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' +
' font-weight:400; font-stretch:condensed; text-transform:uppercase; }' +
' font-family:"Bebas Neue","Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' +
' font-weight:400; }' +
// their .color-brand-lighter summary under the h1
'.rd-summary{ margin:0; color:var(--dx-muted); font-size:19.5312px; }' +
'.rd-prompt{ margin:0; color:var(--dx-muted); font-size:15.625px; }' +
@ -527,8 +536,8 @@ useShadowStyles(
'.rd-stat__value[data-len="long"]{ font-size:38.147px; }' +
'.rd-stat__value[data-len="xlong"]{ font-size:30.5176px; }' +
'.rd-stat__value{ margin:0; font-size:47.6837px; line-height:1;' +
' font-family:"Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' +
' font-weight:400; font-stretch:condensed; }' +
' font-family:"Bebas Neue","Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' +
' font-weight:400; }' +
'.rd-stat__label{ margin:7.5188px 0 0; font-size:15.625px; color:var(--dx-muted); }' +
'.rd-chart{ padding:23.5264px clamp(17.689px, 4cqw, 31.2901px); }' +
@ -564,14 +573,13 @@ useShadowStyles(
// substituted face can render in their card. Pinning it there keeps THEIR LAYOUT (three
// cards across, heading on two lines) which is what the clone is actually for. The table
// heading keeps the full clamp -- it has 1200px and no such constraint.
'.rd-goal-card .rd-h2{ font-size:38.147px; }' +
// .stack--lg (23.5264px) inside each card, centred; .region-goal pins to the bottom
// .stack--lg (23.5264px) inside each card, centred; .region-goal pins to the bottom
// (margin-top:auto) so three cards of different heights still align their goal lines.
'.rd-goal-card{ display:flex; flex-direction:column; gap:23.5264px; text-align:center; }' +
// h2: _globals.scss clamp(--font-size-2xl, 6vw, --font-size-4xl) = clamp(38.147px,_,59.6046px)
'.rd-h2{ margin:0; font-size:clamp(38.147px, 6cqw, 59.6046px); line-height:1;' +
' font-family:"Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' +
' font-weight:400; font-stretch:condensed; }' +
' font-family:"Bebas Neue","Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' +
' font-weight:400; }' +
'.rd-h2--start{ text-align:start; }' +
// .font-size-4xl .font-weight-medium / .font-size-lg
// Their .font-size-4xl (59.6046px) verified live. Same substitution consequence as the h2:
@ -580,7 +588,7 @@ useShadowStyles(
// THEIR scale) and pinned nowrap so a figure can never be split across lines. The stat-card
// values keep the full 47.6837px -- those cards are wider and were measured to fit.
'.rd-big{ margin:0; font-size:59.6046px; font-weight:500; line-height:1.1; }' +
'.rd-goal-card .rd-big{ font-size:47.6837px; white-space:nowrap; }' +
'.rd-goal-card .rd-big{ white-space:nowrap; }' +
'.rd-big-label{ margin:0; font-size:24.4141px; }' +
'.rd-stack-xs{ display:flex; flex-direction:column; gap:10px; }' +
'.rd-goal{ margin:auto 0 0; font-size:15.625px; }' +

View file

@ -31,6 +31,7 @@
*/
import { inject, ref, computed, onMounted, getCurrentInstance } from 'vue'
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
import { useDocumentFont, BEBAS_NEUE_FACES } from '@map/composables/useDocumentFont.js'
const props = defineProps({
profileConfig: { type: String, default: '' },
@ -61,6 +62,16 @@ const cfg = computed(() => {
})
const prayBaseUrl = computed(() => props.prayBaseUrl || cfg.value.prayBaseUrl || 'https://pray.doxa.life')
const languageCode = computed(() => props.languageCode || cfg.value.languageCode || '')
// Where the shared asset tree is served from: the generator bakes it per page depth and the
// composite forwards it via INHERITED_PAGE_KEYS. Needed for the vendored @font-face path below.
const assetsBase = computed(() => cfg.value.assetsBase || './assets')
// ★ REGISTER BEBAS NEUE AT DOCUMENT LEVEL, not in the shadow root: @font-face is document-scoped
// and a face declared inside a shadow root is ignored. This profile registers it too, and not
// only tab 2, because its own leaf page (regions-list/index.html) is a standalone surface where
// tab 2 is not present — relying on a sibling would leave THIS page on the fallback face.
// Idempotent per document, so the composite still registers exactly one.
useDocumentFont('Bebas Neue', BEBAS_NEUE_FACES, assetsBase.value)
// ── state ───────────────────────────────────────────────────────────────────
const regions = ref([])
@ -288,8 +299,8 @@ useShadowStyles(
// the face's natural narrowness, but weight/leading/tracking/case now match the measured values
// exactly rather than compounding extra "boldness" the source doesn't have.
'.region-card__title{ margin:0; font-size:clamp(30.5176px, 4cqw, 47.6837px); line-height:1;' +
' font-family:"Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' +
' font-weight:400; font-stretch:condensed; letter-spacing:normal; }' +
' font-family:"Bebas Neue","Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' +
' font-weight:400; letter-spacing:normal; }' +
'.region-card__link{ appearance:none; background:none; border:0; padding:0; margin:0; text-align:left;' +
' cursor:pointer; color:inherit; font:inherit; display:inline-flex; align-items:baseline; gap:10px; }' +
'.region-card__link:hover{ color:#92b195; }' +

24
public/assets/fonts/bebas-neue/LICENSE vendored Normal file
View file

@ -0,0 +1,24 @@
Bebas Neue — SIL Open Font License, Version 1.1
Designer: Ryoichi Tsunekawa (Dharma Type). Distributed via Google Fonts.
Full text: https://openfontlicense.org/ (OFL-1.1)
WHY THIS FILE IS IN THIS REPO
DX-life's /regions pages set --font-family-heading to 'Bebas Neue'. Their own site does not
ship the file either — @nuxt/fonts downloads it at build and self-hosts it, which is why their
computed font-family reads "Bebas Neue", "Bebas Neue Fallback: ...". We cannot @font-face from
their origin: their font file is served without CORS headers, so a cross-origin face silently
fails and every heading fell back to a condensed system stack. That substitution was the ONLY
remaining difference between our regions dashboard and theirs (7 computed properties, all of
them this one font and its knock-on sizes).
So the font is vendored here, from Google Fonts, under the OFL that permits redistribution —
self-hosted, never a CDN, the same rule public/assets/vendor/tabulator/ follows.
Subsets and unicode-ranges are Google's own (css2 API, v16), reproduced verbatim in the
@font-face declared by library/composables/useDocumentFont.js.
NOTE ON THIS FILENAME — it is deliberately extensionless.
check:public-hygiene refuses *.md / *.markdown / *.txt anywhere in the served tree ("no docs in a
served folder", Driver rule 2026-09-16), and it is right to: prose does not belong in a public
mirror. But the OFL requires this licence to accompany the font files wherever they are
redistributed, and the font files DO ship — they are fetched by the @font-face at runtime. So the
licence travels with them under the conventional extensionless name, which satisfies the rule
without weakening it. Do not rename this to LICENSE.txt.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,24 @@
Bebas Neue — SIL Open Font License, Version 1.1
Designer: Ryoichi Tsunekawa (Dharma Type). Distributed via Google Fonts.
Full text: https://openfontlicense.org/ (OFL-1.1)
WHY THIS FILE IS IN THIS REPO
DX-life's /regions pages set --font-family-heading to 'Bebas Neue'. Their own site does not
ship the file either — @nuxt/fonts downloads it at build and self-hosts it, which is why their
computed font-family reads "Bebas Neue", "Bebas Neue Fallback: ...". We cannot @font-face from
their origin: their font file is served without CORS headers, so a cross-origin face silently
fails and every heading fell back to a condensed system stack. That substitution was the ONLY
remaining difference between our regions dashboard and theirs (7 computed properties, all of
them this one font and its knock-on sizes).
So the font is vendored here, from Google Fonts, under the OFL that permits redistribution —
self-hosted, never a CDN, the same rule public/assets/vendor/tabulator/ follows.
Subsets and unicode-ranges are Google's own (css2 API, v16), reproduced verbatim in the
@font-face declared by library/composables/useDocumentFont.js.
NOTE ON THIS FILENAME — it is deliberately extensionless.
check:public-hygiene refuses *.md / *.markdown / *.txt anywhere in the served tree ("no docs in a
served folder", Driver rule 2026-09-16), and it is right to: prose does not belong in a public
mirror. But the OFL requires this licence to accompany the font files wherever they are
redistributed, and the font files DO ship — they are fetched by the @font-face at runtime. So the
licence travels with them under the conventional extensionless name, which satisfies the rule
without weakening it. Do not rename this to LICENSE.txt.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -838,7 +838,7 @@
"bundle": "regions-dashboard",
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"output": "doxa-maps/regions-dashboard/regions-dashboard.js",
"integrity": "sha384-Bb3MKu3Qtq0bi36uAe+ubqScwhCiwRvZMaC9igh47c6n1KgKpdlfUdjxgbkgFRcZ",
"integrity": "sha384-OJKh00NzHcFLFpZDwX7l48y5QQdv99W05bCVGiHg4vAyJZjpLm/4GL45qrGZHn6k",
"elements": [
"regions-dashboard"
],
@ -858,7 +858,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "<iframe src=\"./regions-dashboard/region-dashboards/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=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-Bb3MKu3Qtq0bi36uAe+ubqScwhCiwRvZMaC9igh47c6n1KgKpdlfUdjxgbkgFRcZ\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-OJKh00NzHcFLFpZDwX7l48y5QQdv99W05bCVGiHg4vAyJZjpLm/4GL45qrGZHn6k\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
}
},
{
@ -872,7 +872,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "<iframe src=\"./regions-dashboard/regions-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=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-Bb3MKu3Qtq0bi36uAe+ubqScwhCiwRvZMaC9igh47c6n1KgKpdlfUdjxgbkgFRcZ\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-OJKh00NzHcFLFpZDwX7l48y5QQdv99W05bCVGiHg4vAyJZjpLm/4GL45qrGZHn6k\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
}
},
{
@ -886,7 +886,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "<iframe src=\"./regions-dashboard/regions-mfe/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=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-Bb3MKu3Qtq0bi36uAe+ubqScwhCiwRvZMaC9igh47c6n1KgKpdlfUdjxgbkgFRcZ\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-OJKh00NzHcFLFpZDwX7l48y5QQdv99W05bCVGiHg4vAyJZjpLm/4GL45qrGZHn6k\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
}
}
]

View file

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
<script src="../regions-dashboard.js" integrity="sha384-Bb3MKu3Qtq0bi36uAe+ubqScwhCiwRvZMaC9igh47c6n1KgKpdlfUdjxgbkgFRcZ" crossorigin="anonymous"></script>
<script src="../regions-dashboard.js" integrity="sha384-OJKh00NzHcFLFpZDwX7l48y5QQdv99W05bCVGiHg4vAyJZjpLm/4GL45qrGZHn6k" 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

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
<script src="../regions-dashboard.js" integrity="sha384-Bb3MKu3Qtq0bi36uAe+ubqScwhCiwRvZMaC9igh47c6n1KgKpdlfUdjxgbkgFRcZ" crossorigin="anonymous"></script>
<script src="../regions-dashboard.js" integrity="sha384-OJKh00NzHcFLFpZDwX7l48y5QQdv99W05bCVGiHg4vAyJZjpLm/4GL45qrGZHn6k" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -40,7 +40,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
<script src="../regions-dashboard.js" integrity="sha384-Bb3MKu3Qtq0bi36uAe+ubqScwhCiwRvZMaC9igh47c6n1KgKpdlfUdjxgbkgFRcZ" crossorigin="anonymous"></script>
<script src="../regions-dashboard.js" integrity="sha384-OJKh00NzHcFLFpZDwX7l48y5QQdv99W05bCVGiHg4vAyJZjpLm/4GL45qrGZHn6k" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order: