Commit graph

108 commits

Author SHA1 Message Date
Doxa Maps
4428156bfe Country Posters' panes are in the page address: on its own leaf the open pane is ?pane= (Map; the first pane is the default), and nested it announces to the shell, the same opt-in as Regions and UPG100 2026-10-03 06:36:09 +00:00
Doxa Maps
8b30be2481 Merge commit '1d8f5f1cc' into poster-design-plugin/experimental 2026-10-03 05:10:30 +00:00
Doxa Maps
69510aae86 Merge the pilot (development) 1fa35309a into poster-design-plugin/size-labels
Conflicts resolved by taking the pilot's side: upg100's
my-upg-100-list/poster-wall.meta.json (its new label) and the generated
files (regenerated). upg100's posterDesign block is re-added in the next
commit.
2026-10-03 00:58:33 +00:00
Doxa Maps
daa757d972 No India tab on the pilot by dev mode alone: the India preview (its tab and its whole-country poster) needs an explicit opt-in too, ?preview=india or localStorage 'dxm-preview', and every built bundle still compiles the whole read away. The gates hold the opt-in and that dev mode alone stays withheld. 2026-10-03 00:20:35 +00:00
Doxa Maps
ebbee89eea Merge development into repo/p2-neutral 2026-10-02 15:49:50 +00:00
Doxa Maps
62c739f57d Country Posters lists its poster in Poster Design: country-poster.letter (letter, phone-friendly), titled by the Country Posters tab label 2026-10-02 13:27:54 +00:00
Doxa Maps
ea8a74b350 check:poster-section covers card-action, with poisons for an ignored attribute and an event that cannot leave the shadow root 2026-10-02 12:43:51 +00:00
Doxa Maps
fc5b26ace9 check:country-sheet-one-path self-test: the Regions-list phone-block poison runs only while the list draws its own sheets 2026-10-02 11:31:18 +00:00
Doxa Maps
cd31ec1dfd Merge remote-tracking branch 'origin/development' into regions/poster-sections
# Conflicts:
#	plugin-designs/country-posters/scripts/check-poster-section.mjs
#	plugin-designs/regions-dashboard/regions-list.vue
#	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/country-posters/poster-section/index.html
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/manifest.json
#	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-10-02 11:19:59 +00:00
Doxa Maps
50266ad32e Merge development (2fc9b94f0) into the India tab
# 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/country-posters/poster-section/index.html
#	public/dx-maps/doxa-maps-spa/manifest.json
#	public/dx-maps/manifest.json
#	public/dx-maps/poster-design/poster-design-mfe/index.html
#	public/dx-maps/poster-design/poster-design.js
#	public/dx-maps/poster-design/poster-sizes/index.html
#	public/dx-maps/poster-design/poster-styles/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-10-02 11:05:14 +00:00
Doxa Maps
dc9014bb83 check:poster-section covers min-card-px and show-header, with poisons for a dropped attribute and an unwired view 2026-10-02 10:38:59 +00:00
Doxa Maps
6932bebd2c check:country-sheet-one-path accepts a Regions list that delegates to <dxm-poster-section>: the list is checked like the wall only while it calls makeCountrySheet itself, and the library country type must withhold India's rows and poster either way (arm H). 2026-10-02 09:53:06 +00:00
Doxa Maps
02b44a7343 No caller can open India's withheld poster: posterWithheld()/largeSheet() read the DEV-only preview themselves (no opener argument). The open preview is proved under Vite (check:poster-section C2, DEV true as on the pilot's dev server); check:country-sheet-one-path fails if an opener argument comes back. 2026-10-02 08:50:58 +00:00
Doxa Maps
8b83c34a79 P2: comments state the reason without quoting anyone or naming a role
Seventeen lines in 15 files. Six quoted short fragments from feedback; eleven used "design note" where a
person once stood ("design note selects 2+ rows", "a design note design call"). Each now states the
reason in neutral terms and keeps the technical content and dates.
All edits are comments, except one string: the safety_note text in
library/scripts/research/derive-city-candidates.mjs, a research script that is not bundled and whose
output is not committed. No logic changes.
2026-10-02 08:45:40 +00:00
Doxa Maps
f1b2cd34f4 Re-derive country-posters.json region fields from live wagf_region
Each country's region is set to the live wagf_region its groups carry (file
label spelling); only the region field changes (stats, bbox, count, India row
untouched). The stale 'Other' bucket (18 countries) empties out and each moves
to its real region: USA and the non-Spanish Caribbean + the Guianas to North
America & Non-Spanish Caribbean; Andorra/Monaco/San Marino to Europe; Cocos,
Christmas, Niue, Norfolk, Tokelau, Wallis & Futuna to Oceania. Europe goes
27 -> 30, matching the live Regions dashboard.

check:poster-section drops 'other' from its covering scopes (the bucket is now
empty, so the /regions/other scope resolves to zero countries); the seven real
regions still cover all 175 countries exactly once.

Region-only diff (18 region lines); B25 India withheld unchanged
(check:country-sheet-one-path, poster-section, poster-browser-equiv,
poster-design-catalogue all PASS).
2026-10-02 08:38:11 +00:00
Doxa Maps
665ef7608a Whole India prints at 5 x 8 ft (60x96) ONLY (the Driver); other countries' sizes are unchanged. check:country-sheet-one-path: every India request but a packet page gets 60x96; a poison offers 66x66 again. 2026-10-02 08:14:09 +00:00
Doxa Maps
0dc9765f77 The preview read is DEV-only: no built bundle can open India's withheld poster from a global
previewUnreleased() is import.meta.env && import.meta.env.DEV && globalThis.DXM_PREVIEW_UNRELEASED === true, and the
India tab uses the same expression inline, so every BUILT bundle compiles both away. A page, an embed or a reader's
console setting the global can no longer print the withheld poster from production; only the Vite dev server (the
pilot's Plugin Studio, whose element bootstrap sets it) previews it. posterWithheld()/largeSheet() take the preview
state as an optional argument, so a gate can test an open preview directly.
check:country-sheet-one-path arm G: a global alone does NOT open the preview outside DEV; withheld by default; an
open preview prints 66x66; the India tab is gated on the DEV read; and the built tree mentions the flag 0 times
(the stale ungated build failed this check, as it should). A poison for each.
2026-10-02 08:08:26 +00:00
Doxa Maps
f804bd8bcc India's whole-country poster stays withheld everywhere except an explicit PREVIEW context
It is not released yet, and the pilot syncs to DX Life (and the partner handoff) within minutes. So WITHHELD.IND is
{ poster: true, rows: true, preview: true }: posterWithheld() is false ONLY when the host page sets
globalThis.DXM_PREVIEW_UNRELEASED === true (the Plugin Studio on the pilot, where it is reviewed); never by a URL
parameter. Every other host keeps the withheld sentence on India's card, and Country Posters' India tab exists only
under that flag. The rows (list, packet, cards) stay withheld everywhere.
check:country-sheet-one-path arm G proves (a) withheld by default and (b) printing at 66x66 with the flag (only
=== true opens it), rows withheld in both, the India tab gated, with a poison for each; check:poster-section arm C
expects the sentence by default.
2026-10-02 07:53:41 +00:00
Doxa Maps
2992f5b941 The whole-India poster ships on an India tab (66x66 by default); its list, packet and cards stay withheld
countrySheet.js WITHHELD now says WHAT of a whole country is withheld: { IND: { poster: false, rows: true } }, with
posterWithheld() and rowsWithheld() (sheetWithheld() keeps meaning the poster, the name Poster Design reads).
- India's whole-country POSTER prints again, 66x66 by default (60x96 and 36x60 on request); largeSheet() names it.
- Its ROWS (the prayer list, packet and cards: about a thousand pages) stay withheld with the same sentence, in the
  wall, the Regions list and the 'country' poster type. India's state posters are unchanged.
- Country Posters gains an INDIA tab: the same wall filtered to India, labelled with India's own name in the
  reader's language (Intl), between the posters and the map.
check:country-sheet-one-path arm G checks the split (poster live at 66x66, rows withheld, state cards never
withheld, both callers read the right half), with poisons for un-withheld rows and a wall that prints them;
check:poster-section arm C follows. The by-state, leaderless India layout follows as its own PR.
2026-10-02 07:51:10 +00:00
Doxa Maps
2cab21c5a9 Poster section page: its @description; the library index and capability exemplars regenerated; the tree rebuilt 2026-10-02 07:07:18 +00:00
Doxa Maps
a95b88ed65 <dxm-poster-section>: one poster section, any poster type, as a reusable element
The section the Country Posters tab draws (a collapsible region head + its poster cards) is now usable on its
own, for any poster set, by parameters:
- library/components/poster/posterTypes.js: a TYPE REGISTRY. A type is an adapter (items for a scope, the
  section's title, the print actions). The library registers 'country' (library data + the shared sheet path,
  so a withheld whole-country poster stays withheld); plugins register their own types from their own code
  (UPG 100 lists, regions, continents later). No plugin code in the library.
- 'country' scopes: a region key in any spelling. DX Life's /regions slug ('latin-america-and-caribbean'),
  the API's value, the wall's slug and the English name all reduce to one canonical key.
- PosterSectionView.vue: one section, drawn by a PosterWall in a new SECTION-ONLY mode (no wall head; off by
  default, so every existing wall renders as before), embedded so the page scrolls it.
- <dxm-poster-section type scope collapsible collapsed locale assets-base api-base-url is-dark>: the
  attributes map onto the standard element's profile-config (posterSectionConfig.js, pure), so it keeps the
  per-instance i18n and store. registerPosterSectionElement() from any bundle; Country Posters ships it first.
- country-posters/poster-section: a page showing two sections (Africa open, Oceania collapsed).
- poster.sectionNone (11 locales): an unknown type or an empty scope says so, never a blank.
check:poster-section (gates:pre) + self-test: the registry, DX Life's 8 scopes covering every country once,
withheld India, the attribute mapping, and PosterSection.vue injecting every name its template uses; 3 poisons.
The known collapse-while-scrolled landing is left exactly as it is.
2026-10-02 06:56:48 +00:00
Doxa Maps
fe743ff48d The whole-India poster is withheld for now: "Too many people groups to fit on one poster legibly"
India's whole-country poster does not ship yet; a solution is in progress. countrySheet.js gains WITHHELD (India)
and sheetWithheld(item):
- makeCountrySheet draws nothing for a withheld country, in any format, before fetching a single record.
- largeSheet() is null for it, so the Country Posters wall and the Regions list show their existing
  messages.countryPosterTooMany ("Too many people groups to fit on one poster legibly — a solution is in
  progress.", all eleven locales) on the card instead of a poster.
- Both callers also withhold its list, packet and cards with the same sentence (about a thousand pages, offered
  when the poster is).
- India's STATE and union-territory posters are separate cards (indiaState) and are untouched; so are the India
  section and its first place.
- sheetFormatFor keeps the large-sheet size rule itself (it returns with the poster).
check:country-sheet-one-path arm G: India stays withheld (no sheet in any of 7 formats, 0 records fetched, its
state cards never withheld, both callers show the sentence and reject its rows), with a poison for un-withholding
it and one for a wall that prints its list.
2026-10-01 22:18:31 +00:00
Doxa Maps
6dfc7dd7a8 check:side-lane-photo-pixels: every name clear of every OTHER photo too (a long inner-column name must not run into the outer column's photo above or below) 2026-10-01 18:46:44 +00:00
Doxa Maps
1b496b3b31 Large side-lane sheets: a photo sits in a fixed slot beside its name, never on its letters
Measured on the shipped India sheets in the browser (getBBox, Lato loaded): 74 of 151 photos on the 60x96 and
32 on the 66x66 overlapped their own name, by up to 7 px (half a letter at 20.7 pt). The photo was placed from
an ESTIMATED text width, and the real width runs wider.
Now the photo sits in a fixed slot on the LEADER side of its name, and the name moves out by the slot. A
side-lane name is anchored at its leader-side end (left column: text-anchor end; right: start), so its glyphs
lie wholly on the far side of that anchor and the photo wholly on the near side: they cannot overlap whatever
width the font draws. Only a name with a photo takes the slot, so the columns and the type keep their size
(India 60x96 stays 20.7 pt).
Measured after: India 60x96 and 66x66 have 0 photos on, and 0 touching, their name. 0 proper crossings on all
three India formats. 36x60 (no photos) is byte-identical. Re-pinned.
- check:side-lanes: every photo on its name's anchor side, at the 4 px gap (a source twin, always measured).
  A self-test poison restores the estimated-width placement: 167 photos off their side, caught.
- check:side-lane-photo-pixels (browser): every photo box clear of its name's real drawn box (getBBox), with
  the same poison in its self-test.
2026-10-01 18:42:18 +00:00
Doxa Maps
a63a873ef4 Country Posters: India's state and union territory cards named in the reader's language; the state table retried after a failure
countryPosters.stateNames x11, keyed by ISO 3166-2, for the India section's CARD labels (the wall, the print HUD, the
packet and list titles). The printed sheet stays English by recorded decision, like every country poster.
Generated, not typed: scripts/emit-india-state-names.mjs reads Wikidata labels by ISO 3166-2 (P300), dissolved items
excluded; Wikidata is CC0 (source, licence, query, date and every fallback in data/india-state-names.meta.json).
- Four codes ISO has renamed (IN-CT/OR/TG/UT -> CG/OD/TS/UK) are queried under the current code.
- English is the table's own name. Where the table is briefer than its item ("Delhi" vs "National Capital Territory
  of Delhi"), the same-named item's labels win, so hi/ru match the English.
- Reviewed by eye (hi, ar, zh): two explicit overrides with their evidence (ar Odisha = the ar.wikipedia title,
  not the pre-2011 label; zh Dadra and Nagar Haveli and Daman and Diu = Simplified, the only label being
  Traditional). A zh name from a plain "zh" label with no reviewed override FAILS the generator (poisoned: it did).
The India section retries a failed table fetch at 5 s, 20 s and 60 s (bounded, cancelled on unmount), instead of
staying hidden until the filter changes.
check:country-sheet-one-path ARM D: every locale's stateNames == the table's 36 codes (a runtime-built key the i18n
call-site gates cannot see), English == the table, and the licence recorded; its two poisons join the self-test.
2026-10-01 11:41:37 +00:00
Doxa Maps
838008b991 Desktop-only cards on a phone: the list, packet and cards say "This needs a desktop or laptop computer."
On a phone, India's Prayer List (Full detail, Lightweight) reported "that list has no people groups to print" on a
card of 855: its rows resolved [] and the print path read that as an empty list. Now, in the wall and the Regions
list alike, a desktop-only card's rows REJECT with the notice before any record is fetched, and the card shows the
same words: a new poster.phoneLimitAll ("This needs a desktop or laptop computer.", all eleven locales). The
existing "the largest sizes are off" stays for cards that are only partly blocked.
check:country-sheet-one-path arm F asserts it for both callers, with a poison for each.
2026-10-01 09:45:34 +00:00
Doxa Maps
2f163e04c1 Large side-lane sheets: photos print in the sheet's own document, and a raster never draws a broken image
Measured on the 60x96 print: every photo beside a name rasterised as the browser's broken-image glyph. An SVG
rasterised through <img> is an isolated document that fetches no external resource, and none of the people-group
photo hosts (media.joshuaproject.net, joshuaproject.net, images.peoplegroups.org and its resizer,
peoplegroupspublic.blob.core.windows.net, s3.doxa.life) sends CORS, so a photo cannot be inlined as data: in the
browser either.
- poster-raster.js: rasterPoster drops every <image> whose href is not data: (the basemap tiles are data: and stay),
  so a download shows the paper, never the glyph. hasExternalImages() says when a sheet carries such photos.
- PosterWall: printing a generated sheet that carries photos prints THE SHEET ITSELF through printDocument, where
  the photos load, on its own @page (60in 96in), instead of a raster shrunk onto letter. Same HUD steps.
- check:side-lanes: photo arms (0 external images reach the raster; the wall prints such a sheet as a document),
  each with a poison in its self-test.
- check:side-lane-photo-pixels: the pixel side, a browser gate (a data: photo draws red; 99/99 external slots stay
  flat; without the strip 0/99 do). Declared on-demand until its first browser-seat run.
2026-10-01 09:45:33 +00:00
Doxa Maps
a1c74004a0 Merge development (353bf078c) into the whole-India landing: package.json gates unioned (check:side-lanes added), poster-render re-pinned on the merged file 2026-10-01 08:24:45 +00:00
Doxa Maps
d01087a9cc Country Posters: the header share button is a rounded square, like Big Picture's and UPG 100's 2026-10-01 07:32:43 +00:00
Doxa Maps
6d0253d909 countrySheet: a requested large size wins; LARGE_SHEETS only supplies India's 60x96 default
India can print at 60x96 (the default), 66x66 or 36x60. makeCountrySheet used to map any non-packet request to the
default, so a 66x66 or 36x60 request drew the 60x96 sheet. sheetFormatFor(item, format) (exported, pure) now keeps
a requested size the country can print at, falls back to its default otherwise, keeps a packet page a page, and
returns exactly what was asked for every other country.
check:country-sheet-one-path asserts that table (India 66x66/36x60/60x96/letter/3x4/packet; Nepal 3x3/letter;
China 3x4), with two poisons: India ignoring a requested 66x66, and a packet page turned into a large sheet.
2026-10-01 06:07:48 +00:00
Doxa Maps
1af359ac42 poster-render: side-lane CSS adds no byte to other formats; photos only from the known photo hosts
5B fixes on the side-lane mode:
- The side-lane styles' template slot sat on its own line, so every OTHER format's page gained one newline. It is
  now joined onto </style>, emitting nothing at all off side lanes.
- A photo is drawn only over https from the hosts that serve people-group photos (media.joshuaproject.net,
  joshuaproject.net, images.peoplegroups.org, peoplegroupspublic.blob.core.windows.net), never the generic
  placeholder; anything else is dropped. Re-pinned.
check:side-lanes' seeded data now also carries photos on a host that is NOT allowed; none may be drawn.
2026-10-01 06:03:48 +00:00
Doxa Maps
455fa8ab7d One rule for countries too large for paper: countrySheet.js's LARGE_SHEETS; whole-India list, packet and cards on a desktop
CORRECTS the previous commit's "no prayer list, packet or cards for whole India": the current direction is that
whole India's poster, list, packet and cards (about a thousand pages) are offered DESKTOP-ONLY, and a phone shows
the existing poster.phoneLimit sentence instead of failing.
countrySheet.js now exports LARGE_SHEETS ({ IND: 60x96, desktopOnly }) and largeSheet(item), and makeCountrySheet
itself prints such a country in its large format (a packet page stays a page) with its "Administrative Areas"
cell from the shared state table ("36 states and union territories"). So every caller gets the same sheet: the
Regions list's India no longer has to disagree with Country Posters (regions-list's own lines follow, from regions).
The wall drops its India-only code and follows the same rule.
2026-10-01 05:55:55 +00:00
Doxa Maps
1c61cbb926 Country Posters: the whole-India poster prints, every group named
India's card is no longer "too many to fit": it prints as the 60x96 side-lane sheet (all 855 groups named beside
the map, crossing-free leaders, real photos), whatever paper the wall asks for, until the shared size picker
offers 66x66 and 36x60 too. Its facts row reads "36 states and union territories" (English, from the wall
head's plural key). As ruled, the whole-India card offers no prayer list, packet or cards; the state cards keep
theirs. Its card preview is the real sheet.
check:side-lanes (+ :self-test, gates:pre): the three side-lane formats on a seeded worst case (855 groups,
stacked and clustered) through the real renderer: every name once, 0 crossings re-measured from the SVG, no
overflow, photos only where real; without the lane clamp the same data crosses 36 times, and the arm fails.
2026-10-01 05:52:47 +00:00
Doxa Maps
77751ddcb6 Merge origin/development (53fcf6d09) into studio/p-assembly 2026-10-01 05:32:16 +00:00
Doxa Maps
9de5da9e4a Country Posters: the India section's header counts its states and union territories, not "countries"
The India section's cards are India itself, its 34 state and union territory posters and the two with none listed,
so "· 37 countries" was untrue. Through PosterWall's sectionItemCountKey, that section alone counts its state cards
(36, from the data) with countryPosters.indiaItemCount; every other section keeps the countries count.
The key in all 11 locales, in each locale's own plural forms (the same form counts as regions.countryCount).
2026-10-01 05:11:52 +00:00
Doxa Maps
e38103149d Country Posters: previews for the 34 India state and union territory posters
Each state's sheet drawn from live records with the browser's own inputs (SPARSE 3x3, the indiaState series, the
served boundaries and places), shot in the shared browser at 3000 px, and reduced by make-previews.py to the 560 px
card thumbnail and the 1500 px download, as the country previews are. Every record pinned; every layout octilinear.
2026-10-01 01:03:51 +00:00
Doxa Maps
ddb7a4850c Country Posters: India is its own section, first, above Asia, counted once
India's country card, its 34 state and union territory posters and the two with none listed now share one section,
headed by India's name and counted once (855, through PosterWall's sectionTotal), which puts it above every regional
section. One line at the top of the wall says why India is set apart. Asia keeps every other Asian country.
check:country-sheet-one-path ARM E: the wall passes sectionTotal, India's card is in the India section, PosterWall's
default is still the card sum, and over the real data India comes first with 855 (India 855 > Asia 454 > Africa 314).
2026-10-01 01:03:50 +00:00
Doxa Maps
4de20daed6 P assembly: the last census lines, stated neutrally
The census on the assembled branches still found eleven comments that attributed a choice to a dated
request, quoted it, or spoke in the first person: pplr-data-maps (geocoder, pin card, pin indicator, tree,
families, religion, semantic trees), research-dashboard's ramp note, upg-100-list's funnel note, and two
dated QA tags each in countries-map and research-map. Comments only; behaviour unchanged.
2026-10-01 00:57:41 +00:00
Doxa Maps
202a0244e2 Privacy: neutral comments in Country Posters (no quotes, date tags or agent names)
Comments only; behaviour unchanged. Each rewritten line keeps its technical fact and drops the attribution:
- design-note and brief quotations restated as plain design statements (country-poster-wall.vue, index.js,
  countries-map.vue);
- "(qa: <date> …)" tags and "user feedback / user reported" attributions removed (countries-map.vue);
- fleet agent names replaced by what was measured (countries-map.vue, country-posters-mfe.vue);
- series.json's India-state note: the approval date is gone; the wording stays the editable default.
2026-10-01 00:51:05 +00:00
Doxa Maps
1e300309c8 Country Posters: one poster for each of India's states and union territories
The unfiltered wall gains an "India — states and union territories" section: 34 cards, one per state or union
territory with people groups listed (from the shared india-states table, fetched and sha-checked only when the
section is shown), each with its poster, prayer packet and cards. Nagaland and Mizoram get a card saying no
unreached people groups are listed there, so no division silently disappears. A host's filtered wall
(countries/region) is unchanged and never loads the table.

src/indiaStateSheet.js draws a state's sheet through ONE path: its records by slug, its outline from the
ADM1 boundaries the renderer already loads (matched on shapeName; the shared collection is copied, never
mutated), India's hue, and the indiaState series ("India State Maps", map N of 34). Show on map for a state
frames India, since the countries map draws countries.

check:country-sheet-one-path grows the state arms: inside this plugin only the helper calls generateSheet,
the wall must use makeIndiaStateSheet, and over the served table + ADM1 file: 36 divisions, the 34 with groups
numbered 1..34 each with an outline, the rest named, the ADM1 collection unmutated. Self-test 10/10.
Rendered headlessly through poster-render for Gujarat (90 pins), Lakshadweep (1), Andaman and Nicobar (9):
the state's name as title, "India State Maps", its series position, no country-series text, no "Province".
2026-09-30 23:33:34 +00:00
Doxa Maps
b0d0fcaf91 seriesFor: state that every no-sheet country shares one series, and gate it
A second country without a sheet size would silently join India's oversized
series and print India as "map 1 of 2". The comment now says so, and
check:country-sheet-one-path fails when more than one country has no sheet,
naming them, so that change is a decision rather than drift. Its self-test
plants a second one (China) and requires the arm to fail.
2026-09-30 21:57:25 +00:00
Doxa Maps
ffbb07e4a4 Country Posters wall draws its sheets through makeCountrySheet
The wall had its own inline wrapper around generateCountrySheet, a second
copy of @map/packet/countrySheet.js, which the Regions tab uses. Two copies
of one wrapper drifted twice (a teal Regions print, then India's series). The
wall now calls makeCountrySheet with the same country list, still handing it
the data's own English record rather than the localized card.

Behaviour: identical sheets for every country with records; a country whose
records come back empty now yields no sheet (the wall falls through to its
stored preview), as the Regions tab already did.

check:country-sheet-one-path (in gates:pre, with a self-test) parses every
plugin source: a direct generateCountrySheet call fails, every
makeCountrySheet call must pass the series list, both known callers must be
found, and seriesFor gives named answers over the real data (India 1 of 1,
each 3x3 country N of 173, an absent code no series). It fails on
development c4655072a for all three defects.
2026-09-30 21:57:25 +00:00
Doxa Maps
6c9b844b8e Country Posters: the wall shows a host's countries, or one region, flat, on request
profile-config gains two optional keys for the country-poster-wall profile: `countries` (ISO-3 codes, or
{code, name, count} records, in the host's order) and `region` (one WAGF region as the data names it).
With either, the wall is flat: one section, nothing collapsed, two columns unless `columns` says otherwise,
no heading unless `heading` is given, because it sits under the host's own region heading. A requested
country with no poster keeps its card and says so in the regions catalogue's words. With neither key,
every binding is what it was, so the plain wall is unchanged. PosterWall itself is untouched; only the
country-posters bundle rebuilds. The usage lines in index.js and the profile's meta note name the keys.
2026-09-30 12:17:39 +00:00
Doxa Maps
1728372a1e Reshoot the 173 country previews in the SPARSE layout
The country poster previews were the dense layout -- small facts table, both
vision columns, a smaller map -- while every UPG-100 thumbnail is SPARSE. Now
that the click-time print is SPARSE too, the stored country previews have to be,
or the card and the print disagree.

Generated with SPARSE=1 and checked BEFORE any browser time:
  · the generator's own layout guards: 173 of 173 ok, octilinear, 0 diagonals.
  · SPARSE on all 173: 0 sheets draw a dense-table element; all 173 carry the
    bold "N UPG's" count.
  · real values: 0 sheets show 0, NaN or blank population. Worst cases by UPG
    count: Sudan 105 / ~20.7M, Brazil 103 / ~63K, Laos 95 / ~968K.
Shot on the fleet's shared Chromium (no private browser), one page at a time:
173 of 173, 0 failed, all 3000x3000, none blank. Smoke-tested and looked at
first: Sudan shows the bold facts row, no vision columns, "1 of ~170 maps".

ALL 173 CHANGE: 173 source thumbnails, 173 full-size and 173 served previews
differ from development, 0 strays, nothing written to a stray library/ path.

China is deliberately NOT here: its thumbnail stays the dense "map 174 of 174"
it has tonight. Its print becomes SPARSE with "map 1 of 1" via the small-total
guard. The remaining numbering difference is R-CHN-SERIES-TIER, a product call
after the demo.
2026-09-30 03:30:10 +00:00
Doxa Maps
087f562e04 Reshoot the 174 country previews with the region hue and ink badges
The poster walls' card THUMBNAILS are stored WebP files, not generated at the
click, and all 174 were last shot on 09-25 -- teal. Since the region hue
landed, the PRINT has been hued, so both Country Posters and the Regions tab
showed a teal thumbnail above a hued poster. The Experimental section shows on
Deep Research, so that mismatch was visible.

Shot in one pass on the shared browser: 174 of 174, 0 failed, 0 retries,
23:00:37-23:10:07Z, one engine, DSF 2. Measured by the shooter: none blank (at
least 1,000 distinct colours each), and the count of sheets by their --zc hue
matches the region census exactly -- 41 Africa, 27 Asia, 27 Europe, 21 Middle
East, 18 Other, 17 Oceania, 14 North America, 9 Latin America. Asia is 27, not
28, because India has no sheet.

★ ALL 174 CHANGE, and that is the check that matters here. make-previews used to
write one directory too high (library/plugin-designs/..., library/data/posters)
while reporting success, so a reshoot could complete, look complete, and change
no served file at all. With that fixed, 174 of 174 source thumbnails, 174 of
174 full-size sources and 174 of 174 served previews differ from development,
with 0 untracked strays.

China was regenerated first with the whole-series count: 'map 174 of 174' and
'one of a 170-map set', where it had printed 'map 1 of 1' and 'a 0-map set'.
2026-09-29 23:18:26 +00:00
Doxa Maps
99816626af Every shadow stylesheet gets its own label, and a gate keeps it that way
useShadowStyles keys its <style> by the label and overwrites an existing
tag with the same key, so two components sharing a label keep only the
last one's CSS in a shared shadow root. The regions list lost its sheet
this way to the region card, which had kept the list's label when it was
extracted.

check:shadow-style-labels-unique (gates:pre) fails any label two calls
share, globally rather than per shadow root, so a copied or forked
component is caught when it is copied. It reads the real parsers,
classifies every reference to the function (a rebinding, .call, a
re-export or a namespace import fails instead of hiding a call),
cross-checks the AST against the token stream, and covers the other
ways two calls share a key: unlabelled calls under the dev server's
per-component key, and a fixed label over CSS that varies per caller.

countries-map.vue, a fork of research-map.vue, carried the same label;
it is now 'countries-map', with the country-posters bundle rebuilt and
the tree regenerated. The composable's JSDoc called the label a
debugging name; it now says it is the key.
2026-09-29 17:42:44 +00:00
Doxa Maps
45d931fa40 Repair what the union resolution duplicated
Resolving package.json conflicts by unioning unique lines is right for a file
that holds one entry per line. Applied to ordinary source it duplicates
declarations, because both sides of a hunk keep their copy and nothing
de-duplicates across the join.

Eleven plugin entry points ended with the same import twice, and the poster
renderer with two identical `const sheet`. Each is a SyntaxError: every one of
those bundles would have failed to build, and the poster export would not run.

Found by parse-checking every changed .js against the merge base, not by the
gates -- gates:pre passed 101 of 102 with all twelve files broken, because its
parse gates do not cover plugin entry points.

One measurement trap worth recording. `node --check` on a .js file parses it as
CommonJS, so a bare `import` is a syntax error and ALL 28 entry points appear
broken, on development too. That reading says the tree is on fire and is simply
wrong. Copying each file to a .mjs and checking that parses it as a module,
which separates the eleven that are genuinely broken here from the rest that
are fine.
2026-09-29 16:01:45 +00:00
Doxa Maps
c9ffa34e93 Merge branch 'bundler-2/provide-warnings' into bundler-2/handoff
# Conflicts:
#	internal/check-element-bootstrap.mjs
#	internal/check-provide-shadowing.mjs
#	library/elements/defineMapElement.js
#	library/elements/provide-own.js
#	package.json
#	plugin-designs/all-people-groups/index.js
#	plugin-designs/cities-internet/index.js
#	plugin-designs/country-posters/index.js
#	plugin-designs/doxa-research-map/index.js
#	plugin-designs/gospel-internet/index.js
#	plugin-designs/gospel-resources/index.js
#	plugin-designs/key-cities/index.js
#	plugin-designs/my-upg-100-list/index.js
#	plugin-designs/pplr-data-maps/index.js
#	plugin-designs/regions-dashboard/index.js
#	plugin-designs/upg-neighbor/index.js
2026-09-29 14:50:37 +00:00
Doxa Maps
8793d47f0e countries-map paints idle regions with the library's regionIdle, not its own copy
useLegendMapBridge.js now exports regionIdle (sr, pair 1). The local
function is deleted and the name imported beside the bridge's other
exports; all 15 calls keep their values, the dynamic regionIdle(v)
included. Built bundle: the idle expression occurs exactly once before
and after (the local copy before, the library's after), 1 byte apart;
the country-posters composite still mounts. check:region-paint-single-
source PASS. Also drops a comment left behind when clearCountryHighlight
moved to the same library module.
2026-09-29 13:29:18 +00:00
Doxa Maps
07eb74c33c Move four identical bodies into the library
From the fleet census: 620 function bodies indexed across 29 plugin trees,
16 identical in two or more. These are the four cheapest — none closes over
anything beyond its own parameters, so each is a file move plus an import
rather than a new dependency to thread.

hostElement resolves the custom element a component is mounted inside, one
hop out through the shadow root. It was identical in three plugins, and it
is the piece worth sharing for a reason other than line count: every plugin
ships through defineCustomElement, a composite nests two shadow roots, and
code that forgets the hop operates on the wrong node while looking correct.
A document-level query for a node inside a shadow root returns null on a
working build, which reads as a broken feature rather than a wrong query.
Three copies were three chances to write that.

findScrollportAncestor walks up to the nearest ancestor that actually
scrolls, crossing shadow boundaries on the way — parentElement stops at a
root, so a plugin in a custom element would otherwise find no scrollport and
conclude the page does not scroll.

findNodeInTree and buildFlatLegendMatchExpr join useLegendMapBridge, which
already holds four functions from the same seam. They sit at module level
rather than inside the factory because they close over nothing: a pure
function hidden in a closure can only be reached by constructing the whole
bridge.

Call sites keep their old names through a one-line local binding, so no
call changed and the diff is the declaration plus an import.

Rebuild-and-compare, all five affected bundles, before -> after:
  regions-dashboard   1,098,469 -> 1,098,479   +10
  country-posters     1,484,053 -> 1,484,028   -25
  doxa-research-map   1,354,051 -> 1,354,061   +10
  dashboard-plus-grid   915,660 ->   915,644   -16
  big-picture           366,907 ->   366,719  -188
  net -209, and country-posters gains 25 bytes against the 1.5 MB ceiling.
Every behaviour-bearing token counted, not set-compared, and unchanged in
all three map bundles: regions-fill, peoplePraying, engagementStatus,
adoptionStatus, overflowY, scrollHeight, getRootNode, _flat_filter, religion.

Owners cleared their own files first: regions for regions-list.vue, upg100
for countries-map.vue. check:selection-kinds, check:legend-matches-source,
check:legend-data-contract, check:packet-variants, check:no-dead-library and
check:no-cross-plugin-imports all pass.
2026-09-29 09:19:04 +00:00