Commit graph

1547 commits

Author SHA1 Message Date
Doxa Maps
4c45d76c68 PPLR data maps: d3 is pinned, integrity-checked and kept off the host page's window
The critic fact-check (CRITIC-9 / CRITIC-5): the ROP Sunburst loaded d3@7 (a floating range, no
SRI) as window.d3, overwriting a host's own d3, or running on whatever d3 the host already had.
ensureD3() now loads d3@7.9.0 exactly with integrity + crossorigin, keeps it in the module
(pplrD3()) and puts the host's window.d3 back (or leaves none). SemanticSunburst reads pplrD3(),
and if a caller forgot to await ensureD3 it loads it and builds instead of asking for a refresh.
Headless proof: the stubbed-DOM loader test, 6/6 (host d3 restored, none leaked, exact version +
integrity + crossorigin, a failure rejects). BUNDLE=pplr-data-maps builds. Plugin-only.
needs eyes: PPLR > ROP Sunburst draws; on a host page with its own window.d3 it is untouched.
2026-09-26 02:19:25 +00:00
Doxa Maps
e1b9db2265 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 02:10:35 +00:00
Doxa Maps
fcb1c8285e Port their box-sizing reset into the shadow root, and delete the seven patches it replaces
app/assets/styles/base/_reset.scss:3-8 applies border-box to every element on
DX-life. Our leaf document carries the identical rule already -- but these
components render inside a SHADOW ROOT, and a document-level `*` selector does not
cross that boundary. So every element in here was content-box while every element
of theirs was border-box, and no scoped component style could reveal it. That is
how it survived seven global-rule fixes, and it is why this codebase had accrued
seven separate per-element box-sizing:border-box patches: each was a local
workaround for the reset that never arrived.

What it cost, measured rather than described: their legend swatch is width:10px
with a 1px border -- 10px under border-box, 12px under content-box. Two swatch
columns of 1px each are exactly the 2px by which our legend panel measured wider
than theirs (167 vs 165) after the rest of the legend was aligned to the pixel.
The same label measured 129px on both sides in the same Poppins, so the text was
never the cause.

The port is a geometric NO-OP and that is why it is safe to do in one move: the
blast radius was measured FIRST, by injecting this exact rule into every shadow
root and diffing every element's rect. 0 of 431 elements moved on
region-dashboards, 0 of 678 on regions-list, 301 already border-box by their own
declarations. The detector was negative-tested, because a zero from a check that
cannot fail proves nothing. So the whole value of this commit is the DELETION --
six per-element patches plus the interim `.rcm *` subtree rule, which the global
reset strictly contains.

Placement is plugin-local, not library/useShadowStyles.js. Putting it there would
fix all 25 bundles in one line and is tempting for exactly that reason, but the
blast radius above was measured on THESE two pages only; 23 other bundles would
have their geometry changed on no evidence. RULE 2 says default to the plugin
folder until a second consumer is named.

One module rather than three copies: three roots inject into the shared shadow
root and any of them can be the one that mounts, so all three need it.
2026-09-26 02:10:30 +00:00
Doxa Maps
694dad7bab Docs: an iframe updates itself; a script embed's integrity hash pins the bytes, so re-copy it after each release
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
From the critic's SRI check. how-to's embed section had no word on it; the CLI section said the
hash changes on every build, which is only true when the bundle's bytes change.
2026-09-26 02:07:14 +00:00
Doxa Maps
3361cb0ed8 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 02:01:53 +00:00
Doxa Maps
e72afe7985 Gospel map: the country gap list says whether the training is there too
The rows under "No resource found" name the way in. For 182 of the 369 groups
with nothing, that bridge language also carries the Zume discipleship course, and
the row did not say so — which is the difference between "there is a way in" and
"there is a way in and the course to train the first believers already exists in
it". A mobiliser scanning a country is deciding where to start, and that is the
deciding fact.

The bridge's own name stays first, because the language is the decision and the
training is what makes it actionable. It reads "way in: French · Discipleship
training", with the label coming from the catalogue so it follows the reader's
locale like every other label on the row.

Nothing new is fetched or linked: it reads the same Zume URL already verified and
already on the bridge panel, so the doctrine screen is unchanged at 16,963.
2026-09-26 02:00:48 +00:00
Doxa Maps
bc369d9cda Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:57:38 +00:00
Doxa Maps
d8b3541865 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:53:48 +00:00
Doxa Maps
79965b860b Gospel map: offer the bridge language's discipleship training
The point of this map is not that somebody reads a page. It is that the first
believers in a group are trained and become the first messengers to their own
people and their neighbours. Zume is the piece that does that, and it is
published in 52 languages.

Measured across the 369 Doxa groups with nothing: ZERO have Zume in their own
language, and 182 have a bridge language that does. The map was showing Zume only
to groups that already had something — the half that needs it least — while for
half the gap the training already exists in a language their neighbours speak.

Both bridge panels now carry it beside the Scripture and the film. All 19 distinct
URLs behind those 182 groups were fetched and answer 200, with a bogus locale
404ing so the status means something; every one is on zume.training, already a
screened publisher, so the doctrine screen is unchanged at 16,963 links.
2026-09-26 01:49:58 +00:00
Doxa Maps
d535a7d97d Merge main into bundler-2/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:48:50 +00:00
Doxa Maps
084e3ec5b7 Revert the popup number format to a fixed en-US: grouping is part of the held decision
NUMERALS ARE HELD covers the whole formatted number, not just the digit system.
-u-nu-latn keeps digits Latin but lets the SEPARATORS follow the locale, so
de reads 1.234.567 and ru 1 234 567 -- and choosing that is the held decision.
I read "numerals" as "digits", shipped it at d988c6f1, and then wrote a check
asserting that grouping SHOULD vary, which passed green while certifying the
breach. A check encoding the wrong intent turns a policy breach into evidence of
compliance, which is worse than having no check. It now asserts one format across
all eleven locales, with a negative control that the reverted form produced five.

Reverted on the shepherd's instruction; gospel shipped the same change and was
asked to revert its number part too, so no single map settles this.

The try/catch goes with it rather than being kept "just in case": it existed
because a locale-derived tag can throw RangeError, and a string literal cannot.

EVIDENCE FOR THE RULING, read from their master, because it cuts both ways:
  RegionDetail.vue:16   n.toLocaleString(`${locale.value}-u-nu-latn`)
                        their own comment: "Locale grouping separators with Latin
                        digits, matching the rest of the site."
  CountryMap.vue:128    toLocaleString(languageCode)   <- the popup, no subtag
So per-locale grouping is THEIR deliberate site-wide convention, and this
element's two other formatters clone that line verbatim. Those are left alone and
flagged, not reverted: changing them would override DX-life's documented choice
rather than stop a map from freelancing, and that is a bigger call than mine.
The popup is the one place theirs follows the locale for digits as well, so it is
also the one place the hold's own rationale actually bites.

And the rationale bites via the REGION, not the language: ar resolves
numberingSystem=latn (1,234,567) while ar-EG resolves arab. A host setting
profile-config.locale to 'ar-EG' is the real exposure, and a fixed en-US is immune.
2026-09-26 01:47:39 +00:00
Doxa Maps
1016bb4740 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:40:23 +00:00
Doxa Maps
9eb2557b35 Gospel research: Bible for Children checked, measured, and left out
A pool nobody here had tried, and the reason it stays out is worth writing down
so the next tick does not spend itself on the same site.

It is reachable and it 404s properly, so unlike the shells that defeated deaf
sources, its answers can be trusted. Its index publishes 118 languages with no
pagination and no stated total.

Out on coverage first: of the 294 languages in the Doxa gap, exactly ONE name
matches a folder there. 82 of the 118 match a language this index carries
somewhere, so the catalogue is real and does overlap us — just not the part with
nothing, which is the only part a new pool is worth adding for.

Out on the join key second: no ISO code is published anywhere, in the index or on
a story page. The folder IS the language name, so joining would mean matching by
name, the guess this build removed when Doxa's own API made it unnecessary, and
the guess that would have handed Akha in Laos one of three sub-varieties. The
single gap match above is a name match and worth nothing on its own.

Out on doctrine third, and that word is chosen carefully: no statement of faith
is served at any of the usual paths. This is unverified, not suspected. The brief
says leave a source out when its doctrine is unclear and say why, so that is what
this is, and it is not a finding against them.

No resource, link or count changes; the index differs only by its generated date.
2026-09-26 01:39:51 +00:00
Doxa Maps
d988c6f1ad Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:37:56 +00:00
Doxa Maps
1e9064e4c6 Merge main into bundler-2/work 2026-09-26 01:37:54 +00:00
Doxa Maps
17d50c8275 The map popup's population could print Arabic-Indic digits, against the numerals hold
Numerals are HELD pending the Driver's call: text translates, digits stay Latin.
Two of this element's three number formatters already carried -u-nu-latn; the map
popup's population was the odd one out, and it is the one a reader of an Arabic map
would actually have seen.

THE REASON IS NARROWER THAN I FIRST WROTE, and I measured it after asserting it.
Bare 'ar' was never the problem: on full-ICU Node it resolves numberingSystem=latn
and prints 1,234,567. It is the REGIONED tag that switches systems --

    ar     -> latn -> 1,234,567
    ar-EG  -> arab -> ١٬٢٣٤٬٥٦٧

so the codes this element ships (SUPPORTED_LOCALES, and localeFromUrl() which strips
the region at .split('-')[0]) were already compliant. The exposure is a tag arriving
from OUTSIDE: a host setting profile-config.locale to 'ar-EG' reaches that line with
its region intact. The subtag makes the hold hold whatever arrives, rather than
depending on every future caller to strip a region first.

-u-nu-latn is also closer to their output than the hardcoded 'en-US' it replaced,
which is the point worth keeping: it holds the DIGITS while letting the grouping
SEPARATORS follow the locale, so de still reads 1.234.567 and ru 1 234 567. Their
formatPopulation follows the locale outright; when the hold lifts, dropping the
subtag in all three restores exact parity.

Also added the try/catch the two sibling formatters have and this one lacked. A
malformed tag throws RangeError, and this runs while building popup HTML, so an
uncaught throw takes out the whole popup instead of one number.

Verified: 11/11 locales print Latin digits; 5 distinct grouping formats survive, so
it is not flattened to en-US; and the negative control uses ar-EG, an actual
violation, because a control built on bare 'ar' passed for the wrong reason and
proved nothing.
2026-09-26 01:37:49 +00:00
Doxa Maps
003fd1c92b Merge main into bundler-2/work 2026-09-26 01:33:36 +00:00
Doxa Maps
6ece14dca4 Rebuild doxa-research-map, which the landing precondition caught as stale
The merge brought source changes into this bundle that my own composite-freshness
run did not flag — that gate checks composites, the landing precondition checks
every bundle. The scan refused the push and named it, which is the first time my
lander has stopped a landing instead of waving it through; the '&&' between scan
and push earned its keep on its first outing.
2026-09-26 01:33:35 +00:00
Doxa Maps
72fb327951 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:30:10 +00:00
Doxa Maps
2eac0fb3c1 Gospel leaves: numbers follow the reader's locale, not the browser's
toLocaleString() with no argument formats for the JS runtime's locale, which has
nothing to do with the locale the plugin was asked to render in. The Arabic build
on an English browser got English grouping and the same page on a French browser
got French grouping: one plugin, one locale, two different numbers. All four
leaves now format with the locale i18n actually resolved.

numberingSystem is pinned to latn, and the obvious justification for that is
wrong, so here is the measured one. Against full ICU, the eleven tags this bundle
ships all resolve to latn already — plain "ar" included — so for them the pin
changes nothing. It earns its place only if a host passes a region tag: ar-EG
resolves to arab and fa to arabext, and those would switch the digits. Numeral
format is held for the Driver, so the pin keeps that his decision rather than a
host's.

What does change is grouping, and it is visible: Hindi groups in lakhs, so
1234567 reads 12,34,567, and French and Russian use a space. Those are correct
for the locale and differ from what shipped before.

The bare calls left in the built bundle are in library components this bundle
does not render — LegendProgressBar and PosterWall — and belong to whoever owns
library, not here.
2026-09-26 01:29:52 +00:00
Doxa Maps
05b3c3217b Rebuild pplr-data-maps, and regenerate the tree
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:26:26 +00:00
Doxa Maps
0776443961 PPLR data maps: the Globe/Mercator toggle works on MapLibre too
Three views called map.setProjection(projection.value) with the bare name ('globe'|'mercator'),
unguarded, including inside style.load handlers. Mapbox takes the name; MapLibre 5 takes a
specification object ({ type }), so under provider=maplibre the toggle did nothing or threw
mid-restyle. setProjectionFor(map, name) passes the engine's shape and is guarded; all six call
sites use it. Found by the engine-asymmetric API sweep (universal-props matrix, new column).
Headless: a fake-map unit test (MapLibre gets {type}, Mapbox the string, a throw is swallowed,
null/empty no-op) 5/5; BUNDLE=pplr-data-maps builds. Plugin-local: pplrData.js has no other consumer.
needs eyes: PPLR Religion view with ?provider=maplibre: the 🌐/🗺 button switches globe and mercator.
2026-09-26 01:23:15 +00:00
Doxa Maps
6d7da1c0f7 plugin-designs/README: the tree is dx-maps, and a bundle's tag is its folder name
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
Four path lines said public/doxa-maps/ (the folder was renamed in 09014f8a), and the embed
example used a <doxa-map> tag, but a bundle registers the tag named after its folder
(template-bundle/index.js), so the example is <your-map>.
2026-09-26 01:19:53 +00:00
Doxa Maps
f4833def5b Rebuild doxa-vision-card, and regenerate the tree
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:14:53 +00:00
Doxa Maps
504be20040 Doxa Vision Card: take the page language from profile-config lang as well as locale
Composites forward the page language as `lang` (dashboard-plus-grid, research-map-plus-grid,
the mfes). The card read only `locale`, so nested in one it fell back to English. Now locale,
then lang, then ?lang, then <html lang>, per the universal-props contract. Headless: the bundle
builds. needs eyes: a vision card inside a composite with lang=ar renders in Arabic, right-to-left.
2026-09-26 01:10:51 +00:00
Doxa Maps
2a548d2bae Merge main into bundler-2/work 2026-09-26 01:02:09 +00:00
Doxa Maps
6104b10fc0 Gospel map: read the Mapbox token through the library's channel
resources-map read profileConfig.tk || window.DOXA_TOKEN. DOXA_TOKEN is set by a
few dev pages and nothing else, so in the studio and on every built page this map
ignored the page's token entirely. It now takes profile-config tk, then
ProfileLoader's injected mapboxToken, then window.MAP_TOKEN, as the
universal-props contract says.

The pattern is copied from the same fix on cities-internet and key-cities
(1cf57f7a) rather than re-invented. Three raw maps each deciding for themselves
how to find a token is how all three came to be wrong in the same way.

Headless: the built bundle no longer contains DOXA_TOKEN at all, and carries the
injected token and MAP_TOKEN instead.
2026-09-26 00:58:02 +00:00
Doxa Maps
09b931adb0 Merge main into bundler-2/work 2026-09-26 00:53:04 +00:00
Doxa Maps
8e49ec41d6 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:52:04 +00:00
Doxa Maps
aacbc7a760 Integrate main into bundler-2/work 2026-09-26 00:49:34 +00:00
Doxa Maps
b5068166ac The theme toggle picks a style the running engine can load
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
The map booted correctly under ?provider=maplibre and then went blank
the first time a reader touched the light/dark toggle: handleToggleTheme
called setStyle with a hardcoded mapbox:// URL, which MapLibre cannot
load at all. The boot path two hundred lines below already did this
properly — resolveNamedStyle('paper', upgProvider) — so the file
disagreed with itself about how a style is chosen.

The registry names the same INTENT for both engines: 'paper' is light
(mapbox light-v11 / OpenFreeMap positron), 'ink' is dark (dark-v11 /
OpenFreeMap dark).

BEHAVIOUR-PRESERVING ON MAPBOX, and checkable rather than asserted:
resolveNamedStyle returns URLs byte-identical to the literals this
replaces — 'paper' -> light-v11, 'ink' -> dark-v11. Only the MapLibre
branch changes, from an unloadable URL to a real one.

⚠ A STRING-PRESENCE GREP CANNOT PROVE THIS LANDED, which is worth
recording because it nearly satisfied me. The built bundle already
contained openfreemap.org/styles/dark BEFORE the change — the registry
is compiled in for the boot path — so "is the MapLibre URL in the
bundle" answers yes either way. The falsifiable question is what the
CALL SITE references, and at the compiled layer:

  before  setStyle(f.value?"mapbox://…/dark-v11":"mapbox://…/light-v11")
  after   setStyle(f.value?vi("ink",s).style||"mapbox://…/dark-v11"
                          :vi("paper",s).style||"mapbox://…/light-v11")

where vi is the minified resolveNamedStyle(name, provider). Measured by
building both ways.

The `||` fallbacks keep the old literals as a last resort if a name ever
stops resolving, matching the boot path's own guard rather than
inventing a second policy.
2026-09-26 00:47:51 +00:00
Doxa Maps
b76cf8f74f The partner-embed check becomes something a person can open
Under the Playwright policy only rega runs a browser here, so this
check's result has to come from someone else's eyes. But the partner
page only ever existed INSIDE check-embedded-rtl — two createServer calls
on ephemeral ports — so "open a partner page at a foreign origin" was not
a thing anyone but the gate could do. NEEDS-EYES rows 3, 4 and 6 name a
runnable probe or an exact URL; row 7 was mine, and it named a construct
that lived in my own process.

--emit writes the same pages to disk, with the two-terminal recipe and
what to look at, so the item is reproducible by whoever has the browser.

⚠ THEY GO IN documentation/, NOT _qa-cycle/. I wrote them there first and
then checked: _qa-cycle is gitignored (.gitignore:113), so the files
could never have travelled to the person who needs them — which is the
entire point. documentation/ is tracked and already carries
README-embed-example.md.

⚠ AND THE ?lang=ar FIXTURE CARRIES NO locale IN ITS profile-config —
1100 bytes against 1114. The two channels reach the document-direction
code by different routes and detectLocale() reads the URL FIRST, so a
config that also supplied the locale would let a reviewer believe the URL
had done it when it had not. The first emit produced all three files
BYTE-IDENTICAL, which would have handed someone three pages they could
not tell apart; I only caught it by checking the emitted sizes rather
than trusting that the flag had taken effect.

The CASES array now carries the ?lang= row itself, so this stands alone:
the emit produces every fixture committed beside it. It previously
depended on the library/ commit for that row, which left the repo with a
fixture the tool would not regenerate — worse than either half.

Also: --emit was being consumed as the baseUrl positional ("SKIP —
nothing served at --emit"). Flags are filtered out of it now. That is the
same bug, in the same shape, that check-leaf-english-leaks had three days
ago — worth knowing it recurs in any gate that takes both a positional
and flags.
2026-09-26 00:47:12 +00:00
Doxa Maps
c534781bac MapLibre region fills drew nothing: the worldview clause filtered out every feature
rega measured it by eye at b0cd3140 on the built tree: regions-mfe under
?provider=maplibre draws the basemap and 2,107 pins, the boundary geojson returns
200, and the fill layer holds 0 features. Mapbox draws 156. A filter that admits
nothing looks exactly like data that never arrived.

countryFilter() is two clauses ANDed. The ISO half was fine — the field bridge
three lines above it already copies iso3 -> iso_3166_1_alpha_3 onto every geojson
feature before setData, so one name is read everywhere. The WORLDVIEW half has no
bridge and cannot have one: it exists because the Mapbox tileset repeats a country
once per worldview and the highlight would otherwise draw two or three times over.
The geojson has no such duplication and carries no worldview property at all, so
both sides of the `any` were false on every feature and the `all` emptied the
layer. It is Mapbox-only, not something to translate, so MapLibre now gets the ISO
clause alone.

I NEARLY FIXED THE WRONG HALF. Reading the RAW geojson I saw { iso3, shapeGroup,
shapeName }, concluded the ISO key was wrong too, and branched it — adding a
second name for a fact the bridge already normalises. The bridge was three lines
above the filter I was editing. Reverted; the ISO clause is untouched.

Proven headless, fail-first, by EVALUATING both filters against the real 162
features with MapLibre's own parser after applying the bridge:
  OLD filter admits   0 / 162   <- rega's bug, reproduced without a browser
  NEW filter admits  14 / 14    <- every requested country
  Mapbox path unchanged: still 14/14, and still drops a duplicate worldview copy
The control asserts the OLD filter still admits 0, so the check reports when it
has stopped demonstrating the bug it was written for.

Needs eyes: rega to re-shoot row 13 on this sha.
2026-09-26 00:38:15 +00:00
Doxa Maps
4bb0dbed47 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:37:30 +00:00
Doxa Maps
e02f50ad41 Rebuild cities-internet key-cities country-posters, and regenerate the tree
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:34:05 +00:00
Doxa Maps
3342548548 Rebuild my three bundles after integrating main 2026-09-26 00:33:39 +00:00
Doxa Maps
0d2f83c9f8 Country posters: "Export poster…" opens the dialog again
countries-map mounted <PosterDialog v-if="showPoster"> with :poster and :active-tab, props the
dialog does not declare, and without v-model or getMap. PosterDialog shows only while its
modelValue is true, so the button opened nothing, on both engines. It now passes v-model and a
getMap accessor, and unwraps the legend-rows ref. loadPoster() also called useMapPoster with an
options object; useMapPoster(getSourceMap) takes the map accessor. Headless: the bundle builds.
needs eyes: country-posters map > menu > Export poster… shows the dialog, and Render downloads.
2026-09-26 00:29:30 +00:00
Doxa Maps
295e6a7909 Cities with Internet + key-cities: read the Mapbox token through the library's channel, not window.DOXA_TOKEN
Both raw maps read profileConfig.tk || window.DOXA_TOKEN. DOXA_TOKEN is set only by a few dev
pages, so in the Plugin Studio and on every built page these maps ignored the page's token
(window.MAP_TOKEN, the shared token). They now take profile-config tk, then ProfileLoader's
injected mapboxToken, then window.MAP_TOKEN, as the universal-props contract says. Found by the
draft check:universal-props (TOK-GLOBAL). Headless: both bundles build, and DOXA_TOKEN no longer
appears in either shipped file.
2026-09-26 00:29:30 +00:00
Doxa Maps
7f7ff76616 Integrate main into bundler-2/work
# Conflicts:
#	public/dx-maps/big-picture/big-picture.js
#	public/dx-maps/big-picture/big-picture/big-picture/index.html
#	public/dx-maps/big-picture/big-picture/frontier/index.html
#	public/dx-maps/big-picture/big-picture/index.html
#	public/dx-maps/dashboard-plus-grid/dashboard-plus-grid.js
#	public/dx-maps/dashboard-plus-grid/dashboard-plus-grid/default/index.html
#	public/dx-maps/dashboard-plus-grid/dashboard-plus-grid/index.html
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/doxa-research-map/doxa-research-map.js
#	public/dx-maps/doxa-research-map/research-map/index.html
#	public/dx-maps/doxa-research-map/research-map/maplibre/index.html
#	public/dx-maps/manifest.json
#	public/dx-maps/research-map-plus-grid/research-map-plus-grid.js
#	public/dx-maps/research-map-plus-grid/research-map-plus-grid/default/index.html
#	public/dx-maps/research-map-plus-grid/research-map-plus-grid/index.html
2026-09-26 00:25:07 +00:00
Doxa Maps
b0cd3140bd Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:19:52 +00:00
Doxa Maps
0f839f1071 MapLibre: reading the projection threw, so a region dashboard never framed
Driver, on MapLibre: opening a region dashboard does not zoom to the region the
way Mapbox does. This is why.

fitTheirWay read `m.getProjection().name` OUTSIDE its try. The two engines
disagree about both halves of that API:
  Mapbox    getProjection() -> { name: 'globe' }    setProjection('mercator')
  MapLibre  getProjection() -> { type: 'globe' } | undefined
                                                  setProjection({ type: 'mercator' })
MEASURED in maplibre-gl@5's own source, which we load from jsDelivr:
Map.getProjection() returns `this.stylesheet?.projection`, and the OpenFreeMap
style we hand MapLibre declares no projection key at all — its top level is
version, sources, sprite, glyphs, layers. So getProjection() is UNDEFINED there
and `.name` threw a TypeError.

Because the read sat outside the try, the throw escaped fitTheirWay AND escaped
applySubject(), of which it is the last statement. The camera was never framed:
the map stayed wherever it was instead of flying to the region.

The read is now defensive and accepts both shapes, and the WRITE is
engine-correct: Mapbox takes the bare string, MapLibre reads e?.type, so handing
it a string would set undefined rather than fail loudly.

It was wrong in a second way worth recording: on a MapLibre style that DOES set
globe, the old read returned null and silently skipped the mercator correction
that exists to stop the fit pulling back. So it both crashed on one shape and
under-corrected on another.

Proven headless per the Playwright policy, with the old expression run against
the same stubs as the control: it THROWS TypeError on the real MapLibre shape and
returns null where it should see globe, while the new one returns 'globe',
'mercator', 'globe', null, null across the five engine shapes. A check that
cannot be shown to fail proves nothing, so the check fails if the old expression
ever stops throwing.

Needs eyes: MapLibre, region dashboard — does it now fly to the region.
2026-09-26 00:19:26 +00:00
Doxa Maps
15d9d47a05 Rebuild pplr-data-maps, and regenerate the tree
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:17:24 +00:00
Doxa Maps
2be2debe47 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work 2026-09-26 00:16:45 +00:00
Doxa Maps
c5fbb24aba Gospel list: name the translator on the language rows too
The map sheet and both bridge panels say who produced the Scripture; the language
list was the one surface a reader can arrive at that still answered "where"
without "who". 757 of the 5,067 rows now carry the organisation and year beside
the language.

A name rather than a link, for the same reason as everywhere else: the doctrine
screen is an allowlist, and a publisher must not enter this map as a side effect
of a data refresh. Measured after the change — 16,963 links, unchanged, and not
one credit contains a URL.

It needs no catalogue entry because an organisation's name is the same in every
locale. That is also why it can sit beside the translated labels around it
without leaving a hole in them.
2026-09-26 00:16:22 +00:00
Doxa Maps
0de6a7c2f8 PPLR data maps: keep the loading globe up until the pins are drawn, not merely added
Six views set dataReady (which removes the LoadingGlobe) straight after addSource(). The engine
then still tiles tens of thousands of points in its worker, so the globe vanished and the map sat
empty with a full legend. Measured on the DX-life gallery: 0 features for 20 s, then 19,376.
whenGeojsonDrawn(map) resolves once every GeoJSON source is loaded AND a frame has rendered
(not 'idle', which an animating map may never reach), with a 45 s cap so it can never hang.
Religion, pins, coverage, translations, language families and Rosetta cards await it before
dataReady. Plugin-local: pplrData.js has no consumer outside pplr-data-maps.
Headless proof: a fake-map unit test (already loaded / last source late / never loads -> false at
the cap / style mid-swap / no map), 9/9 pass; BUNDLE=pplr-data-maps build + tree + check:sri PASS.
2026-09-26 00:14:16 +00:00
Doxa Maps
08f89f55b3 Big Picture's header speaks the reader's language, and both composites turn round for it
TWO DEFECTS FROM THE UNIVERSAL-PROPS MATRIX, and they are the same defect at two
levels: a component can be perfectly localized and still show English, and a
page can be perfectly translated and still be laid out backwards.

★ THE HEADER HAD NO i18n AT ALL. Every label at the top of Big Picture was an
English literal passed as a PROP — FilterDropdown translates nothing, it renders
what the caller hands it — so Region, Bloc, People Group and Religion sat in
English above an Arabic page. They now read the catalogue, grid namespace first
because this header drives the cap-2 grid and its sibling reads the same keys.
Reset uses controls.reset_all, so its English becomes "Reset all": an existing
entry rather than invented wording, and arguably more accurate, since it clears
the search too.

Its search placeholder and two aria-labels have no usable entry — the nearest,
grid.search, drops "or countries", which this search actually covers — so they
are on the DECIDE card rather than quietly reworded. They are invisible to
check:composite-locale-leaks by design: its criterion is that the catalogue
already holds the string, and it does not.

★ RTL IS A DIRECTION, NOT A TRANSLATION. createAppI18n reflects an RTL locale
onto document.documentElement, which is right for a leaf page it owns and
useless for an element dropped into somebody else's page — the case these
composites exist for. A host asking for Arabic got Arabic WORDS in a
left-to-right layout: readable glyphs in the wrong place, which reads as a
styling quirk rather than the bug it is.

Both composites now set `dir` on their custom-element HOST rather than on the
layout inside it, and that choice is the fix: `dir` takes effect through the
inherited CSS `direction`, and inheritance crosses shadow boundaries, so one
attribute covers the composite's own chrome AND every nested element beneath it
— including the grid half the audit found bare. Only ever SET, never cleared: a
host page that declares its own dir owns that decision.

VERIFIED HEADLESS: three bundles build; setAttribute("dir","rtl") is present in
both composites and controls.reset_all in big-picture; freshness and SRI clean,
nothing else stale; gates:pre 6/6. NEEDS EYES: Big Picture and Simple Research
at ?lang=ar — header labels in Arabic, and the layout actually mirrored.
2026-09-26 00:13:46 +00:00
Doxa Maps
8dcd407e29 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:10:55 +00:00
Doxa Maps
2070b0c6f1 Gospel leaves: one active-tab colour, and it is the house one
#10b981 is Tailwind emerald and is not in this product's palette. Worse, the four
gospel leaves did not agree with each other: the map's active mode button was
near-black while the list, the tables and the charts were emerald, so the same
control looked like two different controls depending on which tab you were on.

Light is now the house dark on white, dark is the house sage on near-black, and
all four leaves share it. Contrast measured rather than eyeballed, since this
cannot be checked in a browser here: 9.86:1 and 7.89:1, both well past AA for
12px bold. Sage with #3b463d text was the obvious pairing and was rejected at
4.20:1, under the 4.5 this size needs.

The chart COLOURS are deliberately untouched. They encode meaning — scripture,
film, found, nothing, unresolved — and have to stay distinguishable from each
other, which is a different constraint from matching a palette. Recolouring them
is a judgement about legibility and belongs in its own change with someone
looking at it.
2026-09-26 00:09:22 +00:00
Doxa Maps
7f707807d6 Merge remote-tracking branch 'origin/main' into rega/research-gallery-embed
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:05:06 +00:00
Doxa Maps
8f5bd5efb4 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work 2026-09-25 23:57:06 +00:00