Commit graph

3821 commits

Author SHA1 Message Date
Doxa Maps
3bfaa24238 Rebuild the card consumers and the gallery for the re-read fixes, and regenerate the tree 2026-09-29 21:07:27 +00:00
Doxa Maps
d38e066ce2 The info popup's stacked-pages hint is visible
The shadow card behind a packet's first page sits at z-index:-1; without a
stacking context of its own it was painted under the dialog's white
background and never seen. isolation:isolate on the stack keeps it just
behind the page.
2026-09-29 21:04:26 +00:00
Doxa Maps
614c3248d3 Card names hyphenate only where a word cannot fit
hyphens:auto on every name let the browser split ANY word at a line end, so
multi-word names could break mid-word ("Northern Conchu-/cos"), which is
worse on a people group's name than the unhyphenated break it replaced. The
previous commit is reverted; hyphenation now applies only to names holding a
14+ letter word (12 of 2,107), with hyphenate-limit-chars:10 4 4 so a short
word is never split: the only multi-word ones are "Deaf <X>", and Deaf
stays whole.
2026-09-29 21:04:26 +00:00
Doxa Maps
1000a7ab5c Revert "A card name that must break mid-word gets a hyphen"
This reverts commit 7cdf72bfd4.
2026-09-29 21:03:46 +00:00
Doxa Maps
be3184207c Merge remote-tracking branch 'origin/development' into upg100/page-fill
# Conflicts:
#	public/dx-maps/country-posters/countries-map/index.html
#	public/dx-maps/country-posters/country-poster-wall/index.html
#	public/dx-maps/country-posters/country-posters-mfe/index.html
#	public/dx-maps/country-posters/country-posters.js
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/manifest.json
#	public/dx-maps/my-upg-100-list/my-upg-100-list.js
#	public/dx-maps/my-upg-100-list/poster-wall/index.html
#	public/dx-maps/my-upg-100-list/upg-100-list/index.html
#	public/dx-maps/my-upg-100-list/upg-100-mfe/index.html
#	public/dx-maps/regions-dashboard/region-dashboards/index.html
#	public/dx-maps/regions-dashboard/regions-dashboard.js
#	public/dx-maps/regions-dashboard/regions-list/index.html
#	public/dx-maps/regions-dashboard/regions-mfe/index.html
2026-09-29 20:54:55 +00:00
Doxa Maps
1ab8524cfb Merge remote-tracking branch 'origin/development' into regions/country-poster-hue 2026-09-29 20:45:42 +00:00
Doxa Maps
d0cbca5f4a Rebuild the five packet consumers for the grid reflow and the card-name hyphens, and regenerate the tree 2026-09-29 20:42:52 +00:00
Doxa Maps
b605b30ae1 Rebuild the three consumers stale after the merge
landing-preconditions step 4 named country-posters, my-upg-100-list and
regions-dashboard; each built with BUNDLE, then tree, then fix:sri. No source of
another plugin changed -- their bundles catch up with the shared library they
already import.
2026-09-29 20:42:01 +00:00
Doxa Maps
42537f11c9 The knows-Christ grid fills the page: the same 5,200 boxes, 80 x 65
52 columns exist only because a year has 52 weeks; on the knows-Christ page
a box is a share of people, and at 52 x 11px the grid used about half the
sheet's width. Without axes the same 5,200 boxes are laid out 80 x 65 (both
divide 5,200, so the rectangle is whole), the columns stretch to the frame
and the cells stay square, still shaded from the top in reading order. The
height this frees goes to a larger legend. The life calendar keeps its 52
week columns and its axes.
2026-09-29 20:41:29 +00:00
Doxa Maps
92ceebbcf5 Merge remote-tracking branch 'origin/development' into upg100/page-fill 2026-09-29 20:40:44 +00:00
Doxa Maps
78d57a4ab7 Regenerate the tree after merging development
The merge's conflicts were all generated output, resolved by taking
development's side and regenerating rather than hand-merging bundles.
2026-09-29 20:38:06 +00:00
Doxa Maps
1980c9000e Merge remote-tracking branch 'origin/development' into regions/country-poster-hue
# Conflicts:
#	public/dx-maps/country-posters/countries-map/index.html
#	public/dx-maps/country-posters/country-poster-wall/index.html
#	public/dx-maps/country-posters/country-posters-mfe/index.html
#	public/dx-maps/country-posters/country-posters.js
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/manifest.json
#	public/dx-maps/my-upg-100-list/my-upg-100-list.js
#	public/dx-maps/my-upg-100-list/poster-wall/index.html
#	public/dx-maps/my-upg-100-list/upg-100-list/index.html
#	public/dx-maps/my-upg-100-list/upg-100-mfe/index.html
#	public/dx-maps/regions-dashboard/region-dashboards/index.html
#	public/dx-maps/regions-dashboard/regions-dashboard.js
#	public/dx-maps/regions-dashboard/regions-list/index.html
#	public/dx-maps/regions-dashboard/regions-mfe/index.html
2026-09-29 20:37:20 +00:00
Doxa Maps
c934f8020e Merge remote-tracking branch 'origin/development' into upg100/mapinfo-toplayer
# Conflicts:
#	public/dx-maps/doxa-maps-spa/doxa-maps-spa.js
#	public/dx-maps/doxa-maps-spa/doxa-maps-spa/app/index.html
#	public/dx-maps/doxa-maps-spa/doxa-maps-spa/index.html
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/manifest.json
2026-09-29 20:35:44 +00:00
Doxa Maps
f6a3f85a2c Rebuild the three consumers of the shared country-hue rule
The rule lives in library/packet/posterSheets.js so the browser and the Node
generator cannot disagree, which puts it in every bundle that generates a country
sheet. landing-preconditions step 4 named country-map, country-posters and
regions-dashboard; each built with BUNDLE, then tree, then fix:sri.

No source of country-posters changed -- only its compiled bundle catches up with
the library it already imported.
2026-09-29 20:32:09 +00:00
Doxa Maps
fa7720cc93 Caption for Simple Research's example packet, in all eleven locales
mapInfo.tab.research-map-plus-grid.examplePacket ("Example packet: Middle
East Core"), the titleKey the gallery puts on that tab's pages example so
the packet reads as an example zone. The gallery bundle carries the mapInfo
area, so it is rebuilt.
2026-09-29 20:31:40 +00:00
Doxa Maps
7cdf72bfd4 A card name that must break mid-word gets a hyphen
hyphens:auto on the name, with the deck's <html lang> naming the language,
so a 16-letter name like Liechtensteiners that overflow-wrap has to split
breaks with a hyphen rather than silently mid-word.
2026-09-29 20:28:51 +00:00
Doxa Maps
f46134771e Merge origin/development into studio/bp-example 2026-09-29 20:28:42 +00:00
Doxa Maps
4a153d5b7b Big Picture's info popup shows real output: an excerpt of its spreadsheet
Big Picture's export is a spreadsheet, so its example is a kind:'table' excerpt (sr): the six largest
groups by population, of 2,107, with the live table's own column keys (dashboard.people_group,
.country, .region, .population), so the popup header and the table's header cannot drift.

Cost, measured: those keys bring the 'dashboard' area into the gallery bundle, which grows from
369,635 to 420,172 bytes (123,536 to 136,998 gzipped, +13.5 KB). The alternative, header keys
duplicated into 'mapInfo' in eleven locales, is a translation job for after the demo.
2026-09-29 20:25:42 +00:00
Doxa Maps
b8c7e9a391 Rebuild the five packet consumers for the unrounded totals, and regenerate the tree 2026-09-29 20:21:28 +00:00
Doxa Maps
7795eba447 The knows-Christ totals come from the unrounded share
Only the printed percentage rounds. A large list at 0.004% is tens of
thousands of people, which printed as 0 when the total was computed from
the rounded figure; a share below the last printed digit now reads
"<0.01%" beside its real total. check:evangelical-share asserts it.
2026-09-29 20:20:02 +00:00
Doxa Maps
588e28e10c Merge remote-tracking branch 'origin/development' into upg100/christian-page 2026-09-29 20:15:02 +00:00
Doxa Maps
b4b15fcd71 Rebuild the five packet consumers for the people-based knows-Christ page, and regenerate the tree 2026-09-29 20:14:55 +00:00
Doxa Maps
bb1241d1ee Merge origin/development into studio/sections 2026-09-29 20:10:38 +00:00
Doxa Maps
c00bf1034f Regenerate the library index for usePaneConfig, which landed without it (check:library-index) 2026-09-29 20:10:25 +00:00
Doxa Maps
d78e485643 "Who among them knows Christ" counts people, not weeks
The page reused the life calendar's grid and counted its shaded boxes in
weeks ("0.61% · 32 weeks"), under a week axis and a year axis, with a lede
calling it "one human life in weeks". On this page a box is an equal share
of the list's PEOPLE, so the same 5,200 boxes are now drawn with no week or
year axis, and the legend states each side in people: how many follow
Jesus and how many do not yet, each with its share (the two percentages
sum to 100 as printed), plus how many people one box stands for. Numbers
are formatted in the reader's locale.

The labels become "Followers of Jesus" / "Not yet following Jesus" and the
lede drops the weeks, in all eleven languages; the served strings file is
re-pinned. check:evangelical-share asserted the weeks figure; it now
asserts the people totals, the bare percentage and the absence of weeks
and axes, with the life page (which keeps its axes) as the negative
control. check:packet-variants found the grid by an exact class string
and now matches the class prefix.
2026-09-29 20:08:55 +00:00
Doxa Maps
70d87f6a3c Rebuild doxa-maps-spa for the published section order, and regenerate the tree 2026-09-29 20:00:58 +00:00
Doxa Maps
fa69209035 The gallery's published section order: Prayer Progress before the UPG-100 List
The Deep Research page publishes the rail as Dashboards (Big Picture, Simple Research, Regions),
Prayer Mobilization (Prayer Progress, UPG-100 List), Gospel Research (Cities with Internet, Gospel
Resources), then the Experimental folder. Only the Prayer Mobilization pair moves. Big Picture now
says "desktop only" on every width, not only once a phone has disabled it.

check:spa-tab-order asserted the old four-name order with UPG-100 first; it now asserts all seven
published rows in order (still relative, with tab 1 positional). It needs a browser: rega runs it.
2026-09-29 20:00:36 +00:00
Doxa Maps
a2da3fe97b Colour each country poster by its region, instead of one teal for all 173
★ THE REPORT WAS THAT THE COUNTRY POSTER'S CSS LOOKS WORSE THAN THE UPG-100
POSTER'S, AND IT IS NOT A CSS DIFFERENCE. Measured before editing anything: a
country sheet (Sudan) and a 100-list sheet (europe) generated from the same tree
have <style> blocks of 253 lines each, 18,475 vs 18,489 bytes, byte-identical
EXCEPT one custom property --

    country : --zc:#2bb
    upg100  : --zc:hsl(103, 72%, 56%)

poster-render.js has exactly ONE <style> block and both series render through it,
so typography, margins, header, legend and sheet fill are literally the same
rules. There was no second stylesheet and nothing to port; a CSS rewrite would
have been wasted work and a collision with the sheet-fill work in flight.

--zc drives the zone fill, the pin fill and the pin-number background -- the
three most visible things on a sheet -- and all 173 country posters set it to the
same hardcoded teal while each 100-list sheet carried its own hue. That is the
whole of the difference.

★ THE RULE LIVES IN library/packet/posterSheets.js BECAUSE BOTH PATHS MUST
AGREE, and getting that wrong is the most useful thing that happened here. A
first attempt defined the region-to-hue mapping in the Node generator alone and
broke check:poster-browser-equiv by exactly 26 bytes on country-npl -- the length
of 'hsl(45, 72%, 56%)' over '#2bb', twice, because --zc is emitted at two places.
The browser generates these sheets at click time from posterSheets.js, so a rule
one side knows and the other does not is two different posters for the same
country, which is precisely what that gate exists to refuse. One definition,
imported by the Node generator; countryZone takes the region, and countrySheet.js
forwards it so the print wall's path carries it too.

The formula mirrors leafColor in the 100-list's legend-tree.js -- an even hue
spread at 72%/56%, comma-HSL because Mapbox paint expressions reject the slash
syntax. It is restated rather than imported because library/ must not depend on
plugin-designs/; the dependency runs the other way. If that rule changes there,
this changes in the same commit.

★ BY REGION, NOT BY COUNTRY INDEX. 173 countries over 360 degrees is ~2 degrees
apart: indistinguishable, and meaningless on a poster seen ALONE with no sibling
to be told apart from. A region is a grouping the reader already has, so Sudan
and Chad reading as related is true rather than decorative.

★ THE LIST IS DECLARED, NOT DERIVED FROM WHAT A RUN CONTAINS. Indexing into the
regions present in one run would give a country one hue in a single-sheet render
and another in a full build, so re-rendering would change the colour of a poster
somebody had already printed. APPEND a new region; never reorder, which would
change the hue of every region after the insertion. An unrecognised region keeps
the old teal rather than being folded into 'Other' -- folding would silently give
two regions the same hue and hide that the list needs a line.

PROVED BY ARTIFACT, after the refactor:
  Sudan   BEFORE --zc:#2bb   AFTER hsl(180, 72%, 56%)   Middle East
  Chad    hsl(0, 72%, 56%)     Nigeria hsl(0, 72%, 56%)   both Africa -- same region, same hue
  Nepal   hsl(45, 72%, 56%)                               Asia -- differs
  check:poster-browser-equiv: country-npl browser 921548 = node 921548, byte-identical.

★ A LEGIBILITY PROBLEM THIS INHERITS AND DOES NOT CAUSE, reported rather than
silently absorbed: .pin-num is #FFFFFF over .pin-num-bg, filled with --zc. At
72%/56% white text fails WCAG 4.5:1 on SIX of the eight region hues (hue 0 reads
4.26, 45 1.91, 90 1.63, 135 1.74, 180 1.62, 315 3.79; only 225 and 270 pass).
It is PRE-EXISTING and already shipping on the 100-list's own sheets -- europe's
hsl(103) gives white 1.70:1 -- so matching the rule exactly is right for the
reported complaint and makes legibility no worse than it already is. The fix is a
line in poster-render.js's shared <style> block, which is not this change's to
make; it is with that file's owner.

Also folds in a pre-existing punctuation nit found in second read: the hi value
of "Loading results..." ended '..।' -- two ASCII dots plus U+0964 DANDA, a full
stop -- neither an ellipsis nor correct after one. Now '...', matching the
English. Keyset unchanged, so parity is untouched and still 0 debt.

gates:pre PASS 107 FAIL 0 NM 1 of 108.
2026-09-29 19:59:32 +00:00
Doxa Maps
40e5876a96 Rebuild the five card consumers for the name sizing, and regenerate the tree 2026-09-29 19:58:04 +00:00
Doxa Maps
e018ec47b3 A long people-group name is never cut off on a prayer card
The name now sits in a narrow box beside the photo, and the dataset has
16-letter single words (Pagativeshagallu, Liechtensteiners) that would have
overflowed it sideways and been clipped without a sign. The size steps by
the longest word as well as the length, and overflow-wrap:anywhere is the
last resort.
2026-09-29 19:56:47 +00:00
Doxa Maps
db56766667 Merge remote-tracking branch 'origin/development' into upg100/card-photo-sharp 2026-09-29 19:54:55 +00:00
Doxa Maps
0bb66b99ad Rebuild the five bundles the card-photo change reaches, and regenerate the tree
country-posters, doxa-research-map, my-upg-100-list, regions-dashboard and
upg-neighbor all print cards through library/packet/card-render.js.
2026-09-29 19:51:01 +00:00
Doxa Maps
a569868fef Merge remote-tracking branch 'origin/development' into regions/country-map-refetch 2026-09-29 19:44:14 +00:00
Doxa Maps
b6fe075e92 Prayer-card photos print sharp: sized from their pixels, not stretched
The people-group photos are small: every one sampled across the dataset is
at most 200 px wide, typically 200x250, and the API offers no larger
variant. The card stretched that across its full top band with
object-fit:cover, so a poker card printed a face at about 80 ppi and a
postcard at about 50: visibly blurred, on the one part of the card that
is a person.

The photo is now a framed portrait at the source's own 4:5 shape, sized
from its pixels at 180 ppi (about 1.1 x 1.4 in), on a warm band with the
name beside it (below it on a landscape card). Every stock prints a
200 px photo at about 190 ppi inside its frame. A bigger card gets more
room around the face, never a bigger, blurrier face.
2026-09-29 19:43:58 +00:00
Doxa Maps
b3e67c7f2b Merge remote-tracking branch 'origin/development' into bundler-2/panelang 2026-09-29 19:38:36 +00:00
Doxa Maps
2b210b78f0 Merge remote-tracking branch 'origin/development' into regions/country-map-refetch
# Conflicts:
#	package.json
2026-09-29 19:36:16 +00:00
Doxa Maps
0adb75a0c8 Rebuild research-map-plus-grid for the locale re-forward
Step 4 of the landing preconditions names this composite alone: it is the only
source that changed.
2026-09-29 19:35:19 +00:00
Doxa Maps
cff06fb8e6 Merge origin/development into studio/deep-research 2026-09-29 19:34:32 +00:00
Doxa Maps
b0d08224c1 A live language switch never reached the panes inside Simple Research
The composite re-pushed its FILTER state to the map and the grid on every
change, and nothing else. So a host switching language moved the composite's own
chrome and stopped there: the outer element received the new profile-config,
the push re-parsed each child's EXISTING attribute, and the boot `lang` survived
every write. Measured on a live en to ar switch: the map and the grid both stayed
English while the frame around them changed.

The panes were never at fault. Each child's own chain is fully reactive -- it is
reactive to its own prop, and its prop was frozen.

The map now carries the locale in the same push that carries the filters. The
grid needs its own line, because its three linked facets travel as separate
attributes while its language travels in profile-config, which this composite
set only when a host supplied a list, and never again. And a locale change now
triggers a push at all: the existing watchers cover filter state only.

The grid write is conditional so an unchanged locale writes nothing. That
matters here more than it looks: setting a pane's attribute makes it re-filter
and emit, and the composite reads those emissions -- which is what the `pushing`
guard above exists for, after a measured round trip once cancelled a selection
the composite had just applied.

Verified two-sided by driving the real pushToChildren against stub elements:
the locale reaches both panes, and a repeat at the same locale adds no write.
Removing the map's line fails that assertion alone and leaves the grid's passing.
2026-09-29 19:30:31 +00:00
Doxa Maps
7a5c9bd9fa Merge remote-tracking branch 'origin/development' into regions/pane-config-land 2026-09-29 19:30:06 +00:00
Doxa Maps
4f44a9b23e Rebuild doxa-maps-spa with every tab's info text, and regenerate the tree 2026-09-29 19:29:36 +00:00
Doxa Maps
525ce20a10 Merge origin/development into studio/deep-research (every tab's mapInfo text) 2026-09-29 19:29:04 +00:00
Doxa Maps
bd566e0d18 Merge remote-tracking branch 'origin/development' into regions/pane-config-land 2026-09-29 19:24:39 +00:00
Doxa Maps
c6f9e11427 The info popup keeps Tab inside it, as aria-modal promises
Tab from the last control wraps to the first, and Shift+Tab from the first
to the last, reading the focused element from the shadow root.
2026-09-29 19:22:10 +00:00
Doxa Maps
19339aacbf Rebuild regions-dashboard after merging development
The pane re-forward is compiled into this bundle, and landing-preconditions
step 4 named regions-dashboard as the only consumer the library change reaches.
Built with BUNDLE=regions-dashboard, then tree, then fix:sri.
2026-09-29 19:17:46 +00:00
Doxa Maps
37f3aa1221 All seven gallery tabs carry their info entry; a tab whose text is not bundled shows no button
Each production tab reads mapInfo.tab.<tabId>.lead and .takeaway, and Regions also its note, with
the India/China reasoning beside it. Only files already in the tree are listed as examples (the
UPG-100 poster); the rest join when their shots land. A tab's button renders only when its lead
key resolves in the bundled catalogue, so a key that has not landed yet hides the button instead of
opening a popup of raw key names.
2026-09-29 19:17:42 +00:00
Doxa Maps
74d2d67f19 Every map's "what can this do for you?" text, in one catalogue area
Adds the lead and takeaway for six more maps to mapInfo, keyed by the
gallery's tab ids (cities-internet, gospel-resources, dashboard-plus-grid,
research-map-plus-grid, prayer-map, regions-dashboard), plus the Regions
note, in all eleven locales. Each map's owner wrote and checked its own
text; this commit only gathers it, because the gallery ships one area and
one lane editing its eleven files cannot collide with another.

Checked mechanically before writing: every locale present, keys free of
dots (the gallery resolves keys by splitting on them), no numerals, every
locale different from English, and every string in its own locale's
script, since a stray character from another script passes every other
catalogue gate.
2026-09-29 19:17:14 +00:00
Doxa Maps
a1d9a1e318 Merge origin/development into studio/deep-research (MapInfo as landed; upg100's files take development's side) 2026-09-29 19:16:45 +00:00
Doxa Maps
656503a28d Merge remote-tracking branch 'origin/development' into regions/pane-config-land
# Conflicts:
#	package.json
2026-09-29 19:12:46 +00:00
Doxa Maps
e643e8a30e country-map: key the refetch by value, let only the newest response win, show the wait
Three defects on country-map/country-map, which is production -- DX Life's
country pages. Found by auditing the element rather than from a report.

1. ANY profile-config change refetched all 2,106 records. The watch getter
   returned a NEW ARRAY literal, and Vue compares a watch value with Object.is,
   so a fresh array always reads as changed; both computeds read the injected
   cfg, so the effect re-ran on every config change and the callback then fired
   unconditionally. MEASURED with real Vue: flipping isDark refetched the whole
   endpoint and redrew the map, and so did a host adding pinHint. A joined
   STRING compares by value, so only a real language or country change refetches
   -- which must still refetch, because the API localises the names.
   This was latent waste until the composite re-forward made config writes
   routine. It is now on every upstream locale switch, so the two changes are
   complementary rather than independent.

2. A SLOW EARLIER RESPONSE OVERWROTE A NEWER ONE. loadPoints is async and had no
   sequencing at all -- 0 abort or generation tokens in the file -- so two runs
   could be in flight and the one that STARTED first could FINISH last. Both
   assigned points, so the map showed the previous country's pins with no error
   and nothing for the reader to notice. Every run now takes a ticket and a stale
   ticket writes nothing: not the points, not loadFailed, not the spinner the
   current run is still using. fetch is left to complete rather than aborted,
   because the response is cached for the next switch back.

3. `loading` WAS WRITE-ONLY: assigned in three places and read in none, zero
   template references. A reader on a country page waited on an empty map -- no
   outline, no pins, no message -- which is indistinguishable from a country that
   genuinely has no people groups, and this element fetches the whole list before
   it can draw one pin. "Loading results..." was already in the catalogue in all
   eleven locales, so saying so cost no new string and no parity debt.

check:country-map-refetch guards all three. It drives the REAL reactive chain
with real Vue and takes the watch key expression OUT OF THE SHIPPED SFC, because
bug 1 is entirely a question of what Vue considers changed and is invisible to
any test that fakes reactivity or re-types the watch.

Mutation-tested, 5 mutations, all caught by name. The first version of the gate
MISSED one: a bare /if \(!current\(\)\) return/ grep matched the guard in the
catch block, so removing only the guard before the points write still passed.
The assertions are positional now -- the guard must sit immediately before the
assignment it protects -- and the catch guard is asserted separately. That hole
existed because the behavioural half of the test reproduced the guard's shape
inside the gate instead of reading the component, which is the self-consistent
oracle this repo's other geometry gate explicitly warns against.

Registered in scripts and gates:pre, verified by re-parsing: one key, 107
checks. Bundle rebuilt (BUNDLE=country-map), then tree, then fix:sri.
2026-09-29 19:11:37 +00:00