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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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).
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".
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.
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.