pageLink() drops ?tk= from the page's address: a leaf page reads a token from
there and leaves it in place, so pressing Share would have sent it. The URL is
rewritten only when tk is present; every other link is the address as it stands.
The comments name the page, not who measured it, and no longer cite a request.
check:map-menu-anchor strips a same-line comment before testing each return, so
a fallback named only in a comment no longer passes.
ShareButton: the first tab is "Share this page", the link to exactly what the
reader is looking at. Where the page owns its address (urlOwner 'app' or 'host',
on the map's own profile-config or any element above it across shadow roots)
that is the page's own URL, read at open and at copy; on a partner's page it is
the map's own page, as before. The second tab, "Embed", says in plain words what
embedding is and why it helps, keeps the buttons.shareSteps list, then the paste
hint, the sizes and the code. Copy/sizes labels come from the catalogue.
MapControlMenu: a standalone anchor (a Share button outside any map toolbar)
resolves where its menu lives when it opens, and places it below the button,
toward the side with room, inside the viewport, at the readable width (340 or the
viewport minus its edges), converting into the menu's real containing block. The
render-time area tag that sent header menus far left and narrow is gone. Map
toolbars keep their placement unchanged.
English only for now (the new share.json keys are recorded as translation debt in
check:i18n-parity). check:map-menu-anchor reads a resolution that lives in a named
function, every named-area return must keep its structural fallback.
The header claimed that every write to the address bar goes through commitUrl. Only the view keys and the filters
do. The tree's other history writers are pinned by check:view-address's census. The header also says why a push
copies the previous state: a Vue Router page is a 'host' owner, so its router does its own pushes.
Comment only.
library/composables/useViewAddress.js is the page's address for the view a reader is on: ?tab= &pane= &place=, with
a level rule, an id whitelist, and ONE history write (commitUrl). It keeps history.state and sets its `current` to
the new URL, so a link survives the next in-app navigation on a Vue Router host. The OUTERMOST owner writes,
named by profile-config urlOwner:
- 'app' writes history itself;
- 'host' hands its router one dxm-address;
- absent, nothing is written and links are still read.
Nested elements announce dxm-view. Back/Forward is read and never written.
useShareableView's filter write used to call replaceState(null, ...) itself, which wiped the router's state. It
now goes through commitUrl (writeFilterView). A filter write keeps tab/pane/place, and a tab/pane/place write keeps
the filters.
Level 2 is `pane`, not `view`: ?view= is already published by four of our pages.
check:view-address (gates:pre) runs on a simulated browser history. It covers:
- the whitelist and the level rule;
- one push per tab change, with state + current kept;
- no write when unchanged, on a partner page, or by a host owner;
- the filters and the view keys keeping each other through writes, Back and Forward;
- a census of every history writer in library/ and plugin-designs/ (6 today). A new writer fails until it is listed.
The self-test has 14 poisons, each caught. Real-source mutations are caught too: drop current, drop the unchanged
guard, drop the level rule, an uncomposed event, no length cap, an aliased pushState in a plugin.
UPG100's zone-poster code lived only inside its plugin, so Poster Design
(which draws from the library) could list UPG100's posters but never show
them. It is now COPIED, unchanged, into library/packet/upg100Zones/
(zone-sheet-print, zone-sheet, legend-tree, selector-evaluator,
zone-geometry, zones-for-list, clusters.json; only the library import paths
are shorter). UPG100's own files are untouched.
Poster Design adds a UPG100 zone posters family drawn from that copy with a
real zone (middle-east-core) and all the records, as UPG100's own wall
does: the letter, 3 x 3 and 3 x 4 zone posters under UPG100's own design
names (so the drawn card replaces the no-preview plugin card), and the
prayer packet's page 1 (the full letter zone poster). Keys in 11 locales.
check:upg100-zone-copy (in gates:pre) keeps the copy equal to UPG100's
originals beyond the import paths; once UPG100 switches to the library copy
and deletes its originals it becomes a one-path gate. Its self-test proves
a one-character edit, a changed clusters.json, a missing file, a half
switch and a re-definition each fail. check:poster-design-catalogue allows
a template to carry a plugin's design name only when it declares that
plugin (poisoned). Source only: poster-design is rebuilt when the heavy
slot reopens.
The four Wall sources both sides changed (blessPoster.js, wall.css, wallCanvas.js, check-wall-no-bg-photos.mjs)
merged without conflict: the pilot's side is the comment-only privacy rewording of those files (c1a2f3698); both
sides are kept (no agent names; every branch change present). The generated files (the wall bundle, its leaf page
and the two manifests) were taken from the pilot and rebuilt from the merged source, then fix:sri and the tree.
Styles now lists the production designs by family, and puts every
experimental design last, in one Experimental (in progress) group that
starts collapsed (a click opens it). Experimental: the side-lane country
sheets (66x66, 36x60, and 60x96, still being designed), the map print (no
preview: it prints the live map), and every other plugin's design (made by
its own plugin, so not drawn here). templates.js marks them experimental;
posterDesign.family.experimental is new in all 11 locales.
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.
- The life calendar and the reached chart share one grid at the page's
full printable width: each week a 22x11 box, bold year numbers every
5 years (larger every 10), week numbers 1/13/26/39/52, a clear rule
every 10 years and light rules at the quarters. The reached chart has
no week or year numbers; each 10-row block is labelled with its share
of the list's people, 10% to 100%.
- Page 1: the UPG100 series sets its own one-paragraph Jesus column
(series.json strategyBody) and prints the explainer's first paragraph
only (sideBoxMore), so the three columns balance and the map grows.
The long text is one constant shared by both header layouts; the
Country and India-state posters print it unchanged.
- The points page takes, per language, the largest size tier that fits
one sheet, up to the earlier two-sheet sizes. The tier comes from a
character-count estimate; the render gate fails if the real page is
ever taller than that estimate.
- The twelve prayer points and the themes fit one sheet again, as large
as the page allows (points 18.5px, themes 19px); measured in all 11
languages, the tightest keeps 75px under the last point.
- Page 1 header columns read: Jesus' Strategy to Feed the 5000 | the
facts | What is a UPG100 List? The facts' labels are bold.
- The header columns are measured for a fallback font too, so the right
column no longer runs to the border when Lato is absent.
- check:packet-render expects one points sheet.
Points: text 22.5px (~9.2pt on letter), headings 25px, the Mark 5 passage 20px, the themes 21px; the themes and
points 1–6 on the first sheet, 7–12 and the credit on the second, each titled with its range. Measured in all 11
languages: the fullest first sheet keeps ~330px. Full detail: tally columns 160px (the worksheet's), heads 15px
in two lines in every language, the first-page block 720px (the tallest, ru, uses 692), 11 rows on the first page.
Gates: the render gate measures BOTH points sheets (pointsOver), counts the points by .pt-h across the document,
expects 2 points sheets; the structure gate reads consecutive points sheets as one entry; profile-table probes the
15px tier between the two budgets wherever they fall.
Only the full layout (HEAD_COLUMNS, the packet's page 1, printed on letter at 92%): the column text 14 → 22px
(~8.3pt), the fact keys and the verse reference 19px (~7pt), the column headings 23px, the footer's three blocks
13.5 → 22px with their lines re-measured; the Matthew 9:36 verse is set on two balanced lines at 19.5px. The band's
measure fills its column (0.96), a country list longer than twelve prints ten and '+N' (the Deaf bloc names 66),
and the full footer band is 400px. All 28 zones render; each map is 858px (it was 1,206). The series-wide rules
are unchanged, so the SPARSE posters are byte-identical.
The fine print (the Metacamp credit on the wheel and points pages, the privacy line) sat 22px (0.14in) from the
edge on letter, inside the band printers cannot ink; it now sits at 50px. The points page gives back the room:
point text 18.5 → 18px, 6 → 5px between points, the Mark 5 passage 17 → 16px, the body 14px higher. Measured in
all 11 languages: the tightest (fr, hi) keep 46px under the last point (check:packet-render's pointsOver gates it).
Hindi (and Marathi, Nepali) name Noto Sans Devanagari, Mangal, Nirmala UI and Kohinoor Devanagari after the
vendored Noto Serif Devanagari, so a print without the inlined face still lands on a Devanagari font.
The points page fits ONE sheet only because its sizes are tuned to the longest language (studio's ask): pointsOver
fails a page whose content outgrows its box (two-sided: 26px text fails; all 11 languages PASS at 18.5px).
Each point's heading carries class pt-h, and the gate counts those: counting every line that starts 'N. ' read
German's '1. Petrus 5:6–11' (its name for 1 Peter, point 11's reference) as a thirteenth point.
Full detail: tally columns 96 → 116px, the once-per-page question heads 12 → 15px in a 62px head row (three short
lines), so they read on paper; the first page holds 11 rows. Points page: the themes and scenes 15 → 19px (~7.7pt
on letter), the twelve points 19 → 18.5px to make room. Measured in all 11 languages: every first list page,
Full detail's reserved block (612 of 640px) and the points page (the tightest, fr, keeps 43px) still fit.
Centered set: the ring numbers ride the axis BELOW the cross, 9 at the bottom, so the eye climbs 9 → 1 to it;
the dots turn half a circle to keep the number lane clear. The ring legend opens with what a ring means in
plain words (sets_rings_lede x11) before listing the rings that hold someone.
Life in weeks + the reached grid: each grid is ONE inline SVG, two paths of square subpaths (empty, shaded),
hairlines between decades, small week and year numbers; measured on the two pages together: 10,553 page nodes
→ 86, load 474 → 214 ms, print 641 → 320 ms. The reached grid now has the life grid's exact shape (same
geometry, no week or year numbers, centred), shaded from the top by this list's share.
Gates: variants and render decode each grid's subpaths back to box indexes in reading order (5,200 distinct,
Jesus' 33 years = the first 1,716, the share from the top, the same viewBox for both); two-sided: shading
the LAST 33 years fails both. Gospel's three optional nits folded in (it un’altra, example_note x5, ru чёрточка).
Themes (bless the nations, perfect unity, protection from evil, hearing God's voice, true identity in Christ,
deep relational health, the priesthood of believers) to weave into the wheel's five-minute blocks, then the
scenes treasure, mountain and sea, each with its two references from the Wall of People Groups' poster
(Haggai 2:7 · Matthew 13:44, Isaiah 2:2 · Matthew 21:21, Habakkuk 2:14 · Matthew 8:26). Point 12: the blessing,
the great, the greater and one of the greatest blessings of John 17, unity and protection, beyond all we ask
or think (John 17:3 · John 17:11–23 · Ephesians 3:20). Words drafted by the gospel lane x11; books Haggai,
Isaiah, Habakkuk, Ephesians x11. The page still fits one sheet in every language (19px text, 6px between points).
Gates: parity fails a point whose references are not English's (ten languages kept point 12's old ones) and
needs 7 themes + 3 scenes per language; variants checks the themes block and point 12 in both packets.
The tab label in both shells (doxa-maps-spa, posterverse) x11 in each language's own grammar (de 'UPG100-Poster',
es 'Carteles UPG100', zh 'UPG100 海报', …), upgMap displayName and wallHeading x11, the three meta labels, the
nav item and the dev title; the spa's default tab label, the posterverse description, the UPG-100 legend's
count column and the poster-sections noun. Values only: ids, keys, paths and file names stay.
Values only: keys, ids, paths and file names stay (my-upg-100-list, tab.upg-100). Catalogues legend, mapStrategy,
messages, search, tabs and upgMap in all 11 languages (13 keys); the shells' tab label in doxa-maps-spa and
posterverse x11 (German 'Poster der UPG100-Liste'); the three meta labels, the dev page title and the nav
label. poster-render's last-resort literals (used only by a series with no name of its own) follow:
'UPG100 List', 'What is a UPG100 List?'.
Full detail: the question no longer repeats under every tally cell; the heads stand once per page over the
cells' own columns, and each cell is all tally room (96px columns, taller boxes). The worksheet's boxes
get a little more room too.
Both lists' first page: the intro and the blessing (Numbers 6:24-26, its credit, one line of references, the
wheel pointer) at full width, then ONE band like the poster's (ruled above and below, three columns between
short rules): the pace table (strongest to slower, weekly marked, each load computed from the list), what the
three columns ask, and an EXAMPLE row of tally cells under the table's own heads, exactly as wide as the
tally block and directly over it. One code path (explainTop, explainBand) for both packets.
Measured with a 100-group list in all 11 languages: the worksheet's first page holds 10 rows (the tallest,
ru, keeps 67px), Full detail's 12 under a 640px block (the tallest uses 612); the example sits over the real
cells to the pixel. Gates: packet-variants checks the band in BOTH packets (once, before the first row,
computed paces, one example row, heads once per page); packet-render reads the page sizes from the
renderer, fails a clipped first-page block, and measures text direction against the content box (a padded
cell is still pinned left). New strings x11: howto_bless_col, example_title, example_note.
series.json upg100: seriesName 'UPG100 List', sideBoxHeading 'What is a UPG100 List?', label 'UPG100 — …'.
packet-strings: every 'UPG 100' / 'UPG-100' in the four strings that name the series, in all 11 languages
(map_page_series, funnel_kicker, funnel_packets, funnel_tip; 44 values). The structure gate's literals follow.
A device whose fonts lack U+0671 printed it as a box. Only those 13 code points change (0671: 13 -> 0, 0627:
+13); the bold verse is still a substring of the passage. check:packet-strings-parity fails on any U+0671 in
an ar value (it fails on the previous file). The Arabic scripture blocks also name Arabic faces before serif.
generateSheet gains `sparse` (default: every format but 'packet', so every existing caller is unchanged);
the UPG-100 zone sheet answers the packet's 'packet' request with the full letter poster, the same
1500x1941 page. check:poster-browser-equiv compares that sheet with Node's letter format without SPARSE.
Opt-in per series (series.json poster.headColumns, on for upg100 only), so every other series' sheet is
unchanged. The band is laid out by ONE function that both measureHeader() and the renderer call, so the
predicted header height is the drawn one. Each block is centred in an equal column between short rules,
with the inset the first column lacked. The footer's three blocks are drawn at the 13.5px they are wrapped
and spaced for (they were drawn at 12px), so the text grows with no change to the lines or the band's
height, and they are centred for that size.
SOURCE ONLY: the served copies, the integrity pin and its bundles are regenerated at landing.
loadPlaces memoised an empty table on ANY failure, so one network error meant no
city dots for the rest of the session, while the other pinned loaders retry. A
table that is not served (or a reader offline) is now forgotten, so a later print
tries again; wrong bytes, refused after the fresh refetch, stay refused for the
session.
The print-time files are pinned (poster-render.js and its classic copy,
packet-strings.json, ne-places.json, india-states.json) and were fetched with
cache: 'force-cache', which returns any cached copy, however old. After a
re-pin, a reader who had printed before kept the previous copy: it failed its
pin on every print and the print fell back without a word. Page 1 became the
stored poster, a non-English packet would print in English, and India's state
cards would be lost.
sha384.js fetchPinned fetches force-cache first (fast, and offline once
cached) and, when the copy is not served or fails its pin, once more with
cache: 'reload', which skips and refreshes the HTTP cache; only that answer
decides. posterSheets (the generator and the places table), packetStrings and
indiaStates all fetch through it. The classic-script path refreshes the cache
the same way and retries a refused tag once.
check:pinned-fetch-fresh models the HTTP cache with stale copies: page 1 still
draws, the packet keeps every language, India keeps its 36 states; a matching
cached copy is used with one request; wrong bytes are refused. The previous
loaders fail it. Self-test poisons: no fresh refetch, never the cache, a
mismatch accepted, a loader fetching its pinned file directly.
What the three columns ask; the blessing to pray over each group, Numbers 6:24-26 in full with its credit
(the public-domain text per language, compared verse by verse with its source; ro and hi print the English,
as the packet's other scripture does); one line of further blessing references (the Synodal's own Psalm
numbers in Russian); the prayer wheel at the end; and a pace table, daily (strongest) to every three months
(slower), weekly marked as the healthiest, each pace's daily load computed from the list's size.
The first page holds 11 rows (16 before); later pages keep 18. Measured with a 100-group list in all 11
languages: the longest first pages (ru, hi) keep 77px under their last row, the references fit one line.
check:packet-variants asserts the description, once, before the first row, and the computed pace; the
render gate follows the new pagination.
The tick boxes become tally cells, on the lightweight worksheet and on the full packet's profile rows, so a
list prayed through again and again counts every time. The headings are the questions themselves, broken
into balanced lines; the worksheet's tally columns widen to 160px so English heads take two lines. The
worksheet's note no longer says there is no pace to keep. Measured in all 11 languages: every worksheet
sheet and every profile row still fits (16 + 18 rows a sheet unchanged).