From fa69209035767502ca2ed5896f178121a7614bdd Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Tue, 29 Sep 2026 20:00:36 +0000 Subject: [PATCH 1/3] The gallery's published section order: Prayer Progress before the UPG-100 List The Deep Research page publishes the rail as Dashboards (Big Picture, Simple Research, Regions), Prayer Mobilization (Prayer Progress, UPG-100 List), Gospel Research (Cities with Internet, Gospel Resources), then the Experimental folder. Only the Prayer Mobilization pair moves. Big Picture now says "desktop only" on every width, not only once a phone has disabled it. check:spa-tab-order asserted the old four-name order with UPG-100 first; it now asserts all seven published rows in order (still relative, with tab 1 positional). It needs a browser: rega runs it. --- internal/check-spa-tab-order.mjs | 11 ++++++++--- package.json | 2 +- plugin-designs/doxa-maps-spa/doxa-maps-spa.vue | 10 +++++++--- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/internal/check-spa-tab-order.mjs b/internal/check-spa-tab-order.mjs index ca8cb8eb2..091bdcfe2 100644 --- a/internal/check-spa-tab-order.mjs +++ b/internal/check-spa-tab-order.mjs @@ -2,8 +2,9 @@ /** * check-spa-tab-order.mjs — the cap-5 product SPA must open on the Big Picture, in the specified order. * - * WHAT THIS PROTECTS. The rail was specified explicitly: cap-5 tab order (Big Picture, UPG-100, - * Prayer Progress, Gospel Resources). Tab 1 is not a preference — it is the LANDING + * WHAT THIS PROTECTS. The rail's order is PUBLISHED (the Deep Research page, 2026-09-29) and must not + * change: Big Picture, Simple Research, Regions · Prayer Progress, UPG-100 List · Cities with Internet, + * Gospel Resources, then the Experimental folder. Tab 1 is not a preference — it is the LANDING * SURFACE, the first thing anyone opening doxa-maps-spa sees, and the opening step of the * onboarding ramp. Today that ordering is held only by the order of entries in a source array and * by comments explaining why; nothing fails if someone reorders them. @@ -59,7 +60,11 @@ await __treeGuard(BASE, __ROOT, 'SPA-TAB-ORDER') // // So: assert what was actually specified. Tab 1 must still be Big Picture — that IS positional, // it is the landing surface — and the other three must appear after it, in order. -const EXPECTED = ['Big Picture', 'UPG-100', 'Prayer Progress', 'Gospel Resources'] +// ★ ALL SEVEN SINCE 2026-09-29. The published Deep Research order names every production row, so the +// gate asserts every one of them, in order; the earlier four-name list had UPG-100 before Prayer +// Progress, which the published order reverses. As before, the order is relative: a row between two +// named ones is allowed, a named row out of order is not; tab 1 is positional. +const EXPECTED = ['Big Picture', 'Simple Research', 'Regions', 'Prayer Progress', 'UPG-100', 'Cities with Internet', 'Gospel Resources'] const WALK = `(sel)=>{const o=[],s=new Set();const w=(r)=>{if(!r||s.has(r))return;s.add(r);try{o.push(...r.querySelectorAll(sel))}catch(e){};for(const e of r.querySelectorAll('*'))if(e.shadowRoot)w(e.shadowRoot)};w(document);return o}` diff --git a/package.json b/package.json index b1396081e..87174f1bb 100644 --- a/package.json +++ b/package.json @@ -604,7 +604,7 @@ "check:engine-contract": "the map must use the engine it was ASKED for or fail VISIBLY — never a substitute. resources-map read `engineGlobal(provider) || window.mapboxgl`; engineGlobal already defaults to mapbox, so that could only fire for provider 'maplibre' and then returned MAPBOX — a keyless page silently handed the engine that needs a token, which the profile then does not give it, so its tiles 401. Invisible to every other gate: the leaf mounts, renders and logs nothing. Six runtime measurements (2 providers x engine present / blocked / both blocked, CDN blocked by request routing the way a proxy or an offline kiosk does) The static arm was DELETED once check:no-silent-engine went into gates:post (main 23976fb0): two gates owning one source rule meant this leaf was checked twice and every other leaf once, and the narrower copy is the one that drifts. Mapbox arms inject a dummy MAP_TOKEN, because without one the element never mounts on a static tree and that is the environment, not the product. Engine attribution is read off the canvas class, not a debug handle. Browser gate. --poison names where the falsifiable source arm went rather than pretending to have one; the tree-wide gate self-tests with --self-test, not --poison.", "check:link-coverage": "rule 4 of the brief — 'verify a URL resolves before shipping it' — as a gate instead of a habit. verify-gospel-links.mjs does the verifying; nothing asserted the record COVERS what is shipped, so the honest state of the corpus was a number someone had to go and measure. DISCOVERS the URLs by recursing the pin index for any http string rather than naming fields: every field list in this bundle has gone stale (ga and se shipped unscreened, the SUN block and the access table were each added after the fact), and the recursion found 16 links my own hand-rolled measurement had missed. Resolves each against THREE records — the verification table, translator-org-links.json (contacts, fetched by their own script) and sun-deaf-index.json (proved by content against a catch-all control, which is stronger than a status code) — and fails on any unrecorded link, any shipped link recorded BROKEN, and any 'unknown' on a target a status code CAN prove. The status-blind list holds one URL SHAPE, not a host: jesusfilm.org/watch/jesus/ discriminates and 2,049 links depend on that, while /watch/?languageId= does not. Static, sub-second. Self-test: `bun run check:link-coverage:poison`.", "check:snapshot-guard": "every gospel-resources catalogue fetcher must write through scripts/_snapshot-guard.mjs, which refuses a write that loses more than a tenth of the previous snapshot. Written after a rate-limited FCBH run silently replaced 1,666 video scopes with 1,103. Static, sub-second. Self-test: `bun run check:snapshot-guard:poison` injects a raw write and the check must fail on it.", - "check:spa-tab-order": "the cap-5 SPA must open on Big Picture and keep the specified order (Big Picture, UPG-100, Prayer Progress, Gospel Resources) — asserted as PRESENCE + tab-1 + RELATIVE order on the RENDERED rail, because the rail gained three sections and now renders 12 rows with others between them. ⚠ NOT WAVE-WIRED: it FAILS rather than skips when the SPA is unreachable, deliberately (\"a gate that cannot reach its subject has not passed, it has not run\") — correct standalone, but gates:post runs on checkouts with no server. Needs `bun run serve` on 4173.", + "check:spa-tab-order": "the cap-5 SPA must open on Big Picture and keep the published Deep Research order (Big Picture, Simple Research, Regions, Prayer Progress, UPG-100 List, Cities with Internet, Gospel Resources) — asserted as PRESENCE + tab-1 + RELATIVE order on the RENDERED rail, because the rail gained three sections and now renders 12 rows with others between them. ⚠ NOT WAVE-WIRED: it FAILS rather than skips when the SPA is unreachable, deliberately (\"a gate that cannot reach its subject has not passed, it has not run\") — correct standalone, but gates:post runs on checkouts with no server. Needs `bun run serve` on 4173.", "check:square-map-controls": "MapToolbar controls=\"square\" must be the ENGINE'S grouped card, not a square of ours. Reads node_modules/maplibre-gl/dist/maplibre-gl.css and compares our ported values against THAT FILE -- 4px corners, 0 0 0 2px rgba(0,0,0,.1) ring, 1px solid #ddd dividers -- because the look asked for is the engine default (DX-life adds NavigationControl and overrides nothing), so the target is published rather than a matter of taste. Asserts the three deliberate deviations: the engine's 29px is NOT adopted (touch target over pixel parity), there is NO overflow:hidden (it clips a focus ring; outer corners come from first/last child rounding, the engine's own mechanism), and a forced-colors block ships. Also asserts the BLAST RADIUS: round is the default and none of the nine MapToolbar consumers passes controls=, so no map changes -- opting one in turns it red. CSS assertions read the text passed to useShadowStyles, not the file, because the prop's doc comment quotes the engine's 29px and a checker that cannot tell a comment from a declaration finds the documentation it stands on.", "check:stale-sweep-claim": "a caveat that has stopped being true is a wrong number. The gospel surfaces carry a paragraph saying which pools were searched; while the GRN sweep ran they truthfully said part of it was unread, the sweep finished, and the sentence stayed for four more commits. The DATA decides here: undecided gap codes mean the claim is allowed, all-decided means it must go, so it re-arms itself for the next slow pool. Does NOT flag a claim rendered under a v-if on the pending count — that form expires on its own. Self-test: `--poison`. Static, sub-second.", "check:surfaces-read-the-tier": "a surface may READ the tier the pin index computed, never re-derive 'this group has nothing' from the raw resource fields. That hand-rolled field list went stale every time a source was added: 7 codes drawn as having nothing while the map showed them a link, then 28 when Scripture Earth landed. Static, sub-second. Self-test: `bun run check:surfaces-read-the-tier:poison` re-injects the old formula into every surface and each must be caught.", diff --git a/plugin-designs/doxa-maps-spa/doxa-maps-spa.vue b/plugin-designs/doxa-maps-spa/doxa-maps-spa.vue index 0bc75f066..c6997065c 100644 --- a/plugin-designs/doxa-maps-spa/doxa-maps-spa.vue +++ b/plugin-designs/doxa-maps-spa/doxa-maps-spa.vue @@ -278,8 +278,9 @@ const NAV_MODEL = [ // newcomer the concrete new artifact, THEN ask them to pray it. { key: 'prayer-mobilization', label: 'Prayer Mobilization', i18n: 'sec.prayer', icon: 'heart', tabs: [ - { id: 'upg-100', icon: 'list' }, // 1. UPG-100 List — the NEW thing, introduced first - { id: 'prayer-map', icon: 'embed' }, // 2. Prayer Progress — now pray the list + // Prayer Progress, then the UPG-100 List: the published order of this section, fixed. + { id: 'prayer-map', icon: 'embed' }, + { id: 'upg-100', icon: 'list' }, ] }, // Gospel Research — RENAMED section (was "Research"). Cities with Internet then Gospel Resources, // per the spec's table (rows 5-6). The plain, uncomposited "Research Map" tab (doxa-research-map) @@ -962,9 +963,12 @@ export default defineComponent({ // at the layout level and this shell is what turns that click into a message instead // of a mount. const disabled = this.isDesktopOnly(t.id) + // A desktop-only map says so on EVERY width, not only once a phone has disabled it: + // a desktop reader should know before sharing the link to a phone. + const desktopOnly = disabled || this.mobileFlagOf(t.id) === 'desktop-only' return { key: t.id, label: this.tabLabel(t), sub: this.tabSub(t), icon: r.icon, - badge: disabled ? this.tr('desktopOnly') : r.badge, disabled + badge: desktopOnly ? this.tr('desktopOnly') : r.badge, disabled } }), seen) From 70d87f6a3cb895f9b606b46c6755814649e1e2e5 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Tue, 29 Sep 2026 20:00:58 +0000 Subject: [PATCH 2/3] Rebuild doxa-maps-spa for the published section order, and regenerate the tree --- public/dx-maps/doxa-maps-spa/doxa-maps-spa.js | 2 +- public/dx-maps/doxa-maps-spa/doxa-maps-spa/app/index.html | 2 +- public/dx-maps/doxa-maps-spa/doxa-maps-spa/index.html | 2 +- public/dx-maps/doxa-maps-spa/manifest.json | 4 ++-- public/dx-maps/manifest.json | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/public/dx-maps/doxa-maps-spa/doxa-maps-spa.js b/public/dx-maps/doxa-maps-spa/doxa-maps-spa.js index 6f0db9d09..3a565fc23 100644 --- a/public/dx-maps/doxa-maps-spa/doxa-maps-spa.js +++ b/public/dx-maps/doxa-maps-spa/doxa-maps-spa.js @@ -241,4 +241,4 @@ @media (prefers-reduced-motion: reduce){ .mi-pointer{ animation:none; } } -`,"map-info"),(I,X)=>(F(),H("div",{class:"mi",dir:i()?"rtl":"ltr",lang:a()},[M("button",{ref_key:"btnEl",ref:W,type:"button",class:et(["mi-btn",e.placement==="top-left"?"mi-at-left":"mi-at-right"]),"aria-label":xe(n)("mapInfo.open"),title:xe(n)("mapInfo.open"),"aria-haspopup":"dialog","aria-expanded":String(D.value),onClick:P},[...X[1]||(X[1]=[M("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false"},[M("circle",{cx:"12",cy:"12",r:"10",fill:"none",stroke:"currentColor","stroke-width":"2"}),M("rect",{x:"11",y:"10",width:"2",height:"7",rx:"1",fill:"currentColor"}),M("circle",{cx:"12",cy:"7",r:"1.3",fill:"currentColor"})],-1)])],10,fg),d.value&&!D.value?(F(),H("div",{key:0,class:et(["mi-pointer",e.placement==="top-left"?"mi-at-left":"mi-at-right"]),"aria-hidden":"true"},[M("span",null,q(xe(n)("mapInfo.pointer")),1),(F(),H("svg",hg,[e.placement==="top-left"?(F(),H("path",gg)):(F(),H("path",mg))]))],2)):de("",!0),D.value?(F(),H("div",{key:1,class:"mi-scrim",onClick:Ia(L,["self"]),onKeydown:j},[M("div",{ref_key:"dialogEl",ref:C,class:"mi-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"mi-title-"+e.storageKey},[M("div",$g,[M("h2",{id:"mi-title-"+e.storageKey,class:"mi-title"},q(xe(n)("mapInfo.title")),9,_g),M("button",{ref_key:"closeEl",ref:V,type:"button",class:"mi-close","aria-label":xe(n)("mapInfo.close"),onClick:L},"×",8,vg)]),M("div",yg,[e.leadKey||e.lead?(F(),H("p",wg,q(s(e.leadKey,e.lead)),1)):de("",!0),e.takeawayKey||e.takeaway?(F(),H("p",kg,[M("b",null,q(xe(n)("mapInfo.takeaway")),1),Dt(" "+q(s(e.takeawayKey,e.takeaway)),1)])):de("",!0),(F(!0),H(ne,null,Ke(e.examples,(Y,ce)=>_a((F(),H("section",{key:ce,class:"mi-ex"},[M("h3",null,q(Ue(Y)),1),Y.kind==="image"?(F(),H(ne,{key:0},[M("img",{class:"mi-img mi-poster",src:Q(Y.src),alt:Y.alt||Ue(Y),decoding:"async",onError:te=>b[ce]=!0},null,40,xg),Y.full?(F(),H("div",Tg,[M("a",{class:"mi-full",href:Q(Y.full),target:"_blank",rel:"noopener"},q(xe(n)("mapInfo.openFull")),9,Lg)])):de("",!0)],64)):Y.kind==="pages"&&(Y.pages||[]).length?(F(),H(ne,{key:1},[y[ce]?(F(),H(ne,{key:1},[M("div",Mg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:te=>se(ce)},q(xe(n)("mapInfo.collapsePages")),9,Ag)]),M("div",Cg,[(F(!0),H(ne,null,Ke(Y.pages,(te,ae)=>(F(),H("button",{key:ae,type:"button",class:"mi-hit mi-open mi-page","aria-label":xe(n)("mapInfo.collapsePages"),onClick:Oe=>se(ce)},[M("img",{class:"mi-img",src:Q(te),alt:Ue(Y)+" "+r(ae+1),loading:"lazy",decoding:"async",onError:ye},null,40,Ng)],8,Ig))),128))]),M("div",Fg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:te=>se(ce)},q(xe(n)("mapInfo.collapsePages")),9,Dg)])],64)):(F(),H(ne,{key:0},[M("button",{type:"button",class:et(["mi-hit mi-page",{"mi-stack":Y.pages.length>1}]),"aria-label":xe(n)("mapInfo.expandPages",{n:r(Y.pages.length)}),"aria-expanded":"false",onClick:te=>se(ce)},[M("img",{class:"mi-img",src:Q(Y.pages[0]),alt:Ue(Y),decoding:"async",onError:te=>b[ce]=!0},null,40,Og)],10,Sg),Y.pages.length>1?(F(),H("div",Eg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"false",onClick:te=>se(ce)},q(xe(n)("mapInfo.expandPages",{n:r(Y.pages.length)})),9,Pg)])):de("",!0)],64))],64)):Y.kind==="deck"&&(Y.cards||[]).length?(F(),H(ne,{key:2},[y[ce]?(F(),H(ne,{key:1},[M("div",Hg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:te=>se(ce)},q(xe(n)("mapInfo.collapseDeck")),9,jg)]),M("div",Vg,[(F(!0),H(ne,null,Ke(Y.cards,(te,ae)=>(F(),H("img",{key:ae,class:"mi-img",src:Q(te),alt:Ue(Y)+" "+r(ae+1),loading:"lazy",decoding:"async",onError:ye},null,40,Bg))),128))]),M("div",Kg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:te=>se(ce)},q(xe(n)("mapInfo.collapseDeck")),9,qg)])],64)):(F(),H(ne,{key:0},[M("button",{type:"button",class:"mi-hit mi-deck","aria-label":xe(n)("mapInfo.expandDeck",{n:r(Y.cards.length)}),"aria-expanded":"false",onClick:te=>se(ce)},[(F(!0),H(ne,null,Ke($t(Y),(te,ae)=>(F(),H("img",{key:ae,class:"mi-card",src:Q(te),alt:"",decoding:"async",onError:Oe=>ae===0?b[ce]=!0:ye(Oe),style:wo({insetInlineStart:ae*36+"px",transform:"rotate("+(ae-2)*4+"deg)",zIndex:10-ae})},null,44,Wg))),128))],8,Rg),M("div",zg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"false",onClick:te=>se(ce)},q(xe(n)("mapInfo.expandDeck",{n:r(Y.cards.length)})),9,Ug)])],64))],64)):Y.kind==="table"&&(Y.columns||[]).length?(F(),H(ne,{key:3},[M("div",Gg,[M("table",Xg,[M("thead",null,[M("tr",null,[(F(!0),H(ne,null,Ke(Y.columns,(te,ae)=>(F(),H("th",{key:ae,scope:"col"},q(he(te)),1))),128))])]),M("tbody",null,[(F(!0),H(ne,null,Ke(Y.rows||[],(te,ae)=>(F(),H("tr",{key:ae},[(F(!0),H(ne,null,Ke(te,(Oe,_t)=>(F(),H("td",{key:_t},q(typeof Oe=="number"?r(Oe):Oe),1))),128))]))),128))])])]),Y.total&&Y.total>(Y.rows||[]).length?(F(),H("p",Yg,q(xe(n)("mapInfo.moreRows",{n:r(Y.total-(Y.rows||[]).length)})),1)):de("",!0)],64)):de("",!0)])),[[Aa,!b[ce]]])),128)),e.noteKey||e.note?(F(),H("p",Jg,q(s(e.noteKey,e.note)),1)):de("",!0)]),M("div",Zg,[M("label",null,[M("input",{type:"checkbox",checked:g.value,onChange:X[0]||(X[0]=Y=>E(Y.target.checked))},null,40,Qg),M("span",null,q(xe(n)("mapInfo.pointerOff")),1)])])],8,bg)],32)):de("",!0)],8,dg))}},tm=":host{display:block;position:relative;height:var(--doxa-maps-spa-height, 85vh);min-height:480px}:host{font-size:16px;line-height:normal;font-weight:400;font-style:normal;font-variant:normal;font-stretch:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;text-align:start;text-indent:0;text-shadow:none;white-space:normal;-webkit-hyphens:manual;hyphens:manual;visibility:visible;cursor:auto}:host([hidden]){display:none}.dms-pane{position:absolute;top:0;right:0;bottom:0;left:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;--profile-min-h: 0}.dms-slot{position:relative;min-height:100%}.dms-hint{position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-items:center;text-align:center;color:#6d766e;font-size:13px;padding:20px}.dms-hint.err{color:#f87171}.dms-hint small{color:var(--dx-muted, #6d766e)}.dms-help-close:focus-visible{outline:2px solid #3f8f5a;outline-offset:2px}.dms-help-scrim{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;display:flex;align-items:center;justify-content:center;background:#00000059;padding:16px}.dms-help{max-width:420px;width:100%;color:#3b463d;background:#fff;border-radius:12px;padding:18px 20px 14px;box-shadow:0 12px 32px #0003;font-size:14px;line-height:1.5}.dms-help-title{margin:0 0 8px;font-size:16px}.dms-help-what,.dms-help-how{margin:0 0 10px}.dms-help-close{float:right;font:inherit;padding:6px 14px;border-radius:8px;border:1px solid #d1d4cd;background:#f3f3f1;cursor:pointer}.dms-notice{position:fixed;left:50%;bottom:24px;transform:translate(-50%);z-index:40;max-width:320px;text-align:center;font-size:13px;line-height:1.4;color:#3b463d;background:#fff;border:1px solid #d1d4cd;border-radius:10px;padding:10px 16px;box-shadow:0 8px 24px #0000001f}.dms-mobile-notice{position:sticky;top:0;z-index:30;display:flex;align-items:flex-start;gap:8px;padding:10px 12px;font-size:13px;line-height:1.4;color:#3b463d;background:#fff8e6;border-bottom:1px solid #f0d58c}.dms-mobile-notice span{flex:1}.dms-mobile-notice-x{flex:none;min-width:32px;min-height:32px;border:0;border-radius:6px;background:transparent;color:inherit;font-size:18px;line-height:1;cursor:pointer}.dms-mobile-notice-x:focus-visible{outline:2px solid #3b463d;outline-offset:1px}.dms-logo{display:inline-flex;align-items:center}.dms-logo svg{display:block}.dms-locale{position:relative;padding:8px 12px 0;display:flex;justify-content:flex-end}.dms-locale-btn{display:inline-flex;align-items:center;gap:8px;font:inherit;font-size:12px;padding:5px 10px;border:1px solid #d1d4cd;border-radius:8px;background:#d1d4cd;color:#3b463d;cursor:pointer}.dms-locale-btn:hover{background:#d1d4cd}.dms-flag{font-size:14px;line-height:1}.dms-locale-name{max-width:12ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dms-dots{color:#6d766e;margin-left:2px}.dms-locale-menu{position:absolute;top:100%;right:12px;margin-top:4px;z-index:30;min-width:180px;list-style:none;padding:6px;border:1px solid #d1d4cd;border-radius:10px;background:#fff;box-shadow:0 12px 32px #00000080;max-height:320px;overflow:auto}.dms-locale-opt{display:flex;align-items:center;gap:8px;width:100%;text-align:left;font:inherit;font-size:13px;padding:7px 9px;border:0;border-radius:7px;background:none;color:#3b463d;cursor:pointer}.dms-locale-opt:hover,.dms-locale-opt.active{background:#d1d4cd;color:#3b463d}.dms-locale-opt.active .dms-locale-name{color:#92b195}.dms-locale-en{margin-left:auto;font-size:11px;color:#6d766e}";function xl(){try{const e=new URLSearchParams(location.search),t=(e.get("lang")||e.get("locale")||"").split("-")[0].toLowerCase();if(ns.includes(t))return t}catch{}try{const e=(document.documentElement.lang||"").split("-")[0].toLowerCase();if(ns.includes(e))return e}catch{}return""}const ls=[{key:"dashboards",label:"Dashboards",i18n:"sec.dashboards",icon:"chart",tabs:[{id:"dashboard-plus-grid",icon:"chart"},{id:"research-map-plus-grid",icon:"map"},{id:"regions-dashboard",icon:"map"}]},{key:"prayer-mobilization",label:"Prayer Mobilization",i18n:"sec.prayer",icon:"heart",tabs:[{id:"upg-100",icon:"list"},{id:"prayer-map",icon:"embed"}]},{key:"gospel-research",label:"Gospel Research",i18n:"sec.gospel",icon:"search",tabs:[{id:"cities-internet",icon:"wifi"},{id:"gospel-resources",icon:"book"}]},{key:"experimental",label:"Experimental",i18n:"sec.experimental",icon:"flask",folder:!0,open:!1,tabs:[]}];function om(e){const t={},o=e&&Array.isArray(e.bundles)?e.bundles:[];for(const a of o)for(const n of Array.isArray(a&&a.profiles)?a.profiles:[])n&&(n.mobile==="desktop-only"||n.mobile==="larger-screens")&&(t[a.bundle+"/"+n.profile]=n.mobile);return t}const am=new Set(["doxa-maps-spa","plugin-studio","template-bundle","people-groups-grid","research-dashboard","big-picture","demo-map","golden-path-check","doxa-research-map","stack-demo"]),Tl={"prayer-walk-planner":1,"gospel-internet":2,"upg-neighbor":3,"key-cities":4,"all-people-groups":5,"country-posters":6,"doxa-vision-card":7},cs=[{id:"dashboard-plus-grid",label:"Big Picture",sub:"dashboard + people-groups grid, stacked",emoji:"🌍",bundle:"dashboard-plus-grid",profile:"dashboard-plus-grid"},{id:"research-map",label:"Research Map",sub:"prayer · engagement · regions",emoji:"🗺️",bundle:"doxa-research-map",profile:"research-map"},{id:"research-map-plus-grid",label:"Simple Research",sub:"research map + people-groups grid",emoji:"🗺️",bundle:"research-map-plus-grid",profile:"research-map-plus-grid"},{id:"prayer-map",label:"Prayer Progress",sub:"simple world prayer map",emoji:"🙏",bundle:"doxa-simple-map",profile:"doxa-simple-map",instance:"prayer"},{id:"cities-internet",label:"Cities with Internet",sub:"connectivity of key cities",emoji:"📡",bundle:"cities-internet",profile:"connectivity-map"},{id:"gospel-resources",label:"Gospel Resources",sub:"resources by place",emoji:"📖",bundle:"gospel-resources",profile:"resources-map"},{id:"regions-dashboard",label:"Regions",sub:"regions and their countries",emoji:"🌐",bundle:"regions-dashboard",profile:"regions-mfe"},{id:"upg-100",label:"UPG-100 List",sub:"my unreached list + posters",emoji:"📋",bundle:"my-upg-100-list",profile:"upg-100-mfe"}];sm(ls);const Ka=new Set(["doxa-research-map","doxa-simple-map","cities-internet-map","gospel-resources-map","my-upg-100-list-map","doxa-map","doxa-maps-spa","dashboard-plus-grid","research-dashboard-map","demo-map","all-people-groups","country-posters-map","key-cities-map","research-map-plus-grid","gospel-internet-board"]),qa=new Set(["dashboard-plus-grid","research-map-plus-grid"]);function nm(){const e=Object.fromEntries(cs.map(o=>[o.id,o])),t=new Set;for(const o of ls)if(o.key!=="experimental")for(const a of o.tabs||[]){const n=e[a.id];n&&n.bundle&&t.add(n.bundle)}return t}function Ll(e,t){const o=[];for(const a of e)!a||t.has(a.key)||(t.add(a.key),o.push(a));return o}function sm(e){const t=new Map,o=[];for(const a of e)if(a.key!=="experimental")for(const n of a.tabs||[]){if(!n||!n.id)continue;const s=t.get(n.id);if(s===void 0){t.set(n.id,a.key);continue}(s!==a.key||o.indexOf(n.id)===-1)&&o.push(n.id+" ("+s+" + "+a.key+")")}return o.length&&typeof console<"u"&&console.error("[doxa-maps-spa] duplicate tab key(s) across NAV_MODEL sections: "+o.join(", ")+" — VerticalTabsLayout keys its tab-ref map and `active` highlight by id, so a row declared in two sections paints twice and stalls keyboard nav. See the duplicate-key trap in SPEC-the-six-map-product-and-its-tab-order.md."),o}function rm(e){return String(e).split(/[-_]/).filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}function im(e){const t=nm(),o=e&&Array.isArray(e.bundles)?e.bundles:[],a=[];for(const n of o){const s=n&&n.bundle;if(!s||t.has(s)||am.has(s)||n.stage==="production")continue;const r=Array.isArray(n.profiles)?n.profiles:[];if(!r.length||r.every(d=>d.widget||Array.isArray(d.targets)&&!d.targets.includes("web")))continue;const i=r.find(d=>d.isMap)||r.find(d=>d.profile===s)||r[0],l=i.element||Array.isArray(n.elements)&&n.elements[0]||s,c=n.scriptUrl||i.scriptUrl||"";c&&a.push({id:s,label:i.title||rm(s),sub:(i.description||"").trim().replace(/[,;]\s*$/,"")||"experimental bundle",emoji:"🧪",tag:l,bundle:s,profile:i.profile||s,scriptUrl:c,heavy:Ka.has(l)||Ka.has(s),scroll:qa.has(l)||qa.has(s),discovered:!0})}return a.sort((n,s)=>{const r=Tl[n.id]||999,i=Tl[s.id]||999;return r!==i?r-i:n.label.localeCompare(s.label)}),a}function lm(e,t){const o=e&&Array.isArray(e.bundles)?e.bundles:[],a=Object.fromEntries(o.map(s=>[s.bundle,s])),n={};for(const s of t){const r=a[s.bundle];if(!r)continue;const i=Array.isArray(r.profiles)?r.profiles:[],l=i.find(T=>T.profile===s.profile)||i[0],c=l&&l.element||Array.isArray(r.elements)&&r.elements[0]||s.bundle,d=r.scriptUrl||l&&l.scriptUrl||"";if(!d)continue;const g=l&&Array.isArray(l.instances)?l.instances:[],$=!!(s.instance&&g.some(T=>(T&&(T.id||T.instance))===s.instance));n[s.id]={tag:c,scriptUrl:d,profile:l&&l.profile||s.profile,instance:$?s.instance:"",heavy:Ka.has(c)||Ka.has(s.bundle),scroll:qa.has(c)||qa.has(s.bundle)}}return n}const cm=lo({name:"DoxaMapsSpa",inheritAttrs:!1,components:{VerticalTabsLayout:ng,BackToTopButton:oi,MapInfo:em},props:{treeBase:{type:String,default:""},profileConfig:{type:[String,Object],default:""},heading:{type:String,default:"Deep Research"},tokenUrl:{type:String,default:""},tk:{type:String,default:""},language:{type:String,default:""},apiBaseUrl:{type:String,default:""},provider:{type:String,default:""},tab:{type:String,default:""}},emits:["tab-change"],setup(){return{injectedBase:ro("dmsTreeBase","")}},data(){return{paneEls:{},activeIndex:0,showHeader:!1,narrow:!1,_mql:null,_onMedia:null,disabledNotice:"",_noticeTimer:null,helpOpen:!1,mobileNoticeDismissed:{},mobileFlags:null,manifestError:"",manifestBase:"",runtime:{},locale:ig(),hostLang:xl(),localeOpen:!1,switcherLangs:sg,tabs:cs.map(e=>({...e,tag:"",scriptUrl:"",heavy:!1,scroll:!1,resolved:!1,mounted:!1,state:"idle",error:""}))}},computed:{largerScreenText(){return $o("messages.largerScreenNotice",this.uiLocale)||"This experimental map is built for larger screens. It opens here, but parts of it may not fit or work well on a phone."},activePaneEl(){return this.paneEls[this.activeIndex]||null},activeHelp(){const e=this.tabs[this.activeIndex];return e&&e.discovered?yl(e.id,this.uiLocale):null},cfg(){let e=this.profileConfig;if(typeof e=="string")try{e=e?JSON.parse(e):{}}catch{e={}}return e&&typeof e=="object"?e:{}},base(){const e=(this.treeBase||this.cfg.treeBase||this.injectedBase||"").trim();return e?e.replace(/\/+$/,"")+"/":""},assetsBase(){const e=String(this.cfg.assetsBase||"").trim();return/^https?:\/\//i.test(e)||e.startsWith("/")?e.replace(/\/+$/,""):this.manifestBase?this.manifestBase.replace(/\/+$/,"")+"/assets":""},showInfo(){const e=this.cfg.info;return!(e===!1||e==="false"||e==="off")},headingText(){return String(this.cfg.heading||this.heading||"").trim()||"Deep Research"},showExperimental(){const e=this.cfg.experimental;return!(e===!1||e==="false"||e==="hidden"||e==="off")},navGroups(){const e=Object.fromEntries(this.tabs.map(o=>[o.id,o])),t=new Set;return ls.map(o=>{let a=Ll((o.tabs||[]).filter(n=>e[n.id]).map(n=>{const s=e[n.id],r=this.isDesktopOnly(s.id);return{key:s.id,label:this.tabLabel(s),sub:this.tabSub(s),icon:n.icon,badge:r?this.tr("desktopOnly"):n.badge,disabled:r}}),t);return o.key==="experimental"&&!this.showExperimental?{key:o.key,rows:[]}:(o.key==="experimental"&&(a=a.concat(Ll(this.tabs.filter(n=>n.discovered).map(n=>({key:n.id,label:this.tabLabel(n),sub:this.tabSub(n),icon:"flask",badge:this.narrow&&this.mobileFlagOf(n.id)==="larger-screens"?this.tr("mobileNotBuilt"):this.tr("lab")})),t))),{key:o.key,label:o.i18n?this.tr(o.i18n):o.label,icon:o.icon,folder:!!o.folder,open:o.open,rows:a})}).filter(o=>o.rows.length)},showLocaleSwitcher(){return this.showHeader},activeLang(){return rg(this.locale)||{code:this.locale,flag:"🌐",nativeName:this.locale}},effectiveLocale(){const e=(this.language||this.cfg.language||this.cfg.locale||this.cfg.lang||"").trim(),t=this.showLocaleSwitcher?this.locale:"";return(e||t||this.hostLang||"en").split("-")[0].toLowerCase()},uiLocale(){return ns.includes(this.effectiveLocale)?this.effectiveLocale:"en"},uiDir(){return this.uiLocale==="ar"?"rtl":"ltr"},layoutLabels(){const e={};for(const t of["toggleList","openViews","expandList","collapseList","collapse"])e[t]=this.tr(t);return e},effectiveProvider(){const e=String(this.provider||this.cfg.provider||"").trim().toLowerCase();return e==="maplibre"||e==="mapbox"?e:""},activeKey(){const e=this.tabs[this.activeIndex];return e?e.id:""}},mounted(){this.watchWidth(),this.watchHostLang(),this.select(this.initialIndex()),this.loadManifest(),this._onHostedHelp=e=>this.onHostedHelp(e),this.$el.addEventListener("doxa:help",this._onHostedHelp)},beforeUnmount(){this._langObs&&(this._langObs.disconnect(),this._langObs=null),this._onHostedHelp&&(this.$el.removeEventListener("doxa:help",this._onHostedHelp),this._onHostedHelp=null),!(!this._mql||!this._onMedia)&&(this._mql.removeEventListener?this._mql.removeEventListener("change",this._onMedia):this._mql.removeListener&&this._mql.removeListener(this._onMedia),this._mql=null,this._onMedia=null)},watch:{activeIndex(){this.helpOpen=!1},effectiveLocale(){const e=(a,n)=>{try{const s=this._slots&&this._slots[a];s&&(s.innerHTML="")}catch{}n.mounted=!1,n.state="idle",n.error=""};this.tabs.forEach((a,n)=>{a.mounted&&n!==this.activeIndex&&e(n,a)});const t=this.activeIndex,o=this.tabs[t];!o||!o.mounted||(e(t,o),this.mountElement(t))},tab(e){e&&this.onSelect(e)}},methods:{openHelp(){this.helpOpen=!0,this.$nextTick(()=>this.$refs.helpClose&&this.$refs.helpClose.focus())},closeHelp(){this.helpOpen=!1;const e=this._helpReturn;this._helpReturn=null,this.$nextTick(()=>e&&e.focus&&e.focus())},infoFor(e){const t=this.showInfo&&e&&pg[e.id];return t&&(!t.leadKey||$o(t.leadKey,"en"))?t:null},tabHasHelp(e){return!!(e&&e.discovered&&yl(e.id,this.uiLocale))},onHostedHelp(e){if(!this.activeHelp)return;e.stopPropagation();const t=e.composedPath?e.composedPath():[];this._helpReturn=t.find(o=>o&&o.tagName==="BUTTON")||null,this.openHelp()},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},tr(e,t){return Va(this.uiLocale,e,t)},t(e,t){return Va(this.uiLocale,e,t)},tabLabel(e){return!e.discovered||cg("tab."+e.id)?Va(this.uiLocale,"tab."+e.id):e.label},tabSub(e){return e.discovered?this.uiLocale==="en"?e.sub:this.tr("experimentalSub"):Va(this.uiLocale,"sub."+e.id)},watchHostLang(){typeof MutationObserver>"u"||typeof document>"u"||(this._langObs=new MutationObserver(()=>{this.hostLang=xl()}),this._langObs.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]}))},watchWidth(){typeof window>"u"||!window.matchMedia||(this._mql=window.matchMedia("(max-width: 760px)"),this.narrow=this._mql.matches,this._onMedia=e=>{const t=this.narrow;this.narrow=!!e.matches,t!==this.narrow&&this.isDesktopOnly(this.activeKey)&&this.select(this.firstVisibleIndex())},this._mql.addEventListener?this._mql.addEventListener("change",this._onMedia):this._mql.addListener&&this._mql.addListener(this._onMedia))},mobileFlagOf(e){const t=this.tabs.find(o=>o.id===e);return t&&this.mobileFlags&&this.mobileFlags[t.bundle+"/"+t.profile]||null},isDesktopOnly(e){return this.narrow&&this.mobileFlagOf(e)==="desktop-only"},showsMobileNotice(e){return this.narrow&&this.mobileFlagOf(e)==="larger-screens"&&!this.mobileNoticeDismissed[e]},dismissMobileNotice(e){this.mobileNoticeDismissed={...this.mobileNoticeDismissed,[e]:!0}},firstVisibleIndex(){let e=-1;for(const t of this.navGroups)for(const o of t.rows){const a=this.tabs.findIndex(n=>n.id===o.key);if(!(a<0)&&(e<0&&(e=a),!o.disabled))return a}return e>=0?e:0},loadManifest(){const e=this.resolve("manifest.json"),t=c=>{try{return new URL(c,location.href).href.replace(/[^/]*$/,"")}catch{return""}},o={url:e,root:t(e)},a={url:this.resolve("doxa-maps-spa/manifest.json"),root:o.root};let n=!1;try{n=new URL(e,location.href).origin!==location.origin}catch{}const s=n?[a,o]:[o,a],r="/public/dx-maps/manifest.json";s.some(c=>c.url===r)||s.push({url:r,root:t(r)});const i=[],l=c=>{if(c>=s.length){this.manifestError="manifest.json not found (tried "+i.join(", ")+")",console.error("[doxa-maps-spa] "+this.manifestError+" — every tab except Big Picture is composed from it, so their panes cannot mount.");return}const{url:d,root:g}=s[c];return i.push(d),fetch(d,{credentials:"same-origin"}).then($=>{if(!$||!$.ok)throw new Error(d+" → HTTP "+($?$.status:"?"));return $.json()}).then($=>{if(!$)throw new Error(d+" → empty");this.manifestError="",this.manifestBase=g||"",this.applyManifest($)}).catch(()=>l(c+1))};try{l(0)}catch{}},applyManifest(e){this.runtime=e&&e.runtime&&typeof e.runtime=="object"?e.runtime:{},this.mobileFlags=om(e),this.applyPageGlobals();const t=lm(e,cs),o=this.activeKey,a=[];for(const l of this.tabs){if(l.discovered){a.push(l);continue}const c=t[l.id];c&&(Object.assign(l,c,{resolved:!0}),a.push(l))}const n=new Set(a.map(l=>l.id));if(this.showExperimental)for(const l of im(e))n.has(l.id)||a.push({...l,resolved:!0,mounted:!1,state:"idle",error:""});this.tabs=a;const s=this.requestedTab(),r=s?this.tabs.findIndex(l=>l.id===s):-1,i=this.tabs.findIndex(l=>l.id===o);r>=0&&!this.isDesktopOnly(s)&&!this._honouredTab?this.select(r):this.select(i>=0&&!this.isDesktopOnly(o)?i:this.firstVisibleIndex()),this._honouredTab=!0},requestedTab(){let e="";try{e=new URLSearchParams(location.search).get("tab")||""}catch{}return String(this.tab||this.cfg.tab||e||"").trim()},initialIndex(){const e=this.requestedTab(),t=e?this.tabs.findIndex(o=>o.id===e):-1;return t>=0&&(this._honouredTab=!0),t>=0&&!this.isDesktopOnly(e)?t:this.firstVisibleIndex()},setLocale(e){this.locale=e,this.localeOpen=!1,lg(e)},onSelect(e){if(this.isDesktopOnly(e)){const o=this.tabs.find(a=>a.id===e);this.disabledNotice=($o("messages.desktopOnlyNotice",this.uiLocale)||"{label} only supports desktop — open this page on a desktop to use it.").replace("{label}",o?this.tabLabel(o):e),clearTimeout(this._noticeTimer),this._noticeTimer=setTimeout(()=>{this.disabledNotice=""},4e3);return}const t=this.tabs.findIndex(o=>o.id===e);t!==-1&&this.select(t)},resolve(e){const t=String(e);if(/^(https?:)?\/\//.test(t)||t.startsWith("/"))return t;const o=t.replace(/^\.\//,"");return this.manifestBase?this.manifestBase.replace(/\/+$/,"")+"/"+o:this.base?this.base.replace(/\/+$/,"")+"/"+o:"../"+o},select(e){const t=this.activeIndex;if(this.activeIndex=e,t!==e&&t>=0){const a=this.tabs[t];a&&a.heavy&&a.mounted&&this.releaseTab(t,a)}const o=this.tabs[e];o&&((t!==e||!this._announced)&&(this._announced=!0,this.$emit("tab-change",{id:o.id,label:o.label})),o.scriptUrl&&(this.narrow&&this.mobileFlags===null||this.isDesktopOnly(o.id)||o.mounted||this.$nextTick(()=>{this.activeIndex===e&&this.mountElement(e)})))},releaseTab(e,t){try{const o=this._slots&&this._slots[e];o&&(o.innerHTML="")}catch{}this._slots&&delete this._slots[e],t.mounted=!1,t.state="idle",t.error=""},childConfig(e){const t={profile:e.profile||e.id,instanceId:e.instance||"dms-"+e.id};this.effectiveLocale&&(t.locale=this.effectiveLocale);const o=this.tk||this.cfg.tk||this.runtime.token;return o&&(t.tk=o),(this.tokenUrl||this.cfg.tokenUrl)&&(t.tokenUrl=this.tokenUrl||this.cfg.tokenUrl),this.effectiveProvider&&(t.provider=this.effectiveProvider),this.base&&(t.treeBase=this.base),this.assetsBase&&(t.assetsBase=this.assetsBase),t.urlSync=!1,t},applyPageGlobals(){if(typeof window>"u")return;const e=(this.apiBaseUrl||this.cfg.apiBaseUrl||this.runtime.apiBaseUrl||"").trim();e&&!window.MAP_APP_API_URL&&(window.MAP_APP_API_URL=e.replace(/\/+$/,""));const t=this.tk||this.cfg.tk||this.runtime.token;t&&!window.MAP_TOKEN&&(window.MAP_TOKEN=t),this.effectiveProvider&&!window.MAP_PROVIDER&&(window.MAP_PROVIDER=this.effectiveProvider)},mountElement(e){const t=this.tabs[e];t.mounted=!0,t.state="loading";const o=this.resolve(t.scriptUrl);bl(o).then(()=>sh(t.tag)).then(()=>{try{if(t.heavy&&this.activeIndex!==e){t.mounted=!1,t.state="idle";return}const a=this._slots&&this._slots[e];if(!a){t.state="error",t.error="no slot";return}a.innerHTML="";const n=document.createElement(t.tag);n.setAttribute("profile-config",JSON.stringify(this.childConfig(t))),this.base&&n.setAttribute("tree-base",this.base.replace(/\/+$/,"")),n.style.cssText=t.scroll?"display:block;position:static;width:100%;height:auto;":"display:block;position:absolute;inset:0;width:100%;height:100%;min-height:0;",a.appendChild(n),t.state="ready"}catch(a){t.state="error",t.error="mount failed: "+(a&&a.message||String(a))}}).catch(a=>{t.state="error",t.error=a&&a.message||String(a)})}}}),pm={class:"dms-locale"},um=["aria-expanded"],dm={class:"dms-flag"},fm={class:"dms-locale-name"},hm={key:0,class:"dms-locale-menu",role:"listbox"},gm=["aria-selected"],mm=["onClick"],bm={class:"dms-flag"},$m={class:"dms-locale-name"},_m={class:"dms-locale-en"},vm=["hidden","data-doxa-help"],ym={key:0,class:"dms-mobile-notice",role:"status"},wm=["aria-label","onClick"],km={key:2,class:"dms-hint"},xm={key:3,class:"dms-hint err"},Tm={key:4,class:"dms-hint err"},Lm={key:0,class:"dms-notice",role:"status"},Sm={id:"dms-help-title",class:"dms-help-title"},Om={class:"dms-help-what"},Em={class:"dms-help-how"};function Pm(e,t,o,a,n,s){const r=ka("MapInfo"),i=ka("BackToTopButton"),l=ka("VerticalTabsLayout");return F(),uo(l,{dir:e.uiDir,lang:e.uiLocale,labels:e.layoutLabels,title:e.headingText,"nav-label":e.t("navLabel"),header:e.showHeader,groups:e.navGroups,active:e.activeKey,"onUpdate:active":e.onSelect},Rc({brand:Mo(()=>[t[5]||(t[5]=M("span",{class:"dms-logo","aria-hidden":"true"},[M("svg",{viewBox:"0 0 24 24",width:"22",height:"22",fill:"none",stroke:"#92b195","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[M("circle",{cx:"12",cy:"12",r:"9"}),M("polygon",{points:"12 6 14 12 12 18 10 12",fill:"#92b195",stroke:"none"}),M("polygon",{points:"6 12 12 10 18 12 12 14",fill:"#92b195",opacity:"0.55",stroke:"none"})])],-1))]),meta:Mo(()=>[Dt(q(e.t("meta",{n:e.tabs.length})),1)]),default:Mo(()=>[(F(!0),H(ne,null,Ke(e.tabs,(c,d)=>_a((F(),H("section",{key:c.id,class:"dms-pane",ref_for:!0,ref:g=>{g?e.paneEls[d]=g:delete e.paneEls[d]},hidden:d!==e.activeIndex,"data-doxa-help":e.tabHasHelp(c)?"":null,"data-doxa-gallery":""},[!c.heavy||d===e.activeIndex?(F(),H(ne,{key:0},[e.showsMobileNotice(c.id)?(F(),H("div",ym,[M("span",null,q(e.largerScreenText),1),M("button",{type:"button",class:"dms-mobile-notice-x","aria-label":e.tr("dismiss"),onClick:g=>e.dismissMobileNotice(c.id)},"×",8,wm)])):de("",!0),M("div",{class:"dms-slot",ref_for:!0,ref:g=>e.setSlot(d,g)},null,512),e.infoFor(c)?(F(),uo(r,Cr({key:"info-"+c.id},{ref_for:!0},e.infoFor(c),{"assets-base":e.assetsBase,locale:e.effectiveLocale}),null,16,["assets-base","locale"])):de("",!0),c.state==="loading"?(F(),H("div",km,q(e.tr("loading",{label:e.tabLabel(c)})),1)):c.state==="error"?(F(),H("div",xm,[Dt(q(e.tr("loadFailed",{label:e.tabLabel(c)})),1),t[7]||(t[7]=M("br",null,null,-1)),M("small",null,q(c.error),1)])):c.state==="idle"&&!c.scriptUrl&&e.manifestError?(F(),H("div",Tm,[Dt(q(e.tr("loadFailed",{label:e.tabLabel(c)})),1),t[8]||(t[8]=M("br",null,null,-1)),M("small",null,q(e.manifestError),1),t[9]||(t[9]=M("br",null,null,-1)),M("small",null,q(e.tr("manifestHint")),1)])):de("",!0)],64)):de("",!0)],8,vm)),[[Aa,d===e.activeIndex]])),128)),e.disabledNotice?(F(),H("div",Lm,q(e.disabledNotice),1)):de("",!0),e.helpOpen&&e.activeHelp?(F(),H("div",{key:1,class:"dms-help-scrim",onClick:t[3]||(t[3]=Ia((...c)=>e.closeHelp&&e.closeHelp(...c),["self"])),onKeydown:t[4]||(t[4]=Zr(Ia((...c)=>e.closeHelp&&e.closeHelp(...c),["stop","prevent"]),["esc"]))},[M("div",{class:"dms-help",role:"dialog","aria-modal":"true","aria-labelledby":"dms-help-title",onKeydown:t[2]||(t[2]=Zr(Ia(c=>e.$refs.helpClose&&e.$refs.helpClose.focus(),["prevent"]),["tab"]))},[M("h2",Sm,q(e.tabLabel(e.tabs[e.activeIndex])),1),M("p",Om,[M("strong",null,q(e.activeHelp.what),1)]),M("p",Em,q(e.activeHelp.how),1),M("button",{ref:"helpClose",type:"button",class:"dms-help-close",onClick:t[1]||(t[1]=(...c)=>e.closeHelp&&e.closeHelp(...c))},q(e.tr("close")),513)],32)],32)):de("",!0),Ae(i,{target:e.activePaneEl,labels:{backToTop:e.tr("backToTop")}},null,8,["target","labels"])]),_:2},[e.showLocaleSwitcher?{name:"toolbar",fn:Mo(()=>[M("div",pm,[M("button",{type:"button",class:"dms-locale-btn","aria-expanded":String(e.localeOpen),"aria-label":"Change language",onClick:t[0]||(t[0]=c=>e.localeOpen=!e.localeOpen)},[M("span",dm,q(e.activeLang.flag),1),M("span",fm,q(e.activeLang.nativeName),1),t[6]||(t[6]=M("span",{class:"dms-dots","aria-hidden":"true"},"⋮",-1))],8,um),e.localeOpen?(F(),H("ul",hm,[(F(!0),H(ne,null,Ke(e.switcherLangs,c=>(F(),H("li",{key:c.code,role:"option","aria-selected":String(c.code===e.locale)},[M("button",{type:"button",class:et(["dms-locale-opt",{active:c.code===e.locale}]),onClick:d=>e.setLocale(c.code)},[M("span",bm,q(c.flag),1),M("span",$m,q(c.nativeName),1),M("span",_m,q(c.name),1)],10,mm)],8,gm))),128))])):de("",!0)])]),key:"0"}:void 0]),1032,["dir","lang","labels","title","nav-label","header","groups","active","onUpdate:active"])}const Mm=Nn(cm,[["render",Pm],["styles",[tm]]]),Am=rh(),Cm=Kp(Mm,{configureApp(e){e.provide("dmsTreeBase",Am)}});typeof customElements<"u"&&!customElements.get("doxa-maps-spa")&&customElements.define("doxa-maps-spa",Cm)})(); +`,"map-info"),(I,X)=>(F(),H("div",{class:"mi",dir:i()?"rtl":"ltr",lang:a()},[M("button",{ref_key:"btnEl",ref:W,type:"button",class:et(["mi-btn",e.placement==="top-left"?"mi-at-left":"mi-at-right"]),"aria-label":xe(n)("mapInfo.open"),title:xe(n)("mapInfo.open"),"aria-haspopup":"dialog","aria-expanded":String(D.value),onClick:P},[...X[1]||(X[1]=[M("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false"},[M("circle",{cx:"12",cy:"12",r:"10",fill:"none",stroke:"currentColor","stroke-width":"2"}),M("rect",{x:"11",y:"10",width:"2",height:"7",rx:"1",fill:"currentColor"}),M("circle",{cx:"12",cy:"7",r:"1.3",fill:"currentColor"})],-1)])],10,fg),d.value&&!D.value?(F(),H("div",{key:0,class:et(["mi-pointer",e.placement==="top-left"?"mi-at-left":"mi-at-right"]),"aria-hidden":"true"},[M("span",null,q(xe(n)("mapInfo.pointer")),1),(F(),H("svg",hg,[e.placement==="top-left"?(F(),H("path",gg)):(F(),H("path",mg))]))],2)):de("",!0),D.value?(F(),H("div",{key:1,class:"mi-scrim",onClick:Ia(L,["self"]),onKeydown:j},[M("div",{ref_key:"dialogEl",ref:C,class:"mi-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"mi-title-"+e.storageKey},[M("div",$g,[M("h2",{id:"mi-title-"+e.storageKey,class:"mi-title"},q(xe(n)("mapInfo.title")),9,_g),M("button",{ref_key:"closeEl",ref:V,type:"button",class:"mi-close","aria-label":xe(n)("mapInfo.close"),onClick:L},"×",8,vg)]),M("div",yg,[e.leadKey||e.lead?(F(),H("p",wg,q(s(e.leadKey,e.lead)),1)):de("",!0),e.takeawayKey||e.takeaway?(F(),H("p",kg,[M("b",null,q(xe(n)("mapInfo.takeaway")),1),Dt(" "+q(s(e.takeawayKey,e.takeaway)),1)])):de("",!0),(F(!0),H(ne,null,Ke(e.examples,(Y,ce)=>_a((F(),H("section",{key:ce,class:"mi-ex"},[M("h3",null,q(Ue(Y)),1),Y.kind==="image"?(F(),H(ne,{key:0},[M("img",{class:"mi-img mi-poster",src:Q(Y.src),alt:Y.alt||Ue(Y),decoding:"async",onError:te=>b[ce]=!0},null,40,xg),Y.full?(F(),H("div",Tg,[M("a",{class:"mi-full",href:Q(Y.full),target:"_blank",rel:"noopener"},q(xe(n)("mapInfo.openFull")),9,Lg)])):de("",!0)],64)):Y.kind==="pages"&&(Y.pages||[]).length?(F(),H(ne,{key:1},[y[ce]?(F(),H(ne,{key:1},[M("div",Mg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:te=>se(ce)},q(xe(n)("mapInfo.collapsePages")),9,Ag)]),M("div",Cg,[(F(!0),H(ne,null,Ke(Y.pages,(te,ae)=>(F(),H("button",{key:ae,type:"button",class:"mi-hit mi-open mi-page","aria-label":xe(n)("mapInfo.collapsePages"),onClick:Oe=>se(ce)},[M("img",{class:"mi-img",src:Q(te),alt:Ue(Y)+" "+r(ae+1),loading:"lazy",decoding:"async",onError:ye},null,40,Ng)],8,Ig))),128))]),M("div",Fg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:te=>se(ce)},q(xe(n)("mapInfo.collapsePages")),9,Dg)])],64)):(F(),H(ne,{key:0},[M("button",{type:"button",class:et(["mi-hit mi-page",{"mi-stack":Y.pages.length>1}]),"aria-label":xe(n)("mapInfo.expandPages",{n:r(Y.pages.length)}),"aria-expanded":"false",onClick:te=>se(ce)},[M("img",{class:"mi-img",src:Q(Y.pages[0]),alt:Ue(Y),decoding:"async",onError:te=>b[ce]=!0},null,40,Og)],10,Sg),Y.pages.length>1?(F(),H("div",Eg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"false",onClick:te=>se(ce)},q(xe(n)("mapInfo.expandPages",{n:r(Y.pages.length)})),9,Pg)])):de("",!0)],64))],64)):Y.kind==="deck"&&(Y.cards||[]).length?(F(),H(ne,{key:2},[y[ce]?(F(),H(ne,{key:1},[M("div",Hg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:te=>se(ce)},q(xe(n)("mapInfo.collapseDeck")),9,jg)]),M("div",Vg,[(F(!0),H(ne,null,Ke(Y.cards,(te,ae)=>(F(),H("img",{key:ae,class:"mi-img",src:Q(te),alt:Ue(Y)+" "+r(ae+1),loading:"lazy",decoding:"async",onError:ye},null,40,Bg))),128))]),M("div",Kg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:te=>se(ce)},q(xe(n)("mapInfo.collapseDeck")),9,qg)])],64)):(F(),H(ne,{key:0},[M("button",{type:"button",class:"mi-hit mi-deck","aria-label":xe(n)("mapInfo.expandDeck",{n:r(Y.cards.length)}),"aria-expanded":"false",onClick:te=>se(ce)},[(F(!0),H(ne,null,Ke($t(Y),(te,ae)=>(F(),H("img",{key:ae,class:"mi-card",src:Q(te),alt:"",decoding:"async",onError:Oe=>ae===0?b[ce]=!0:ye(Oe),style:wo({insetInlineStart:ae*36+"px",transform:"rotate("+(ae-2)*4+"deg)",zIndex:10-ae})},null,44,Wg))),128))],8,Rg),M("div",zg,[M("button",{type:"button",class:"mi-toggle","aria-expanded":"false",onClick:te=>se(ce)},q(xe(n)("mapInfo.expandDeck",{n:r(Y.cards.length)})),9,Ug)])],64))],64)):Y.kind==="table"&&(Y.columns||[]).length?(F(),H(ne,{key:3},[M("div",Gg,[M("table",Xg,[M("thead",null,[M("tr",null,[(F(!0),H(ne,null,Ke(Y.columns,(te,ae)=>(F(),H("th",{key:ae,scope:"col"},q(he(te)),1))),128))])]),M("tbody",null,[(F(!0),H(ne,null,Ke(Y.rows||[],(te,ae)=>(F(),H("tr",{key:ae},[(F(!0),H(ne,null,Ke(te,(Oe,_t)=>(F(),H("td",{key:_t},q(typeof Oe=="number"?r(Oe):Oe),1))),128))]))),128))])])]),Y.total&&Y.total>(Y.rows||[]).length?(F(),H("p",Yg,q(xe(n)("mapInfo.moreRows",{n:r(Y.total-(Y.rows||[]).length)})),1)):de("",!0)],64)):de("",!0)])),[[Aa,!b[ce]]])),128)),e.noteKey||e.note?(F(),H("p",Jg,q(s(e.noteKey,e.note)),1)):de("",!0)]),M("div",Zg,[M("label",null,[M("input",{type:"checkbox",checked:g.value,onChange:X[0]||(X[0]=Y=>E(Y.target.checked))},null,40,Qg),M("span",null,q(xe(n)("mapInfo.pointerOff")),1)])])],8,bg)],32)):de("",!0)],8,dg))}},tm=":host{display:block;position:relative;height:var(--doxa-maps-spa-height, 85vh);min-height:480px}:host{font-size:16px;line-height:normal;font-weight:400;font-style:normal;font-variant:normal;font-stretch:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;text-align:start;text-indent:0;text-shadow:none;white-space:normal;-webkit-hyphens:manual;hyphens:manual;visibility:visible;cursor:auto}:host([hidden]){display:none}.dms-pane{position:absolute;top:0;right:0;bottom:0;left:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;--profile-min-h: 0}.dms-slot{position:relative;min-height:100%}.dms-hint{position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-items:center;text-align:center;color:#6d766e;font-size:13px;padding:20px}.dms-hint.err{color:#f87171}.dms-hint small{color:var(--dx-muted, #6d766e)}.dms-help-close:focus-visible{outline:2px solid #3f8f5a;outline-offset:2px}.dms-help-scrim{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;display:flex;align-items:center;justify-content:center;background:#00000059;padding:16px}.dms-help{max-width:420px;width:100%;color:#3b463d;background:#fff;border-radius:12px;padding:18px 20px 14px;box-shadow:0 12px 32px #0003;font-size:14px;line-height:1.5}.dms-help-title{margin:0 0 8px;font-size:16px}.dms-help-what,.dms-help-how{margin:0 0 10px}.dms-help-close{float:right;font:inherit;padding:6px 14px;border-radius:8px;border:1px solid #d1d4cd;background:#f3f3f1;cursor:pointer}.dms-notice{position:fixed;left:50%;bottom:24px;transform:translate(-50%);z-index:40;max-width:320px;text-align:center;font-size:13px;line-height:1.4;color:#3b463d;background:#fff;border:1px solid #d1d4cd;border-radius:10px;padding:10px 16px;box-shadow:0 8px 24px #0000001f}.dms-mobile-notice{position:sticky;top:0;z-index:30;display:flex;align-items:flex-start;gap:8px;padding:10px 12px;font-size:13px;line-height:1.4;color:#3b463d;background:#fff8e6;border-bottom:1px solid #f0d58c}.dms-mobile-notice span{flex:1}.dms-mobile-notice-x{flex:none;min-width:32px;min-height:32px;border:0;border-radius:6px;background:transparent;color:inherit;font-size:18px;line-height:1;cursor:pointer}.dms-mobile-notice-x:focus-visible{outline:2px solid #3b463d;outline-offset:1px}.dms-logo{display:inline-flex;align-items:center}.dms-logo svg{display:block}.dms-locale{position:relative;padding:8px 12px 0;display:flex;justify-content:flex-end}.dms-locale-btn{display:inline-flex;align-items:center;gap:8px;font:inherit;font-size:12px;padding:5px 10px;border:1px solid #d1d4cd;border-radius:8px;background:#d1d4cd;color:#3b463d;cursor:pointer}.dms-locale-btn:hover{background:#d1d4cd}.dms-flag{font-size:14px;line-height:1}.dms-locale-name{max-width:12ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dms-dots{color:#6d766e;margin-left:2px}.dms-locale-menu{position:absolute;top:100%;right:12px;margin-top:4px;z-index:30;min-width:180px;list-style:none;padding:6px;border:1px solid #d1d4cd;border-radius:10px;background:#fff;box-shadow:0 12px 32px #00000080;max-height:320px;overflow:auto}.dms-locale-opt{display:flex;align-items:center;gap:8px;width:100%;text-align:left;font:inherit;font-size:13px;padding:7px 9px;border:0;border-radius:7px;background:none;color:#3b463d;cursor:pointer}.dms-locale-opt:hover,.dms-locale-opt.active{background:#d1d4cd;color:#3b463d}.dms-locale-opt.active .dms-locale-name{color:#92b195}.dms-locale-en{margin-left:auto;font-size:11px;color:#6d766e}";function xl(){try{const e=new URLSearchParams(location.search),t=(e.get("lang")||e.get("locale")||"").split("-")[0].toLowerCase();if(ns.includes(t))return t}catch{}try{const e=(document.documentElement.lang||"").split("-")[0].toLowerCase();if(ns.includes(e))return e}catch{}return""}const ls=[{key:"dashboards",label:"Dashboards",i18n:"sec.dashboards",icon:"chart",tabs:[{id:"dashboard-plus-grid",icon:"chart"},{id:"research-map-plus-grid",icon:"map"},{id:"regions-dashboard",icon:"map"}]},{key:"prayer-mobilization",label:"Prayer Mobilization",i18n:"sec.prayer",icon:"heart",tabs:[{id:"prayer-map",icon:"embed"},{id:"upg-100",icon:"list"}]},{key:"gospel-research",label:"Gospel Research",i18n:"sec.gospel",icon:"search",tabs:[{id:"cities-internet",icon:"wifi"},{id:"gospel-resources",icon:"book"}]},{key:"experimental",label:"Experimental",i18n:"sec.experimental",icon:"flask",folder:!0,open:!1,tabs:[]}];function om(e){const t={},o=e&&Array.isArray(e.bundles)?e.bundles:[];for(const a of o)for(const n of Array.isArray(a&&a.profiles)?a.profiles:[])n&&(n.mobile==="desktop-only"||n.mobile==="larger-screens")&&(t[a.bundle+"/"+n.profile]=n.mobile);return t}const am=new Set(["doxa-maps-spa","plugin-studio","template-bundle","people-groups-grid","research-dashboard","big-picture","demo-map","golden-path-check","doxa-research-map","stack-demo"]),Tl={"prayer-walk-planner":1,"gospel-internet":2,"upg-neighbor":3,"key-cities":4,"all-people-groups":5,"country-posters":6,"doxa-vision-card":7},cs=[{id:"dashboard-plus-grid",label:"Big Picture",sub:"dashboard + people-groups grid, stacked",emoji:"🌍",bundle:"dashboard-plus-grid",profile:"dashboard-plus-grid"},{id:"research-map",label:"Research Map",sub:"prayer · engagement · regions",emoji:"🗺️",bundle:"doxa-research-map",profile:"research-map"},{id:"research-map-plus-grid",label:"Simple Research",sub:"research map + people-groups grid",emoji:"🗺️",bundle:"research-map-plus-grid",profile:"research-map-plus-grid"},{id:"prayer-map",label:"Prayer Progress",sub:"simple world prayer map",emoji:"🙏",bundle:"doxa-simple-map",profile:"doxa-simple-map",instance:"prayer"},{id:"cities-internet",label:"Cities with Internet",sub:"connectivity of key cities",emoji:"📡",bundle:"cities-internet",profile:"connectivity-map"},{id:"gospel-resources",label:"Gospel Resources",sub:"resources by place",emoji:"📖",bundle:"gospel-resources",profile:"resources-map"},{id:"regions-dashboard",label:"Regions",sub:"regions and their countries",emoji:"🌐",bundle:"regions-dashboard",profile:"regions-mfe"},{id:"upg-100",label:"UPG-100 List",sub:"my unreached list + posters",emoji:"📋",bundle:"my-upg-100-list",profile:"upg-100-mfe"}];sm(ls);const Ka=new Set(["doxa-research-map","doxa-simple-map","cities-internet-map","gospel-resources-map","my-upg-100-list-map","doxa-map","doxa-maps-spa","dashboard-plus-grid","research-dashboard-map","demo-map","all-people-groups","country-posters-map","key-cities-map","research-map-plus-grid","gospel-internet-board"]),qa=new Set(["dashboard-plus-grid","research-map-plus-grid"]);function nm(){const e=Object.fromEntries(cs.map(o=>[o.id,o])),t=new Set;for(const o of ls)if(o.key!=="experimental")for(const a of o.tabs||[]){const n=e[a.id];n&&n.bundle&&t.add(n.bundle)}return t}function Ll(e,t){const o=[];for(const a of e)!a||t.has(a.key)||(t.add(a.key),o.push(a));return o}function sm(e){const t=new Map,o=[];for(const a of e)if(a.key!=="experimental")for(const n of a.tabs||[]){if(!n||!n.id)continue;const s=t.get(n.id);if(s===void 0){t.set(n.id,a.key);continue}(s!==a.key||o.indexOf(n.id)===-1)&&o.push(n.id+" ("+s+" + "+a.key+")")}return o.length&&typeof console<"u"&&console.error("[doxa-maps-spa] duplicate tab key(s) across NAV_MODEL sections: "+o.join(", ")+" — VerticalTabsLayout keys its tab-ref map and `active` highlight by id, so a row declared in two sections paints twice and stalls keyboard nav. See the duplicate-key trap in SPEC-the-six-map-product-and-its-tab-order.md."),o}function rm(e){return String(e).split(/[-_]/).filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}function im(e){const t=nm(),o=e&&Array.isArray(e.bundles)?e.bundles:[],a=[];for(const n of o){const s=n&&n.bundle;if(!s||t.has(s)||am.has(s)||n.stage==="production")continue;const r=Array.isArray(n.profiles)?n.profiles:[];if(!r.length||r.every(d=>d.widget||Array.isArray(d.targets)&&!d.targets.includes("web")))continue;const i=r.find(d=>d.isMap)||r.find(d=>d.profile===s)||r[0],l=i.element||Array.isArray(n.elements)&&n.elements[0]||s,c=n.scriptUrl||i.scriptUrl||"";c&&a.push({id:s,label:i.title||rm(s),sub:(i.description||"").trim().replace(/[,;]\s*$/,"")||"experimental bundle",emoji:"🧪",tag:l,bundle:s,profile:i.profile||s,scriptUrl:c,heavy:Ka.has(l)||Ka.has(s),scroll:qa.has(l)||qa.has(s),discovered:!0})}return a.sort((n,s)=>{const r=Tl[n.id]||999,i=Tl[s.id]||999;return r!==i?r-i:n.label.localeCompare(s.label)}),a}function lm(e,t){const o=e&&Array.isArray(e.bundles)?e.bundles:[],a=Object.fromEntries(o.map(s=>[s.bundle,s])),n={};for(const s of t){const r=a[s.bundle];if(!r)continue;const i=Array.isArray(r.profiles)?r.profiles:[],l=i.find(T=>T.profile===s.profile)||i[0],c=l&&l.element||Array.isArray(r.elements)&&r.elements[0]||s.bundle,d=r.scriptUrl||l&&l.scriptUrl||"";if(!d)continue;const g=l&&Array.isArray(l.instances)?l.instances:[],$=!!(s.instance&&g.some(T=>(T&&(T.id||T.instance))===s.instance));n[s.id]={tag:c,scriptUrl:d,profile:l&&l.profile||s.profile,instance:$?s.instance:"",heavy:Ka.has(c)||Ka.has(s.bundle),scroll:qa.has(c)||qa.has(s.bundle)}}return n}const cm=lo({name:"DoxaMapsSpa",inheritAttrs:!1,components:{VerticalTabsLayout:ng,BackToTopButton:oi,MapInfo:em},props:{treeBase:{type:String,default:""},profileConfig:{type:[String,Object],default:""},heading:{type:String,default:"Deep Research"},tokenUrl:{type:String,default:""},tk:{type:String,default:""},language:{type:String,default:""},apiBaseUrl:{type:String,default:""},provider:{type:String,default:""},tab:{type:String,default:""}},emits:["tab-change"],setup(){return{injectedBase:ro("dmsTreeBase","")}},data(){return{paneEls:{},activeIndex:0,showHeader:!1,narrow:!1,_mql:null,_onMedia:null,disabledNotice:"",_noticeTimer:null,helpOpen:!1,mobileNoticeDismissed:{},mobileFlags:null,manifestError:"",manifestBase:"",runtime:{},locale:ig(),hostLang:xl(),localeOpen:!1,switcherLangs:sg,tabs:cs.map(e=>({...e,tag:"",scriptUrl:"",heavy:!1,scroll:!1,resolved:!1,mounted:!1,state:"idle",error:""}))}},computed:{largerScreenText(){return $o("messages.largerScreenNotice",this.uiLocale)||"This experimental map is built for larger screens. It opens here, but parts of it may not fit or work well on a phone."},activePaneEl(){return this.paneEls[this.activeIndex]||null},activeHelp(){const e=this.tabs[this.activeIndex];return e&&e.discovered?yl(e.id,this.uiLocale):null},cfg(){let e=this.profileConfig;if(typeof e=="string")try{e=e?JSON.parse(e):{}}catch{e={}}return e&&typeof e=="object"?e:{}},base(){const e=(this.treeBase||this.cfg.treeBase||this.injectedBase||"").trim();return e?e.replace(/\/+$/,"")+"/":""},assetsBase(){const e=String(this.cfg.assetsBase||"").trim();return/^https?:\/\//i.test(e)||e.startsWith("/")?e.replace(/\/+$/,""):this.manifestBase?this.manifestBase.replace(/\/+$/,"")+"/assets":""},showInfo(){const e=this.cfg.info;return!(e===!1||e==="false"||e==="off")},headingText(){return String(this.cfg.heading||this.heading||"").trim()||"Deep Research"},showExperimental(){const e=this.cfg.experimental;return!(e===!1||e==="false"||e==="hidden"||e==="off")},navGroups(){const e=Object.fromEntries(this.tabs.map(o=>[o.id,o])),t=new Set;return ls.map(o=>{let a=Ll((o.tabs||[]).filter(n=>e[n.id]).map(n=>{const s=e[n.id],r=this.isDesktopOnly(s.id),i=r||this.mobileFlagOf(s.id)==="desktop-only";return{key:s.id,label:this.tabLabel(s),sub:this.tabSub(s),icon:n.icon,badge:i?this.tr("desktopOnly"):n.badge,disabled:r}}),t);return o.key==="experimental"&&!this.showExperimental?{key:o.key,rows:[]}:(o.key==="experimental"&&(a=a.concat(Ll(this.tabs.filter(n=>n.discovered).map(n=>({key:n.id,label:this.tabLabel(n),sub:this.tabSub(n),icon:"flask",badge:this.narrow&&this.mobileFlagOf(n.id)==="larger-screens"?this.tr("mobileNotBuilt"):this.tr("lab")})),t))),{key:o.key,label:o.i18n?this.tr(o.i18n):o.label,icon:o.icon,folder:!!o.folder,open:o.open,rows:a})}).filter(o=>o.rows.length)},showLocaleSwitcher(){return this.showHeader},activeLang(){return rg(this.locale)||{code:this.locale,flag:"🌐",nativeName:this.locale}},effectiveLocale(){const e=(this.language||this.cfg.language||this.cfg.locale||this.cfg.lang||"").trim(),t=this.showLocaleSwitcher?this.locale:"";return(e||t||this.hostLang||"en").split("-")[0].toLowerCase()},uiLocale(){return ns.includes(this.effectiveLocale)?this.effectiveLocale:"en"},uiDir(){return this.uiLocale==="ar"?"rtl":"ltr"},layoutLabels(){const e={};for(const t of["toggleList","openViews","expandList","collapseList","collapse"])e[t]=this.tr(t);return e},effectiveProvider(){const e=String(this.provider||this.cfg.provider||"").trim().toLowerCase();return e==="maplibre"||e==="mapbox"?e:""},activeKey(){const e=this.tabs[this.activeIndex];return e?e.id:""}},mounted(){this.watchWidth(),this.watchHostLang(),this.select(this.initialIndex()),this.loadManifest(),this._onHostedHelp=e=>this.onHostedHelp(e),this.$el.addEventListener("doxa:help",this._onHostedHelp)},beforeUnmount(){this._langObs&&(this._langObs.disconnect(),this._langObs=null),this._onHostedHelp&&(this.$el.removeEventListener("doxa:help",this._onHostedHelp),this._onHostedHelp=null),!(!this._mql||!this._onMedia)&&(this._mql.removeEventListener?this._mql.removeEventListener("change",this._onMedia):this._mql.removeListener&&this._mql.removeListener(this._onMedia),this._mql=null,this._onMedia=null)},watch:{activeIndex(){this.helpOpen=!1},effectiveLocale(){const e=(a,n)=>{try{const s=this._slots&&this._slots[a];s&&(s.innerHTML="")}catch{}n.mounted=!1,n.state="idle",n.error=""};this.tabs.forEach((a,n)=>{a.mounted&&n!==this.activeIndex&&e(n,a)});const t=this.activeIndex,o=this.tabs[t];!o||!o.mounted||(e(t,o),this.mountElement(t))},tab(e){e&&this.onSelect(e)}},methods:{openHelp(){this.helpOpen=!0,this.$nextTick(()=>this.$refs.helpClose&&this.$refs.helpClose.focus())},closeHelp(){this.helpOpen=!1;const e=this._helpReturn;this._helpReturn=null,this.$nextTick(()=>e&&e.focus&&e.focus())},infoFor(e){const t=this.showInfo&&e&&pg[e.id];return t&&(!t.leadKey||$o(t.leadKey,"en"))?t:null},tabHasHelp(e){return!!(e&&e.discovered&&yl(e.id,this.uiLocale))},onHostedHelp(e){if(!this.activeHelp)return;e.stopPropagation();const t=e.composedPath?e.composedPath():[];this._helpReturn=t.find(o=>o&&o.tagName==="BUTTON")||null,this.openHelp()},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},tr(e,t){return Va(this.uiLocale,e,t)},t(e,t){return Va(this.uiLocale,e,t)},tabLabel(e){return!e.discovered||cg("tab."+e.id)?Va(this.uiLocale,"tab."+e.id):e.label},tabSub(e){return e.discovered?this.uiLocale==="en"?e.sub:this.tr("experimentalSub"):Va(this.uiLocale,"sub."+e.id)},watchHostLang(){typeof MutationObserver>"u"||typeof document>"u"||(this._langObs=new MutationObserver(()=>{this.hostLang=xl()}),this._langObs.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]}))},watchWidth(){typeof window>"u"||!window.matchMedia||(this._mql=window.matchMedia("(max-width: 760px)"),this.narrow=this._mql.matches,this._onMedia=e=>{const t=this.narrow;this.narrow=!!e.matches,t!==this.narrow&&this.isDesktopOnly(this.activeKey)&&this.select(this.firstVisibleIndex())},this._mql.addEventListener?this._mql.addEventListener("change",this._onMedia):this._mql.addListener&&this._mql.addListener(this._onMedia))},mobileFlagOf(e){const t=this.tabs.find(o=>o.id===e);return t&&this.mobileFlags&&this.mobileFlags[t.bundle+"/"+t.profile]||null},isDesktopOnly(e){return this.narrow&&this.mobileFlagOf(e)==="desktop-only"},showsMobileNotice(e){return this.narrow&&this.mobileFlagOf(e)==="larger-screens"&&!this.mobileNoticeDismissed[e]},dismissMobileNotice(e){this.mobileNoticeDismissed={...this.mobileNoticeDismissed,[e]:!0}},firstVisibleIndex(){let e=-1;for(const t of this.navGroups)for(const o of t.rows){const a=this.tabs.findIndex(n=>n.id===o.key);if(!(a<0)&&(e<0&&(e=a),!o.disabled))return a}return e>=0?e:0},loadManifest(){const e=this.resolve("manifest.json"),t=c=>{try{return new URL(c,location.href).href.replace(/[^/]*$/,"")}catch{return""}},o={url:e,root:t(e)},a={url:this.resolve("doxa-maps-spa/manifest.json"),root:o.root};let n=!1;try{n=new URL(e,location.href).origin!==location.origin}catch{}const s=n?[a,o]:[o,a],r="/public/dx-maps/manifest.json";s.some(c=>c.url===r)||s.push({url:r,root:t(r)});const i=[],l=c=>{if(c>=s.length){this.manifestError="manifest.json not found (tried "+i.join(", ")+")",console.error("[doxa-maps-spa] "+this.manifestError+" — every tab except Big Picture is composed from it, so their panes cannot mount.");return}const{url:d,root:g}=s[c];return i.push(d),fetch(d,{credentials:"same-origin"}).then($=>{if(!$||!$.ok)throw new Error(d+" → HTTP "+($?$.status:"?"));return $.json()}).then($=>{if(!$)throw new Error(d+" → empty");this.manifestError="",this.manifestBase=g||"",this.applyManifest($)}).catch(()=>l(c+1))};try{l(0)}catch{}},applyManifest(e){this.runtime=e&&e.runtime&&typeof e.runtime=="object"?e.runtime:{},this.mobileFlags=om(e),this.applyPageGlobals();const t=lm(e,cs),o=this.activeKey,a=[];for(const l of this.tabs){if(l.discovered){a.push(l);continue}const c=t[l.id];c&&(Object.assign(l,c,{resolved:!0}),a.push(l))}const n=new Set(a.map(l=>l.id));if(this.showExperimental)for(const l of im(e))n.has(l.id)||a.push({...l,resolved:!0,mounted:!1,state:"idle",error:""});this.tabs=a;const s=this.requestedTab(),r=s?this.tabs.findIndex(l=>l.id===s):-1,i=this.tabs.findIndex(l=>l.id===o);r>=0&&!this.isDesktopOnly(s)&&!this._honouredTab?this.select(r):this.select(i>=0&&!this.isDesktopOnly(o)?i:this.firstVisibleIndex()),this._honouredTab=!0},requestedTab(){let e="";try{e=new URLSearchParams(location.search).get("tab")||""}catch{}return String(this.tab||this.cfg.tab||e||"").trim()},initialIndex(){const e=this.requestedTab(),t=e?this.tabs.findIndex(o=>o.id===e):-1;return t>=0&&(this._honouredTab=!0),t>=0&&!this.isDesktopOnly(e)?t:this.firstVisibleIndex()},setLocale(e){this.locale=e,this.localeOpen=!1,lg(e)},onSelect(e){if(this.isDesktopOnly(e)){const o=this.tabs.find(a=>a.id===e);this.disabledNotice=($o("messages.desktopOnlyNotice",this.uiLocale)||"{label} only supports desktop — open this page on a desktop to use it.").replace("{label}",o?this.tabLabel(o):e),clearTimeout(this._noticeTimer),this._noticeTimer=setTimeout(()=>{this.disabledNotice=""},4e3);return}const t=this.tabs.findIndex(o=>o.id===e);t!==-1&&this.select(t)},resolve(e){const t=String(e);if(/^(https?:)?\/\//.test(t)||t.startsWith("/"))return t;const o=t.replace(/^\.\//,"");return this.manifestBase?this.manifestBase.replace(/\/+$/,"")+"/"+o:this.base?this.base.replace(/\/+$/,"")+"/"+o:"../"+o},select(e){const t=this.activeIndex;if(this.activeIndex=e,t!==e&&t>=0){const a=this.tabs[t];a&&a.heavy&&a.mounted&&this.releaseTab(t,a)}const o=this.tabs[e];o&&((t!==e||!this._announced)&&(this._announced=!0,this.$emit("tab-change",{id:o.id,label:o.label})),o.scriptUrl&&(this.narrow&&this.mobileFlags===null||this.isDesktopOnly(o.id)||o.mounted||this.$nextTick(()=>{this.activeIndex===e&&this.mountElement(e)})))},releaseTab(e,t){try{const o=this._slots&&this._slots[e];o&&(o.innerHTML="")}catch{}this._slots&&delete this._slots[e],t.mounted=!1,t.state="idle",t.error=""},childConfig(e){const t={profile:e.profile||e.id,instanceId:e.instance||"dms-"+e.id};this.effectiveLocale&&(t.locale=this.effectiveLocale);const o=this.tk||this.cfg.tk||this.runtime.token;return o&&(t.tk=o),(this.tokenUrl||this.cfg.tokenUrl)&&(t.tokenUrl=this.tokenUrl||this.cfg.tokenUrl),this.effectiveProvider&&(t.provider=this.effectiveProvider),this.base&&(t.treeBase=this.base),this.assetsBase&&(t.assetsBase=this.assetsBase),t.urlSync=!1,t},applyPageGlobals(){if(typeof window>"u")return;const e=(this.apiBaseUrl||this.cfg.apiBaseUrl||this.runtime.apiBaseUrl||"").trim();e&&!window.MAP_APP_API_URL&&(window.MAP_APP_API_URL=e.replace(/\/+$/,""));const t=this.tk||this.cfg.tk||this.runtime.token;t&&!window.MAP_TOKEN&&(window.MAP_TOKEN=t),this.effectiveProvider&&!window.MAP_PROVIDER&&(window.MAP_PROVIDER=this.effectiveProvider)},mountElement(e){const t=this.tabs[e];t.mounted=!0,t.state="loading";const o=this.resolve(t.scriptUrl);bl(o).then(()=>sh(t.tag)).then(()=>{try{if(t.heavy&&this.activeIndex!==e){t.mounted=!1,t.state="idle";return}const a=this._slots&&this._slots[e];if(!a){t.state="error",t.error="no slot";return}a.innerHTML="";const n=document.createElement(t.tag);n.setAttribute("profile-config",JSON.stringify(this.childConfig(t))),this.base&&n.setAttribute("tree-base",this.base.replace(/\/+$/,"")),n.style.cssText=t.scroll?"display:block;position:static;width:100%;height:auto;":"display:block;position:absolute;inset:0;width:100%;height:100%;min-height:0;",a.appendChild(n),t.state="ready"}catch(a){t.state="error",t.error="mount failed: "+(a&&a.message||String(a))}}).catch(a=>{t.state="error",t.error=a&&a.message||String(a)})}}}),pm={class:"dms-locale"},um=["aria-expanded"],dm={class:"dms-flag"},fm={class:"dms-locale-name"},hm={key:0,class:"dms-locale-menu",role:"listbox"},gm=["aria-selected"],mm=["onClick"],bm={class:"dms-flag"},$m={class:"dms-locale-name"},_m={class:"dms-locale-en"},vm=["hidden","data-doxa-help"],ym={key:0,class:"dms-mobile-notice",role:"status"},wm=["aria-label","onClick"],km={key:2,class:"dms-hint"},xm={key:3,class:"dms-hint err"},Tm={key:4,class:"dms-hint err"},Lm={key:0,class:"dms-notice",role:"status"},Sm={id:"dms-help-title",class:"dms-help-title"},Om={class:"dms-help-what"},Em={class:"dms-help-how"};function Pm(e,t,o,a,n,s){const r=ka("MapInfo"),i=ka("BackToTopButton"),l=ka("VerticalTabsLayout");return F(),uo(l,{dir:e.uiDir,lang:e.uiLocale,labels:e.layoutLabels,title:e.headingText,"nav-label":e.t("navLabel"),header:e.showHeader,groups:e.navGroups,active:e.activeKey,"onUpdate:active":e.onSelect},Rc({brand:Mo(()=>[t[5]||(t[5]=M("span",{class:"dms-logo","aria-hidden":"true"},[M("svg",{viewBox:"0 0 24 24",width:"22",height:"22",fill:"none",stroke:"#92b195","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[M("circle",{cx:"12",cy:"12",r:"9"}),M("polygon",{points:"12 6 14 12 12 18 10 12",fill:"#92b195",stroke:"none"}),M("polygon",{points:"6 12 12 10 18 12 12 14",fill:"#92b195",opacity:"0.55",stroke:"none"})])],-1))]),meta:Mo(()=>[Dt(q(e.t("meta",{n:e.tabs.length})),1)]),default:Mo(()=>[(F(!0),H(ne,null,Ke(e.tabs,(c,d)=>_a((F(),H("section",{key:c.id,class:"dms-pane",ref_for:!0,ref:g=>{g?e.paneEls[d]=g:delete e.paneEls[d]},hidden:d!==e.activeIndex,"data-doxa-help":e.tabHasHelp(c)?"":null,"data-doxa-gallery":""},[!c.heavy||d===e.activeIndex?(F(),H(ne,{key:0},[e.showsMobileNotice(c.id)?(F(),H("div",ym,[M("span",null,q(e.largerScreenText),1),M("button",{type:"button",class:"dms-mobile-notice-x","aria-label":e.tr("dismiss"),onClick:g=>e.dismissMobileNotice(c.id)},"×",8,wm)])):de("",!0),M("div",{class:"dms-slot",ref_for:!0,ref:g=>e.setSlot(d,g)},null,512),e.infoFor(c)?(F(),uo(r,Cr({key:"info-"+c.id},{ref_for:!0},e.infoFor(c),{"assets-base":e.assetsBase,locale:e.effectiveLocale}),null,16,["assets-base","locale"])):de("",!0),c.state==="loading"?(F(),H("div",km,q(e.tr("loading",{label:e.tabLabel(c)})),1)):c.state==="error"?(F(),H("div",xm,[Dt(q(e.tr("loadFailed",{label:e.tabLabel(c)})),1),t[7]||(t[7]=M("br",null,null,-1)),M("small",null,q(c.error),1)])):c.state==="idle"&&!c.scriptUrl&&e.manifestError?(F(),H("div",Tm,[Dt(q(e.tr("loadFailed",{label:e.tabLabel(c)})),1),t[8]||(t[8]=M("br",null,null,-1)),M("small",null,q(e.manifestError),1),t[9]||(t[9]=M("br",null,null,-1)),M("small",null,q(e.tr("manifestHint")),1)])):de("",!0)],64)):de("",!0)],8,vm)),[[Aa,d===e.activeIndex]])),128)),e.disabledNotice?(F(),H("div",Lm,q(e.disabledNotice),1)):de("",!0),e.helpOpen&&e.activeHelp?(F(),H("div",{key:1,class:"dms-help-scrim",onClick:t[3]||(t[3]=Ia((...c)=>e.closeHelp&&e.closeHelp(...c),["self"])),onKeydown:t[4]||(t[4]=Zr(Ia((...c)=>e.closeHelp&&e.closeHelp(...c),["stop","prevent"]),["esc"]))},[M("div",{class:"dms-help",role:"dialog","aria-modal":"true","aria-labelledby":"dms-help-title",onKeydown:t[2]||(t[2]=Zr(Ia(c=>e.$refs.helpClose&&e.$refs.helpClose.focus(),["prevent"]),["tab"]))},[M("h2",Sm,q(e.tabLabel(e.tabs[e.activeIndex])),1),M("p",Om,[M("strong",null,q(e.activeHelp.what),1)]),M("p",Em,q(e.activeHelp.how),1),M("button",{ref:"helpClose",type:"button",class:"dms-help-close",onClick:t[1]||(t[1]=(...c)=>e.closeHelp&&e.closeHelp(...c))},q(e.tr("close")),513)],32)],32)):de("",!0),Ae(i,{target:e.activePaneEl,labels:{backToTop:e.tr("backToTop")}},null,8,["target","labels"])]),_:2},[e.showLocaleSwitcher?{name:"toolbar",fn:Mo(()=>[M("div",pm,[M("button",{type:"button",class:"dms-locale-btn","aria-expanded":String(e.localeOpen),"aria-label":"Change language",onClick:t[0]||(t[0]=c=>e.localeOpen=!e.localeOpen)},[M("span",dm,q(e.activeLang.flag),1),M("span",fm,q(e.activeLang.nativeName),1),t[6]||(t[6]=M("span",{class:"dms-dots","aria-hidden":"true"},"⋮",-1))],8,um),e.localeOpen?(F(),H("ul",hm,[(F(!0),H(ne,null,Ke(e.switcherLangs,c=>(F(),H("li",{key:c.code,role:"option","aria-selected":String(c.code===e.locale)},[M("button",{type:"button",class:et(["dms-locale-opt",{active:c.code===e.locale}]),onClick:d=>e.setLocale(c.code)},[M("span",bm,q(c.flag),1),M("span",$m,q(c.nativeName),1),M("span",_m,q(c.name),1)],10,mm)],8,gm))),128))])):de("",!0)])]),key:"0"}:void 0]),1032,["dir","lang","labels","title","nav-label","header","groups","active","onUpdate:active"])}const Mm=Nn(cm,[["render",Pm],["styles",[tm]]]),Am=rh(),Cm=Kp(Mm,{configureApp(e){e.provide("dmsTreeBase",Am)}});typeof customElements<"u"&&!customElements.get("doxa-maps-spa")&&customElements.define("doxa-maps-spa",Cm)})(); diff --git a/public/dx-maps/doxa-maps-spa/doxa-maps-spa/app/index.html b/public/dx-maps/doxa-maps-spa/doxa-maps-spa/app/index.html index 04687a560..e4ac1be9e 100644 --- a/public/dx-maps/doxa-maps-spa/doxa-maps-spa/app/index.html +++ b/public/dx-maps/doxa-maps-spa/doxa-maps-spa/app/index.html @@ -61,7 +61,7 @@ - + - + \n\n\n" + "script": "\n\n\n" }, "instances": [ { diff --git a/public/dx-maps/manifest.json b/public/dx-maps/manifest.json index cef705169..92ca18750 100644 --- a/public/dx-maps/manifest.json +++ b/public/dx-maps/manifest.json @@ -361,7 +361,7 @@ "bundle": "doxa-maps-spa", "scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js", "output": "dx-maps/doxa-maps-spa/doxa-maps-spa.js", - "integrity": "sha384-yngki2IqP9U/C9ViLIWHmyI0AhpQhOraOeRs5msKfniBS4Vlv7zgsB065ovhwTfF", + "integrity": "sha384-8kPnPQEf/NcXxMHx6Jr5LV/sZG61fn/bBO6K9BmqlSo4ykN3Fn59t+IXWkVjb2Lj", "elements": [ "doxa-maps-spa" ], @@ -389,7 +389,7 @@ "scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { From c00bf1034fec286b8e74085524997d0f38758ac6 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Tue, 29 Sep 2026 20:10:25 +0000 Subject: [PATCH 3/3] Regenerate the library index for usePaneConfig, which landed without it (check:library-index) --- documentation/reference-library-index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/documentation/reference-library-index.md b/documentation/reference-library-index.md index e120d23be..3a4a2338b 100644 --- a/documentation/reference-library-index.md +++ b/documentation/reference-library-index.md @@ -193,6 +193,8 @@ and a change here can break other maps. `import … from '@map/composables/useMapTheme.js'` - **useOptionalT** — ★ NO .-SHAPED EXAMPLES IN THIS FILE'S COMMENTS. check:i18n-keys-exist reads any such `import … from '@map/composables/useOptionalT.js'` +- **usePaneConfig** — usePaneConfig — keep a composite's panes' profile-config in step with the outer element's. + `import … from '@map/composables/usePaneConfig.js'` - **usePosterPrints** — usePosterPrints.js — THE print actions every poster wall shares. `import … from '@map/composables/usePosterPrints.js'` - **usePplrInstance** — usePplrInstance.js — per-map "instance store" mediator.