The host page of every full-page map (and the Plugin Studio) sized the
element to the viewport in a way that tracks the phone's address bar:
- the built fixed-viewport leaf used position:fixed with inset:0, which
follows the DYNAMIC viewport, so the map and its legend sheet resized
on every scroll that moved the bar;
- the Plugin Studio page and the dev server's leaf and studio pages used
100vh, the LARGE viewport, taller than the view while the bar shows, so
the page itself scrolled by the bar's height and the app seemed to
resize.
All four now use height:100svh (100% first as the fallback where svh is
unknown), anchored top-left, and set --profile-min-h:0 so ProfileLoader's
100dvh floor cannot grow the element when the bar hides. On a desktop svh
equals the viewport, so nothing moves there. Scroll-page leaves (the
cap-4 stacks) are unchanged.
Regenerated the tree: 51 leaf pages and the Plugin Studio page change
only this rule and its comment; no bundle changes.
The mapInfo catalogue ships in seven bundles (cities-internet,
dashboard-plus-grid, doxa-maps-spa, doxa-research-map, doxa-simple-map,
gospel-resources, research-dashboard) and the tab layout in two
(doxa-maps-spa, plugin-studio): eight rebuilt, then the tree and SRI.
Pages and manifests change only those bundles' integrity hashes.
BUNDLE=<name> bun x vite build for cities-internet, gospel-internet,
gospel-resources, plugin-studio and rudder-voice, then bun run tree and fix:sri.
Regenerated on this tip, never merged: the scan refused the previous sha with
gospel-internet stale (committed 7361a689e3a6 against a rebuild of ce15dd0ba73f).
Since 2026-09-28 resolveMapProvider returns MapLibre for 'auto' whether or not a token is present;
only an explicit provider selects Mapbox. Four comments still said "Mapbox when a token is
available": useMapProvider.js's own header (and its note on the `token` argument),
useMapInstance.js at the provider option, check-provider-switch.mjs's contract note, and the
PROVIDER note that generate-tree writes into every leaf page.
The leaf page's note now says what the page does: it finds a token first only when one is on offer,
because place search uses one on either engine, and the element decides the engine. The 64 leaf
pages are regenerated and differ only in that note. The three JS files change in comments only
(compared minified, without renaming).
check:composite-freshness found stale on main: doxa-maps-spa
plugin-studio
prayer-walk-planner
template-bundle. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: template-bundle. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: template-bundle. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: template-bundle. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: country-map. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: template-bundle. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: key-cities
template-bundle. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: key-cities
template-bundle. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
RQ-RGPRINT, standalone /regions-dashboard/region-dashboards/ on a035408e2,
Chromium print media: ONE page, Letter. The map DID draw — basemap, region
fills and dots all rasterised. But the document under print media was 900px
tall, one viewport, while the content continued to y=1753. The sheet showed the
stats and the map, then blank to the bottom, and the region list ending at
"Oceania" was simply absent.
The cause is the leaf, not the plugin: `#slot, <tag> { position:fixed; inset:0 }`.
A fixed element paints once, on the first page. Every leaf taller than a screen
has been printing its top screenful and dropping the rest, and no shadow-root
rule could reach it — a shadow root cannot restyle its host's document rule,
which is why the dashboard's own print CSS landed and changed nothing here.
min-height rather than a bare release: a full-bleed map leaf takes its SIZE from
that fixed rule, so height:auto alone can leave a zero-height box and print an
empty page — a worse failure than the one being fixed. The obvious knob is the
wrong one: isMap is true for region-dashboards, which is a scrolling dashboard,
not a full-bleed map. The floor keeps a definite box for the map case while
letting a taller document flow onto page two.
Still to be looked at, and asked for: one printed full-bleed map leaf, to
confirm the floor holds a canvas that was sized by the fixed rule. The
dashboard case is measured; that one is reasoned.
No generated leaf page has ever carried an @media print rule — measured across
the tree: zero, out of 63. Two consequences, both on every plugin:
The page background is #0a0e15. Browsers drop background colours by default, so
this is invisible until a reader ticks "Background graphics" to get the MAP on
paper — and that reader, the one who most wants the printout, gets the sheet
flooded black around it.
#status is the loading overlay: position:fixed, inset:0, above everything. It
is emptied once the element mounts, but it is still a full-sheet layer, and a
page printed before or during load prints "loading…" over content that did in
fact load. It is hidden only while it is NOT an error: an error still prints,
because a blank sheet with the explanation suppressed is worse than a sheet
that says what went wrong.
Deliberately NOT in this commit: releasing the leaf's position:fixed. The bare
leaf pins the element with `#slot, <tag> { position:fixed; inset:0 }`, which is
why a standalone dashboard still prints one screenful even after its own print
rules landed — a shadow root cannot restyle its host's document rule. Releasing
it would make a full-bleed map leaf resolve its height against auto and could
print an empty box, so the discriminator is not `isMap` (region-dashboards is
isMap:true and is a scrolling dashboard, not a full-bleed map) and I will not
guess one from source. It needs one printed page looked at first.
check:composite-freshness found stale on main: key-cities
template-bundle. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: dashboard-plus-grid
doxa-maps-spa
doxa-research-map
gospel-resources
plugin-studio
research-map-plus-grid
stack-demo. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
DEDUP-AUDIT.md (measured today: 253 files, 31 cross-plugin duplicate clusters,
622 duplicated lines) ranks this tenth by raw cost and first by suitability. It
is the only cluster where the copies are identical in code, close over nothing,
and sit in two plugins with one owner between them.
loadScriptOnce (13 lines) and whenTagDefined (11) were byte-identical between
doxa-maps-spa and plugin-studio. deriveTreeBase (9) differed by ONE COMMENT LINE
and not one character of code -- drift in the documentation of a shared function,
which is its own argument for having one copy.
They are one concern, not three: load a bundle's script once, wait for its custom
element to register, and work out the tree base to load it from. That is what a
capability-5 app shell does to nest another plugin, and both plugins here ARE the
capability-5 shells. Any future shell needs the same three.
Verbatim move: no parameterisation, no behaviour change, callers import instead
of declaring. The comments travel with the code because each records a
measurement -- particularly the one explaining why onload is not a usable success
signal for a dev-server ES module.
ONE BEHAVIOUR CHANGE, AND IT IS AN IMPROVEMENT: the _loaded cache is now shared.
Two shells on one page previously kept separate caches and each loaded the same
bundle; the second now reuses the first's promise.
deriveTreeBase reads document.currentScript, so it is only valid AT MODULE
EVALUATION TIME. The call sites did not move -- both entries still call it at
module top level -- and the library file documents the constraint, because a
later call silently returns '' and every nested bundle URL would break.
Verified: both bundles build; each built file contains all three functions
exactly once and still derives currentScript; check:sri, check:series-isolation,
check:studio-rail and check:capability-derived all PASS.
library/utils/embedScript.js is the build owner's under rule 5B. The
plugin-designs and public/ changes are in the same commit because they import it
-- landing them apart breaks the build in between.
check:composite-freshness found stale on main: all-people-groups
cities-internet
country-posters
dashboard-plus-grid
demo-map
doxa-research-map
doxa-simple-map
gospel-internet
gospel-resources
my-upg-100-list
plugin-studio
pplr-data-maps
prayer-walk-planner
regions-dashboard
research-dashboard
template-bundle
upg-neighbor. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: all-people-groups
cities-internet
country-posters
dashboard-plus-grid
demo-map
doxa-research-map
doxa-simple-map
gospel-internet
key-cities
my-upg-100-list
plugin-studio
pplr-data-maps
prayer-walk-planner
regions-dashboard
research-dashboard
template-bundle
upg-neighbor. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: country-posters
doxa-maps-spa
key-cities
my-upg-100-list
plugin-studio
pplr-data-maps
regions-dashboard. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: cities-internet
country-posters
doxa-research-map
doxa-simple-map
my-upg-100-list
plugin-studio
rudder-voice. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: none; also rebuilt: rudder-voice plugin-studio. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: all-people-groups
cities-internet
country-posters
dashboard-plus-grid
demo-map
doxa-research-map
doxa-simple-map
gospel-internet
gospel-resources
key-cities
my-upg-100-list
pplr-data-maps
regions-dashboard
research-dashboard
template-bundle
upg-neighbor
wall-of-people-groups; also rebuilt: rudder-voice plugin-studio. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: none; also rebuilt: rudder-voice plugin-studio. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: plugin-studio. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: country-posters
gospel-internet
gospel-resources
key-cities
my-upg-100-list
plugin-studio
regions-dashboard. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
check:composite-freshness found stale on main: all-people-groups
big-picture
cities-internet
country-posters
dashboard-plus-grid
demo-map
doxa-maps-spa
doxa-research-map
doxa-simple-map
gospel-internet
gospel-resources
my-upg-100-list
people-groups-grid
plugin-studio
prayer-walk-planner
regions-dashboard
research-dashboard. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.