Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
Some checks are pending
build-gate / build (push) Waiting to run

# Conflicts:
#	public/doxa-maps/index.html
This commit is contained in:
doxa-maps-88655c70 2026-09-25 01:02:29 +00:00
commit 1465e3a7bb
13 changed files with 70 additions and 22 deletions

View file

@ -222,10 +222,40 @@ async function measure(width, lang) {
// what its buttons SAY has not been fixed. scrollWidth > clientWidth is the browser telling us
// the text did not fit its box.
const clipped = ctrls.filter((e) => e.scrollWidth > e.clientWidth + 1)
// ★ DENSITY: how many posters share a row, and how wide each is.
// The Driver asked for "around 4 per row on desktop, like Instagram". The grid is ONE rule for
// every width — repeat(auto-fill, minmax(210px,1fr)) — so the count falls out of the viewport
// rather than being chosen, and NOTHING measured it. The card's own verify says it: "perRow is
// currently printed nowhere and asserted nowhere. A number printed but not asserted on is
// decoration."
// ⚠ REPORTED, NOT YET ASSERTED, and that is deliberate. The desktop target is settled (~4) but
// the MOBILE one is not: 3 per row at 390px is a ~120px card, which cannot hold the wrapped
// print footer this same gate asserts is readable. Asserting a number the Driver has not
// ruled on would encode my taste as a requirement. Measuring it first is what makes the
// ruling answerable — and it is the precondition for tuning, since you cannot tune toward a
// target you are not measuring.
// Row-mates are found by TOP EDGE, not by index: a grid row is a set of boxes sharing a y,
// and counting "every Nth card" assumes the very layout under question.
// ⚠ IT IS THE MAX, AND THE WALL IS SECTIONED. Grouping every card by top edge at 1440px gives
// row sizes [5,5,5,3,3,2,2,1,1] — the short rows are the REMAINDERS of collapsible sections,
// not a density failure. Reading the first row alone would be right here by luck and wrong on
// a wall whose first section holds one poster. The max across all rows is the density the
// Driver's "around 4 per row" is about; cardW is reported beside it because the two move
// together and the width is what explains the count.
let perRow = 0, cardW = 0
if (cards.length) {
const byTop = new Map()
for (const c of cards) {
const t = Math.round(c.getBoundingClientRect().top / 8) * 8
byTop.set(t, (byTop.get(t) || 0) + 1)
}
perRow = Math.max(...byTop.values())
cardW = Math.round(cards[0].getBoundingClientRect().width)
}
return { cards: cards.length, rows: cards.filter((c) => c.querySelector('.pfs')).length,
overflowing, worst, intrusions, coveringPreview, worstY,
previewsPainted, previewsBroken, noPreview, clipped: clipped.length,
controls: ctrls.length, tiny: tiny.length }
controls: ctrls.length, tiny: tiny.length, perRow, cardW }
})()`)
await page.close()
return { width, lang, hover, reach, ...out }
@ -247,6 +277,7 @@ for (const r of results) {
+ ` · over-preview ${r.coveringPreview}${r.worstY ? ` (${r.worstY}px)` : ''}`
+ ` · previews ${r.previewsPainted} painted`
+ `${r.previewsBroken ? `/${r.previewsBroken} BROKEN` : ''}${r.noPreview ? `/${r.noPreview} none` : ''}`
+ ` · max ${r.perRow}/row @ ${r.cardW}px`
+ ` · ${r.controls} control(s), ${r.tiny} too small, ${r.clipped} clipped`
+ (r.reach ? ` · last card ${r.reach.lastInView ? 'reachable' : 'UNREACHABLE'}` : '')
+ (r.hover

View file

@ -320,8 +320,17 @@ const LEGEND_TABS = [
info: 'Region — sort the UPG-100 lists by world area (Africa, India, Middle East, Deaf, …). Counts are the UUPGs and population summed across every list beneath it.' },
{ id: 'upg100Zone', label: 'UPG-100 Lists',
info: 'UPG-100 Lists — each one is a prayer list of the unreached people groups in an area, and is what the map paints and colours. Every list prints as its own packet.' },
{ id: 'upg100Group', label: 'People Group',
info: 'People Group — the individual unreached groups inside a list, largest prayer need first. Each map dot is one of these.' },
// ★ THE 'People Group' TAB WAS REMOVED BECAUSE IT COULD NEVER RENDER ANYTHING — measured, not
// a matter of taste. SemanticTreeLegend renders tab N as collectAtDepth(nodes, N), so a tab's
// index IS a tree depth. This legend's tree is exactly TWO levels deep: 9 regions -> 28 lists.
// MEASURED 2026-09-25 by expanding every caret on the Region tab — 37 rows, 9 at indent 0 and
// 28 at indent 1, deepest level 1. There is no level 2, so tab index 2 resolved to an empty set
// and the panel rendered its "No data at this level" empty state with the tab ACTIVE.
// The Driver said "it doesn't need to have a People Group tab inside the legend"; the reason is
// that clicking it showed nothing at all.
// ⚠ IF PEOPLE-GROUP ROWS ARE EVER WANTED BACK, a third tab is not the mechanism — the tree would
// need a third level (list -> group). Re-adding the tab without deepening the data reproduces
// exactly this empty state.
]
// The generation the legend OPENS on: index 1 = the UPG-100 Lists tab. A reader
// should meet the lists first and reach for Region only to sort them.

View file

@ -433,7 +433,15 @@ useShadowStyles(
// `.with-icon .icon.right { margin-inline-start: 1rem }` — 10px at their 10px root. We had
// the same 10px via `gap`, which looks identical but means their rule would not apply, so
// the mechanism is now theirs: margin on the icon, gap left alone.
'.region-card__link{ appearance:none; background:none; border:0; padding:0; margin:0; text-align:left;' +
// ★ text-align:START, not left. Theirs is a NuxtLink, an inline <a> that shrink-wraps to its
// text; ours must be a <button> because this element changes the embed's subject in place instead
// of navigating a route. A button's UA default is text-align:center, so the port overrode it -- but
// it overrode it with the PHYSICAL `left`, which is identical to `start` in English and its
// opposite in Arabic. MEASURED on live /ar/regions vs ours at dir=rtl: same 246.9px row and the
// same 102.7px of text, their label flush to the row's RIGHT edge (gap 0px, the RTL reading start)
// and ours flush LEFT -- every label stranded 144.2px on the wrong side. Invisible in English,
// which is exactly why it survived a 37-property card diff and an 11-property bullet diff.
'.region-card__link{ appearance:none; background:none; border:0; padding:0; margin:0; text-align:start;' +
' cursor:pointer; color:inherit; font:inherit; font-weight:500;' +
' display:inline-flex; align-items:baseline; }' +
'.region-card__link:hover{ color:#92b195; }' +
@ -491,7 +499,7 @@ useShadowStyles(
// #4e594f, font-weight medium. MEASURED on their live /regions: rgb(78, 89, 79). Ours used
// var(--dx-text), which resolves to rgb(42, 51, 42) — the body ink, not their link ink.
'.country-link{ appearance:none; background:none; border:0; padding:2px 0; margin:0;' +
' text-align:left; cursor:pointer; color:#4e594f; font:inherit; font-size:var(--font-size-md);' +
' text-align:start; cursor:pointer; color:#4e594f; font:inherit; font-size:var(--font-size-md);' +
' font-weight:500; width:100%; position:relative; }' +
// inset-inline-start, NOT left: the bullet hangs off the text's starting edge, which is the
// RIGHT edge in Arabic. With `left:-16px` it stayed on the physical left in RTL — measured

File diff suppressed because one or more lines are too long

View file

@ -681,7 +681,7 @@
"bundle": "my-upg-100-list",
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"output": "doxa-maps/my-upg-100-list/my-upg-100-list.js",
"integrity": "sha384-NlPYE8Ka9bbUPBeUKZ8tppvBrvF9xdMXZlHtaUym05SxsppfTes/YtnAbr1wq4es",
"integrity": "sha384-AMIwL3sB+dFKS1OkVcGIX1lDbK1ZB5RyvjfhVNexuEe12HIjB1GToYbTaL2ZF5x1",
"elements": [
"my-upg-100-list-map"
],
@ -701,7 +701,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-NlPYE8Ka9bbUPBeUKZ8tppvBrvF9xdMXZlHtaUym05SxsppfTes/YtnAbr1wq4es\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-AMIwL3sB+dFKS1OkVcGIX1lDbK1ZB5RyvjfhVNexuEe12HIjB1GToYbTaL2ZF5x1\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
},
{
@ -715,7 +715,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-NlPYE8Ka9bbUPBeUKZ8tppvBrvF9xdMXZlHtaUym05SxsppfTes/YtnAbr1wq4es\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-AMIwL3sB+dFKS1OkVcGIX1lDbK1ZB5RyvjfhVNexuEe12HIjB1GToYbTaL2ZF5x1\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
},
{
@ -729,7 +729,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-NlPYE8Ka9bbUPBeUKZ8tppvBrvF9xdMXZlHtaUym05SxsppfTes/YtnAbr1wq4es\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-AMIwL3sB+dFKS1OkVcGIX1lDbK1ZB5RyvjfhVNexuEe12HIjB1GToYbTaL2ZF5x1\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
}
]
@ -879,7 +879,7 @@
"bundle": "regions-dashboard",
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"output": "doxa-maps/regions-dashboard/regions-dashboard.js",
"integrity": "sha384-7ouNc0JA9dufo2S3LgvdwQ/znMBgiow5pEeOs2xWejN7xOuqGRm9wPepdm3uS40z",
"integrity": "sha384-enb1WwvsLsMhEBv18htUxch3X43a+eYv9xl34b8rmL/zPy6a8mJ3zXNa1RptdnX/",
"elements": [
"regions-dashboard"
],
@ -899,7 +899,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "<iframe src=\"./regions-dashboard/region-dashboards/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-7ouNc0JA9dufo2S3LgvdwQ/znMBgiow5pEeOs2xWejN7xOuqGRm9wPepdm3uS40z\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-enb1WwvsLsMhEBv18htUxch3X43a+eYv9xl34b8rmL/zPy6a8mJ3zXNa1RptdnX/\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
}
},
{
@ -913,7 +913,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "<iframe src=\"./regions-dashboard/regions-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-7ouNc0JA9dufo2S3LgvdwQ/znMBgiow5pEeOs2xWejN7xOuqGRm9wPepdm3uS40z\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-enb1WwvsLsMhEBv18htUxch3X43a+eYv9xl34b8rmL/zPy6a8mJ3zXNa1RptdnX/\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
}
},
{
@ -927,7 +927,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "<iframe src=\"./regions-dashboard/regions-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-7ouNc0JA9dufo2S3LgvdwQ/znMBgiow5pEeOs2xWejN7xOuqGRm9wPepdm3uS40z\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-enb1WwvsLsMhEBv18htUxch3X43a+eYv9xl34b8rmL/zPy6a8mJ3zXNa1RptdnX/\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
}
}
]

File diff suppressed because one or more lines are too long

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
<script src="../my-upg-100-list.js" integrity="sha384-NlPYE8Ka9bbUPBeUKZ8tppvBrvF9xdMXZlHtaUym05SxsppfTes/YtnAbr1wq4es" crossorigin="anonymous"></script>
<script src="../my-upg-100-list.js" integrity="sha384-AMIwL3sB+dFKS1OkVcGIX1lDbK1ZB5RyvjfhVNexuEe12HIjB1GToYbTaL2ZF5x1" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
<script src="../my-upg-100-list.js" integrity="sha384-NlPYE8Ka9bbUPBeUKZ8tppvBrvF9xdMXZlHtaUym05SxsppfTes/YtnAbr1wq4es" crossorigin="anonymous"></script>
<script src="../my-upg-100-list.js" integrity="sha384-AMIwL3sB+dFKS1OkVcGIX1lDbK1ZB5RyvjfhVNexuEe12HIjB1GToYbTaL2ZF5x1" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -40,7 +40,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
<script src="../my-upg-100-list.js" integrity="sha384-NlPYE8Ka9bbUPBeUKZ8tppvBrvF9xdMXZlHtaUym05SxsppfTes/YtnAbr1wq4es" crossorigin="anonymous"></script>
<script src="../my-upg-100-list.js" integrity="sha384-AMIwL3sB+dFKS1OkVcGIX1lDbK1ZB5RyvjfhVNexuEe12HIjB1GToYbTaL2ZF5x1" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
<script src="../regions-dashboard.js" integrity="sha384-7ouNc0JA9dufo2S3LgvdwQ/znMBgiow5pEeOs2xWejN7xOuqGRm9wPepdm3uS40z" crossorigin="anonymous"></script>
<script src="../regions-dashboard.js" integrity="sha384-enb1WwvsLsMhEBv18htUxch3X43a+eYv9xl34b8rmL/zPy6a8mJ3zXNa1RptdnX/" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
<script src="../regions-dashboard.js" integrity="sha384-7ouNc0JA9dufo2S3LgvdwQ/znMBgiow5pEeOs2xWejN7xOuqGRm9wPepdm3uS40z" crossorigin="anonymous"></script>
<script src="../regions-dashboard.js" integrity="sha384-enb1WwvsLsMhEBv18htUxch3X43a+eYv9xl34b8rmL/zPy6a8mJ3zXNa1RptdnX/" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -40,7 +40,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
<script src="../regions-dashboard.js" integrity="sha384-7ouNc0JA9dufo2S3LgvdwQ/znMBgiow5pEeOs2xWejN7xOuqGRm9wPepdm3uS40z" crossorigin="anonymous"></script>
<script src="../regions-dashboard.js" integrity="sha384-enb1WwvsLsMhEBv18htUxch3X43a+eYv9xl34b8rmL/zPy6a8mJ3zXNa1RptdnX/" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order: