exp's maps keep the reason and drop the speaker: no comment quotes or cites the Driver

21 lines in seven of exp's bundles (upg-neighbor 4, prayer-walk-planner 8, doxa-simple-map 2, pplr-data-maps 2, wall-of-people-groups 1, doxa-vision-card 1, all-people-groups 3): each keeps its engineering reason, its dates and its measurements; the speaker and the quotes go (a quote becomes a plain statement of the defect). Comments only. Five bundles rebuild byte-identical; doxa-simple-map and pplr-data-maps change only in their Vue scoped-style ids, which hash the SFC source.
This commit is contained in:
Doxa Maps 2026-09-29 08:27:42 +00:00
parent 7e309d1777
commit c2473d0e41
12 changed files with 24 additions and 24 deletions

View file

@ -24,7 +24,7 @@
* (library/scripts/people-groups/build-points.mjs; 0.74 MB instead of the 7.5 MB slim file) — plus
* the live DOXA set via the standard pray-tools pipeline.
*
* ★ LOAD ORDER (2026-09-25, the Driver: "not even loading, takes a very long time"). Pins used to
* ★ LOAD ORDER (2026-09-25: the map was reported as not loading, or taking a very long time). Pins used to
* wait for BOTH the 7.5 MB file AND the live prayer API before anything drew. Now the compact
* file alone draws every pin by GSEC, and the DOXA overlay recolours its pins black when the API
* answers. A slow or unreachable API costs the black layer, never the map.
@ -110,7 +110,7 @@ const assetsBase = computed(() => resolveAssetsBase(profileConfig?.value || {})
// place for the two to drift apart.
// C4 wave 3d: the guard is library/composables/useOptionalI18n now — this site needs more than `t`,
// so it takes the {t, te, locale} form rather than useOptionalT.
// ★ THE LOCALE-HONOURING FALLBACK, per dx-shepherd's ruling (2026-09-27) and the Driver's goal (d):
// ★ THE LOCALE-HONOURING FALLBACK (ruled 2026-09-27, product goal (d)):
// a BARE-HOST EMBED WITH ?lang=ar MUST RENDER ARABIC. Recorded in COMMON.md as the embed contract.
// This file used to pass its inline EN map as the fallback, which served ENGLISH to exactly the hosts
// that cannot install vue-i18n — the seven bundles here that install none. tStatic honours the runtime
@ -133,7 +133,7 @@ const uiLocale = computed(() => {
})
const fmt = (n) => { try { return Number(n).toLocaleString(uiLocale.value) } catch (_) { return Number(n).toLocaleString() } }
// ─── The four categories (the Driver's palette) ──────────────────────────────
// ─── The four categories (the chosen palette) ────────────────────────────────
// Tuned for the LIGHT basemap (2026-09-25; was a near-black map, where the black DOXA pins vanished).
// Same four meanings and hues; yellow and green are a step darker because pure #f1c40f / #2ecc71
// wash out on near-white, and every pin carries a thin dark ring instead of a white one.

View file

@ -371,7 +371,7 @@ function _flatItemsToStlNodes(items) {
}
const legendNodes = computed(() => _flatItemsToStlNodes(flatLegend.items.value))
const legendTitle = computed(() => t('legend.titleBar.legend'))
// Prayer progress bar (header of the prayer legend; Driver 2026-09-16). The payload
// Prayer progress bar (header of the prayer legend; 2026-09-16). The payload
// is null on every non-prayer tab → no bar. Passed as a prop to the desktop STL
// below AND provide()d so the MOBILE sheet's embedded <SemanticTreeLegend>
// (LegendMobile.vue, untouched) picks it up via inject('legendProgress') — one
@ -628,7 +628,7 @@ watch(isDark, (dark) => { pplrInstance.theme.value = dark ? 'dark' : 'light' },
// ─── The Prayer look without a key ────────────────────────────────────────────
// On Mapbox this map is Standard at lightPreset 'night': near-black navy sea, slate land, rose
// borders — the "dark green" the Driver called our most beautiful map. Without a token the engine
// borders — the "dark green" look this map must keep. Without a token the engine
// is MapLibre and the basemap is OpenFreeMap `fiord`, which is slate-blue everywhere (sea #38435c,
// land #45516e: 13 units apart, and blue-grey borders). These colours are MEASURED from the Mapbox
// render, not chosen: pixels of this leaf at its own world view on Mapbox (main 4ca2dcf9) read ocean

View file

@ -9,8 +9,8 @@
* @bundle doxa-vision-card
* @element doxa-vision-card
*
* ★ WHY IT WAS REBUILT (2026-09-25). The Driver: "the data doesn't make sense … super false
* information." The old card rotated four TYPED-IN figures (7,398 / 3,240 / 42% / 1,910) with no
* ★ WHY IT WAS REBUILT (2026-09-25). Its figures were reported as making no sense, and they could
* not be traced: the old card rotated four TYPED-IN figures (7,398 / 3,240 / 42% / 1,910) with no
* source. Now NO number is written here. They come from data/people-groups/vision-funnel.json,
* which library/scripts/people-groups/build-vision-funnel.mjs computes from the IMB people-group
* CSV in the repo and a saved snapshot of the live DOXA list, and which is compiled in at build

View file

@ -1,7 +1,7 @@
<script setup>
import { dataUrl, glFor, exposeMap, releaseMap, whenGeojsonDrawn } from '../utils/pplrData.js'
import { usePplrT } from '../composables/usePplrT.js'
import { formatCount } from '@map/utils/formatCount.js' // counts stay fixed en-US: numerals are held for the Driver
import { formatCount } from '@map/utils/formatCount.js' // counts stay fixed en-US: numerals are held, pending a product decision
import { tStatic } from '@map/i18n/index.js'
/**
* pplr-coverage.vue — Country choropleth: avg # of locales filled per PG in that country.

View file

@ -7,7 +7,7 @@
import { inject, onMounted, onBeforeUnmount, ref } from 'vue'
import { glFor, exposeMap, releaseMap, whenGeojsonDrawn } from '../utils/pplrData.js'
import { usePplrT } from '../composables/usePplrT.js'
import { formatCount } from '@map/utils/formatCount.js' // counts stay fixed en-US: numerals are held for the Driver
import { formatCount } from '@map/utils/formatCount.js' // counts stay fixed en-US: numerals are held, pending a product decision
import { tStatic } from '@map/i18n/index.js'
import { useMapInstance } from '@map/composables/useMapInstance.js'
import { addCountryPolygons, addPGPoints, popupForPG, POPUP_CSS } from '../utils/pplrMap.js'

View file

@ -10,9 +10,9 @@
/* ★ FULL-VIEWPORT MOUNT (BUG-PRAYER-WALK-PLANNER-MAP-DOES-NOT-FILL-THE-PAGE). This page used
to stage the element inside a centred 1100px card with a fixed 640px .frame — measured on
the dev server, the map painted a 781x584 window at y=206 in a 1440x900 viewport, which is
exactly the Driver's report: "the map is showing up but it's not filling the full page."
exactly the reported defect: the map showed, but did not fill the page.
The BUILT leaf already mounts full-viewport; the dev harness now matches it (two-host rule:
what the Driver sees on the dev server must be what the leaf ships). The client-side API
what a tester sees on the dev server must be what the leaf ships). The client-side API
note lives in the component header now — a planner is a full-page tool, not a demo card:
document.querySelector('prayer-walk-planner').addPolygon(coords, title) /
window.PrayerWalkPlanner.first(). */

View file

@ -17,8 +17,8 @@
* component never uses — see golden-path-check/index.js's header for the concrete failure
* that mistake causes (a thrown setup() removes the whole shadow-DOM subtree silently).
*
* ★ CLIENT-SIDE API, NOT A BACKEND. The Driver's brief: "Although this is JAMstack, we're
* not building any API into it. The only API we can build has to be CLIENT SIDE." The root
* ★ CLIENT-SIDE API, NOT A BACKEND. The site is JAMstack with no server API of its own, so the
* only API this tool can offer is CLIENT SIDE. The root
* component defineExpose()s addPolygon/deletePolygon/selectPolygon/print/list methods.
* Because this bundle mounts the SFC AS the defineCustomElement root (not nested under
* ProfileLoader), Vue's custom-element bridge surfaces those exposed methods directly on the
@ -32,7 +32,7 @@ import { createAppI18n } from '@map/i18n/index.js'
// ★ configureApp WITHOUT changing the mounting shape. This bundle deliberately mounts the
// SFC AS the custom-element root so Vue's bridge surfaces its defineExpose()d client-side
// API on the DOM element (the Driver's "the only API we can build has to be CLIENT SIDE").
// API on the DOM element (a JAMstack site: the only API it can offer is client side).
// That decision and i18n are ORTHOGONAL — the second argument takes configureApp whichever
// component is the root, so this keeps addPolygon/print/listPolygons on the element.
//

View file

@ -12,8 +12,8 @@
* MapLibre/OpenFreeMap VECTOR basemap instead, already proven keyless elsewhere in
* this repo — library/styles/registry.js).
*
* ── CLIENT-SIDE API (the Driver's explicit ask: "if you build a client-side API into
* the prayer walk planner, then you can connect an AGENT to it") ──────────────────────
* ── CLIENT-SIDE API (why it exists: with a client-side API, an AGENT can be connected to
* the prayer walk planner) ──────────────────────
*
* Two ways to reach it, both backed by the SAME reactive state:
*
@ -61,7 +61,7 @@ import { localizeBasemapLabels } from '@map/maps/localize-labels.js'
import { translate, LOCALES } from './src/strings.js'
// ─── The host's attributes stay on the host ───────────────────────────────────
// ★ THE "VERY TINY MAP" (Driver; measured 2026-09-25: 747x76 in the Research Gallery at 1280x800,
// ★ THE TINY MAP (measured 2026-09-25: 747x76 in the Research Gallery at 1280x800,
// and 390x0 on a phone, while the standalone leaf filled 1003x739). This SFC is mounted AS the
// custom-element root (index.js — that is what puts the client API on the element), so Vue's
// attribute fallthrough copied every non-prop attribute of <prayer-walk-planner> onto the root
@ -106,7 +106,7 @@ const uiLocale = computed(() => {
const uiDir = computed(() => (uiLocale.value === 'ar' ? 'rtl' : 'ltr'))
const tr = (key, params) => translate(uiLocale.value, key, params)
const moreOpen = ref(false) // the phone "More" menu
// PHONE: the zone list folds behind a ☰ button (Driver, test round 2 #8) and opens as a drawer over the
// PHONE: the zone list folds behind a ☰ button (test round 2 #8) and opens as a drawer over the
// map; on a wide screen it is the sidebar as before. It used to be simply hidden on a phone, so a
// walker could not see, select, rename or delete a zone there.
const listOpen = ref(false)
@ -461,7 +461,7 @@ async function printInternal(ids) {
const esc = (s) => String(s == null ? '' : s).replace(/[<>&]/g, (c) => ({ '<': '&lt;', '>': '&gt;', '&': '&amp;' }[c]))
// ── PER-ZONE PRINT MAP: a PAGE-SHAPED, PRINT-RESOLUTION render of each zone ──────────────
// The Driver: "the printed map is a ~10px sliver". Cause, measured 2026-09-25: print used to
// The printed map was a ~10px sliver. Cause, measured 2026-09-25: print used to
// fitBounds the LIVE map and snapshot its canvas, so the printed image was exactly the size
// and shape of whatever the live map happened to be on screen: 747x76 inside the Research
// Gallery, which is the sliver. Even full-page it was screen-resolution and screen-shaped.

View file

@ -151,7 +151,7 @@ onMounted(async () => {
if (u) openGroup(u)
})
// A GREEN dot opens that reached group in Mobilize: the unreached neighbours its believers can
// reach, the letter's audience (Driver, test round 2: "on the Campaign side you can't click green dots").
// reach, the letter's audience (test round 2: green dots on the Campaigns map could not be clicked).
m.on('click', 'cp-r', (ev) => {
const id = ev.features?.[0]?.properties?.id
const r = active.value?.reached.find((g) => g.pgid === id)

View file

@ -1,5 +1,5 @@
/**
* letter.js — the LETTER to a reached group's believers (Driver, test round 2: UPG Neighbor is a letter
* letter.js — the LETTER to a reached group's believers (test round 2: UPG Neighbor is a letter
* generator for the green dots). It names the unreached peoples that count this group among their nearest
* reached neighbours, at ONE E-level, closest first: the same list the map draws and the CSV exports.
*

View file

@ -53,7 +53,7 @@ const { map, initializeMap, destroy } = useMapInstance({
})
// ─── Selection ────────────────────────────────────────────────────────────────
// BOTH DIRECTIONS (Driver, 2026-09-28): a red dot shows the reached groups to mobilize for it; a green dot
// BOTH DIRECTIONS (2026-09-28): a red dot shows the reached groups to mobilize for it; a green dot
// shows the unreached groups its believers are nearest to. One selection, whichever kind it is.
const selected = computed(() => data.value?.groups.find((g) => g.pgid === nbState.pgid) || null)
const isReachedSel = computed(() => !!selected.value?.reached)
@ -62,7 +62,7 @@ const allNeighbors = computed(() => {
if (!g) return []
return g.reached ? data.value.unreachedNeighborsOf(g) : data.value.neighborsOf(g)
})
// THE LETTER'S AUDIENCE (Driver, test round 2: UPG Neighbor is a letter generator for GREEN groups).
// THE LETTER'S AUDIENCE (test round 2: UPG Neighbor is a letter generator for GREEN groups).
// A reached group's unreached neighbours are shown ONE E-level at a time: E-1 (the same language) by
// default, E-2 / E-3 on request, closest first. The list, the map lines and the CSV all follow it.
const levelCounts = computed(() => {

View file

@ -4,7 +4,7 @@
* ★ WHY. The wall gave every one of its ~2,100 card images its full-size href at once, so the
* browser fetched and DECODED every photo even when the whole 4000×3000 wall was on screen and each
* photo was a few pixels wide. Decoded bitmaps are uncompressed, so that was the bulk of the ~1.4 GB
* the Driver measured. A map never does this: it draws light tiles when zoomed out and loads detail
* measured in testing. A map never does this: it draws light tiles when zoomed out and loads detail
* only for what is in view. Same rule here:
* - zoomed out (a card smaller than `minPx` on screen): NO photos, just the light image slot;
* - zoomed in: HD photos only for the cards in view (plus a margin), and they are UNLOADED again