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.
This commit is contained in:
parent
cf0146775b
commit
8b83c34a79
15 changed files with 21 additions and 21 deletions
|
|
@ -148,7 +148,7 @@ function assetsBaseFor(depth) {
|
|||
// depth is measured from the WEB-ROOT; the tree root is one level in, hence depth - 1.
|
||||
return DEST_CONFIG.assetsBaseUrl || `${'../'.repeat(Math.max(0, depth - 1))}assets`
|
||||
}
|
||||
// design note 2026-07-11: the staging TOP must not mention deployment orgs (doxa/GO/...). The visible
|
||||
// The staging TOP must not mention deployment orgs (doxa/GO/...). The visible
|
||||
// title is the PRODUCT title (config displayTitle, default org-free), never the deployment TREE_NAME
|
||||
// (TREE_NAME stays in URLs/paths where it is a folder name, not branding).
|
||||
const DISPLAY_TITLE = (typeof DEST_CONFIG.displayTitle === 'string' && DEST_CONFIG.displayTitle.trim())
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* a rect×rect overlap of the sheet against .mapboxgl-ctrl-bottom-left/-right
|
||||
* (their VISIBLE children) in every sheet state.
|
||||
*
|
||||
* WHY: "it feels wrong on my phone" is not evidence a fix can be checked against. This
|
||||
* WHY: a sense that the sheet feels wrong on a phone is not evidence a fix can be checked against. This
|
||||
* probe turns the gesture into a per-step table (finger delta vs measured sheet height),
|
||||
* the release into an expected/actual state, and the attribution into overlap px² —
|
||||
* run it BEFORE a fix (baseline json) and AFTER (same json shape) and diff.
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ const packetOpen = ref(false)
|
|||
const { scrimRef, scrimStyle } = useViewportScrim(exportMenuOpen)
|
||||
// Feature flag: show the Export affordance. Gated here in the SHARED legend so
|
||||
// one switch covers every bundle. It was false by an earlier coder decision;
|
||||
// design note 2026-07-31 asked for the button back on the 100-list legend, and the
|
||||
// the button came back on the 100-list legend (2026-07-31), and the
|
||||
// export path is functional (the menu emits 'export' with 'poster' | 'packet',
|
||||
// and a profile wires @export to a real download).
|
||||
// A profile STILL has to opt in with :export-enabled="true" — this flag only
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* either edge can be summoned where you reach for it. A HOVERED strip is
|
||||
* pinned: it never auto-hides (even while you scroll) until you leave it.
|
||||
*
|
||||
* RIGHT is the primary side on EVERY form factor (design note, 2026-07-30): people
|
||||
* RIGHT is the primary side on EVERY form factor (since 2026-07-30): people
|
||||
* expect a scrollbar on the right, and a scroll hint that moves between edges
|
||||
* depending on device is the one thing it must not do. An earlier version flipped
|
||||
* to LEFT on mobile for thumb reach; consistency won. Both strips stay summonable
|
||||
|
|
@ -71,7 +71,7 @@ export function useEdgeScrollAffordance(wrapper, opts = {}) {
|
|||
const show = (e) => { e.style.opacity = '1' }
|
||||
const hide = (e) => { e.style.opacity = '0' }
|
||||
|
||||
// Primary side: RIGHT on BOTH desktop and mobile (design note, 2026-07-30).
|
||||
// Primary side: RIGHT on BOTH desktop and mobile (since 2026-07-30).
|
||||
// It used to flip to LEFT on mobile on a thumb-reach argument, but that made the
|
||||
// affordance appear on a different edge depending on device — the one place a
|
||||
// scroll hint must be predictable. People expect a scrollbar on the right, and
|
||||
|
|
|
|||
|
|
@ -699,7 +699,7 @@ function drawSeg(){
|
|||
const target = isMobile() ? 'mobile' : 'desktop'
|
||||
const tree = navForTarget(NAV, target)
|
||||
const open = new Map(tree.filter(n=>n.kind==='folder').map(n=>[n.id, !!n.open]))
|
||||
// The profile shown on first load (design note: the prayer map is the first map they see).
|
||||
// The profile shown on first load (the prayer map is the first map a reader sees).
|
||||
// Declared HERE, above its first use — a `const` further down the module would be in
|
||||
// the temporal dead zone at this point and throw.
|
||||
const DEFAULT_PROFILE = 'prayer-progress'
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
// No church, believer, meeting-point or fellowship data of any kind. This maps
|
||||
// PUBLISHED RESOURCE AVAILABILITY per language — "does a translation exist" — which
|
||||
// is public bibliographic fact. It must never gain a field describing where
|
||||
// Christians are. (design note boundary, 2026-08-01.)
|
||||
// Christians are. (A standing boundary since 2026-08-01.)
|
||||
//
|
||||
// HONESTY RULE: a language absent from eBible is recorded `has_scripture:false`
|
||||
// with `checked_pools:['ebible']`. That means "not found in the pools we checked",
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ const stats = {
|
|||
internet_researched: clusters.filter((c) => c.internet_access !== 'unknown').length,
|
||||
generated: '2026-08-01',
|
||||
scope_note: 'Scope is the full 2,106-record DX people-group corpus. No separate "2000 list" artefact exists on disk — verified by search — so this corpus IS the scope.',
|
||||
safety_note: 'Contains NO gospel-resource, church or believer field, and must not gain one. That join is held pending design note architecture (separate store, never joined to UPG locations in a public artifact).',
|
||||
safety_note: 'Contains NO gospel-resource, church or believer field, and must not gain one. That join is held pending a separate architecture (separate store, never joined to UPG locations in a public artifact).',
|
||||
};
|
||||
|
||||
if (!existsSync(OUT)) mkdirSync(OUT, { recursive: true });
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
// Root cause: a one-element dfrac sweep + leaders still drawn beside
|
||||
// the numbered badges + a DENSE_AT threshold that exists only as a
|
||||
// comment. Fixing it changes the look of 41 posters in the SHARED
|
||||
// template, which is a design note design call.
|
||||
// template, which is a product design call.
|
||||
// ALSO expect ONE "no crossing count" failure for country-chn: it is
|
||||
// the 3x4 tier, built by a SEPARATE run, so the 173-country manifest
|
||||
// does not cover it. That is the guard refusing to call an unmeasured
|
||||
|
|
|
|||
|
|
@ -1446,8 +1446,8 @@ function switchTab(tabId) {
|
|||
// search query doesn't leak across tabs (qa-buildinng-round-1 Bug 11).
|
||||
// clearGeocoderProgrammatic uses its internal _geoBeingCleared to skip the legend-
|
||||
// deselect side effect — pure text reset. Flip the FEATURES flag to keep
|
||||
// search queries across tabs (the user said "could go either way" — sticking
|
||||
// with clear-on-switch as the default per A4).
|
||||
// search queries across tabs (either behaviour is acceptable; clear-on-switch
|
||||
// stays the default per A4).
|
||||
if (!FEATURES.geocoderPersistAcrossTabs) clearGeocoderProgrammatic()
|
||||
const tab = tabs.value.find(t => t.id === tabId)
|
||||
if (!tab || !map.value) return
|
||||
|
|
|
|||
|
|
@ -1802,8 +1802,8 @@ function switchTab(tabId) {
|
|||
// search query doesn't leak across tabs (qa-buildinng-round-1 Bug 11).
|
||||
// clearGeocoderProgrammatic uses its internal _geoBeingCleared to skip the legend-
|
||||
// deselect side effect — pure text reset. Flip the FEATURES flag to keep
|
||||
// search queries across tabs (the user said "could go either way" — sticking
|
||||
// with clear-on-switch as the default per A4).
|
||||
// search queries across tabs (either behaviour is acceptable; clear-on-switch
|
||||
// stays the default per A4).
|
||||
if (!FEATURES.geocoderPersistAcrossTabs) clearGeocoderProgrammatic()
|
||||
const tab = tabs.value.find(t => t.id === tabId)
|
||||
if (!tab || !map.value) return
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ const selCount = computed(() => selectedTerritories.value.length)
|
|||
const copyFlash = ref('') // transient "Copied!" / "Copy failed" label
|
||||
let countryNameMap = null // iso3→label, built from live records
|
||||
|
||||
// ── R1.2 PIVOT (design note 2026-06-11): MOBILE-FRIENDLY "Batch Select" mode ──────
|
||||
// ── R1.2 PIVOT (2026-06-11): MOBILE-FRIENDLY "Batch Select" mode ──────
|
||||
// The selection INPUT GESTURE is a visible toggle button + plain taps — NO
|
||||
// shift/ctrl/meta (touch devices have no modifier keys; D-8 removes them). When
|
||||
// batchMode is ON a plain tap on a map `tapestry-fill` feature OR a legend row
|
||||
|
|
@ -670,7 +670,7 @@ useShadowStyles(
|
|||
'.map-toolbar .mcb.upg-batch-on.dark{border-color:#34d399!important}' +
|
||||
// ── R1.3 (j): legend MULTI-SELECT marker (batch mode). The SHARED legend only
|
||||
// paints ONE .selected row (its internal single selectedId). In batch mode the
|
||||
// design note selects 2+ rows, so the profile marks EVERY legend row that maps to a
|
||||
// the reader selects 2+ rows, so the profile marks EVERY legend row that maps to a
|
||||
// selected zone with .upg-batch-row (applied profile-side by markLegendBatchRows
|
||||
// — we never edit the shared component). Emerald left-rail + tint so multiple
|
||||
// rows clearly read as selected at once; the dot gets an emerald ring.
|
||||
|
|
@ -3343,7 +3343,7 @@ onBeforeUnmount(() => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- R1.4 (L4 — Brief: single button + progressive disclosure): the land-
|
||||
<!-- R1.4 (L4 — single button + progressive disclosure): the land-
|
||||
division HUD renders ONLY while batch mode is ON. The map-rail
|
||||
.upg-rail-batch (above, in the MapToolbar) is the SINGLE batch entry
|
||||
point — the old always-visible HUD .upg-batch-btn is gone. Inside batch
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ const spec = computed(() => ({
|
|||
{ id: 'map', label: t('tabs.map'), at: [1, 0], config: { profile: 'upg-100-list' } },
|
||||
],
|
||||
// The View switcher lives in this element's own header, so the layout's
|
||||
// "… below ↓" pill would be a second, redundant control (shell design note 2026-08-01).
|
||||
// "… below ↓" pill would be a second, redundant control (the shell's rule since 2026-08-01).
|
||||
paneHint: false,
|
||||
}))
|
||||
|
||||
|
|
|
|||
|
|
@ -1349,8 +1349,8 @@ onMounted(() => {
|
|||
border-radius: 12px; overflow: hidden; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
/* SQUARE, NOT A LETTERBOX — the image is the point of the card.
|
||||
Reported 2026-09-22: the images need to be larger, and more like squares than
|
||||
rectangles, so the people image is easier to see. The old rule was a fixed
|
||||
The images are larger, and closer to squares than to wide rectangles, so the
|
||||
people image is easier to see. The old rule was a fixed
|
||||
height:130px against a column that is at least 220px wide (see .grid.uupgs-list above), i.e. a
|
||||
220x130 letterbox — roughly 1.7:1 — which crops a standing person to a band and renders faces small.
|
||||
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ const preFiltered = computed(() => rows.value.filter((p) => {
|
|||
// and `people_praying` is NOT in the field list they request — they fetch
|
||||
// people_committed. So the field is always undefined and the filter matches nothing.
|
||||
// MEASURED on their live /regions/india: 855 rows before, 0 after clicking Engaged.
|
||||
// The scope ruling is "it exists on DX-life and must MATCH", so this reproduces their
|
||||
// The scope rule is that what exists on DX Life must match it here, so this reproduces their
|
||||
// result rather than quietly correcting it. Reading people_committed instead would make
|
||||
// us DIFFER. Raised upstream as a product question: the fix is one word, in their file.
|
||||
if (k === 'engaged') { if (!((p.people_praying ?? 0) > 0)) return false; continue }
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ useShadowStyles(`
|
|||
tabs share ONE radius variable and can never drift. This bar only sizes them to its own control scale
|
||||
and restores the tap target — the same treatment the Share button already had, now covering both so
|
||||
the ⓘ matches it exactly. Scoped to .rd-topbar, so the map toolbars keep their 40px round buttons.
|
||||
Reported 2026-09-28 ("too large"): ShareButton is a 40px round map control + a 2px rainbow ring, 44px
|
||||
At map size they were too large for this bar: ShareButton is a 40px round map control + a 2px rainbow ring, 44px
|
||||
in a 38px bar. Here both take 28px (+ Share's ring = 32px, the search box's height), icon 16px. */
|
||||
.rd-topbar .rd-header-btns{ display:inline-flex; align-items:center; gap:8px; flex:0 0 auto; }
|
||||
.rd-topbar .rd-header-btns .mcb{ --map-btn-size:28px; position:relative; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue