From 0ab6ca169532d47e4f352b8e555a26fcefba21bc Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Wed, 30 Sep 2026 22:59:45 +0000 Subject: [PATCH 01/11] Research Gallery: Bible Posters stays off the Experimental shelf Bible Posters lives on Posterverse's Experimental shelf, so the gallery excludes it, as it already excludes Posterverse itself. One poster plugin, shown once. --- plugin-designs/doxa-maps-spa/doxa-maps-spa.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugin-designs/doxa-maps-spa/doxa-maps-spa.vue b/plugin-designs/doxa-maps-spa/doxa-maps-spa.vue index 1d0d19941..efd980cc6 100644 --- a/plugin-designs/doxa-maps-spa/doxa-maps-spa.vue +++ b/plugin-designs/doxa-maps-spa/doxa-maps-spa.vue @@ -364,7 +364,10 @@ const NOT_EXPERIMENTAL = new Set([ // posterverse is the OTHER capability-5 shell (the poster plugins). Shown here it would be a // whole second rail inside this pane: a shell does not nest a shell, for the same reason this // shell excludes itself above. - 'posterverse' + 'posterverse', + // bible-posters lives on POSTERVERSE's Experimental shelf, and only there: one poster plugin, shown + // once, in the shell that gathers the poster plugins. + 'bible-posters' ]) // ── EXPERIMENTAL ORDER = KINGDOM IMPACT, not the alphabet ──────────────────────────────── From ac108b5117aadfc5eb6e0f4664c559f926ee03fe Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Thu, 1 Oct 2026 05:47:24 +0000 Subject: [PATCH 02/11] Posterverse: Bible Posters' ids are confirmed, and composes declares it bible-posters/bible-posters is the id the Bible Posters plugin ships, so its Experimental row is no longer provisional, and posterverse.meta.json composes it. Lands in the SAME push as the bible-posters bundle: without it the ref is unresolved (check:capability-derived), and with the bundle but without this commit check:posterverse-shelf fails arm D. --- plugin-designs/posterverse/posterverse.meta.json | 5 +++-- plugin-designs/posterverse/src/tabs.js | 11 +++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugin-designs/posterverse/posterverse.meta.json b/plugin-designs/posterverse/posterverse.meta.json index 115ba40ef..c8a6b3dc4 100644 --- a/plugin-designs/posterverse/posterverse.meta.json +++ b/plugin-designs/posterverse/posterverse.meta.json @@ -1,11 +1,12 @@ { - "_comment": "Declares the composability tier. 'nested-mfe-spa' = capability 5: an app shell whose single element renders a vertical-tab rail of whole poster plugins, each mounted as its own real element from the manifest (no iframes). The tier is DERIVED from `composes` at tree generation (composing a cap-4 makes this cap-5) and this `type` is checked against it. `composes` lists every row in src/tabs.js whose bundle exists; a provisional row (bible-posters) joins the list in the SAME push as its bundle, since an unresolved ref fails check:capability-derived and a missing one fails check:posterverse-shelf.", + "_comment": "Declares the composability tier. 'nested-mfe-spa' = capability 5: an app shell whose single element renders a vertical-tab rail of whole poster plugins, each mounted as its own real element from the manifest (no iframes). The tier is DERIVED from `composes` at tree generation (composing a cap-4 makes this cap-5) and this `type` is checked against it. `composes` lists every row in src/tabs.js. A new row's ref joins this list in the SAME push as its bundle, since an unresolved ref fails check:capability-derived and a missing one fails check:posterverse-shelf.", "type": "nested-mfe-spa", "composes": [ "my-upg-100-list/upg-100-mfe", "country-posters/country-posters-mfe", "poster-design/poster-design-mfe", - "wall-of-people-groups/wall-of-people-groups" + "wall-of-people-groups/wall-of-people-groups", + "bible-posters/bible-posters" ], "label": "Posterverse (vertical-tab app shell: every poster plugin)" } diff --git a/plugin-designs/posterverse/src/tabs.js b/plugin-designs/posterverse/src/tabs.js index 2e53cd35e..c251b6605 100644 --- a/plugin-designs/posterverse/src/tabs.js +++ b/plugin-designs/posterverse/src/tabs.js @@ -10,10 +10,10 @@ * appears, whatever the manifest holds. * * ★ A ROW WHOSE BUNDLE IS NOT IN THE TREE IS PRUNED, not painted dead. That is how a row can be listed - * before its plugin lands: Bible Posters is declared with PROVISIONAL ids and stays invisible until a - * bundle of that id exists. Its owner confirms the ids; change the `bundle`/`profile` here to match, - * never the row `id` (the id is the stable key for ?tab= links). A provisional row's `composes` entry - * lands in the same push as its bundle (check:posterverse-shelf arm D). + * before its plugin lands: mark it `provisional: true` and it stays invisible until a bundle of that id + * exists. Its owner confirms the ids; change the `bundle`/`profile` here to match, never the row `id` + * (the id is the stable key for ?tab= links). A new row's `composes` entry lands in the same push as + * its bundle (check:posterverse-shelf arm D). * * ★ MOUNT THE COMPOSITE, NOT A LEAF. The profile named here is the one that mounts. my-upg-100-list and * country-posters each ship a leaf map, a leaf wall and the capability-4 composite of the two; the @@ -32,8 +32,7 @@ export const TABS = [ { id: 'country-posters', section: 'posters', icon: 'map', bundle: 'country-posters', profile: 'country-posters-mfe' }, { id: 'poster-design', section: 'posters', icon: 'poster', bundle: 'poster-design', profile: 'poster-design-mfe' }, { id: 'wall-of-people-groups', section: 'experimental', icon: 'flask', bundle: 'wall-of-people-groups', profile: 'wall-of-people-groups' }, - // Provisional ids: no bible-posters bundle exists yet, so this row is pruned until one does. - { id: 'bible-posters', section: 'experimental', icon: 'flask', bundle: 'bible-posters', profile: 'bible-posters', provisional: true }, + { id: 'bible-posters', section: 'experimental', icon: 'flask', bundle: 'bible-posters', profile: 'bible-posters' }, ] // Bundles that must never be a Posterverse row. The allow-list above already excludes them; this set From 12e2ebafab3bd1e68f8ce642a95163f04504f774 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Thu, 1 Oct 2026 05:47:33 +0000 Subject: [PATCH 03/11] Rebuild posterverse for the confirmed Bible Posters row BUNDLE=posterverse vite build only. The tree is regenerated once on the merged tree that also carries the bible-posters bundle (generate-tree refuses the new composes ref until that bundle is present). --- public/dx-maps/posterverse/posterverse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/dx-maps/posterverse/posterverse.js b/public/dx-maps/posterverse/posterverse.js index 14d9bfc43..6a664c69e 100644 --- a/public/dx-maps/posterverse/posterverse.js +++ b/public/dx-maps/posterverse/posterverse.js @@ -152,4 +152,4 @@ @media (prefers-reduced-motion: reduce) { .vtl-nav, .vtl-collapse-ic, .vtl-tab, .vtl-tier, .vtl-fab, .vtl-scrim { transition: none !important; animation: none !important; } } -`,Al=Yo({name:"VerticalTabsLayout",components:{BackToTopButton:_r},props:{active:{type:String,default:""},title:{type:String,default:""},items:{type:Array,default:()=>[]},groups:{type:Array,default:()=>[]},navLabel:{type:String,default:"Sections"},labels:{type:Object,default:()=>({})},initialNavOpen:{type:Boolean,default:!0},header:{type:Boolean,default:!0},initialRailCollapsed:{type:Boolean,default:!1},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["update:active"],setup(){return _l(Pl,"vertical-tabs-layout"),{T:Ml}},data(){return{navOpen:this.initialNavOpen,railCollapsed:this.initialRailCollapsed,_tabEls:{},folderOverride:{},narrow:!1,_mql:null,_onMedia:null,activatedKeys:{},hostState:{},hostError:{},_hostSlots:{},_hostMounted:{},hostEls:{}}},computed:{fabShown(){return this.narrow&&!this.header&&!this.navOpen},activeHostEl(){return this.hostEls[this.active]||null},railShown(){return this.narrow?this.navOpen:!0},homeLink(){const e=String(this.homeHref||"").trim();return!e||/^(javascript|data|vbscript):/i.test(e.replace(/[\u0000- ]/g,""))?"":e},homeText(){return this.homeLabel||this.label("home")},allRows(){if(this.groups&&this.groups.length){const e=[];for(const t of this.groups)for(const o of t.rows||[])e.push(o);return e}return this.items},orderedKeys(){return this.allRows.map(e=>e.key)},elementRows(){return this.allRows.filter(e=>e&&e.element)},mountedElementRows(){return this.elementRows.filter(e=>this.activatedKeys[e.key])}},watch:{active:{immediate:!0,handler(e){this.activateElement(e)}}},mounted(){try{window.matchMedia&&(this._mql=window.matchMedia("(max-width: 760px)"),this.narrow=this._mql.matches,this.reconcileForWidth(),this._onMedia=e=>{this.narrow=e.matches,this.reconcileForWidth()},this._mql.addEventListener?this._mql.addEventListener("change",this._onMedia):this._mql.addListener&&this._mql.addListener(this._onMedia))}catch{}this.$nextTick(()=>this.activateElement(this.active))},beforeUnmount(){try{this._mql&&this._onMedia&&(this._mql.removeEventListener?this._mql.removeEventListener("change",this._onMedia):this._mql.removeListener&&this._mql.removeListener(this._onMedia))}catch{}this._mql=null,this._onMedia=null},methods:{registerTab(e,t){t&&(this._tabEls[e]=t)},isNarrow(){return this.narrow},reconcileForWidth(){this.narrow?(this.navOpen=!1,this.railCollapsed=!1):this.navOpen=!0},label(e){const t={toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse",home:"Back to homepage"};return this.labels&&this.labels[e]||t[e]},expandRail(){!this.narrow&&this.railCollapsed&&(this.railCollapsed=!1)},toggleRail(){this.narrow?this.navOpen=!this.navOpen:this.railCollapsed=!this.railCollapsed},setHostSlot(e,t){t&&(this._hostSlots[e]=t,this.$nextTick(()=>this.mountHostElement(e)))},activateElement(e){!e||!this.elementRows.find(o=>o.key===e)||(this.activatedKeys[e]||(this.activatedKeys={...this.activatedKeys,[e]:!0},this.$nextTick(()=>this.watchContextLoss(e)),this.hostState={...this.hostState,[e]:"loading"}),this.$nextTick(()=>this.mountHostElement(e)))},deepCanvases(e,t=[]){if(!e)return t;for(const o of e.querySelectorAll("*"))o.tagName==="CANVAS"&&t.push(o),o.shadowRoot&&this.deepCanvases(o.shadowRoot,t);return t},watchContextLoss(e){const t=this._hostSlots[e];if(t)for(const o of this.deepCanvases(t))o.__vtlLossBound||(o.__vtlLossBound=!0,o.addEventListener("webglcontextlost",()=>{this.hostState={...this.hostState,[e]:"lost"}},{once:!0}))},reloadHostElement(e){const t=this._hostSlots[e];t&&(t.innerHTML=""),this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"loading"},this.$nextTick(()=>this.mountHostElement(e))},mountHostElement(e){if(this._hostMounted[e])return;const t=this.elementRows.find(n=>n.key===e),o=this._hostSlots[e];!t||!o||(this._hostMounted[e]=!0,this.hostState={...this.hostState,[e]:"loading"},Ll(t.src).then(()=>Ol(t.element)).then(()=>{xl(t.element,t.src),o.innerHTML="";const n=document.createElement(t.element),s=t.attrs||{};for(const r in s){const a=s[r],i=a!=null&&typeof a=="object"?JSON.stringify(a):String(a);try{n[r]=a}catch{}try{n.setAttribute(r,i)}catch{}}n.style.cssText="display:block;position:absolute;inset:0;width:100%;height:100%;",o.appendChild(n);for(const r of[0,250,1500])setTimeout(()=>this.watchContextLoss(e),r);this.hostState={...this.hostState,[e]:"ready"}}).catch(n=>{this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"error"},this.hostError={...this.hostError,[e]:n&&n.message||String(n)}}))},iconSvg(e){return e?yl(e):""},initial(e){const t=(e||"").trim();return t?t.charAt(0).toUpperCase():"•"},isFolderClosed(e){const t=this.folderOverride[e.key];return t!=null?!t:e.open!==!0},toggleFolder(e){const t=this.folderOverride[e],o=(this.groups||[]).find(s=>s.key===e),n=t??(o&&o.open===!0);this.folderOverride={...this.folderOverride,[e]:!n}},pick(e){this.$emit("update:active",e),this.narrow&&(this.navOpen=!1)},onKey(e){const t=this.orderedKeys;if(!t.length)return;const o=t.indexOf(this.active);let n=-1;if(e.key==="ArrowDown"||e.key==="ArrowRight")n=(o+1)%t.length;else if(e.key==="ArrowUp"||e.key==="ArrowLeft")n=(o-1+t.length)%t.length;else if(e.key==="Home")n=0;else if(e.key==="End")n=t.length-1;else return;e.preventDefault();const s=t[n];this.pick(s),this.$nextTick(()=>{const r=this._tabEls[s];r&&r.focus&&r.focus()})}}}),Cl={key:0,class:"vtl-top"},Fl=["aria-expanded","aria-label"],Il={class:"vtl-brand"},Nl={class:"vtl-title"},El={class:"vtl-meta"},Rl=["aria-expanded","aria-label"],Wl={class:"vtl-body"},Dl=["aria-label","aria-hidden","role","aria-orientation"],zl=["href","aria-label","title"],Hl=["innerHTML"],Bl={class:"vtl-home-tx"},Ul=["aria-expanded","aria-label"],jl=["innerHTML"],Vl={class:"vtl-collapse-tx"},ql=["aria-expanded","onClick"],Kl={key:0,class:"vtl-cap"},Gl={class:"vtl-tl"},Jl={key:1,class:"vtl-td"},Xl=["innerHTML"],Zl={key:1,class:"vtl-tier"},Yl={key:0,class:"vtl-cap"},Ql={class:"vtl-tl"},ec={key:1,class:"vtl-td"},tc={class:"vtl-rows"},oc=["aria-selected","aria-disabled","tabindex","onClick"],nc=["innerHTML"],sc={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},rc={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},ic={class:"vtl-tab-text"},ac={class:"vtl-tab-label"},lc={key:0,class:"vtl-tab-badge"},cc={key:0,class:"vtl-tab-sub"},pc=["innerHTML"],dc=["aria-selected","aria-disabled","tabindex","onClick"],uc=["innerHTML"],fc={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},hc={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},gc={class:"vtl-tab-text"},mc={class:"vtl-tab-label"},$c={key:0,class:"vtl-tab-sub"},bc={class:"vtl-main"},_c={class:"vtl-content"},vc=["hidden"],yc={key:0,class:"vtl-host-hint"},wc={key:1,class:"vtl-host-hint"},xc=["onClick"],Tc={key:2,class:"vtl-host-hint err"};function kc(e,t,o,n,s,r){const a=tn("BackToTopButton");return C(),F("div",{class:Xe(["vtl",{"nav-open":e.navOpen,"rail-collapsed":e.railCollapsed,"no-header":!e.header}]),style:Jt(e.fabShown?{"--map-fab-clearance":"calc(56px + env(safe-area-inset-bottom))","--map-fab-beside":"calc(56px + env(safe-area-inset-left))"}:null)},[e.header?(C(),F("header",Cl,[I("button",{class:"vtl-menu",type:"button","aria-expanded":String(e.navOpen),onClick:t[0]||(t[0]=i=>e.navOpen=!e.navOpen),"aria-label":e.label("toggleList")},"☰",8,Fl),I("span",Il,[Mt(e.$slots,"brand")]),I("b",Nl,D(e.title),1),I("span",El,[Mt(e.$slots,"meta")])])):le("",!0),e.fabShown?(C(),F("button",{key:1,class:"vtl-fab",type:"button","aria-expanded":String(e.navOpen),onClick:t[1]||(t[1]=i=>e.navOpen=!0),"aria-label":e.label("openViews")},"☰",8,Rl)):le("",!0),e.narrow?(C(),At(a,{key:2,target:e.activeHostEl,labels:{backToTop:e.T("actions.backToTop","Back to top")}},null,8,["target","labels"])):le("",!0),I("div",Wl,[I("nav",{class:"vtl-nav","aria-label":e.navLabel,"aria-hidden":String(!e.railShown),role:e.$slots.rail?null:"tablist","aria-orientation":e.$slots.rail?null:"vertical"},[e.homeLink?(C(),F("a",{key:0,class:"vtl-home",href:e.homeLink,target:"_top","aria-label":e.homeText,title:e.railCollapsed&&!e.narrow?e.homeText:null},[I("span",{class:"vtl-home-ic","aria-hidden":"true",innerHTML:e.iconSvg("home")},null,8,Hl),I("span",Bl,D(e.homeText),1)],8,zl)):le("",!0),I("button",{type:"button",class:"vtl-collapse","aria-expanded":String(!e.railCollapsed),"aria-label":e.railCollapsed?e.label("expandList"):e.label("collapseList"),onClick:t[2]||(t[2]=(...i)=>e.toggleRail&&e.toggleRail(...i))},[I("span",{class:"vtl-collapse-ic","aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,8,jl),I("span",Vl,D(e.label("collapse")),1)],8,Ul),e.$slots.rail?Mt(e.$slots,"rail",{collapsed:e.railCollapsed&&!e.narrow,expand:e.expandRail,pick:e.pick},void 0,void 0,1):e.groups&&e.groups.length?(C(!0),F(oe,{key:2},St(e.groups,i=>(C(),F("div",{class:"vtl-grp",key:i.key},[i.folder?(C(),F("button",{key:0,type:"button",class:"vtl-tier vtl-tier-btn","aria-expanded":String(!e.isFolderClosed(i)),onClick:l=>e.toggleFolder(i.key)},[i.badge?(C(),F("span",Kl,D(i.badge),1)):le("",!0),I("span",Gl,D(i.label),1),i.count!=null?(C(),F("span",Jl,D(i.count),1)):le("",!0),I("span",{class:Xe(["vtl-chev",{open:!e.isFolderClosed(i)}]),"aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,10,Xl)],8,ql)):(C(),F("div",Zl,[i.badge?(C(),F("span",Yl,D(i.badge),1)):le("",!0),I("span",Ql,D(i.label),1),i.count!=null?(C(),F("span",ec,D(i.count),1)):le("",!0)])),Jo(I("div",tc,[(C(!0),F(oe,null,St(i.rows,l=>(C(),F("button",{key:l.key,type:"button",role:"tab",class:Xe(["vtl-tab",{active:l.key===e.active,disabled:l.disabled}]),"aria-selected":String(l.key===e.active),"aria-disabled":l.disabled?"true":null,tabindex:l.key===e.active?0:-1,ref_for:!0,ref:p=>e.registerTab(l.key,p),onClick:p=>e.pick(l.key),onKeydown:t[3]||(t[3]=p=>e.onKey(p))},[l.icon?(C(),F("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(l.icon)},null,8,nc)):l.emoji?(C(),F("span",sc,D(l.emoji),1)):(C(),F("span",rc,D(e.initial(l.label)),1)),I("span",ic,[I("span",ac,[ht(D(l.label),1),l.badge?(C(),F("span",lc,D(l.badge),1)):le("",!0)]),l.sub?(C(),F("span",cc,[I("span",{innerHTML:l.sub},null,8,pc)])):le("",!0)])],42,oc))),128))],512),[[gn,!i.folder||!e.isFolderClosed(i)]])]))),128)):(C(!0),F(oe,{key:3},St(e.items,i=>(C(),F("button",{key:i.key,type:"button",role:"tab",class:Xe(["vtl-tab",{active:i.key===e.active,disabled:i.disabled}]),"aria-selected":String(i.key===e.active),"aria-disabled":i.disabled?"true":null,tabindex:i.key===e.active?0:-1,ref_for:!0,ref:l=>e.registerTab(i.key,l),onClick:l=>e.pick(i.key),onKeydown:t[4]||(t[4]=l=>e.onKey(l))},[i.icon?(C(),F("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(i.icon)},null,8,uc)):i.emoji?(C(),F("span",fc,D(i.emoji),1)):(C(),F("span",hc,D(e.initial(i.label)),1)),I("span",gc,[I("span",mc,D(i.label),1),i.sub?(C(),F("span",$c,D(i.sub),1)):le("",!0)])],42,dc))),128))],8,Dl),I("main",bc,[e.header?Mt(e.$slots,"toolbar",{},void 0,void 0,0):le("",!0),I("div",_c,[(C(!0),F(oe,null,St(e.mountedElementRows,i=>Jo((C(),F("section",{key:i.key,class:"vtl-host",hidden:i.key!==e.active,ref_for:!0,ref:l=>{l?e.hostEls[i.key]=l:delete e.hostEls[i.key]}},[I("div",{class:"vtl-host-slot",ref_for:!0,ref:l=>e.setHostSlot(i.key,l)},null,512),e.hostState[i.key]==="loading"?(C(),F("div",yc,D(e.T("messages.loadingNamed","Loading {name}…").replace("{name}",i.label)),1)):e.hostState[i.key]==="lost"?(C(),F("div",wc,[ht(D(e.T("messages.mapContextLost","This map was unloaded to free graphics memory."))+" ",1),I("button",{type:"button",class:"vtl-host-reload",onClick:l=>e.reloadHostElement(i.key)},D(e.T("buttons.reloadMap","Reload Map")),9,xc)])):e.hostState[i.key]==="error"?(C(),F("div",Tc,[ht(D(e.T("messages.couldNotLoadNamed","Could not load {name}.").replace("{name}",i.label)),1),t[5]||(t[5]=I("br",null,null,-1)),I("small",null,D(e.hostError[i.key]),1)])):le("",!0)],8,vc)),[[gn,i.key===e.active]])),128)),Mt(e.$slots,"default")])])])],6)}const Sc=_n(Al,[["render",kc],["styles",[Sl]]]),yo={en:{"sec.posters":"Posters","sec.experimental":"Experimental","tab.upg-100":"UPG 100 List Posters","sub.upg-100":"my unreached list + posters","tab.country-posters":"Country Posters","sub.country-posters":"a poster for every country","tab.poster-design":"Poster Design","sub.poster-design":"every poster style and size","tab.wall-of-people-groups":"Wall of People Groups","tab.bible-posters":"Bible Posters",experimentalSub:"experimental bundle",lab:"lab",loading:"Loading {label}…",loadFailed:"Could not load {label}.",manifestHint:"This tab is composed from manifest.json — build the tree, or serve the built tree, to load it.",backToTop:"Back to top",home:"Back to homepage",toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse"},es:{"sec.posters":"Carteles","sec.experimental":"Experimental","tab.upg-100":"Carteles de la lista UPG 100","sub.upg-100":"mi lista de no alcanzados + carteles","tab.country-posters":"Carteles por país","sub.country-posters":"un cartel para cada país","tab.poster-design":"Diseño de carteles","sub.poster-design":"todos los estilos y tamaños de cartel","tab.wall-of-people-groups":"Muro de los pueblos","tab.bible-posters":"Carteles bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Cargando {label}…",loadFailed:"No se pudo cargar {label}.",manifestHint:"Esta pestaña se compone a partir de manifest.json: compila el árbol o sirve el árbol compilado para cargarla.",backToTop:"Volver arriba",home:"Volver a la página de inicio",toggleList:"Mostrar u ocultar la lista",openViews:"Abrir la lista de vistas",expandList:"Expandir la lista",collapseList:"Contraer la lista",collapse:"Contraer"},fr:{"sec.posters":"Affiches","sec.experimental":"Expérimental","tab.upg-100":"Affiches de la liste UPG 100","sub.upg-100":"ma liste des non atteints + affiches","tab.country-posters":"Affiches par pays","sub.country-posters":"une affiche pour chaque pays","tab.poster-design":"Conception d’affiches","sub.poster-design":"tous les styles et formats d’affiche","tab.wall-of-people-groups":"Mur des peuples","tab.bible-posters":"Affiches bibliques",experimentalSub:"carte expérimentale",lab:"bêta",loading:"Chargement de {label}…",loadFailed:"Impossible de charger {label}.",manifestHint:"Cet onglet est composé à partir de manifest.json : construisez l'arborescence ou servez l'arborescence construite pour le charger.",backToTop:"Retour en haut",home:"Retour à l’accueil",toggleList:"Afficher ou masquer la liste",openViews:"Ouvrir la liste des vues",expandList:"Déplier la liste",collapseList:"Replier la liste",collapse:"Replier"},de:{"sec.posters":"Poster","sec.experimental":"Experimentell","tab.upg-100":"Poster der UPG 100 Liste","sub.upg-100":"meine Liste der Unerreichten + Poster","tab.country-posters":"Länderposter","sub.country-posters":"ein Poster für jedes Land","tab.poster-design":"Postergestaltung","sub.poster-design":"alle Posterstile und -größen","tab.wall-of-people-groups":"Wand der Volksgruppen","tab.bible-posters":"Bibelposter",experimentalSub:"experimentelle Karte",lab:"Beta",loading:"{label} wird geladen…",loadFailed:"{label} konnte nicht geladen werden.",manifestHint:"Dieser Tab wird aus manifest.json zusammengesetzt – bauen Sie den Baum oder stellen Sie den gebauten Baum bereit, um ihn zu laden.",backToTop:"Nach oben",home:"Zurück zur Startseite",toggleList:"Liste ein-/ausblenden",openViews:"Ansichtsliste öffnen",expandList:"Liste ausklappen",collapseList:"Liste einklappen",collapse:"Einklappen"},pt:{"sec.posters":"Cartazes","sec.experimental":"Experimental","tab.upg-100":"Cartazes da lista UPG 100","sub.upg-100":"minha lista de não alcançados + cartazes","tab.country-posters":"Cartazes por país","sub.country-posters":"um cartaz para cada país","tab.poster-design":"Design de cartazes","sub.poster-design":"todos os estilos e tamanhos de cartaz","tab.wall-of-people-groups":"Mural dos povos","tab.bible-posters":"Cartazes bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Carregando {label}…",loadFailed:"Não foi possível carregar {label}.",manifestHint:"Esta aba é composta a partir do manifest.json — compile a árvore ou sirva a árvore compilada para carregá-la.",backToTop:"Voltar ao topo",home:"Voltar à página inicial",toggleList:"Mostrar ou ocultar a lista",openViews:"Abrir a lista de visualizações",expandList:"Expandir a lista",collapseList:"Recolher a lista",collapse:"Recolher"},it:{"sec.posters":"Poster","sec.experimental":"Sperimentale","tab.upg-100":"Poster della lista UPG 100","sub.upg-100":"la mia lista dei non raggiunti + poster","tab.country-posters":"Poster per paese","sub.country-posters":"un poster per ogni paese","tab.poster-design":"Design dei poster","sub.poster-design":"tutti gli stili e i formati dei poster","tab.wall-of-people-groups":"Muro dei popoli","tab.bible-posters":"Poster biblici",experimentalSub:"mappa sperimentale",lab:"beta",loading:"Caricamento di {label}…",loadFailed:"Impossibile caricare {label}.",manifestHint:"Questa scheda è composta da manifest.json: compila l'albero o pubblica l'albero compilato per caricarla.",backToTop:"Torna su",home:"Torna alla home page",toggleList:"Mostra o nascondi l’elenco",openViews:"Apri l’elenco delle viste",expandList:"Espandi l’elenco",collapseList:"Comprimi l’elenco",collapse:"Comprimi"},ro:{"sec.posters":"Afișe","sec.experimental":"Experimental","tab.upg-100":"Afișe din lista UPG 100","sub.upg-100":"lista mea de neatinși + afișe","tab.country-posters":"Afișe pe țări","sub.country-posters":"un afiș pentru fiecare țară","tab.poster-design":"Design de afișe","sub.poster-design":"toate stilurile și dimensiunile de afiș","tab.wall-of-people-groups":"Zidul popoarelor","tab.bible-posters":"Afișe biblice",experimentalSub:"hartă experimentală",lab:"beta",loading:"Se încarcă {label}…",loadFailed:"{label} nu a putut fi încărcat.",manifestHint:"Această filă este compusă din manifest.json — construiți arborele sau serviți arborele construit pentru a o încărca.",backToTop:"Sus",home:"Înapoi la pagina principală",toggleList:"Afișează sau ascunde lista",openViews:"Deschide lista de vizualizări",expandList:"Extinde lista",collapseList:"Restrânge lista",collapse:"Restrânge"},ru:{"sec.posters":"Плакаты","sec.experimental":"Экспериментальное","tab.upg-100":"Плакаты списка UPG 100","sub.upg-100":"мой список недостигнутых + плакаты","tab.country-posters":"Плакаты по странам","sub.country-posters":"плакат для каждой страны","tab.poster-design":"Дизайн плакатов","sub.poster-design":"все стили и размеры плакатов","tab.wall-of-people-groups":"Стена народов","tab.bible-posters":"Библейские плакаты",experimentalSub:"экспериментальная карта",lab:"бета",loading:"Загрузка: {label}…",loadFailed:"Не удалось загрузить: {label}.",manifestHint:"Эта вкладка собирается из manifest.json — соберите дерево или разместите собранное дерево, чтобы загрузить её.",backToTop:"Наверх",home:"На главную страницу",toggleList:"Показать или скрыть список",openViews:"Открыть список представлений",expandList:"Развернуть список",collapseList:"Свернуть список",collapse:"Свернуть"},ar:{"sec.posters":"ملصقات","sec.experimental":"تجريبي","tab.upg-100":"ملصقات قائمة UPG 100","sub.upg-100":"قائمتي لغير المُبشَّرين + ملصقات","tab.country-posters":"ملصقات الدول","sub.country-posters":"ملصق لكل دولة","tab.poster-design":"تصميم الملصقات","sub.poster-design":"كل أنماط الملصقات وأحجامها","tab.wall-of-people-groups":"جدار الشعوب","tab.bible-posters":"ملصقات الكتاب المقدس",experimentalSub:"خريطة تجريبية",lab:"تجريبي",loading:"جارٍ تحميل {label}…",loadFailed:"تعذّر تحميل {label}.",manifestHint:"تُبنى علامة التبويب هذه من manifest.json — ابنِ الشجرة أو قدّم الشجرة المبنية لتحميلها.",backToTop:"إلى الأعلى",home:"العودة إلى الصفحة الرئيسية",toggleList:"إظهار القائمة أو إخفاؤها",openViews:"فتح قائمة العروض",expandList:"توسيع القائمة",collapseList:"طي القائمة",collapse:"طي"},hi:{"sec.posters":"पोस्टर","sec.experimental":"प्रायोगिक","tab.upg-100":"UPG 100 सूची पोस्टर","sub.upg-100":"मेरी अप्राप्त सूची + पोस्टर","tab.country-posters":"देश पोस्टर","sub.country-posters":"हर देश के लिए एक पोस्टर","tab.poster-design":"पोस्टर डिज़ाइन","sub.poster-design":"हर पोस्टर शैली और आकार","tab.wall-of-people-groups":"जनसमूहों की दीवार","tab.bible-posters":"बाइबल पोस्टर",experimentalSub:"प्रायोगिक मानचित्र",lab:"बीटा",loading:"{label} लोड हो रहा है…",loadFailed:"{label} लोड नहीं हो सका।",manifestHint:"यह टैब manifest.json से बनता है — इसे लोड करने के लिए ट्री बनाएँ या बना हुआ ट्री सर्व करें।",backToTop:"ऊपर जाएँ",home:"होमपेज पर वापस जाएँ",toggleList:"सूची दिखाएँ या छिपाएँ",openViews:"दृश्यों की सूची खोलें",expandList:"सूची फैलाएँ",collapseList:"सूची संक्षिप्त करें",collapse:"संक्षिप्त करें"},zh:{"sec.posters":"海报","sec.experimental":"实验性","tab.upg-100":"UPG 100 名单海报","sub.upg-100":"我的未得之民名单 + 海报","tab.country-posters":"国家海报","sub.country-posters":"每个国家一张海报","tab.poster-design":"海报设计","sub.poster-design":"所有海报样式与尺寸","tab.wall-of-people-groups":"民族之墙","tab.bible-posters":"圣经海报",experimentalSub:"实验性地图",lab:"测试版",loading:"正在加载{label}…",loadFailed:"无法加载{label}。",manifestHint:"此标签页由 manifest.json 组成——请构建目录树或提供已构建的目录树以加载它。",backToTop:"回到顶部",home:"返回首页",toggleList:"显示或隐藏列表",openViews:"打开视图列表",expandList:"展开列表",collapseList:"折叠列表",collapse:"折叠"}},wn=Object.keys(yo);function Mc(e,t,o){let s=(yo[e]||yo.en)[t]??yo.en[t]??t;if(o)for(const r in o)s=s.split("{"+r+"}").join(String(o[r]));return s}const Lc=[{key:"posters",i18n:"sec.posters",icon:"poster"},{key:"experimental",i18n:"sec.experimental",icon:"flask",folder:!0,open:!1}],Or=[{id:"upg-100",section:"posters",icon:"list",bundle:"my-upg-100-list",profile:"upg-100-mfe"},{id:"country-posters",section:"posters",icon:"map",bundle:"country-posters",profile:"country-posters-mfe"},{id:"poster-design",section:"posters",icon:"poster",bundle:"poster-design",profile:"poster-design-mfe"},{id:"wall-of-people-groups",section:"experimental",icon:"flask",bundle:"wall-of-people-groups",profile:"wall-of-people-groups"},{id:"bible-posters",section:"experimental",icon:"flask",bundle:"bible-posters",profile:"bible-posters",provisional:!0}],Oc=new Set(["key-cities","posterverse","doxa-maps-spa","plugin-studio"]),Pc=new Set(["my-upg-100-list-map","country-posters-map"]);function Ac(e,t=()=>{}){const o=e&&Array.isArray(e.bundles)?e.bundles:[],n=Object.fromEntries(o.map(r=>[r&&r.bundle,r])),s=[];for(const r of Or){if(Oc.has(r.bundle))continue;const a=n[r.bundle];if(!a)continue;const i=Array.isArray(a.profiles)?a.profiles:[];let l=i.find(h=>h&&h.profile===r.profile);if(!l){if(l=i.find(h=>h&&h.profile===r.bundle)||i[0],!l)continue;t(`[posterverse] ${r.bundle} has no profile "${r.profile}"; row "${r.id}" opens "${l.profile}" instead`)}const p=l.element||Array.isArray(a.elements)&&a.elements[0]||r.bundle,d=a.scriptUrl||l.scriptUrl||"";d&&s.push({...r,tag:p,scriptUrl:d,profile:l.profile,heavy:Pc.has(p)||!!l.isMap})}return s}const Cc=":host{display:block;position:relative;height:var(--posterverse-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}.pv-pane{position:absolute;top:0;right:0;bottom:0;left:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;--profile-min-h: 0}.pv-slot{position:relative;min-height:100%}.pv-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}.pv-hint.err{color:#b3261e}.pv-hint small{color:#6d766e}";function Pr(){try{const e=new URLSearchParams(location.search),t=(e.get("lang")||e.get("locale")||"").split("-")[0].toLowerCase();if(wn.includes(t))return t}catch{}try{const e=(document.documentElement.lang||"").split("-")[0].toLowerCase();if(wn.includes(e))return e}catch{}return""}const Ar=e=>({...e,tag:e.tag||"",scriptUrl:e.scriptUrl||"",heavy:!!e.heavy,mounted:!1,state:"idle",error:""}),Fc=Yo({name:"Posterverse",inheritAttrs:!1,components:{VerticalTabsLayout:Sc,BackToTopButton:_r},props:{treeBase:{type:String,default:""},profileConfig:{type:[String,Object],default:""},heading:{type:String,default:"Posterverse"},tokenUrl:{type:String,default:""},tk:{type:String,default:""},language:{type:String,default:""},apiBaseUrl:{type:String,default:""},provider:{type:String,default:""},tab:{type:String,default:""},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["tab-change"],setup(){return{injectedBase:Tt("pvTreeBase","")}},data(){return{paneEls:{},activeIndex:0,manifestError:"",manifestBase:"",runtime:{},hostLang:Pr(),tabs:Or.filter(e=>!e.provisional).map(Ar)}},computed:{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=String(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":""},headingText(){return String(this.cfg.heading||this.heading||"").trim()||"Posterverse"},effectiveLocale(){return(String(this.language||this.cfg.language||this.cfg.locale||this.cfg.lang||"").trim()||this.hostLang||"en").split("-")[0].toLowerCase()},uiLocale(){return wn.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","home"])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:""},activePaneEl(){return this.paneEls[this.activeIndex]||null},navGroups(){return Lc.map(e=>({key:e.key,label:this.tr(e.i18n),icon:e.icon,folder:!!e.folder,open:e.open,rows:this.tabs.filter(t=>t.section===e.key).map(t=>({key:t.id,label:this.tabLabel(t),sub:this.tabSub(t),icon:t.icon,badge:e.folder?this.tr("lab"):void 0}))})).filter(e=>e.rows.length)}},watch:{effectiveLocale(){const e=(o,n)=>{try{const s=this._slots&&this._slots[o];s&&(s.innerHTML="")}catch{}n.mounted=!1,n.state="idle",n.error=""};this.tabs.forEach((o,n)=>{o.mounted&&n!==this.activeIndex&&e(n,o)});const t=this.tabs[this.activeIndex];!t||!t.mounted||(e(this.activeIndex,t),this.mountElement(this.activeIndex))},tab(e){e&&this.onSelect(e)}},mounted(){this.watchHostLang(),this.select(this.initialIndex()),this.loadManifest()},beforeUnmount(){this._langObs&&(this._langObs.disconnect(),this._langObs=null)},methods:{tr(e,t){return Mc(this.uiLocale,e,t)},tabLabel(e){return this.tr("tab."+e.id)},tabSub(e){return e.section==="experimental"?this.tr("experimentalSub"):this.tr("sub."+e.id)},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},watchHostLang(){typeof MutationObserver>"u"||typeof document>"u"||(this._langObs=new MutationObserver(()=>{this.hostLang=Pr()}),this._langObs.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]}))},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.tabs.findIndex(t=>t.id===this.requestedTab());return e>=0?e:0},loadManifest(){const e=p=>{try{return new URL(p,location.href).href.replace(/[^/]*$/,"")}catch{return""}},t=this.resolve("manifest.json"),o={url:t,root:e(t)},n={url:this.resolve("doxa-maps-spa/manifest.json"),root:o.root};let s=!1;try{s=new URL(t,location.href).origin!==location.origin}catch{}const r=s?[n,o]:[o,n],a="/public/dx-maps/manifest.json";r.some(p=>p.url===a)||r.push({url:a,root:e(a)});const i=[],l=p=>{if(p>=r.length){this.manifestError="manifest.json not found (tried "+i.join(", ")+")",console.error("[posterverse] "+this.manifestError+" — every tab is composed from it.");return}const{url:d,root:h}=r[p];return i.push(d),fetch(d,{credentials:"same-origin"}).then(w=>{if(!w||!w.ok)throw new Error(d+" → HTTP "+(w?w.status:"?"));return w.json()}).then(w=>{if(!w)throw new Error(d+" → empty");this.manifestError="",this.manifestBase=h||"",this.applyManifest(w)}).catch(()=>l(p+1))};try{l(0)}catch{}},applyManifest(e){this.runtime=e&&e.runtime&&typeof e.runtime=="object"?e.runtime:{},this.applyPageGlobals();const t=this.activeKey;this.tabs=Ac(e,r=>console.warn(r)).map(Ar);const o=this.requestedTab(),n=!this._honouredTab&&o?this.tabs.findIndex(r=>r.id===o):-1,s=this.tabs.findIndex(r=>r.id===t);this._honouredTab=!0,this.select(n>=0?n:s>=0?s:0)},onSelect(e){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 n=this.tabs[t];n&&n.heavy&&n.mounted&&this.releaseTab(t,n)}const o=this.tabs[e];o&&((t!==e||!this._announced)&&(this._announced=!0,this.$emit("tab-change",{id:o.id,label:this.tabLabel(o)})),o.scriptUrl&&(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:"pv-"+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.mapTitle=this.tabLabel(e),t},applyPageGlobals(){if(typeof window>"u")return;const e=String(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",Lr(this.resolve(t.scriptUrl)).then(()=>Tl(t.tag)).then(()=>{try{if(t.heavy&&this.activeIndex!==e){t.mounted=!1,t.state="idle";return}const o=this._slots&&this._slots[e];if(!o){t.state="error",t.error="no slot";return}o.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="display:block;position:absolute;inset:0;width:100%;height:100%;min-height:0;",o.appendChild(n),t.state="ready"}catch(o){t.state="error",t.error="mount failed: "+(o&&o.message||String(o))}}).catch(o=>{t.state="error",t.error=o&&o.message||String(o)})}}}),Ic=["hidden"],Nc={key:0,class:"pv-hint"},Ec={key:1,class:"pv-hint err"},Rc={key:2,class:"pv-hint err"};function Wc(e,t,o,n,s,r){const a=tn("BackToTopButton"),i=tn("VerticalTabsLayout");return C(),At(i,{dir:e.uiDir,lang:e.uiLocale,labels:e.layoutLabels,title:e.headingText,"nav-label":e.tr("sec.posters"),header:!1,"home-href":e.homeHref||e.cfg.homeHref||"","home-label":e.homeLabel||e.cfg.homeLabel||"",groups:e.navGroups,active:e.activeKey,"onUpdate:active":e.onSelect},{default:ds(()=>[(C(!0),F(oe,null,St(e.tabs,(l,p)=>Jo((C(),F("section",{key:l.id,class:"pv-pane",ref_for:!0,ref:d=>{d?e.paneEls[p]=d:delete e.paneEls[p]},hidden:p!==e.activeIndex},[!l.heavy||p===e.activeIndex?(C(),F(oe,{key:0},[I("div",{class:"pv-slot",ref_for:!0,ref:d=>e.setSlot(p,d)},null,512),l.state==="loading"?(C(),F("div",Nc,D(e.tr("loading",{label:e.tabLabel(l)})),1)):l.state==="error"?(C(),F("div",Ec,[ht(D(e.tr("loadFailed",{label:e.tabLabel(l)})),1),t[0]||(t[0]=I("br",null,null,-1)),I("small",null,D(l.error),1)])):l.state==="idle"&&!l.scriptUrl&&e.manifestError?(C(),F("div",Rc,[ht(D(e.tr("loadFailed",{label:e.tabLabel(l)})),1),t[1]||(t[1]=I("br",null,null,-1)),I("small",null,D(e.manifestError),1),t[2]||(t[2]=I("br",null,null,-1)),I("small",null,D(e.tr("manifestHint")),1)])):le("",!0)],64)):le("",!0)],8,Ic)),[[gn,p===e.activeIndex]])),128)),be(a,{target:e.activePaneEl,labels:{backToTop:e.tr("backToTop")}},null,8,["target","labels"])]),_:1},8,["dir","lang","labels","title","nav-label","home-href","home-label","groups","active","onUpdate:active"])}const Dc=_n(Fc,[["render",Wc],["styles",[Cc]]]),zc=kl(),Hc=nl(Dc,{configureApp(e){e.provide("pvTreeBase",zc)}});typeof customElements<"u"&&!customElements.get("posterverse-app")&&customElements.define("posterverse-app",Hc)})(); +`,Al=Yo({name:"VerticalTabsLayout",components:{BackToTopButton:_r},props:{active:{type:String,default:""},title:{type:String,default:""},items:{type:Array,default:()=>[]},groups:{type:Array,default:()=>[]},navLabel:{type:String,default:"Sections"},labels:{type:Object,default:()=>({})},initialNavOpen:{type:Boolean,default:!0},header:{type:Boolean,default:!0},initialRailCollapsed:{type:Boolean,default:!1},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["update:active"],setup(){return _l(Pl,"vertical-tabs-layout"),{T:Ml}},data(){return{navOpen:this.initialNavOpen,railCollapsed:this.initialRailCollapsed,_tabEls:{},folderOverride:{},narrow:!1,_mql:null,_onMedia:null,activatedKeys:{},hostState:{},hostError:{},_hostSlots:{},_hostMounted:{},hostEls:{}}},computed:{fabShown(){return this.narrow&&!this.header&&!this.navOpen},activeHostEl(){return this.hostEls[this.active]||null},railShown(){return this.narrow?this.navOpen:!0},homeLink(){const e=String(this.homeHref||"").trim();return!e||/^(javascript|data|vbscript):/i.test(e.replace(/[\u0000- ]/g,""))?"":e},homeText(){return this.homeLabel||this.label("home")},allRows(){if(this.groups&&this.groups.length){const e=[];for(const t of this.groups)for(const o of t.rows||[])e.push(o);return e}return this.items},orderedKeys(){return this.allRows.map(e=>e.key)},elementRows(){return this.allRows.filter(e=>e&&e.element)},mountedElementRows(){return this.elementRows.filter(e=>this.activatedKeys[e.key])}},watch:{active:{immediate:!0,handler(e){this.activateElement(e)}}},mounted(){try{window.matchMedia&&(this._mql=window.matchMedia("(max-width: 760px)"),this.narrow=this._mql.matches,this.reconcileForWidth(),this._onMedia=e=>{this.narrow=e.matches,this.reconcileForWidth()},this._mql.addEventListener?this._mql.addEventListener("change",this._onMedia):this._mql.addListener&&this._mql.addListener(this._onMedia))}catch{}this.$nextTick(()=>this.activateElement(this.active))},beforeUnmount(){try{this._mql&&this._onMedia&&(this._mql.removeEventListener?this._mql.removeEventListener("change",this._onMedia):this._mql.removeListener&&this._mql.removeListener(this._onMedia))}catch{}this._mql=null,this._onMedia=null},methods:{registerTab(e,t){t&&(this._tabEls[e]=t)},isNarrow(){return this.narrow},reconcileForWidth(){this.narrow?(this.navOpen=!1,this.railCollapsed=!1):this.navOpen=!0},label(e){const t={toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse",home:"Back to homepage"};return this.labels&&this.labels[e]||t[e]},expandRail(){!this.narrow&&this.railCollapsed&&(this.railCollapsed=!1)},toggleRail(){this.narrow?this.navOpen=!this.navOpen:this.railCollapsed=!this.railCollapsed},setHostSlot(e,t){t&&(this._hostSlots[e]=t,this.$nextTick(()=>this.mountHostElement(e)))},activateElement(e){!e||!this.elementRows.find(o=>o.key===e)||(this.activatedKeys[e]||(this.activatedKeys={...this.activatedKeys,[e]:!0},this.$nextTick(()=>this.watchContextLoss(e)),this.hostState={...this.hostState,[e]:"loading"}),this.$nextTick(()=>this.mountHostElement(e)))},deepCanvases(e,t=[]){if(!e)return t;for(const o of e.querySelectorAll("*"))o.tagName==="CANVAS"&&t.push(o),o.shadowRoot&&this.deepCanvases(o.shadowRoot,t);return t},watchContextLoss(e){const t=this._hostSlots[e];if(t)for(const o of this.deepCanvases(t))o.__vtlLossBound||(o.__vtlLossBound=!0,o.addEventListener("webglcontextlost",()=>{this.hostState={...this.hostState,[e]:"lost"}},{once:!0}))},reloadHostElement(e){const t=this._hostSlots[e];t&&(t.innerHTML=""),this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"loading"},this.$nextTick(()=>this.mountHostElement(e))},mountHostElement(e){if(this._hostMounted[e])return;const t=this.elementRows.find(n=>n.key===e),o=this._hostSlots[e];!t||!o||(this._hostMounted[e]=!0,this.hostState={...this.hostState,[e]:"loading"},Ll(t.src).then(()=>Ol(t.element)).then(()=>{xl(t.element,t.src),o.innerHTML="";const n=document.createElement(t.element),s=t.attrs||{};for(const r in s){const a=s[r],i=a!=null&&typeof a=="object"?JSON.stringify(a):String(a);try{n[r]=a}catch{}try{n.setAttribute(r,i)}catch{}}n.style.cssText="display:block;position:absolute;inset:0;width:100%;height:100%;",o.appendChild(n);for(const r of[0,250,1500])setTimeout(()=>this.watchContextLoss(e),r);this.hostState={...this.hostState,[e]:"ready"}}).catch(n=>{this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"error"},this.hostError={...this.hostError,[e]:n&&n.message||String(n)}}))},iconSvg(e){return e?yl(e):""},initial(e){const t=(e||"").trim();return t?t.charAt(0).toUpperCase():"•"},isFolderClosed(e){const t=this.folderOverride[e.key];return t!=null?!t:e.open!==!0},toggleFolder(e){const t=this.folderOverride[e],o=(this.groups||[]).find(s=>s.key===e),n=t??(o&&o.open===!0);this.folderOverride={...this.folderOverride,[e]:!n}},pick(e){this.$emit("update:active",e),this.narrow&&(this.navOpen=!1)},onKey(e){const t=this.orderedKeys;if(!t.length)return;const o=t.indexOf(this.active);let n=-1;if(e.key==="ArrowDown"||e.key==="ArrowRight")n=(o+1)%t.length;else if(e.key==="ArrowUp"||e.key==="ArrowLeft")n=(o-1+t.length)%t.length;else if(e.key==="Home")n=0;else if(e.key==="End")n=t.length-1;else return;e.preventDefault();const s=t[n];this.pick(s),this.$nextTick(()=>{const r=this._tabEls[s];r&&r.focus&&r.focus()})}}}),Cl={key:0,class:"vtl-top"},Fl=["aria-expanded","aria-label"],Il={class:"vtl-brand"},Nl={class:"vtl-title"},El={class:"vtl-meta"},Rl=["aria-expanded","aria-label"],Wl={class:"vtl-body"},Dl=["aria-label","aria-hidden","role","aria-orientation"],zl=["href","aria-label","title"],Hl=["innerHTML"],Bl={class:"vtl-home-tx"},Ul=["aria-expanded","aria-label"],jl=["innerHTML"],Vl={class:"vtl-collapse-tx"},ql=["aria-expanded","onClick"],Kl={key:0,class:"vtl-cap"},Gl={class:"vtl-tl"},Jl={key:1,class:"vtl-td"},Xl=["innerHTML"],Zl={key:1,class:"vtl-tier"},Yl={key:0,class:"vtl-cap"},Ql={class:"vtl-tl"},ec={key:1,class:"vtl-td"},tc={class:"vtl-rows"},oc=["aria-selected","aria-disabled","tabindex","onClick"],nc=["innerHTML"],sc={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},rc={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},ic={class:"vtl-tab-text"},ac={class:"vtl-tab-label"},lc={key:0,class:"vtl-tab-badge"},cc={key:0,class:"vtl-tab-sub"},pc=["innerHTML"],dc=["aria-selected","aria-disabled","tabindex","onClick"],uc=["innerHTML"],fc={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},hc={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},gc={class:"vtl-tab-text"},mc={class:"vtl-tab-label"},$c={key:0,class:"vtl-tab-sub"},bc={class:"vtl-main"},_c={class:"vtl-content"},vc=["hidden"],yc={key:0,class:"vtl-host-hint"},wc={key:1,class:"vtl-host-hint"},xc=["onClick"],Tc={key:2,class:"vtl-host-hint err"};function kc(e,t,o,n,s,r){const a=tn("BackToTopButton");return C(),F("div",{class:Xe(["vtl",{"nav-open":e.navOpen,"rail-collapsed":e.railCollapsed,"no-header":!e.header}]),style:Jt(e.fabShown?{"--map-fab-clearance":"calc(56px + env(safe-area-inset-bottom))","--map-fab-beside":"calc(56px + env(safe-area-inset-left))"}:null)},[e.header?(C(),F("header",Cl,[I("button",{class:"vtl-menu",type:"button","aria-expanded":String(e.navOpen),onClick:t[0]||(t[0]=i=>e.navOpen=!e.navOpen),"aria-label":e.label("toggleList")},"☰",8,Fl),I("span",Il,[Mt(e.$slots,"brand")]),I("b",Nl,D(e.title),1),I("span",El,[Mt(e.$slots,"meta")])])):le("",!0),e.fabShown?(C(),F("button",{key:1,class:"vtl-fab",type:"button","aria-expanded":String(e.navOpen),onClick:t[1]||(t[1]=i=>e.navOpen=!0),"aria-label":e.label("openViews")},"☰",8,Rl)):le("",!0),e.narrow?(C(),At(a,{key:2,target:e.activeHostEl,labels:{backToTop:e.T("actions.backToTop","Back to top")}},null,8,["target","labels"])):le("",!0),I("div",Wl,[I("nav",{class:"vtl-nav","aria-label":e.navLabel,"aria-hidden":String(!e.railShown),role:e.$slots.rail?null:"tablist","aria-orientation":e.$slots.rail?null:"vertical"},[e.homeLink?(C(),F("a",{key:0,class:"vtl-home",href:e.homeLink,target:"_top","aria-label":e.homeText,title:e.railCollapsed&&!e.narrow?e.homeText:null},[I("span",{class:"vtl-home-ic","aria-hidden":"true",innerHTML:e.iconSvg("home")},null,8,Hl),I("span",Bl,D(e.homeText),1)],8,zl)):le("",!0),I("button",{type:"button",class:"vtl-collapse","aria-expanded":String(!e.railCollapsed),"aria-label":e.railCollapsed?e.label("expandList"):e.label("collapseList"),onClick:t[2]||(t[2]=(...i)=>e.toggleRail&&e.toggleRail(...i))},[I("span",{class:"vtl-collapse-ic","aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,8,jl),I("span",Vl,D(e.label("collapse")),1)],8,Ul),e.$slots.rail?Mt(e.$slots,"rail",{collapsed:e.railCollapsed&&!e.narrow,expand:e.expandRail,pick:e.pick},void 0,void 0,1):e.groups&&e.groups.length?(C(!0),F(oe,{key:2},St(e.groups,i=>(C(),F("div",{class:"vtl-grp",key:i.key},[i.folder?(C(),F("button",{key:0,type:"button",class:"vtl-tier vtl-tier-btn","aria-expanded":String(!e.isFolderClosed(i)),onClick:l=>e.toggleFolder(i.key)},[i.badge?(C(),F("span",Kl,D(i.badge),1)):le("",!0),I("span",Gl,D(i.label),1),i.count!=null?(C(),F("span",Jl,D(i.count),1)):le("",!0),I("span",{class:Xe(["vtl-chev",{open:!e.isFolderClosed(i)}]),"aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,10,Xl)],8,ql)):(C(),F("div",Zl,[i.badge?(C(),F("span",Yl,D(i.badge),1)):le("",!0),I("span",Ql,D(i.label),1),i.count!=null?(C(),F("span",ec,D(i.count),1)):le("",!0)])),Jo(I("div",tc,[(C(!0),F(oe,null,St(i.rows,l=>(C(),F("button",{key:l.key,type:"button",role:"tab",class:Xe(["vtl-tab",{active:l.key===e.active,disabled:l.disabled}]),"aria-selected":String(l.key===e.active),"aria-disabled":l.disabled?"true":null,tabindex:l.key===e.active?0:-1,ref_for:!0,ref:p=>e.registerTab(l.key,p),onClick:p=>e.pick(l.key),onKeydown:t[3]||(t[3]=p=>e.onKey(p))},[l.icon?(C(),F("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(l.icon)},null,8,nc)):l.emoji?(C(),F("span",sc,D(l.emoji),1)):(C(),F("span",rc,D(e.initial(l.label)),1)),I("span",ic,[I("span",ac,[ht(D(l.label),1),l.badge?(C(),F("span",lc,D(l.badge),1)):le("",!0)]),l.sub?(C(),F("span",cc,[I("span",{innerHTML:l.sub},null,8,pc)])):le("",!0)])],42,oc))),128))],512),[[gn,!i.folder||!e.isFolderClosed(i)]])]))),128)):(C(!0),F(oe,{key:3},St(e.items,i=>(C(),F("button",{key:i.key,type:"button",role:"tab",class:Xe(["vtl-tab",{active:i.key===e.active,disabled:i.disabled}]),"aria-selected":String(i.key===e.active),"aria-disabled":i.disabled?"true":null,tabindex:i.key===e.active?0:-1,ref_for:!0,ref:l=>e.registerTab(i.key,l),onClick:l=>e.pick(i.key),onKeydown:t[4]||(t[4]=l=>e.onKey(l))},[i.icon?(C(),F("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(i.icon)},null,8,uc)):i.emoji?(C(),F("span",fc,D(i.emoji),1)):(C(),F("span",hc,D(e.initial(i.label)),1)),I("span",gc,[I("span",mc,D(i.label),1),i.sub?(C(),F("span",$c,D(i.sub),1)):le("",!0)])],42,dc))),128))],8,Dl),I("main",bc,[e.header?Mt(e.$slots,"toolbar",{},void 0,void 0,0):le("",!0),I("div",_c,[(C(!0),F(oe,null,St(e.mountedElementRows,i=>Jo((C(),F("section",{key:i.key,class:"vtl-host",hidden:i.key!==e.active,ref_for:!0,ref:l=>{l?e.hostEls[i.key]=l:delete e.hostEls[i.key]}},[I("div",{class:"vtl-host-slot",ref_for:!0,ref:l=>e.setHostSlot(i.key,l)},null,512),e.hostState[i.key]==="loading"?(C(),F("div",yc,D(e.T("messages.loadingNamed","Loading {name}…").replace("{name}",i.label)),1)):e.hostState[i.key]==="lost"?(C(),F("div",wc,[ht(D(e.T("messages.mapContextLost","This map was unloaded to free graphics memory."))+" ",1),I("button",{type:"button",class:"vtl-host-reload",onClick:l=>e.reloadHostElement(i.key)},D(e.T("buttons.reloadMap","Reload Map")),9,xc)])):e.hostState[i.key]==="error"?(C(),F("div",Tc,[ht(D(e.T("messages.couldNotLoadNamed","Could not load {name}.").replace("{name}",i.label)),1),t[5]||(t[5]=I("br",null,null,-1)),I("small",null,D(e.hostError[i.key]),1)])):le("",!0)],8,vc)),[[gn,i.key===e.active]])),128)),Mt(e.$slots,"default")])])])],6)}const Sc=_n(Al,[["render",kc],["styles",[Sl]]]),yo={en:{"sec.posters":"Posters","sec.experimental":"Experimental","tab.upg-100":"UPG 100 List Posters","sub.upg-100":"my unreached list + posters","tab.country-posters":"Country Posters","sub.country-posters":"a poster for every country","tab.poster-design":"Poster Design","sub.poster-design":"every poster style and size","tab.wall-of-people-groups":"Wall of People Groups","tab.bible-posters":"Bible Posters",experimentalSub:"experimental bundle",lab:"lab",loading:"Loading {label}…",loadFailed:"Could not load {label}.",manifestHint:"This tab is composed from manifest.json — build the tree, or serve the built tree, to load it.",backToTop:"Back to top",home:"Back to homepage",toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse"},es:{"sec.posters":"Carteles","sec.experimental":"Experimental","tab.upg-100":"Carteles de la lista UPG 100","sub.upg-100":"mi lista de no alcanzados + carteles","tab.country-posters":"Carteles por país","sub.country-posters":"un cartel para cada país","tab.poster-design":"Diseño de carteles","sub.poster-design":"todos los estilos y tamaños de cartel","tab.wall-of-people-groups":"Muro de los pueblos","tab.bible-posters":"Carteles bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Cargando {label}…",loadFailed:"No se pudo cargar {label}.",manifestHint:"Esta pestaña se compone a partir de manifest.json: compila el árbol o sirve el árbol compilado para cargarla.",backToTop:"Volver arriba",home:"Volver a la página de inicio",toggleList:"Mostrar u ocultar la lista",openViews:"Abrir la lista de vistas",expandList:"Expandir la lista",collapseList:"Contraer la lista",collapse:"Contraer"},fr:{"sec.posters":"Affiches","sec.experimental":"Expérimental","tab.upg-100":"Affiches de la liste UPG 100","sub.upg-100":"ma liste des non atteints + affiches","tab.country-posters":"Affiches par pays","sub.country-posters":"une affiche pour chaque pays","tab.poster-design":"Conception d’affiches","sub.poster-design":"tous les styles et formats d’affiche","tab.wall-of-people-groups":"Mur des peuples","tab.bible-posters":"Affiches bibliques",experimentalSub:"carte expérimentale",lab:"bêta",loading:"Chargement de {label}…",loadFailed:"Impossible de charger {label}.",manifestHint:"Cet onglet est composé à partir de manifest.json : construisez l'arborescence ou servez l'arborescence construite pour le charger.",backToTop:"Retour en haut",home:"Retour à l’accueil",toggleList:"Afficher ou masquer la liste",openViews:"Ouvrir la liste des vues",expandList:"Déplier la liste",collapseList:"Replier la liste",collapse:"Replier"},de:{"sec.posters":"Poster","sec.experimental":"Experimentell","tab.upg-100":"Poster der UPG 100 Liste","sub.upg-100":"meine Liste der Unerreichten + Poster","tab.country-posters":"Länderposter","sub.country-posters":"ein Poster für jedes Land","tab.poster-design":"Postergestaltung","sub.poster-design":"alle Posterstile und -größen","tab.wall-of-people-groups":"Wand der Volksgruppen","tab.bible-posters":"Bibelposter",experimentalSub:"experimentelle Karte",lab:"Beta",loading:"{label} wird geladen…",loadFailed:"{label} konnte nicht geladen werden.",manifestHint:"Dieser Tab wird aus manifest.json zusammengesetzt – bauen Sie den Baum oder stellen Sie den gebauten Baum bereit, um ihn zu laden.",backToTop:"Nach oben",home:"Zurück zur Startseite",toggleList:"Liste ein-/ausblenden",openViews:"Ansichtsliste öffnen",expandList:"Liste ausklappen",collapseList:"Liste einklappen",collapse:"Einklappen"},pt:{"sec.posters":"Cartazes","sec.experimental":"Experimental","tab.upg-100":"Cartazes da lista UPG 100","sub.upg-100":"minha lista de não alcançados + cartazes","tab.country-posters":"Cartazes por país","sub.country-posters":"um cartaz para cada país","tab.poster-design":"Design de cartazes","sub.poster-design":"todos os estilos e tamanhos de cartaz","tab.wall-of-people-groups":"Mural dos povos","tab.bible-posters":"Cartazes bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Carregando {label}…",loadFailed:"Não foi possível carregar {label}.",manifestHint:"Esta aba é composta a partir do manifest.json — compile a árvore ou sirva a árvore compilada para carregá-la.",backToTop:"Voltar ao topo",home:"Voltar à página inicial",toggleList:"Mostrar ou ocultar a lista",openViews:"Abrir a lista de visualizações",expandList:"Expandir a lista",collapseList:"Recolher a lista",collapse:"Recolher"},it:{"sec.posters":"Poster","sec.experimental":"Sperimentale","tab.upg-100":"Poster della lista UPG 100","sub.upg-100":"la mia lista dei non raggiunti + poster","tab.country-posters":"Poster per paese","sub.country-posters":"un poster per ogni paese","tab.poster-design":"Design dei poster","sub.poster-design":"tutti gli stili e i formati dei poster","tab.wall-of-people-groups":"Muro dei popoli","tab.bible-posters":"Poster biblici",experimentalSub:"mappa sperimentale",lab:"beta",loading:"Caricamento di {label}…",loadFailed:"Impossibile caricare {label}.",manifestHint:"Questa scheda è composta da manifest.json: compila l'albero o pubblica l'albero compilato per caricarla.",backToTop:"Torna su",home:"Torna alla home page",toggleList:"Mostra o nascondi l’elenco",openViews:"Apri l’elenco delle viste",expandList:"Espandi l’elenco",collapseList:"Comprimi l’elenco",collapse:"Comprimi"},ro:{"sec.posters":"Afișe","sec.experimental":"Experimental","tab.upg-100":"Afișe din lista UPG 100","sub.upg-100":"lista mea de neatinși + afișe","tab.country-posters":"Afișe pe țări","sub.country-posters":"un afiș pentru fiecare țară","tab.poster-design":"Design de afișe","sub.poster-design":"toate stilurile și dimensiunile de afiș","tab.wall-of-people-groups":"Zidul popoarelor","tab.bible-posters":"Afișe biblice",experimentalSub:"hartă experimentală",lab:"beta",loading:"Se încarcă {label}…",loadFailed:"{label} nu a putut fi încărcat.",manifestHint:"Această filă este compusă din manifest.json — construiți arborele sau serviți arborele construit pentru a o încărca.",backToTop:"Sus",home:"Înapoi la pagina principală",toggleList:"Afișează sau ascunde lista",openViews:"Deschide lista de vizualizări",expandList:"Extinde lista",collapseList:"Restrânge lista",collapse:"Restrânge"},ru:{"sec.posters":"Плакаты","sec.experimental":"Экспериментальное","tab.upg-100":"Плакаты списка UPG 100","sub.upg-100":"мой список недостигнутых + плакаты","tab.country-posters":"Плакаты по странам","sub.country-posters":"плакат для каждой страны","tab.poster-design":"Дизайн плакатов","sub.poster-design":"все стили и размеры плакатов","tab.wall-of-people-groups":"Стена народов","tab.bible-posters":"Библейские плакаты",experimentalSub:"экспериментальная карта",lab:"бета",loading:"Загрузка: {label}…",loadFailed:"Не удалось загрузить: {label}.",manifestHint:"Эта вкладка собирается из manifest.json — соберите дерево или разместите собранное дерево, чтобы загрузить её.",backToTop:"Наверх",home:"На главную страницу",toggleList:"Показать или скрыть список",openViews:"Открыть список представлений",expandList:"Развернуть список",collapseList:"Свернуть список",collapse:"Свернуть"},ar:{"sec.posters":"ملصقات","sec.experimental":"تجريبي","tab.upg-100":"ملصقات قائمة UPG 100","sub.upg-100":"قائمتي لغير المُبشَّرين + ملصقات","tab.country-posters":"ملصقات الدول","sub.country-posters":"ملصق لكل دولة","tab.poster-design":"تصميم الملصقات","sub.poster-design":"كل أنماط الملصقات وأحجامها","tab.wall-of-people-groups":"جدار الشعوب","tab.bible-posters":"ملصقات الكتاب المقدس",experimentalSub:"خريطة تجريبية",lab:"تجريبي",loading:"جارٍ تحميل {label}…",loadFailed:"تعذّر تحميل {label}.",manifestHint:"تُبنى علامة التبويب هذه من manifest.json — ابنِ الشجرة أو قدّم الشجرة المبنية لتحميلها.",backToTop:"إلى الأعلى",home:"العودة إلى الصفحة الرئيسية",toggleList:"إظهار القائمة أو إخفاؤها",openViews:"فتح قائمة العروض",expandList:"توسيع القائمة",collapseList:"طي القائمة",collapse:"طي"},hi:{"sec.posters":"पोस्टर","sec.experimental":"प्रायोगिक","tab.upg-100":"UPG 100 सूची पोस्टर","sub.upg-100":"मेरी अप्राप्त सूची + पोस्टर","tab.country-posters":"देश पोस्टर","sub.country-posters":"हर देश के लिए एक पोस्टर","tab.poster-design":"पोस्टर डिज़ाइन","sub.poster-design":"हर पोस्टर शैली और आकार","tab.wall-of-people-groups":"जनसमूहों की दीवार","tab.bible-posters":"बाइबल पोस्टर",experimentalSub:"प्रायोगिक मानचित्र",lab:"बीटा",loading:"{label} लोड हो रहा है…",loadFailed:"{label} लोड नहीं हो सका।",manifestHint:"यह टैब manifest.json से बनता है — इसे लोड करने के लिए ट्री बनाएँ या बना हुआ ट्री सर्व करें।",backToTop:"ऊपर जाएँ",home:"होमपेज पर वापस जाएँ",toggleList:"सूची दिखाएँ या छिपाएँ",openViews:"दृश्यों की सूची खोलें",expandList:"सूची फैलाएँ",collapseList:"सूची संक्षिप्त करें",collapse:"संक्षिप्त करें"},zh:{"sec.posters":"海报","sec.experimental":"实验性","tab.upg-100":"UPG 100 名单海报","sub.upg-100":"我的未得之民名单 + 海报","tab.country-posters":"国家海报","sub.country-posters":"每个国家一张海报","tab.poster-design":"海报设计","sub.poster-design":"所有海报样式与尺寸","tab.wall-of-people-groups":"民族之墙","tab.bible-posters":"圣经海报",experimentalSub:"实验性地图",lab:"测试版",loading:"正在加载{label}…",loadFailed:"无法加载{label}。",manifestHint:"此标签页由 manifest.json 组成——请构建目录树或提供已构建的目录树以加载它。",backToTop:"回到顶部",home:"返回首页",toggleList:"显示或隐藏列表",openViews:"打开视图列表",expandList:"展开列表",collapseList:"折叠列表",collapse:"折叠"}},wn=Object.keys(yo);function Mc(e,t,o){let s=(yo[e]||yo.en)[t]??yo.en[t]??t;if(o)for(const r in o)s=s.split("{"+r+"}").join(String(o[r]));return s}const Lc=[{key:"posters",i18n:"sec.posters",icon:"poster"},{key:"experimental",i18n:"sec.experimental",icon:"flask",folder:!0,open:!1}],Or=[{id:"upg-100",section:"posters",icon:"list",bundle:"my-upg-100-list",profile:"upg-100-mfe"},{id:"country-posters",section:"posters",icon:"map",bundle:"country-posters",profile:"country-posters-mfe"},{id:"poster-design",section:"posters",icon:"poster",bundle:"poster-design",profile:"poster-design-mfe"},{id:"wall-of-people-groups",section:"experimental",icon:"flask",bundle:"wall-of-people-groups",profile:"wall-of-people-groups"},{id:"bible-posters",section:"experimental",icon:"flask",bundle:"bible-posters",profile:"bible-posters"}],Oc=new Set(["key-cities","posterverse","doxa-maps-spa","plugin-studio"]),Pc=new Set(["my-upg-100-list-map","country-posters-map"]);function Ac(e,t=()=>{}){const o=e&&Array.isArray(e.bundles)?e.bundles:[],n=Object.fromEntries(o.map(r=>[r&&r.bundle,r])),s=[];for(const r of Or){if(Oc.has(r.bundle))continue;const a=n[r.bundle];if(!a)continue;const i=Array.isArray(a.profiles)?a.profiles:[];let l=i.find(h=>h&&h.profile===r.profile);if(!l){if(l=i.find(h=>h&&h.profile===r.bundle)||i[0],!l)continue;t(`[posterverse] ${r.bundle} has no profile "${r.profile}"; row "${r.id}" opens "${l.profile}" instead`)}const p=l.element||Array.isArray(a.elements)&&a.elements[0]||r.bundle,d=a.scriptUrl||l.scriptUrl||"";d&&s.push({...r,tag:p,scriptUrl:d,profile:l.profile,heavy:Pc.has(p)||!!l.isMap})}return s}const Cc=":host{display:block;position:relative;height:var(--posterverse-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}.pv-pane{position:absolute;top:0;right:0;bottom:0;left:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;--profile-min-h: 0}.pv-slot{position:relative;min-height:100%}.pv-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}.pv-hint.err{color:#b3261e}.pv-hint small{color:#6d766e}";function Pr(){try{const e=new URLSearchParams(location.search),t=(e.get("lang")||e.get("locale")||"").split("-")[0].toLowerCase();if(wn.includes(t))return t}catch{}try{const e=(document.documentElement.lang||"").split("-")[0].toLowerCase();if(wn.includes(e))return e}catch{}return""}const Ar=e=>({...e,tag:e.tag||"",scriptUrl:e.scriptUrl||"",heavy:!!e.heavy,mounted:!1,state:"idle",error:""}),Fc=Yo({name:"Posterverse",inheritAttrs:!1,components:{VerticalTabsLayout:Sc,BackToTopButton:_r},props:{treeBase:{type:String,default:""},profileConfig:{type:[String,Object],default:""},heading:{type:String,default:"Posterverse"},tokenUrl:{type:String,default:""},tk:{type:String,default:""},language:{type:String,default:""},apiBaseUrl:{type:String,default:""},provider:{type:String,default:""},tab:{type:String,default:""},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["tab-change"],setup(){return{injectedBase:Tt("pvTreeBase","")}},data(){return{paneEls:{},activeIndex:0,manifestError:"",manifestBase:"",runtime:{},hostLang:Pr(),tabs:Or.filter(e=>!e.provisional).map(Ar)}},computed:{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=String(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":""},headingText(){return String(this.cfg.heading||this.heading||"").trim()||"Posterverse"},effectiveLocale(){return(String(this.language||this.cfg.language||this.cfg.locale||this.cfg.lang||"").trim()||this.hostLang||"en").split("-")[0].toLowerCase()},uiLocale(){return wn.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","home"])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:""},activePaneEl(){return this.paneEls[this.activeIndex]||null},navGroups(){return Lc.map(e=>({key:e.key,label:this.tr(e.i18n),icon:e.icon,folder:!!e.folder,open:e.open,rows:this.tabs.filter(t=>t.section===e.key).map(t=>({key:t.id,label:this.tabLabel(t),sub:this.tabSub(t),icon:t.icon,badge:e.folder?this.tr("lab"):void 0}))})).filter(e=>e.rows.length)}},watch:{effectiveLocale(){const e=(o,n)=>{try{const s=this._slots&&this._slots[o];s&&(s.innerHTML="")}catch{}n.mounted=!1,n.state="idle",n.error=""};this.tabs.forEach((o,n)=>{o.mounted&&n!==this.activeIndex&&e(n,o)});const t=this.tabs[this.activeIndex];!t||!t.mounted||(e(this.activeIndex,t),this.mountElement(this.activeIndex))},tab(e){e&&this.onSelect(e)}},mounted(){this.watchHostLang(),this.select(this.initialIndex()),this.loadManifest()},beforeUnmount(){this._langObs&&(this._langObs.disconnect(),this._langObs=null)},methods:{tr(e,t){return Mc(this.uiLocale,e,t)},tabLabel(e){return this.tr("tab."+e.id)},tabSub(e){return e.section==="experimental"?this.tr("experimentalSub"):this.tr("sub."+e.id)},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},watchHostLang(){typeof MutationObserver>"u"||typeof document>"u"||(this._langObs=new MutationObserver(()=>{this.hostLang=Pr()}),this._langObs.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]}))},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.tabs.findIndex(t=>t.id===this.requestedTab());return e>=0?e:0},loadManifest(){const e=p=>{try{return new URL(p,location.href).href.replace(/[^/]*$/,"")}catch{return""}},t=this.resolve("manifest.json"),o={url:t,root:e(t)},n={url:this.resolve("doxa-maps-spa/manifest.json"),root:o.root};let s=!1;try{s=new URL(t,location.href).origin!==location.origin}catch{}const r=s?[n,o]:[o,n],a="/public/dx-maps/manifest.json";r.some(p=>p.url===a)||r.push({url:a,root:e(a)});const i=[],l=p=>{if(p>=r.length){this.manifestError="manifest.json not found (tried "+i.join(", ")+")",console.error("[posterverse] "+this.manifestError+" — every tab is composed from it.");return}const{url:d,root:h}=r[p];return i.push(d),fetch(d,{credentials:"same-origin"}).then(w=>{if(!w||!w.ok)throw new Error(d+" → HTTP "+(w?w.status:"?"));return w.json()}).then(w=>{if(!w)throw new Error(d+" → empty");this.manifestError="",this.manifestBase=h||"",this.applyManifest(w)}).catch(()=>l(p+1))};try{l(0)}catch{}},applyManifest(e){this.runtime=e&&e.runtime&&typeof e.runtime=="object"?e.runtime:{},this.applyPageGlobals();const t=this.activeKey;this.tabs=Ac(e,r=>console.warn(r)).map(Ar);const o=this.requestedTab(),n=!this._honouredTab&&o?this.tabs.findIndex(r=>r.id===o):-1,s=this.tabs.findIndex(r=>r.id===t);this._honouredTab=!0,this.select(n>=0?n:s>=0?s:0)},onSelect(e){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 n=this.tabs[t];n&&n.heavy&&n.mounted&&this.releaseTab(t,n)}const o=this.tabs[e];o&&((t!==e||!this._announced)&&(this._announced=!0,this.$emit("tab-change",{id:o.id,label:this.tabLabel(o)})),o.scriptUrl&&(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:"pv-"+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.mapTitle=this.tabLabel(e),t},applyPageGlobals(){if(typeof window>"u")return;const e=String(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",Lr(this.resolve(t.scriptUrl)).then(()=>Tl(t.tag)).then(()=>{try{if(t.heavy&&this.activeIndex!==e){t.mounted=!1,t.state="idle";return}const o=this._slots&&this._slots[e];if(!o){t.state="error",t.error="no slot";return}o.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="display:block;position:absolute;inset:0;width:100%;height:100%;min-height:0;",o.appendChild(n),t.state="ready"}catch(o){t.state="error",t.error="mount failed: "+(o&&o.message||String(o))}}).catch(o=>{t.state="error",t.error=o&&o.message||String(o)})}}}),Ic=["hidden"],Nc={key:0,class:"pv-hint"},Ec={key:1,class:"pv-hint err"},Rc={key:2,class:"pv-hint err"};function Wc(e,t,o,n,s,r){const a=tn("BackToTopButton"),i=tn("VerticalTabsLayout");return C(),At(i,{dir:e.uiDir,lang:e.uiLocale,labels:e.layoutLabels,title:e.headingText,"nav-label":e.tr("sec.posters"),header:!1,"home-href":e.homeHref||e.cfg.homeHref||"","home-label":e.homeLabel||e.cfg.homeLabel||"",groups:e.navGroups,active:e.activeKey,"onUpdate:active":e.onSelect},{default:ds(()=>[(C(!0),F(oe,null,St(e.tabs,(l,p)=>Jo((C(),F("section",{key:l.id,class:"pv-pane",ref_for:!0,ref:d=>{d?e.paneEls[p]=d:delete e.paneEls[p]},hidden:p!==e.activeIndex},[!l.heavy||p===e.activeIndex?(C(),F(oe,{key:0},[I("div",{class:"pv-slot",ref_for:!0,ref:d=>e.setSlot(p,d)},null,512),l.state==="loading"?(C(),F("div",Nc,D(e.tr("loading",{label:e.tabLabel(l)})),1)):l.state==="error"?(C(),F("div",Ec,[ht(D(e.tr("loadFailed",{label:e.tabLabel(l)})),1),t[0]||(t[0]=I("br",null,null,-1)),I("small",null,D(l.error),1)])):l.state==="idle"&&!l.scriptUrl&&e.manifestError?(C(),F("div",Rc,[ht(D(e.tr("loadFailed",{label:e.tabLabel(l)})),1),t[1]||(t[1]=I("br",null,null,-1)),I("small",null,D(e.manifestError),1),t[2]||(t[2]=I("br",null,null,-1)),I("small",null,D(e.tr("manifestHint")),1)])):le("",!0)],64)):le("",!0)],8,Ic)),[[gn,p===e.activeIndex]])),128)),be(a,{target:e.activePaneEl,labels:{backToTop:e.tr("backToTop")}},null,8,["target","labels"])]),_:1},8,["dir","lang","labels","title","nav-label","home-href","home-label","groups","active","onUpdate:active"])}const Dc=_n(Fc,[["render",Wc],["styles",[Cc]]]),zc=kl(),Hc=nl(Dc,{configureApp(e){e.provide("pvTreeBase",zc)}});typeof customElements<"u"&&!customElements.get("posterverse-app")&&customElements.define("posterverse-app",Hc)})(); From 5c44b3cdcd1038b050318b60b113581860e2ed02 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Wed, 30 Sep 2026 22:55:25 +0000 Subject: [PATCH 04/11] Add Bible Posters plugin: a whole book of the Bible on one poster A new experimental generator (Posterverse) that renders an ENTIRE BOOK of the Bible in justified, phone-width columns with a bold book-name header, in the languages of the unreached people groups. Text is fetched at render time from public-domain translations via the Free Use Bible API; no Bibles are stored in the repo or public/. v1 offers strict public-domain texts only, with a per-poster credit line: the World English Bible plus the prayer packet's Reina-Valera 1909, Ostervald, Luther 1912, Synodal and Van Dyck (Arabic, right-to-left). Book, text-language and size pickers; the generator reports which size fits a book at a readable type size, and standard paper is honestly shown as too small for a whole book. Interface strings are localized in all 11 locales. Starts from the 12 books the UPG-100 packet cites. --- library/i18n/locales/ar/biblePosters.json | 27 +++ library/i18n/locales/de/biblePosters.json | 27 +++ library/i18n/locales/en/biblePosters.json | 27 +++ library/i18n/locales/es/biblePosters.json | 27 +++ library/i18n/locales/fr/biblePosters.json | 27 +++ library/i18n/locales/hi/biblePosters.json | 27 +++ library/i18n/locales/it/biblePosters.json | 27 +++ library/i18n/locales/pt/biblePosters.json | 27 +++ library/i18n/locales/ro/biblePosters.json | 27 +++ library/i18n/locales/ru/biblePosters.json | 27 +++ library/i18n/locales/zh/biblePosters.json | 27 +++ .../bible-posters/bible-posters.meta.json | 7 + .../bible-posters/bible-posters.vue | 193 ++++++++++++++++++ plugin-designs/bible-posters/index.html | 30 +++ plugin-designs/bible-posters/index.js | 31 +++ .../bible-posters/src/biblePoster.js | 155 ++++++++++++++ .../bible-posters/src/bibleSource.js | 105 ++++++++++ plugin-designs/bible-posters/src/books.js | 39 ++++ plugin-designs/bible-posters/src/sizes.js | 28 +++ .../bible-posters/src/translations.js | 64 ++++++ 20 files changed, 949 insertions(+) create mode 100644 library/i18n/locales/ar/biblePosters.json create mode 100644 library/i18n/locales/de/biblePosters.json create mode 100644 library/i18n/locales/en/biblePosters.json create mode 100644 library/i18n/locales/es/biblePosters.json create mode 100644 library/i18n/locales/fr/biblePosters.json create mode 100644 library/i18n/locales/hi/biblePosters.json create mode 100644 library/i18n/locales/it/biblePosters.json create mode 100644 library/i18n/locales/pt/biblePosters.json create mode 100644 library/i18n/locales/ro/biblePosters.json create mode 100644 library/i18n/locales/ru/biblePosters.json create mode 100644 library/i18n/locales/zh/biblePosters.json create mode 100644 plugin-designs/bible-posters/bible-posters.meta.json create mode 100644 plugin-designs/bible-posters/bible-posters.vue create mode 100644 plugin-designs/bible-posters/index.html create mode 100644 plugin-designs/bible-posters/index.js create mode 100644 plugin-designs/bible-posters/src/biblePoster.js create mode 100644 plugin-designs/bible-posters/src/bibleSource.js create mode 100644 plugin-designs/bible-posters/src/books.js create mode 100644 plugin-designs/bible-posters/src/sizes.js create mode 100644 plugin-designs/bible-posters/src/translations.js diff --git a/library/i18n/locales/ar/biblePosters.json b/library/i18n/locales/ar/biblePosters.json new file mode 100644 index 000000000..ea729d9ba --- /dev/null +++ b/library/i18n/locales/ar/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "ملصقات الكتاب المقدس", + "book": "السفر", + "language": "اللغة", + "size": "الحجم", + "print": "طباعة", + "close": "إغلاق", + "loading": "جارٍ تحميل السفر…", + "fetchFailed": "تعذّر تحميل هذا النص. حاول مرة أخرى.", + "fitsAt": "يتّسع بحجم {pt} نقطة في {cols} أعمدة.", + "tooSmall": "أصغر من أن يُقرأ بهذا الحجم.", + "trySize": "جرّب {size}", + "books": { + "ACT": "أعمال الرسل", + "MAT": "متى", + "JHN": "يوحنا", + "MRK": "مرقس", + "LUK": "لوقا", + "HEB": "العبرانيين", + "GEN": "التكوين", + "1JN": "يوحنا الأولى", + "COL": "كولوسي", + "1CO": "كورنثوس الأولى", + "1PE": "بطرس الأولى", + "JOS": "يشوع" + } +} diff --git a/library/i18n/locales/de/biblePosters.json b/library/i18n/locales/de/biblePosters.json new file mode 100644 index 000000000..575b0b3f3 --- /dev/null +++ b/library/i18n/locales/de/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "Bibel-Poster", + "book": "Buch", + "language": "Sprache", + "size": "Größe", + "print": "Drucken", + "close": "Schließen", + "loading": "Buch wird geladen…", + "fetchFailed": "Dieser Text konnte nicht geladen werden. Bitte erneut versuchen.", + "fitsAt": "Passt bei {pt} pt in {cols} Spalten.", + "tooSmall": "Zu klein, um in dieser Größe lesbar zu sein.", + "trySize": "versuchen Sie {size}", + "books": { + "ACT": "Apostelgeschichte", + "MAT": "Matthäus", + "JHN": "Johannes", + "MRK": "Markus", + "LUK": "Lukas", + "HEB": "Hebräer", + "GEN": "1. Mose", + "1JN": "1. Johannes", + "COL": "Kolosser", + "1CO": "1. Korinther", + "1PE": "1. Petrus", + "JOS": "Josua" + } +} diff --git a/library/i18n/locales/en/biblePosters.json b/library/i18n/locales/en/biblePosters.json new file mode 100644 index 000000000..0d7d5c6af --- /dev/null +++ b/library/i18n/locales/en/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "Bible Posters", + "book": "Book", + "language": "Language", + "size": "Size", + "print": "Print", + "close": "Close", + "loading": "Loading the book…", + "fetchFailed": "Could not load this text. Please try again.", + "fitsAt": "Fits at {pt} pt in {cols} columns.", + "tooSmall": "Too small to read at this size.", + "trySize": "try {size}", + "books": { + "ACT": "Acts", + "MAT": "Matthew", + "JHN": "John", + "MRK": "Mark", + "LUK": "Luke", + "HEB": "Hebrews", + "GEN": "Genesis", + "1JN": "1 John", + "COL": "Colossians", + "1CO": "1 Corinthians", + "1PE": "1 Peter", + "JOS": "Joshua" + } +} diff --git a/library/i18n/locales/es/biblePosters.json b/library/i18n/locales/es/biblePosters.json new file mode 100644 index 000000000..e63aed324 --- /dev/null +++ b/library/i18n/locales/es/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "Carteles bíblicos", + "book": "Libro", + "language": "Idioma", + "size": "Tamaño", + "print": "Imprimir", + "close": "Cerrar", + "loading": "Cargando el libro…", + "fetchFailed": "No se pudo cargar este texto. Inténtalo de nuevo.", + "fitsAt": "Cabe a {pt} pt en {cols} columnas.", + "tooSmall": "Demasiado pequeño para leerse en este tamaño.", + "trySize": "prueba {size}", + "books": { + "ACT": "Hechos", + "MAT": "Mateo", + "JHN": "Juan", + "MRK": "Marcos", + "LUK": "Lucas", + "HEB": "Hebreos", + "GEN": "Génesis", + "1JN": "1 Juan", + "COL": "Colosenses", + "1CO": "1 Corintios", + "1PE": "1 Pedro", + "JOS": "Josué" + } +} diff --git a/library/i18n/locales/fr/biblePosters.json b/library/i18n/locales/fr/biblePosters.json new file mode 100644 index 000000000..dc90054cd --- /dev/null +++ b/library/i18n/locales/fr/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "Affiches bibliques", + "book": "Livre", + "language": "Langue", + "size": "Taille", + "print": "Imprimer", + "close": "Fermer", + "loading": "Chargement du livre…", + "fetchFailed": "Impossible de charger ce texte. Veuillez réessayer.", + "fitsAt": "Tient à {pt} pt sur {cols} colonnes.", + "tooSmall": "Trop petit pour être lu à cette taille.", + "trySize": "essayez {size}", + "books": { + "ACT": "Actes", + "MAT": "Matthieu", + "JHN": "Jean", + "MRK": "Marc", + "LUK": "Luc", + "HEB": "Hébreux", + "GEN": "Genèse", + "1JN": "1 Jean", + "COL": "Colossiens", + "1CO": "1 Corinthiens", + "1PE": "1 Pierre", + "JOS": "Josué" + } +} diff --git a/library/i18n/locales/hi/biblePosters.json b/library/i18n/locales/hi/biblePosters.json new file mode 100644 index 000000000..e628bd9f4 --- /dev/null +++ b/library/i18n/locales/hi/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "बाइबल पोस्टर", + "book": "पुस्तक", + "language": "भाषा", + "size": "आकार", + "print": "प्रिंट करें", + "close": "बंद करें", + "loading": "पुस्तक लोड हो रही है…", + "fetchFailed": "यह पाठ लोड नहीं हो सका। कृपया पुनः प्रयास करें।", + "fitsAt": "{pt} pt पर {cols} स्तंभों में समाता है।", + "tooSmall": "इस आकार में पढ़ने के लिए बहुत छोटा।", + "trySize": "{size} आज़माएँ", + "books": { + "ACT": "प्रेरितों के काम", + "MAT": "मत्ती", + "JHN": "यूहन्ना", + "MRK": "मरकुस", + "LUK": "लूका", + "HEB": "इब्रानियों", + "GEN": "उत्पत्ति", + "1JN": "1 यूहन्ना", + "COL": "कुलुस्सियों", + "1CO": "1 कुरिन्थियों", + "1PE": "1 पतरस", + "JOS": "यहोशू" + } +} diff --git a/library/i18n/locales/it/biblePosters.json b/library/i18n/locales/it/biblePosters.json new file mode 100644 index 000000000..3435b16e9 --- /dev/null +++ b/library/i18n/locales/it/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "Poster biblici", + "book": "Libro", + "language": "Lingua", + "size": "Dimensione", + "print": "Stampa", + "close": "Chiudi", + "loading": "Caricamento del libro…", + "fetchFailed": "Impossibile caricare questo testo. Riprova.", + "fitsAt": "Sta a {pt} pt su {cols} colonne.", + "tooSmall": "Troppo piccolo da leggere a questa dimensione.", + "trySize": "prova {size}", + "books": { + "ACT": "Atti", + "MAT": "Matteo", + "JHN": "Giovanni", + "MRK": "Marco", + "LUK": "Luca", + "HEB": "Ebrei", + "GEN": "Genesi", + "1JN": "1 Giovanni", + "COL": "Colossesi", + "1CO": "1 Corinzi", + "1PE": "1 Pietro", + "JOS": "Giosuè" + } +} diff --git a/library/i18n/locales/pt/biblePosters.json b/library/i18n/locales/pt/biblePosters.json new file mode 100644 index 000000000..fdb0f3d60 --- /dev/null +++ b/library/i18n/locales/pt/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "Cartazes bíblicos", + "book": "Livro", + "language": "Idioma", + "size": "Tamanho", + "print": "Imprimir", + "close": "Fechar", + "loading": "Carregando o livro…", + "fetchFailed": "Não foi possível carregar este texto. Tente novamente.", + "fitsAt": "Cabe a {pt} pt em {cols} colunas.", + "tooSmall": "Pequeno demais para ler neste tamanho.", + "trySize": "tente {size}", + "books": { + "ACT": "Atos", + "MAT": "Mateus", + "JHN": "João", + "MRK": "Marcos", + "LUK": "Lucas", + "HEB": "Hebreus", + "GEN": "Gênesis", + "1JN": "1 João", + "COL": "Colossenses", + "1CO": "1 Coríntios", + "1PE": "1 Pedro", + "JOS": "Josué" + } +} diff --git a/library/i18n/locales/ro/biblePosters.json b/library/i18n/locales/ro/biblePosters.json new file mode 100644 index 000000000..f9923ca81 --- /dev/null +++ b/library/i18n/locales/ro/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "Postere biblice", + "book": "Cartea", + "language": "Limba", + "size": "Dimensiune", + "print": "Printează", + "close": "Închide", + "loading": "Se încarcă cartea…", + "fetchFailed": "Textul nu a putut fi încărcat. Încearcă din nou.", + "fitsAt": "Încape la {pt} pt pe {cols} coloane.", + "tooSmall": "Prea mic pentru a fi citit la această dimensiune.", + "trySize": "încearcă {size}", + "books": { + "ACT": "Faptele Apostolilor", + "MAT": "Matei", + "JHN": "Ioan", + "MRK": "Marcu", + "LUK": "Luca", + "HEB": "Evrei", + "GEN": "Geneza", + "1JN": "1 Ioan", + "COL": "Coloseni", + "1CO": "1 Corinteni", + "1PE": "1 Petru", + "JOS": "Iosua" + } +} diff --git a/library/i18n/locales/ru/biblePosters.json b/library/i18n/locales/ru/biblePosters.json new file mode 100644 index 000000000..820196ccc --- /dev/null +++ b/library/i18n/locales/ru/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "Библейские плакаты", + "book": "Книга", + "language": "Язык", + "size": "Размер", + "print": "Печать", + "close": "Закрыть", + "loading": "Загрузка книги…", + "fetchFailed": "Не удалось загрузить текст. Попробуйте ещё раз.", + "fitsAt": "Помещается при {pt} pt в {cols} колонках.", + "tooSmall": "Слишком мелко для чтения при этом размере.", + "trySize": "попробуйте {size}", + "books": { + "ACT": "Деяния", + "MAT": "Матфея", + "JHN": "Иоанна", + "MRK": "Марка", + "LUK": "Луки", + "HEB": "Евреям", + "GEN": "Бытие", + "1JN": "1 Иоанна", + "COL": "Колоссянам", + "1CO": "1 Коринфянам", + "1PE": "1 Петра", + "JOS": "Иисус Навин" + } +} diff --git a/library/i18n/locales/zh/biblePosters.json b/library/i18n/locales/zh/biblePosters.json new file mode 100644 index 000000000..1f6f60fe3 --- /dev/null +++ b/library/i18n/locales/zh/biblePosters.json @@ -0,0 +1,27 @@ +{ + "title": "圣经海报", + "book": "书卷", + "language": "语言", + "size": "尺寸", + "print": "打印", + "close": "关闭", + "loading": "正在加载书卷…", + "fetchFailed": "无法加载此文本,请重试。", + "fitsAt": "以 {pt} 磅、{cols} 栏排布。", + "tooSmall": "此尺寸下字太小,无法阅读。", + "trySize": "请尝试 {size}", + "books": { + "ACT": "使徒行传", + "MAT": "马太福音", + "JHN": "约翰福音", + "MRK": "马可福音", + "LUK": "路加福音", + "HEB": "希伯来书", + "GEN": "创世记", + "1JN": "约翰一书", + "COL": "歌罗西书", + "1CO": "哥林多前书", + "1PE": "彼得前书", + "JOS": "约书亚记" + } +} diff --git a/plugin-designs/bible-posters/bible-posters.meta.json b/plugin-designs/bible-posters/bible-posters.meta.json new file mode 100644 index 000000000..a59dea557 --- /dev/null +++ b/plugin-designs/bible-posters/bible-posters.meta.json @@ -0,0 +1,7 @@ +{ + "stage": "experimental", + "type": "single", + "label": "Bible Posters", + "targets": ["web"], + "note": "A generator that shows an ENTIRE BOOK of the Bible on one poster, in the languages of the top unreached people groups. Text is fetched at render time from the Free Use Bible API (public-domain / openly-licensed only); no Bibles are stored in the repo. Lives in the Posterverse Experimental shelf." +} diff --git a/plugin-designs/bible-posters/bible-posters.vue b/plugin-designs/bible-posters/bible-posters.vue new file mode 100644 index 000000000..e43eeae89 --- /dev/null +++ b/plugin-designs/bible-posters/bible-posters.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/plugin-designs/bible-posters/index.html b/plugin-designs/bible-posters/index.html new file mode 100644 index 000000000..232e3fca0 --- /dev/null +++ b/plugin-designs/bible-posters/index.html @@ -0,0 +1,30 @@ + + + + + + doxa-maps · bible-posters staging + + + + +
+

bible-posters · staging

+

An entire book of the Bible on one poster, in the languages of the unreached. + Text is fetched at render time from public-domain sources; no Bibles are stored.

+
+ +
+
+ + + diff --git a/plugin-designs/bible-posters/index.js b/plugin-designs/bible-posters/index.js new file mode 100644 index 000000000..7d74642b4 --- /dev/null +++ b/plugin-designs/bible-posters/index.js @@ -0,0 +1,31 @@ +/** + * plugin-designs/bible-posters/index.js + * + * Bundle entry for the Bible Posters generator (Posterverse → Experimental). + * Folder name = bundle name = tag. One flat profile: bible-posters.vue. + * Builds to public/dx-maps/bible-posters/bible-posters.js. + * + * This plugin has NO map — it is a text/poster generator — so it registers no colour strategies and + * needs no Mapbox token; it honours only the reader's LOCALE (interface language) through the provided + * i18n instance, exactly like every other plugin. + * + * + * + */ +import { defineMapElement } from '@map/elements/defineMapElement.js' + +const profileModules = import.meta.glob('./*.vue') + +const BiblePostersElement = defineMapElement({ + profileModules, + configureApp: (app, { pinia, i18n }) => { + // Install i18n AND hand the instance to ProfileLoader by reference; the element root cannot call + // useI18n() itself, so this is how a host sets the plugin's interface language. + }, +}) + +if (typeof customElements !== 'undefined' && !customElements.get('bible-posters')) { + customElements.define('bible-posters', BiblePostersElement) +} + +export default BiblePostersElement diff --git a/plugin-designs/bible-posters/src/biblePoster.js b/plugin-designs/bible-posters/src/biblePoster.js new file mode 100644 index 000000000..32afc7af0 --- /dev/null +++ b/plugin-designs/bible-posters/src/biblePoster.js @@ -0,0 +1,155 @@ +/** + * biblePoster.js — the Bible-book poster layout engine (pure: plan maths + an HTML string, no Vue). + * + * Modeled on wall-of-people-groups/src/blessPoster.js (the wall's engine): a `fit()` search for the + * largest readable type size, an HTML document for the shared in-place print frame, and a screen model + * that mirrors the print exactly ("what the wall shows is what prints"). The CONTENT differs — a book + * is flowing text, not a card grid — so the body is CSS multi-column justified text rather than a grid. + * + * The Driver's layout (§4): a bold BOOK-NAME header, then MULTIPLE COLUMNS about the width of a phone + * screen, ~7-10 words per line, JUSTIFIED, the whole book visible at once. RTL scripts flow right-to-left. + * + * ⚠ This is a MODEL of the layout (character-advance estimates), not a measurement of the rendered page. + * A headless plan proves the arithmetic; only a browser (rega) proves the page. Every number the model + * uses is named here so a rendered measurement can correct the constants. + */ + +const PT = 1 / 72 // one point in inches +export const MIN_READABLE_PT = 6 // a book printed below this is grey noise on a poster +export const MAX_PT = 16 +export const PX_IN = 96 // screen world: CSS px per inch (matches blessPoster.screenPoster) + +// Layout targets (the Driver's words, made numeric — correct against a rendered measurement). +const WORDS_PER_LINE = 8 // "~7-10 words per line" +const AVG_WORD_CHARS = 6 // 5 letters + a space, averaged +const CHARS_PER_LINE = WORDS_PER_LINE * AVG_WORD_CHARS // 48 +const CHAR_EM = 0.5 // average glyph advance as a fraction of the em (justified serif) +const LINE_LH = 1.32 // body line-height +const COL_GAP_IN = 0.28 // gap between columns +const MARGIN_IN = 0.5 // poster margin (all sides) +const HEAD_FRAC = 0.10 // header band as a fraction of poster height (min 0.6in) +const CREDIT_IN = 0.32 // credit-line band height +const CONTENT_SLACK = 1.15 // justification + word-break slack over raw character count + +/** Column width (inches) that yields ~WORDS_PER_LINE words per line at this type size. */ +function colWidthIn(pt) { return CHARS_PER_LINE * CHAR_EM * pt * PT } + +/** + * Plan a book onto a poster of widthIn × heightIn. Returns the chosen columns + type size and whether + * the whole book fits at a readable size. + * @param {{widthIn:number,heightIn:number}} size + * @param {{charCount:number,verseCount:number,blocks:Array}} book + */ +export function planBiblePoster(size, book) { + const W = size.widthIn - 2 * MARGIN_IN + const headH = Math.max(0.6, size.heightIn * HEAD_FRAC) + const H = size.heightIn - 2 * MARGIN_IN - headH - CREDIT_IN + const headingCount = (book.blocks || []).filter((b) => b.kind === 'heading').length + // effective characters the body must hold: text + verse-number glyphs + a line's worth per heading + const effective = Math.ceil(book.charCount * CONTENT_SLACK + book.verseCount * 3 + headingCount * CHARS_PER_LINE) + + const capacityAt = (pt) => { + const colW = colWidthIn(pt) + const cols = Math.max(1, Math.floor((W + COL_GAP_IN) / (colW + COL_GAP_IN))) + const lineIn = pt * LINE_LH * PT + const linesPerCol = Math.max(0, Math.floor(H / lineIn)) + return { pt, colW, cols, linesPerCol, capacity: cols * linesPerCol * CHARS_PER_LINE } + } + + // Largest type size (0.5pt steps) whose capacity holds the whole book. + let chosen = null + for (let pt = MAX_PT; pt >= MIN_READABLE_PT - 0.001; pt -= 0.5) { + const c = capacityAt(pt) + if (c.capacity >= effective) { chosen = c; break } + } + const fits = !!chosen + const plan = chosen || capacityAt(MIN_READABLE_PT) // if nothing fits, report the floor's numbers + return { + fits, effective, + widthIn: size.widthIn, heightIn: size.heightIn, + marginIn: MARGIN_IN, headHIn: headH, creditHIn: CREDIT_IN, + contentWIn: W, contentHIn: H, + cols: plan.cols, colWIn: plan.colW, colGapIn: COL_GAP_IN, + fontPt: plan.pt, lineHeight: LINE_LH, linesPerCol: plan.linesPerCol, + capacity: plan.capacity, + } +} + +/** Given a book and a set of candidate sizes, the smallest that fits (for the "which size" hint). */ +export function fitLadder(sizes, book) { + return sizes.map((s) => { + const p = planBiblePoster({ widthIn: s.widthIn, heightIn: s.heightIn }, book) + return { id: s.id, label: s.label, fits: p.fits, fontPt: p.fontPt, cols: p.cols } + }) +} + +const esc = (v) => String(v ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c])) + +/** The body HTML: headings and verses in reading order; verse numbers are bidi-isolated superscripts. */ +function bodyHtml(book) { + let html = '' + let lastChapter = 0 + for (const b of book.blocks) { + if (b.kind === 'heading') { html += '

' + esc(b.text) + '

'; continue } + if (b.chapter !== lastChapter) { html += '' + esc(b.chapter) + ''; lastChapter = b.chapter } + html += '' + esc(b.number) + '' + esc(b.text) + ' ' + } + return html +} + +/** CSS shared by print and screen. Built by concatenation (no backticks inside — AGENT-BRIEF house rule + * for shadow CSS; kept here for consistency and safe embedding). `unit` scales the poster to px on screen. */ +function posterCss(plan, dir, unit) { + const u = (inches) => (inches * unit).toFixed(2) + (unit === 1 ? 'in' : 'px') + const isRtl = dir === 'rtl' + return '' + + '*{box-sizing:border-box}' + + '.bp{position:relative;width:' + u(plan.widthIn) + ';height:' + u(plan.heightIn) + ';' + + 'padding:' + u(plan.marginIn) + ';background:#fff;color:#1c1c1c;' + + 'font-family:Georgia,"Times New Roman",serif;direction:' + (isRtl ? 'rtl' : 'ltr') + ';' + + '-webkit-print-color-adjust:exact;print-color-adjust:exact;overflow:hidden}' + + '.bp-head{height:' + u(plan.headHIn) + ';display:flex;flex-direction:column;align-items:center;' + + 'justify-content:center;text-align:center;border-bottom:' + u(0.02) + ' solid #1c1c1c}' + + '.bp-title{margin:0;font-weight:700;line-height:1.02;font-size:' + u(plan.headHIn * 0.5) + '}' + + '.bp-body{height:' + u(plan.contentHIn) + ';margin-top:' + u(0.12) + ';' + + 'column-count:' + plan.cols + ';column-gap:' + u(plan.colGapIn) + ';column-fill:auto;' + + 'font-size:' + (unit === 1 ? plan.fontPt + 'pt' : (plan.fontPt * unit / 72).toFixed(2) + 'px') + ';' + + 'line-height:' + plan.lineHeight + ';text-align:justify;hyphens:auto;-webkit-hyphens:auto;' + + 'text-justify:inter-word;overflow:hidden}' + + '.bp-body .bh{font-weight:700;font-size:1.02em;margin:0.5em 0 0.15em;break-after:avoid;' + + 'font-family:-apple-system,"Segoe UI",Arial,sans-serif}' + + '.bp-body .cn{font-weight:700;font-size:1.5em;line-height:1;float:' + (isRtl ? 'right' : 'left') + ';' + + 'margin:' + (isRtl ? '0 0 0 0.12em' : '0 0.12em 0 0') + ';color:#92552a}' + + '.bp-body .vn{font-size:0.62em;font-weight:700;color:#92552a;vertical-align:super;' + + 'unicode-bidi:isolate;margin:0 0.12em}' + + '.bp-body .v{}' + + '.bp-credit{position:absolute;left:' + u(plan.marginIn) + ';right:' + u(plan.marginIn) + ';' + + 'bottom:' + u(plan.marginIn * 0.4) + ';height:' + u(plan.creditHIn) + ';display:flex;align-items:center;' + + 'justify-content:center;text-align:center;font-family:-apple-system,"Segoe UI",Arial,sans-serif;' + + 'font-size:' + u(0.11) + ';color:#6d766e}' +} + +/** The print document: one page, the whole book. `texts` supplies the credit line and optional dir/lang. */ +export function buildBiblePosterHtml(book, size, texts = {}) { + const dir = texts.dir || book.dir || 'ltr' + const plan = planBiblePoster(size, book) + const css = '@page{size:' + size.widthIn + 'in ' + size.heightIn + 'in;margin:0}html,body{margin:0;padding:0}' + + posterCss(plan, dir, 1) + const inner = '

' + esc(book.name) + '

' + + '
' + bodyHtml(book) + '
' + + '
' + esc(texts.credit || '') + '
' + return '' + + '' + esc(book.name) + '' + + '
' + inner + '
' +} + +/** The screen model (WYSIWYG): the same poster, scaled to CSS px. Returns { css, html, worldW, worldH }. */ +export function screenBiblePoster(book, size, texts = {}) { + const dir = texts.dir || book.dir || 'ltr' + const plan = planBiblePoster(size, book) + const css = posterCss(plan, dir, PX_IN) + const html = '

' + esc(book.name) + '

' + + '
' + bodyHtml(book) + '
' + + '
' + esc(texts.credit || '') + '
' + return { css, html, dir, plan, worldW: size.widthIn * PX_IN, worldH: size.heightIn * PX_IN } +} diff --git a/plugin-designs/bible-posters/src/bibleSource.js b/plugin-designs/bible-posters/src/bibleSource.js new file mode 100644 index 000000000..dbfcd71de --- /dev/null +++ b/plugin-designs/bible-posters/src/bibleSource.js @@ -0,0 +1,105 @@ +/** + * bibleSource.js — the RENDER-TIME text client for the Free Use Bible API (bible.helloao.org). + * + * Fetches a whole book on demand and returns a normalized structure the renderer can lay out. + * NOTHING is written to the repo or public/: whole Bibles are never stored (the licence gate and the + * §4 spec). A small in-memory (per-bundle, per-session) cache avoids re-fetching a book the reader + * just looked at; it is discarded on reload. + * + * The API (verified 2026-09-30): + * {base}/{translationId}/books.json → { books: [{ id, commonName, numberOfChapters, ... }] } + * {base}/{translationId}/{BOOK}/{chapter}.json → { chapter: { content: [ {type:'verse',number,content:[...]} + * | {type:'heading',content:[...]} ] } } + * CORS is open (Access-Control-Allow-Origin: *) and no key is required. + */ + +export const API_BASE = 'https://bible.helloao.org/api' + +const booksCache = new Map() // translationId -> [{id, name, chapters, order}] +const bookCache = new Map() // `${translationId}/${bookId}` -> normalized book + +async function getJson(url, signal) { + const res = await fetch(url, { signal, headers: { accept: 'application/json' } }) + if (!res.ok) throw new Error('HTTP ' + res.status + ' for ' + url) + return res.json() +} + +/** The translation's book table: id → localized name + chapter count. Used to build the picker and to + * know which of the 12 packet books this translation actually has (OT books need an OT translation). */ +export async function fetchBooks(translationId, { signal } = {}) { + if (booksCache.has(translationId)) return booksCache.get(translationId) + const d = await getJson(`${API_BASE}/${translationId}/books.json`, signal) + const raw = Array.isArray(d) ? d : (d.books || []) + const books = raw.map((b) => ({ + id: b.id, + name: b.commonName || b.name || b.id, + chapters: b.numberOfChapters || 0, + order: b.order || 0, + })) + booksCache.set(translationId, books) + return books +} + +/** One verse/heading item → plain text. Verse `content` is an array of strings and, occasionally, + * objects (poetry lines, notes). We keep the readable text and drop note apparatus. */ +function itemText(item) { + const parts = Array.isArray(item.content) ? item.content : [item.content] + return parts + .map((p) => { + if (typeof p === 'string') return p + if (p && typeof p === 'object') return p.text || (Array.isArray(p.content) ? p.content.filter((x) => typeof x === 'string').join(' ') : '') + return '' + }) + .filter(Boolean) + .join(' ') + .replace(/\s+/g, ' ') + .trim() +} + +/** + * Fetch an ENTIRE book: every chapter, flattened to an ordered list of blocks. + * Returns { bookId, name, dir, chapters: N, blocks: [{kind:'heading'|'verse', chapter, number?, text}], + * verseCount, charCount }. `onProgress(done, total)` fires per chapter. + */ +export async function fetchBook(translationId, bookId, { signal, onProgress, dir = 'ltr', concurrency = 4 } = {}) { + const key = `${translationId}/${bookId}` + if (bookCache.has(key)) { onProgress?.(1, 1); return bookCache.get(key) } + + const books = await fetchBooks(translationId, { signal }) + const meta = books.find((b) => b.id === bookId) + if (!meta) throw new Error(`${translationId} has no book ${bookId}`) + const total = meta.chapters + const chapterBlocks = new Array(total) // keep chapter order regardless of fetch order + let done = 0 + + async function one(ch) { + const d = await getJson(`${API_BASE}/${translationId}/${bookId}/${ch}.json`, signal) + const content = (d.chapter || d).content || [] + const blocks = [] + for (const item of content) { + if (item.type === 'heading') { const t = itemText(item); if (t) blocks.push({ kind: 'heading', chapter: ch, text: t }) } + else if (item.type === 'verse') { const t = itemText(item); if (t) blocks.push({ kind: 'verse', chapter: ch, number: item.number, text: t }) } + } + chapterBlocks[ch - 1] = blocks + done += 1 + onProgress?.(done, total) + } + + // bounded-concurrency pool over chapters 1..total + const queue = [] + for (let ch = 1; ch <= total; ch++) queue.push(ch) + const workers = new Array(Math.min(concurrency, total)).fill(0).map(async () => { + while (queue.length) { const ch = queue.shift(); await one(ch) } + }) + await Promise.all(workers) + + const blocks = chapterBlocks.flat().filter(Boolean) + let verseCount = 0, charCount = 0 + for (const b of blocks) { if (b.kind === 'verse') verseCount++; charCount += b.text.length } + const book = { bookId, name: meta.name, dir, chapters: total, blocks, verseCount, charCount } + bookCache.set(key, book) + return book +} + +/** Test seam: clear the session caches. */ +export function _clearCache() { booksCache.clear(); bookCache.clear() } diff --git a/plugin-designs/bible-posters/src/books.js b/plugin-designs/bible-posters/src/books.js new file mode 100644 index 000000000..935a5a62c --- /dev/null +++ b/plugin-designs/bible-posters/src/books.js @@ -0,0 +1,39 @@ +/** + * books.js — the 12 books the UPG-100 prayer packet cites, in packet-citation order. + * + * The Bible Posters generator shows an ENTIRE BOOK on one poster. These 12 are the starting set + * (DRIVER-SWARMS-POSTERVERSE-BIBLE-1855 §4): every book referenced by the en packet in + * library/scripts/posters/packet-strings.json. The verse list is the index; the poster offers the book. + * + * `id` — the USFM/OSIS book id the Free Use Bible API (bible.helloao.org) uses in its URLs. + * `en` — an English fallback label for the UI picker BEFORE the fetched translation is known; + * the POSTER HEADER itself uses the fetched translation's own `commonName` (in the text + * language), so a reader sees "يوحنا" / "Johannes", never the English name. + * `testament` — 'OT' books (Genesis, Joshua) exist only in a translation that HAS an Old Testament, + * which narrows the offered language set; the other 10 are New Testament and fetch from + * any NT-only translation too. + * `chaptersHint` — the chapter count for the WEB text (eng_web), used only to size a progress bar and a + * fit pre-estimate; the real count comes from the translation's own books.json at render. + */ +export const PACKET_BOOKS = [ + { id: 'ACT', en: 'Acts', testament: 'NT', chaptersHint: 28 }, + { id: 'MAT', en: 'Matthew', testament: 'NT', chaptersHint: 28 }, + { id: 'JHN', en: 'John', testament: 'NT', chaptersHint: 21 }, + { id: 'MRK', en: 'Mark', testament: 'NT', chaptersHint: 16 }, + { id: 'LUK', en: 'Luke', testament: 'NT', chaptersHint: 24 }, + { id: 'HEB', en: 'Hebrews', testament: 'NT', chaptersHint: 13 }, + { id: 'GEN', en: 'Genesis', testament: 'OT', chaptersHint: 50 }, + { id: '1JN', en: '1 John', testament: 'NT', chaptersHint: 5 }, + { id: 'COL', en: 'Colossians', testament: 'NT', chaptersHint: 4 }, + { id: '1CO', en: '1 Corinthians', testament: 'NT', chaptersHint: 16 }, + { id: '1PE', en: '1 Peter', testament: 'NT', chaptersHint: 5 }, + { id: 'JOS', en: 'Joshua', testament: 'OT', chaptersHint: 24 }, +] + +export const BOOK_BY_ID = Object.fromEntries(PACKET_BOOKS.map((b) => [b.id, b])) + +/** Books this translation can serve: OT books need a translation whose books.json includes them. */ +export function booksForTranslation(availableBookIds) { + const have = new Set(availableBookIds || []) + return PACKET_BOOKS.filter((b) => have.has(b.id)) +} diff --git a/plugin-designs/bible-posters/src/sizes.js b/plugin-designs/bible-posters/src/sizes.js new file mode 100644 index 000000000..f3235fb06 --- /dev/null +++ b/plugin-designs/bible-posters/src/sizes.js @@ -0,0 +1,28 @@ +/** + * sizes.js — the poster size ladder for Bible Posters. + * + * ⚠ TEMPORARY, DO NOT LET IT DIVERGE. studio OWNS the shared size table + picker + * (library/constants/posterSizes.js) and the approved SIZE KEYS + * (_qa-cycle/03-deployment-cycle/tasks/DRIVER-BATCH-AND-BIG-POSTERS-1735 "SIZE KEYS"): + * paper · 36x36 · 36x60 · 66x66 · 60x96, portrait only. As of development ce930476 the shared table + * still holds the OLD US/ISO presets, so this mirrors the APPROVED keys locally to unblock the build. + * REPLACE this with `import { ... } from '@map/constants/posterSizes.js'` (and the shared picker) as + * soon as studio lands the new ladder — ask studio via dx-shepherd; never edit the shared file here. + * + * A book is laid out on the FINISHED poster (width × height, portrait). `sheets` records the panel plan + * for the large sizes (glued print); the multi-panel PRINT path reuses library panelSheets.js and is a + * milestone-2 follow-up — the fit MODEL uses the finished dimensions. + */ +// Labels are locale-neutral DIMENSIONS (in/ft are unit symbols, like cm) so no English word leaks into a +// non-English UI. When studio's shared table lands its localized names (poster.size., e.g. "Standard +// paper"), switch the picker to those; ask studio via dx-shepherd, never edit the shared file here. +export const BIBLE_POSTER_SIZES = [ + { id: 'paper', key: 'paper', label: '8.5 × 11 in', widthIn: 8.5, heightIn: 11, sheets: 1 }, + { id: '36x36', key: '36x36', label: '3 × 3 ft', widthIn: 36, heightIn: 36, sheets: 1 }, + { id: '36x60', key: '36x60', label: '3 × 5 ft', widthIn: 36, heightIn: 60, sheets: 1 }, + { id: '66x66', key: '66x66', label: '5.5 × 5.5 ft', widthIn: 66, heightIn: 66, sheets: 2 }, + { id: '60x96', key: '60x96', label: '5 × 8 ft', widthIn: 60, heightIn: 96, sheets: 3 }, +] + +export const SIZE_BY_ID = Object.fromEntries(BIBLE_POSTER_SIZES.map((s) => [s.id, s])) +export const DEFAULT_SIZE_ID = '36x60' diff --git a/plugin-designs/bible-posters/src/translations.js b/plugin-designs/bible-posters/src/translations.js new file mode 100644 index 000000000..8220b33e1 --- /dev/null +++ b/plugin-designs/bible-posters/src/translations.js @@ -0,0 +1,64 @@ +/** + * translations.js — the LICENCE-VETTED text sources for the Bible Posters generator. + * + * ⚠ LICENSING GATE (bible-poster-plugin's first task; see + * _qa-cycle/01-ideation-research/BIBLE-POSTER-LICENSING.md). A full BOOK is displayed IN FULL on a + * printed, white-label giveaway poster, so ONLY texts whose licence permits that may ship. This v1 + * list is STRICT PUBLIC-DOMAIN ONLY — the exact translations the UPG-100 packet already ships as + * public domain, plus the WEB seed dx-shepherd named. It is safe under EITHER Driver answer to the + * open question (PD-only vs. a licensed/broader set), so it is what builds now. + * + * The CC-BY / CC-BY-SA expansion (the IRV family — Hindi, Tamil, Telugu, Punjabi — and the wider + * UPG languages) is DEFERRED pending the Driver's ruling; do not add a non-public-domain text here + * without dx-shepherd's go-ahead and a per-translation licence check (eBible details + Door43), + * never the transport's blanket "no restrictions" claim nor eBible's Redistributable flag alone. + * + * Transport: the Free Use Bible API (bible.helloao.org) — CORS, no key, per-chapter JSON, fetched at + * RENDER TIME. No whole Bibles are stored in the repo or public/. Each translation carries a + * `licenseUrl` back to its eBible record; `credit` is the poster's printed credit line. + * + * `iso639_3` is the text language, so the picker can offer the languages of the top unreached people + * groups (the Gospel Resources map data keys on iso639_3) once the CC-BY-SA set is approved. + */ + +/** @typedef {Object} Translation + * @property {string} id Free Use Bible API translation id (its URL segment) + * @property {string} iso639_3 text language code + * @property {string} language English language name (UI grouping) + * @property {string} name the translation's English name + * @property {'ltr'|'rtl'} dir text direction + * @property {string} licence the licence class (v1: all 'public-domain') + * @property {string} credit the poster credit line + * @property {string} licenseUrl the licence record of source + */ + +/** v1 STRICT PUBLIC-DOMAIN seed — the packet's 6 + WEB. Every entry has all 66 books (OT+NT). */ +export const TRANSLATIONS = [ + { id: 'eng_web', iso639_3: 'eng', language: 'English', endonym: 'English', name: 'World English Bible', + dir: 'ltr', licence: 'public-domain', + credit: 'World English Bible · public domain · ebible.org (via bible.helloao.org)', + licenseUrl: 'https://ebible.org/Scriptures/details.php?id=eng-web' }, + { id: 'spa_r09', iso639_3: 'spa', language: 'Spanish', endonym: 'Español', name: 'Reina Valera 1909', + dir: 'ltr', licence: 'public-domain', + credit: 'Reina Valera 1909 · dominio público · ebible.org (via bible.helloao.org)', + licenseUrl: 'https://ebible.org/Scriptures/details.php?id=spaRV1909' }, + { id: 'fra_ost', iso639_3: 'fra', language: 'French', endonym: 'Français', name: 'French Ostervald Bible', + dir: 'ltr', licence: 'public-domain', + credit: 'Bible Ostervald · domaine public · ebible.org (via bible.helloao.org)', + licenseUrl: 'https://ebible.org/Scriptures/details.php?id=fra_fob' }, + { id: 'deu_l12', iso639_3: 'deu', language: 'German', endonym: 'Deutsch', name: 'German Luther Bible 1912', + dir: 'ltr', licence: 'public-domain', + credit: 'Lutherbibel 1912 · gemeinfrei · ebible.org (via bible.helloao.org)', + licenseUrl: 'https://ebible.org/Scriptures/details.php?id=deu1912' }, + { id: 'rus_syn', iso639_3: 'rus', language: 'Russian', endonym: 'Русский', name: 'Russian Synodal Bible', + dir: 'ltr', licence: 'public-domain', + credit: 'Синодальный перевод · общественное достояние · ebible.org (via bible.helloao.org)', + licenseUrl: 'https://ebible.org/Scriptures/details.php?id=russyn' }, + { id: 'arb_vdv', iso639_3: 'arb', language: 'Arabic', endonym: 'العربية', name: 'Arabic Van Dyck Bible', + dir: 'rtl', licence: 'public-domain', + credit: 'فان دايك · ملك عام · ebible.org (via bible.helloao.org)', + licenseUrl: 'https://ebible.org/Scriptures/details.php?id=arb-vd' }, +] + +export const TRANSLATION_BY_ID = Object.fromEntries(TRANSLATIONS.map((t) => [t.id, t])) +export const DEFAULT_TRANSLATION_ID = 'eng_web' From cdf0df268d2a5a9d33a3558ad384c7c107647dc1 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Wed, 30 Sep 2026 23:07:10 +0000 Subject: [PATCH 05/11] Bible Posters: language-tagged columns, atomic book fetch, cleaner credits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address studio's 5B nits (non-blocking, folded in before the first render): - Tag each translation with a BCP-47 code and set lang on the poster (html + body) so hyphens:auto works in narrow justified columns — removes rivers on Latin text. - Fetch a whole book atomically: a single chapter failure now aborts the sibling requests and surfaces the error, instead of leaving a half book. - Drop the English word "via" from the per-poster credit lines (a bare separator). - Correct the entry comment: defineMapElement installs i18n; the hook only adds provides. --- .../bible-posters/bible-posters.vue | 6 ++-- plugin-designs/bible-posters/index.js | 5 +-- .../bible-posters/src/biblePoster.js | 5 +-- .../bible-posters/src/bibleSource.js | 33 ++++++++++++------- .../bible-posters/src/translations.js | 24 +++++++------- 5 files changed, 42 insertions(+), 31 deletions(-) diff --git a/plugin-designs/bible-posters/bible-posters.vue b/plugin-designs/bible-posters/bible-posters.vue index e43eeae89..1f29d2fae 100644 --- a/plugin-designs/bible-posters/bible-posters.vue +++ b/plugin-designs/bible-posters/bible-posters.vue @@ -43,7 +43,7 @@ const offeredBooks = computed(() => booksForTranslation(availableBookIds.value)) const plan = computed(() => (book.value ? planBiblePoster(size.value, book.value) : null)) const screen = computed(() => { if (!book.value) return null - return screenBiblePoster(book.value, size.value, { credit: translation.value.credit, dir: translation.value.dir }) + return screenBiblePoster(book.value, size.value, { credit: translation.value.credit, dir: translation.value.dir, lang: translation.value.bcp47 }) }) // Which of the ladder's sizes fit this book, for the "which size" guidance. @@ -89,7 +89,7 @@ async function loadBook() { function print() { if (!book.value) return - const html = buildBiblePosterHtml(book.value, size.value, { credit: translation.value.credit, dir: translation.value.dir }) + const html = buildBiblePosterHtml(book.value, size.value, { credit: translation.value.credit, dir: translation.value.dir, lang: translation.value.bcp47 }) printDocument(html, { labels: { print: t('biblePosters.print'), close: t('biblePosters.close') } }) } @@ -160,7 +160,7 @@ onBeforeUnmount(() => { if (ro) ro.disconnect() }) diff --git a/plugin-designs/bible-posters/index.js b/plugin-designs/bible-posters/index.js index 7d74642b4..757a92145 100644 --- a/plugin-designs/bible-posters/index.js +++ b/plugin-designs/bible-posters/index.js @@ -19,8 +19,9 @@ const profileModules = import.meta.glob('./*.vue') const BiblePostersElement = defineMapElement({ profileModules, configureApp: (app, { pinia, i18n }) => { - // Install i18n AND hand the instance to ProfileLoader by reference; the element root cannot call - // useI18n() itself, so this is how a host sets the plugin's interface language. + // defineMapElement already installs Pinia + i18n and provides the i18n instance to ProfileLoader + // (that is how a host sets the interface language). This hook is only for extra app-level provides; + // Bible Posters needs none. }, }) diff --git a/plugin-designs/bible-posters/src/biblePoster.js b/plugin-designs/bible-posters/src/biblePoster.js index 32afc7af0..774aa6f5a 100644 --- a/plugin-designs/bible-posters/src/biblePoster.js +++ b/plugin-designs/bible-posters/src/biblePoster.js @@ -132,13 +132,14 @@ function posterCss(plan, dir, unit) { /** The print document: one page, the whole book. `texts` supplies the credit line and optional dir/lang. */ export function buildBiblePosterHtml(book, size, texts = {}) { const dir = texts.dir || book.dir || 'ltr' + const lang = texts.lang || '' // a BCP-47 tag so hyphens:auto works and the page declares its language const plan = planBiblePoster(size, book) const css = '@page{size:' + size.widthIn + 'in ' + size.heightIn + 'in;margin:0}html,body{margin:0;padding:0}' + posterCss(plan, dir, 1) const inner = '

' + esc(book.name) + '

' + '
' + bodyHtml(book) + '
' + '
' + esc(texts.credit || '') + '
' - return '' + return '' + '' + esc(book.name) + '' + '
' + inner + '
' } @@ -151,5 +152,5 @@ export function screenBiblePoster(book, size, texts = {}) { const html = '

' + esc(book.name) + '

' + '
' + bodyHtml(book) + '
' + '
' + esc(texts.credit || '') + '
' - return { css, html, dir, plan, worldW: size.widthIn * PX_IN, worldH: size.heightIn * PX_IN } + return { css, html, dir, lang: texts.lang || '', plan, worldW: size.widthIn * PX_IN, worldH: size.heightIn * PX_IN } } diff --git a/plugin-designs/bible-posters/src/bibleSource.js b/plugin-designs/bible-posters/src/bibleSource.js index dbfcd71de..62fd5560e 100644 --- a/plugin-designs/bible-posters/src/bibleSource.js +++ b/plugin-designs/bible-posters/src/bibleSource.js @@ -72,26 +72,35 @@ export async function fetchBook(translationId, bookId, { signal, onProgress, dir const chapterBlocks = new Array(total) // keep chapter order regardless of fetch order let done = 0 + // One book is one atomic fetch: a chapter failure ABORTS the siblings (never a half book), while still + // honouring the caller's own signal. An internal controller chains to it so we can abort from inside. + const internal = new AbortController() + const onExt = () => internal.abort() + if (signal) { if (signal.aborted) internal.abort(); else signal.addEventListener('abort', onExt, { once: true }) } + async function one(ch) { - const d = await getJson(`${API_BASE}/${translationId}/${bookId}/${ch}.json`, signal) - const content = (d.chapter || d).content || [] - const blocks = [] - for (const item of content) { - if (item.type === 'heading') { const t = itemText(item); if (t) blocks.push({ kind: 'heading', chapter: ch, text: t }) } - else if (item.type === 'verse') { const t = itemText(item); if (t) blocks.push({ kind: 'verse', chapter: ch, number: item.number, text: t }) } - } - chapterBlocks[ch - 1] = blocks - done += 1 - onProgress?.(done, total) + try { + const d = await getJson(`${API_BASE}/${translationId}/${bookId}/${ch}.json`, internal.signal) + const content = (d.chapter || d).content || [] + const blocks = [] + for (const item of content) { + if (item.type === 'heading') { const t = itemText(item); if (t) blocks.push({ kind: 'heading', chapter: ch, text: t }) } + else if (item.type === 'verse') { const t = itemText(item); if (t) blocks.push({ kind: 'verse', chapter: ch, number: item.number, text: t }) } + } + chapterBlocks[ch - 1] = blocks + done += 1 + onProgress?.(done, total) + } catch (e) { internal.abort(); throw e } // stop the other workers on the first failure } // bounded-concurrency pool over chapters 1..total const queue = [] for (let ch = 1; ch <= total; ch++) queue.push(ch) const workers = new Array(Math.min(concurrency, total)).fill(0).map(async () => { - while (queue.length) { const ch = queue.shift(); await one(ch) } + while (queue.length && !internal.signal.aborted) { const ch = queue.shift(); await one(ch) } }) - await Promise.all(workers) + try { await Promise.all(workers) } + finally { if (signal) signal.removeEventListener('abort', onExt) } const blocks = chapterBlocks.flat().filter(Boolean) let verseCount = 0, charCount = 0 diff --git a/plugin-designs/bible-posters/src/translations.js b/plugin-designs/bible-posters/src/translations.js index 8220b33e1..73024a880 100644 --- a/plugin-designs/bible-posters/src/translations.js +++ b/plugin-designs/bible-posters/src/translations.js @@ -34,29 +34,29 @@ /** v1 STRICT PUBLIC-DOMAIN seed — the packet's 6 + WEB. Every entry has all 66 books (OT+NT). */ export const TRANSLATIONS = [ - { id: 'eng_web', iso639_3: 'eng', language: 'English', endonym: 'English', name: 'World English Bible', + { id: 'eng_web', iso639_3: 'eng', bcp47: 'en', language: 'English', endonym: 'English', name: 'World English Bible', dir: 'ltr', licence: 'public-domain', - credit: 'World English Bible · public domain · ebible.org (via bible.helloao.org)', + credit: 'World English Bible · public domain · ebible.org · bible.helloao.org', licenseUrl: 'https://ebible.org/Scriptures/details.php?id=eng-web' }, - { id: 'spa_r09', iso639_3: 'spa', language: 'Spanish', endonym: 'Español', name: 'Reina Valera 1909', + { id: 'spa_r09', iso639_3: 'spa', bcp47: 'es', language: 'Spanish', endonym: 'Español', name: 'Reina Valera 1909', dir: 'ltr', licence: 'public-domain', - credit: 'Reina Valera 1909 · dominio público · ebible.org (via bible.helloao.org)', + credit: 'Reina Valera 1909 · dominio público · ebible.org · bible.helloao.org', licenseUrl: 'https://ebible.org/Scriptures/details.php?id=spaRV1909' }, - { id: 'fra_ost', iso639_3: 'fra', language: 'French', endonym: 'Français', name: 'French Ostervald Bible', + { id: 'fra_ost', iso639_3: 'fra', bcp47: 'fr', language: 'French', endonym: 'Français', name: 'French Ostervald Bible', dir: 'ltr', licence: 'public-domain', - credit: 'Bible Ostervald · domaine public · ebible.org (via bible.helloao.org)', + credit: 'Bible Ostervald · domaine public · ebible.org · bible.helloao.org', licenseUrl: 'https://ebible.org/Scriptures/details.php?id=fra_fob' }, - { id: 'deu_l12', iso639_3: 'deu', language: 'German', endonym: 'Deutsch', name: 'German Luther Bible 1912', + { id: 'deu_l12', iso639_3: 'deu', bcp47: 'de', language: 'German', endonym: 'Deutsch', name: 'German Luther Bible 1912', dir: 'ltr', licence: 'public-domain', - credit: 'Lutherbibel 1912 · gemeinfrei · ebible.org (via bible.helloao.org)', + credit: 'Lutherbibel 1912 · gemeinfrei · ebible.org · bible.helloao.org', licenseUrl: 'https://ebible.org/Scriptures/details.php?id=deu1912' }, - { id: 'rus_syn', iso639_3: 'rus', language: 'Russian', endonym: 'Русский', name: 'Russian Synodal Bible', + { id: 'rus_syn', iso639_3: 'rus', bcp47: 'ru', language: 'Russian', endonym: 'Русский', name: 'Russian Synodal Bible', dir: 'ltr', licence: 'public-domain', - credit: 'Синодальный перевод · общественное достояние · ebible.org (via bible.helloao.org)', + credit: 'Синодальный перевод · общественное достояние · ebible.org · bible.helloao.org', licenseUrl: 'https://ebible.org/Scriptures/details.php?id=russyn' }, - { id: 'arb_vdv', iso639_3: 'arb', language: 'Arabic', endonym: 'العربية', name: 'Arabic Van Dyck Bible', + { id: 'arb_vdv', iso639_3: 'arb', bcp47: 'ar', language: 'Arabic', endonym: 'العربية', name: 'Arabic Van Dyck Bible', dir: 'rtl', licence: 'public-domain', - credit: 'فان دايك · ملك عام · ebible.org (via bible.helloao.org)', + credit: 'فان دايك · ملك عام · ebible.org · bible.helloao.org', licenseUrl: 'https://ebible.org/Scriptures/details.php?id=arb-vd' }, ] From 2da7f15ec716f2828bfdf36630737f33ea30532c Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Wed, 30 Sep 2026 23:11:37 +0000 Subject: [PATCH 06/11] Bible Posters: neutral source comments + CSP note for the text host - Reword source comments in agent-written, neutral terms and drop internal task-file paths, so shipped source cites no process documents or attributions (passes check:no-new-driver-references). - documentation/how-to.md: note that Bible Posters needs https://bible.helloao.org in connect-src (text is fetched per book at render time; none is bundled), so a host under a strict CSP does not silently block it. --- documentation/how-to.md | 1 + plugin-designs/bible-posters/src/biblePoster.js | 4 ++-- plugin-designs/bible-posters/src/books.js | 2 +- plugin-designs/bible-posters/src/sizes.js | 6 +++--- plugin-designs/bible-posters/src/translations.js | 11 +++++------ 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/documentation/how-to.md b/documentation/how-to.md index 72d11f83c..87b0e186a 100644 --- a/documentation/how-to.md +++ b/documentation/how-to.md @@ -415,6 +415,7 @@ every third-party script is pinned with an integrity hash (`library/constants/cd | `style-src` | `'unsafe-inline'`, the same CDN hosts | each plugin styles its own shadow root with a `
'+a+"
"}function Mh(e,t,n={}){const o=n.dir||e.dir||"ltr",s=ps(t,e),i=Ic(s,o,Ri),r='

'+xt(e.name)+'

'+Ac(e)+'
'+xt(n.credit||"")+"
";return{css:i,html:r,dir:o,lang:n.lang||"",plan:s,worldW:t.widthIn*Ri,worldH:t.heightIn*Ri}}const Dh=".bpx{display:flex;flex-direction:column;height:100%;min-height:0;background:#f3f3f1;color:#3b463d;font-family:-apple-system,Segoe UI,system-ui,sans-serif}.bpx-bar{display:flex;flex-wrap:wrap;gap:12px;align-items:flex-end;justify-content:space-between;padding:12px 16px;background:#fff;border-bottom:1px solid #d1d4cd}.bpx-title{font-size:18px;font-weight:700}.bpx-controls{display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end}.bpx-field{display:flex;flex-direction:column;gap:3px;font-size:12px;color:#6d766e}.bpx-field select{min-height:36px;padding:0 10px;border:1px solid #d1d4cd;border-radius:8px;background:#fff;color:#3b463d;font:inherit}.bpx-print{min-height:38px;padding:0 18px;border:0;border-radius:8px;background:#3b463d;color:#fff;font:inherit;font-weight:600;cursor:pointer}.bpx-print:disabled{background:#b7bdb4;cursor:default}.bpx-hint{margin:0;padding:8px 16px;font-size:13px;color:#3b463d}.bpx-warn{color:#9a3b2f}.bpx-stage{flex:1 1 0;min-height:0;position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;padding:12px}.bpx-scaler{transform-origin:center center;box-shadow:0 6px 24px #0000002e;background:#fff}.bpx-status{font-size:14px;color:#6d766e}.bpx-credit{margin:0;padding:8px 16px;font-size:11px;color:#6d766e;text-align:center;border-top:1px solid #d1d4cd;background:#fff}",Hh={class:"bpx"},zh={class:"bpx-bar"},Wh={class:"bpx-title"},Uh={class:"bpx-controls"},Bh={class:"bpx-field"},Vh=["value"],jh={class:"bpx-field"},Gh=["value"],Kh={class:"bpx-field"},qh=["value"],Yh=["disabled"],Jh={key:0,class:"bpx-hint"},Xh={key:0},Zh={key:1,class:"bpx-warn"},Qh={key:0,class:"bpx-status"},em={key:0},tm={key:1,class:"bpx-status bpx-warn"},nm=["lang","dir","innerHTML"],om={key:1,class:"bpx-credit"},sm=Object.freeze(Object.defineProperty({__proto__:null,default:Ei({__name:"bible-posters",setup(e){const{t}=xn(),n=at("profileConfig",null),o=typeof n=="object"&&n||{},s=he(o.translation||Th),i=he(o.book||"JHN"),r=he(o.size||Ih),a=he(Ii.map(q=>q.id)),l=he(null),c=he(!1),u=Wn({done:0,total:0}),p=he("");let m=null;const y=re(()=>vh[s.value]||xi[0]),C=re(()=>Ah[r.value]||fs[0]),T=re(()=>yh(a.value)),M=re(()=>l.value?ps(C.value,l.value):null),R=re(()=>l.value?Mh(l.value,C.value,{credit:y.value.credit,dir:y.value.dir,lang:y.value.bcp47}):null),D=re(()=>l.value?fs.map(q=>{const V=ps({widthIn:q.widthIn,heightIn:q.heightIn},l.value);return{id:q.id,label:q.label,fits:V.fits,fontPt:V.fontPt}}):[]),$=re(()=>D.value.find(q=>q.fits)||null);async function b(){try{const q=await Tc(s.value);if(a.value=q.map(V=>V.id),!a.value.includes(i.value)){const V=T.value.find(P=>P.testament==="NT")||T.value[0];V&&(i.value=V.id)}}catch{}}async function v(){const q=new AbortController;m&&m.abort(),m=q,c.value=!0,p.value="",u.done=0,u.total=0;try{const V=await xh(s.value,i.value,{signal:q.signal,dir:y.value.dir,onProgress:(P,ne)=>{u.done=P,u.total=ne}});if(q.signal.aborted)return;l.value=V}catch{q.signal.aborted||(p.value="biblePosters.fetchFailed",l.value=null)}finally{m===q&&(m=null,c.value=!1)}}function S(){if(!l.value)return;const q=Oh(l.value,C.value,{credit:y.value.credit,dir:y.value.dir,lang:y.value.bcp47});mh(q,{labels:{print:t("biblePosters.print"),close:t("biblePosters.close")}})}Ge(s,async()=>{await b(),await v()}),Ge(i,v),yn(async()=>{await b(),await v()}),vn(()=>{m&&m.abort()});const N=he(null),k=he(1);function x(){const q=N.value,V=R.value;if(!q||!V)return;const P=24,ne=(q.clientWidth-P)/V.worldW,Ce=(q.clientHeight-P)/V.worldH;k.value=Math.max(.02,Math.min(ne,Ce))}Ge([R,N],x,{flush:"post"});let K=null;return yn(()=>{K=new ResizeObserver(x),N.value&&K.observe(N.value)}),vn(()=>{K&&K.disconnect()}),(q,V)=>(ue(),ye("div",Hh,[pe("header",zh,[pe("div",Wh,Ae(xe(t)("biblePosters.title")),1),pe("div",Uh,[pe("label",Bh,[pe("span",null,Ae(xe(t)("biblePosters.book")),1),ko(pe("select",{"onUpdate:modelValue":V[0]||(V[0]=P=>i.value=P)},[(ue(!0),ye(He,null,Ho(T.value,P=>(ue(),ye("option",{key:P.id,value:P.id},Ae(xe(t)("biblePosters.books."+P.id)),9,Vh))),128))],512),[[Xs,i.value]])]),pe("label",jh,[pe("span",null,Ae(xe(t)("biblePosters.language")),1),ko(pe("select",{"onUpdate:modelValue":V[1]||(V[1]=P=>s.value=P)},[(ue(!0),ye(He,null,Ho(xe(xi),P=>(ue(),ye("option",{key:P.id,value:P.id},Ae(P.endonym),9,Gh))),128))],512),[[Xs,s.value]])]),pe("label",Kh,[pe("span",null,Ae(xe(t)("biblePosters.size")),1),ko(pe("select",{"onUpdate:modelValue":V[2]||(V[2]=P=>r.value=P)},[(ue(!0),ye(He,null,Ho(xe(fs),P=>(ue(),ye("option",{key:P.id,value:P.id},Ae(P.label),9,qh))),128))],512),[[Xs,r.value]])]),pe("button",{type:"button",class:"bpx-print",disabled:!l.value||c.value,onClick:S},Ae(xe(t)("biblePosters.print")),9,Yh)])]),M.value?(ue(),ye("p",Jh,[M.value.fits?(ue(),ye("span",Xh,Ae(xe(t)("biblePosters.fitsAt",{pt:M.value.fontPt,cols:M.value.cols})),1)):(ue(),ye("span",Zh,[ot(Ae(xe(t)("biblePosters.tooSmall"))+" ",1),$.value?(ue(),ye(He,{key:0},[ot(" — "+Ae(xe(t)("biblePosters.trySize",{size:$.value.label})),1)],64)):wt("",!0)]))])):wt("",!0),pe("div",{class:"bpx-stage",ref_key:"previewBox",ref:N},[c.value?(ue(),ye("div",Qh,[ot(Ae(xe(t)("biblePosters.loading")),1),u.total?(ue(),ye("span",em,Ae(u.done)+" / "+Ae(u.total),1)):wt("",!0)])):p.value?(ue(),ye("div",tm,Ae(xe(t)(p.value)),1)):R.value?(ue(),ye("div",{key:2,class:"bpx-scaler",style:$o({width:R.value.worldW+"px",height:R.value.worldH+"px",transform:"scale("+k.value+")"})},[(ue(),cn(Os("style"),null,{default:Sr(()=>[ot(Ae(R.value.css),1)]),_:1})),pe("div",{class:"bp",lang:R.value.lang||null,dir:R.value.dir,innerHTML:R.value.html},null,8,nm)],4)):wt("",!0)],512),l.value?(ue(),ye("p",om,Ae(y.value.credit),1)):wt("",!0)]))}},[["styles",[Dh]]])},Symbol.toStringTag,{value:"Module"}))})(); diff --git a/public/dx-maps/bible-posters/bible-posters/index.html b/public/dx-maps/bible-posters/bible-posters/index.html new file mode 100644 index 000000000..a79ba0234 --- /dev/null +++ b/public/dx-maps/bible-posters/bible-posters/index.html @@ -0,0 +1,250 @@ + + + + + + + + bible-posters · bible-posters + + + + + +
+
loading…
+ + + + + + + + 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 e6dc5b613..a6ee7abfa 100644 --- a/public/dx-maps/doxa-maps-spa/doxa-maps-spa.js +++ b/public/dx-maps/doxa-maps-spa/doxa-maps-spa.js @@ -285,4 +285,4 @@ .mi-pointer, .mi .mi-pointer.mi-ctl{ animation:none; } .mi-chev{ transition:none; } } -`,"map-info"),(x,Y)=>(C(),N("div",{ref_key:"rootEl",ref:Be,class:"mi",dir:y()?"rtl":"ltr",lang:n()},[Da(O("button",{ref_key:"btnEl",ref:V,type:"button",class:tt(["mi-btn",e.placement==="top-left"?"mi-at-left":"mi-at-right"]),"aria-label":Se(s)("mapInfo.open"),title:Se(s)("mapInfo.open"),"aria-haspopup":"dialog","aria-expanded":String(H.value),onClick:ke},[...Y[1]||(Y[1]=[O("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false"},[O("circle",{cx:"12",cy:"12",r:"10",fill:"none",stroke:"currentColor","stroke-width":"2"}),O("path",{d:"M9.1 9a3 3 0 0 1 5.8 1c0 2-3 3-3 3",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"}),O("circle",{cx:"12",cy:"17",r:"1.3",fill:"currentColor"})],-1)])],10,Um),[[Xa,$()]]),U.value&&!H.value&&$()?(C(),N("div",{key:0,class:tt(["mi-pointer",e.placement==="top-left"?"mi-at-left":"mi-at-right"]),"aria-hidden":"true"},[O("span",null,G(Se(s)("mapInfo.pointer")),1),(C(),N("svg",Hm,[e.placement==="top-left"?(C(),N("path",Vm)):(C(),N("path",Bm))]))],2)):se("",!0),U.value&&!H.value&&!$()&&g.value?(C(),N("div",{key:1,class:tt(["mi-pointer mi-ctl",["mi-ctl-"+g.value.side,{"mi-ctl-strip":g.value.strip}]]),style:Ta(w()),"aria-hidden":"true"},[O("span",{dir:y()?"rtl":"ltr"},G(Se(s)("mapInfo.pointer")),9,Gm),(C(),N("svg",Km,[g.value.side==="left"?(C(),N("path",Xm)):(C(),N("path",Ym))]))],6)):se("",!0),H.value?(C(),N("div",{key:2,class:"mi-scrim",onClick:zo(ot,["self"]),onKeydown:I},[O("div",{ref_key:"dialogEl",ref:k,class:"mi-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"mi-title-"+e.storageKey},[O("div",Zm,[O("h2",{id:"mi-title-"+e.storageKey,class:"mi-title"},G(Se(s)("mapInfo.title")),9,Qm),O("button",{ref_key:"closeEl",ref:me,type:"button",class:"mi-close","aria-label":Se(s)("mapInfo.close"),onClick:ot},"×",8,eh)]),O("div",th,[e.leadKey||e.lead?(C(),N("section",{key:0,class:"mi-bluf","aria-labelledby":"mi-bluf-"+e.storageKey},[O("h3",{id:"mi-bluf-"+e.storageKey,class:"mi-bluf-h"},G(Se(s)("mapInfo.shortDescription")),9,oh),O("p",nh,G(r(e.leadKey,e.lead)),1)],8,ah)):se("",!0),(e.takeawayKey||e.takeaway)&&!d()?(C(),N("p",sh,[O("b",null,G(Se(s)("mapInfo.takeaway")),1),Bt(" "+G(r(e.takeawayKey,e.takeaway)),1)])):se("",!0),d()?(C(),N("details",{key:"st-"+o.value,class:"mi-strategy"},[O("summary",rh,[O("span",null,G(Se(s)("mapInfo.tabStrategy")),1),Y[2]||(Y[2]=O("span",{class:"mi-chev","aria-hidden":"true"},"▾",-1))]),O("p",ih,G(l()),1),c().length?(C(),N("ul",lh,[(C(!0),N(ne,null,Ye(c(),(B,Q)=>(C(),N("li",{key:Q},G(B),1))),128))])):se("",!0)])):se("",!0),(C(!0),N(ne,null,Ye(e.examples,(B,Q)=>Da((C(),N("section",{key:Q,class:"mi-ex"},[O("h3",null,G(de(B)),1),B.kind==="image"?(C(),N(ne,{key:0},[O("img",{class:"mi-img mi-poster",src:X(B.src),alt:B.alt||de(B),decoding:"async",onError:le=>ee[Q]=!0},null,40,ch),B.full?(C(),N("div",ph,[O("a",{class:"mi-full",href:X(B.full),target:"_blank",rel:"noopener"},G(Se(s)("mapInfo.openFull")),9,uh)])):se("",!0)],64)):B.kind==="pages"&&(B.pages||[]).length?(C(),N(ne,{key:1},[we[Q]?(C(),N(ne,{key:1},[O("div",hh,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:le=>b(Q)},G(Se(s)("mapInfo.collapsePages")),9,bh)]),O("div",vh,[(C(!0),N(ne,null,Ye(B.pages,(le,xe)=>(C(),N("button",{key:xe,type:"button",class:"mi-hit mi-open mi-page","aria-label":Se(s)("mapInfo.collapsePages"),onClick:jt=>b(Q)},[O("img",{class:"mi-img",src:X(le),alt:de(B)+" "+m(xe+1),loading:"lazy",decoding:"async",onError:S},null,40,yh)],8,$h))),128))]),O("div",_h,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:le=>b(Q)},G(Se(s)("mapInfo.collapsePages")),9,wh)])],64)):(C(),N(ne,{key:0},[O("button",{type:"button",class:tt(["mi-hit mi-page",{"mi-stack":B.pages.length>1}]),"aria-label":Se(s)("mapInfo.expandPages",{n:m(B.pages.length)}),"aria-expanded":"false",onClick:le=>b(Q)},[O("img",{class:"mi-img",src:X(B.pages[0]),alt:de(B),decoding:"async",onError:le=>ee[Q]=!0},null,40,fh)],10,dh),B.pages.length>1?(C(),N("div",gh,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"false",onClick:le=>b(Q)},G(Se(s)("mapInfo.expandPages",{n:m(B.pages.length)})),9,mh)])):se("",!0)],64))],64)):B.kind==="deck"&&(B.cards||[]).length?(C(),N(ne,{key:2},[we[Q]?(C(),N(ne,{key:1},[O("div",Th,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:le=>b(Q)},G(Se(s)("mapInfo.collapseDeck")),9,Ph)]),O("div",Eh,[(C(!0),N(ne,null,Ye(B.cards,(le,xe)=>(C(),N("img",{key:xe,class:"mi-img",src:X(le),alt:de(B)+" "+m(xe+1),loading:"lazy",decoding:"async",onError:S},null,40,Oh))),128))]),O("div",Mh,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:le=>b(Q)},G(Se(s)("mapInfo.collapseDeck")),9,Ah)])],64)):(C(),N(ne,{key:0},[O("button",{type:"button",class:"mi-hit mi-deck","aria-label":Se(s)("mapInfo.expandDeck",{n:m(B.cards.length)}),"aria-expanded":"false",onClick:le=>b(Q)},[(C(!0),N(ne,null,Ye(je(B),(le,xe)=>(C(),N("img",{key:xe,class:"mi-card",src:X(le),alt:"",decoding:"async",onError:jt=>xe===0?ee[Q]=!0:S(jt),style:Ta({insetInlineStart:xe*36+"px",transform:"rotate("+(xe-2)*4+"deg)",zIndex:10-xe})},null,44,xh))),128))],8,kh),O("div",Sh,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"false",onClick:le=>b(Q)},G(Se(s)("mapInfo.expandDeck",{n:m(B.cards.length)})),9,Lh)])],64))],64)):B.kind==="table"&&(B.columns||[]).length?(C(),N(ne,{key:3},[O("div",Ch,[O("table",Ih,[O("thead",null,[O("tr",null,[(C(!0),N(ne,null,Ye(B.columns,(le,xe)=>(C(),N("th",{key:xe,scope:"col"},G(Ie(le)),1))),128))])]),O("tbody",null,[(C(!0),N(ne,null,Ye(B.rows||[],(le,xe)=>(C(),N("tr",{key:xe},[(C(!0),N(ne,null,Ye(le,(jt,$b)=>(C(),N("td",{key:$b},G(typeof jt=="number"?m(jt):jt),1))),128))]))),128))])])]),B.total&&B.total>(B.rows||[]).length?(C(),N("p",Nh,G(Se(s)("mapInfo.moreRows",{n:m(B.total-(B.rows||[]).length)})),1)):se("",!0)],64)):se("",!0)])),[[Xa,!ee[Q]]])),128)),e.noteKey||e.note?(C(),N("p",Fh,G(r(e.noteKey,e.note)),1)):se("",!0)]),a()?se("",!0):(C(),N("div",Dh,[O("label",null,[O("input",{type:"checkbox",checked:_.value,onChange:Y[0]||(Y[0]=B=>F(B.target.checked))},null,40,Rh),O("span",null,G(Se(s)("mapInfo.pointerOff")),1)])]))],8,Jm)],32)):se("",!0)],8,jm))}},Wh=":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}.mi.dms-info-raise .mi-btn{z-index:60}.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 Ll(){try{const e=new URLSearchParams(location.search),t=(e.get("lang")||e.get("locale")||"").split("-")[0].toLowerCase();if(ls.includes(t))return t}catch{}try{const e=(document.documentElement.lang||"").split("-")[0].toLowerCase();if(ls.includes(e))return e}catch{}return""}const ps=[{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"},{id:"country-posters",icon:"poster"},{id:"poster-design",icon:"grid"}]},{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 qh(e){const t={},a=e&&Array.isArray(e.bundles)?e.bundles:[];for(const o of a)for(const n of Array.isArray(o&&o.profiles)?o.profiles:[])n&&(n.mobile==="desktop-only"||n.mobile==="larger-screens")&&(t[o.bundle+"/"+n.profile]=n.mobile);return t}const jh=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","posterverse"]),Tl={"prayer-walk-planner":1,"gospel-internet":2,"upg-neighbor":3,"key-cities":4,"all-people-groups":5,"doxa-vision-card":7},us=[{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 Posters",sub:"my unreached list + posters",emoji:"📋",bundle:"my-upg-100-list",profile:"upg-100-mfe"},{id:"country-posters",label:"Country Posters",sub:"a poster for every country",emoji:"🗺️",bundle:"country-posters",profile:"country-posters-mfe"},{id:"poster-design",label:"Poster Design",sub:"every poster style and size",emoji:"🎨",bundle:"poster-design",profile:"poster-design-mfe"}];Hh(ps);const Jo=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"]),Zo=new Set(["dashboard-plus-grid","research-map-plus-grid"]);function Uh(){const e=Object.fromEntries(us.map(a=>[a.id,a])),t=new Set;for(const a of ps)if(a.key!=="experimental")for(const o of a.tabs||[]){const n=e[o.id];n&&n.bundle&&t.add(n.bundle)}return t}function Pl(e,t){const a=[];for(const o of e)!o||t.has(o.key)||(t.add(o.key),a.push(o));return a}function Hh(e){const t=new Map,a=[];for(const o of e)if(o.key!=="experimental")for(const n of o.tabs||[]){if(!n||!n.id)continue;const s=t.get(n.id);if(s===void 0){t.set(n.id,o.key);continue}(s!==o.key||a.indexOf(n.id)===-1)&&a.push(n.id+" ("+s+" + "+o.key+")")}return a.length&&typeof console<"u"&&console.error("[doxa-maps-spa] duplicate tab key(s) across NAV_MODEL sections: "+a.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."),a}function Vh(e){return String(e).split(/[-_]/).filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}function Bh(e){const t=Uh(),a=e&&Array.isArray(e.bundles)?e.bundles:[],o=[];for(const n of a){const s=n&&n.bundle;if(!s||t.has(s)||jh.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&&o.push({id:s,label:i.title||Vh(s),sub:(i.description||"").trim().replace(/[,;]\s*$/,"")||"experimental bundle",emoji:"🧪",tag:l,bundle:s,profile:i.profile||s,scriptUrl:c,heavy:Jo.has(l)||Jo.has(s),scroll:Zo.has(l)||Zo.has(s),discovered:!0})}return o.sort((n,s)=>{const r=Tl[n.id]||999,i=Tl[s.id]||999;return r!==i?r-i:n.label.localeCompare(s.label)}),o}function Gh(e,t){const a=e&&Array.isArray(e.bundles)?e.bundles:[],o=Object.fromEntries(a.map(s=>[s.bundle,s])),n={};for(const s of t){const r=o[s.bundle];if(!r)continue;const i=Array.isArray(r.profiles)?r.profiles:[],l=i.find(L=>L.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 m=l&&Array.isArray(l.instances)?l.instances:[],y=!!(s.instance&&m.some(L=>(L&&(L.id||L.instance))===s.instance));n[s.id]={tag:c,scriptUrl:d,profile:l&&l.profile||s.profile,instance:y?s.instance:"",heavy:Jo.has(c)||Jo.has(s.bundle),scroll:Zo.has(c)||Zo.has(s.bundle)}}return n}const Kh=ma({name:"DoxaMapsSpa",inheritAttrs:!1,components:{VerticalTabsLayout:Am,BackToTopButton:oi,MapInfo:zh},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:""},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["tab-change"],setup(){return{injectedBase:ga("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:Nm(),hostLang:Ll(),localeOpen:!1,switcherLangs:Cm,tabs:us.map(e=>({...e,tag:"",scriptUrl:"",heavy:!1,scroll:!1,resolved:!1,mounted:!1,state:"idle",error:""}))}},computed:{largerScreenText(){return Zt("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?wl(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(a=>[a.id,a])),t=new Set;return ps.map(a=>{let o=Pl((a.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 a.key==="experimental"&&!this.showExperimental?{key:a.key,rows:[]}:(a.key==="experimental"&&(o=o.concat(Pl(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:a.key,label:a.i18n?this.tr(a.i18n):a.label,icon:a.icon,folder:!!a.folder,open:a.open,rows:o})}).filter(a=>a.rows.length)},showLocaleSwitcher(){return this.showHeader},activeLang(){return Im(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 ls.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","home"])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=(o,n)=>{try{const s=this._slots&&this._slots[o];s&&(s.innerHTML="")}catch{}n.mounted=!1,n.state="idle",n.error=""};this.tabs.forEach((o,n)=>{o.mounted&&n!==this.activeIndex&&e(n,o)});const t=this.activeIndex,a=this.tabs[t];!a||!a.mounted||(e(t,a),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())},infoProps(e){const{pos:t,...a}=this.infoFor(e)||{};return a},infoPos(e){const t=(this.infoFor(e)||{}).pos||{},{narrow:a,...o}=t;return this.narrow&&a?{...o,...a}:o},infoStyle(e){const t=this.infoPos(e),a={};return t.top&&(a["--map-info-top"]=t.top),t.side&&(a["--map-info-side"]=t.side),a},infoFor(e){const t=this.showInfo&&e&&Wm[e.id];return t&&(!t.leadKey||Zt(t.leadKey,"en"))?t:null},tabHasHelp(e){return!!(e&&e.discovered&&wl(e.id,this.uiLocale))},onHostedHelp(e){if(!this.activeHelp)return;e.stopPropagation();const t=e.composedPath?e.composedPath():[];this._helpReturn=t.find(a=>a&&a.tagName==="BUTTON")||null,this.openHelp()},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},tr(e,t){return Xo(this.uiLocale,e,t)},t(e,t){return Xo(this.uiLocale,e,t)},tabLabel(e){return!e.discovered||Dm("tab."+e.id)?Xo(this.uiLocale,"tab."+e.id):e.label},tabSub(e){return e.discovered?this.uiLocale==="en"?e.sub:this.tr("experimentalSub"):Xo(this.uiLocale,"sub."+e.id)},watchHostLang(){typeof MutationObserver>"u"||typeof document>"u"||(this._langObs=new MutationObserver(()=>{this.hostLang=Ll()}),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(a=>a.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 a of t.rows){const o=this.tabs.findIndex(n=>n.id===a.key);if(!(o<0)&&(e<0&&(e=o),!a.disabled))return o}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""}},a={url:e,root:t(e)},o={url:this.resolve("doxa-maps-spa/manifest.json"),root:a.root};let n=!1;try{n=new URL(e,location.href).origin!==location.origin}catch{}const s=n?[o,a]:[a,o],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:m}=s[c];return i.push(d),fetch(d,{credentials:"same-origin"}).then(y=>{if(!y||!y.ok)throw new Error(d+" → HTTP "+(y?y.status:"?"));return y.json()}).then(y=>{if(!y)throw new Error(d+" → empty");this.manifestError="",this.manifestBase=m||"",this.applyManifest(y)}).catch(()=>l(c+1))};try{l(0)}catch{}},applyManifest(e){this.runtime=e&&e.runtime&&typeof e.runtime=="object"?e.runtime:{},this.mobileFlags=qh(e),this.applyPageGlobals();const t=Gh(e,us),a=this.activeKey,o=[];for(const l of this.tabs){if(l.discovered){o.push(l);continue}const c=t[l.id];c&&(Object.assign(l,c,{resolved:!0}),o.push(l))}const n=new Set(o.map(l=>l.id));if(this.showExperimental)for(const l of Bh(e))n.has(l.id)||o.push({...l,resolved:!0,mounted:!1,state:"idle",error:""});this.tabs=o;const s=this.requestedTab(),r=s?this.tabs.findIndex(l=>l.id===s):-1,i=this.tabs.findIndex(l=>l.id===a);r>=0&&!this.isDesktopOnly(s)&&!this._honouredTab?this.select(r):this.select(i>=0&&!this.isDesktopOnly(a)?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(a=>a.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,Fm(e)},onSelect(e){if(this.isDesktopOnly(e)){const a=this.tabs.find(o=>o.id===e);this.disabledNotice=(Zt("messages.desktopOnlyNotice",this.uiLocale)||"{label} only supports desktop — open this page on a desktop to use it.").replace("{label}",a?this.tabLabel(a):e),clearTimeout(this._noticeTimer),this._noticeTimer=setTimeout(()=>{this.disabledNotice=""},4e3);return}const t=this.tabs.findIndex(a=>a.id===e);t!==-1&&this.select(t)},resolve(e){const t=String(e);if(/^(https?:)?\/\//.test(t)||t.startsWith("/"))return t;const a=t.replace(/^\.\//,"");return this.manifestBase?this.manifestBase.replace(/\/+$/,"")+"/"+a:this.base?this.base.replace(/\/+$/,"")+"/"+a:"../"+a},select(e){const t=this.activeIndex;if(this.activeIndex=e,t!==e&&t>=0){const o=this.tabs[t];o&&o.heavy&&o.mounted&&this.releaseTab(t,o)}const a=this.tabs[e];a&&((t!==e||!this._announced)&&(this._announced=!0,this.$emit("tab-change",{id:a.id,label:a.label})),a.scriptUrl&&(this.narrow&&this.mobileFlags===null||this.isDesktopOnly(a.id)||a.mounted||this.$nextTick(()=>{this.activeIndex===e&&this.mountElement(e)})))},releaseTab(e,t){try{const a=this._slots&&this._slots[e];a&&(a.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 a=this.tk||this.cfg.tk||this.runtime.token;return a&&(t.tk=a),(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.mapTitle=this.tabLabel(e),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 a=this.resolve(t.scriptUrl);vl(a).then(()=>Tg(t.tag)).then(()=>{try{if(t.heavy&&this.activeIndex!==e){t.mounted=!1,t.state="idle";return}const o=this._slots&&this._slots[e];if(!o){t.state="error",t.error="no slot";return}o.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;",o.appendChild(n),t.state="ready"}catch(o){t.state="error",t.error="mount failed: "+(o&&o.message||String(o))}}).catch(o=>{t.state="error",t.error=o&&o.message||String(o)})}}}),Xh={class:"dms-locale"},Yh=["aria-expanded"],Jh={class:"dms-flag"},Zh={class:"dms-locale-name"},Qh={key:0,class:"dms-locale-menu",role:"listbox"},eb=["aria-selected"],tb=["onClick"],ab={class:"dms-flag"},ob={class:"dms-locale-name"},nb={class:"dms-locale-en"},sb=["hidden","data-doxa-help"],rb={key:0,class:"dms-mobile-notice",role:"status"},ib=["aria-label","onClick"],lb={key:2,class:"dms-hint"},cb={key:3,class:"dms-hint err"},pb={key:4,class:"dms-hint err"},ub={key:0,class:"dms-notice",role:"status"},db={id:"dms-help-title",class:"dms-help-title"},fb={class:"dms-help-what"},gb={class:"dms-help-how"};function mb(e,t,a,o,n,s){const r=Eo("MapInfo"),i=Eo("BackToTopButton"),l=Eo("VerticalTabsLayout");return C(),$a(l,{dir:e.uiDir,lang:e.uiLocale,labels:e.layoutLabels,"home-href":e.homeHref||e.cfg.homeHref||"","home-label":e.homeLabel||e.cfg.homeLabel||"",title:e.headingText,"nav-label":e.t("navLabel"),header:e.showHeader,groups:e.navGroups,active:e.activeKey,"onUpdate:active":e.onSelect},Rc({brand:Fa(()=>[t[5]||(t[5]=O("span",{class:"dms-logo","aria-hidden":"true"},[O("svg",{viewBox:"0 0 24 24",width:"22",height:"22",fill:"none",stroke:"#92b195","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[O("circle",{cx:"12",cy:"12",r:"9"}),O("polygon",{points:"12 6 14 12 12 18 10 12",fill:"#92b195",stroke:"none"}),O("polygon",{points:"6 12 12 10 18 12 12 14",fill:"#92b195",opacity:"0.55",stroke:"none"})])],-1))]),meta:Fa(()=>[Bt(G(e.t("meta",{n:e.tabs.length})),1)]),default:Fa(()=>[(C(!0),N(ne,null,Ye(e.tabs,(c,d)=>Da((C(),N("section",{key:c.id,class:"dms-pane",ref_for:!0,ref:m=>{m?e.paneEls[d]=m:delete e.paneEls[d]},hidden:d!==e.activeIndex,"data-doxa-help":e.tabHasHelp(c)?"":null,"data-doxa-gallery":""},[!c.heavy||d===e.activeIndex?(C(),N(ne,{key:0},[e.showsMobileNotice(c.id)?(C(),N("div",rb,[O("span",null,G(e.largerScreenText),1),O("button",{type:"button",class:"dms-mobile-notice-x","aria-label":e.tr("dismiss"),onClick:m=>e.dismissMobileNotice(c.id)},"×",8,ib)])):se("",!0),O("div",{class:"dms-slot",ref_for:!0,ref:m=>e.setSlot(d,m)},null,512),e.infoFor(c)?(C(),$a(r,Ir({key:"info-"+c.id},{ref_for:!0},e.infoProps(c),{style:e.infoStyle(c),placement:e.infoPos(c).placement||"top-right",class:{"dms-info-raise":e.infoPos(c).raise},"assets-base":e.assetsBase,locale:e.effectiveLocale}),null,16,["style","placement","class","assets-base","locale"])):se("",!0),c.state==="loading"?(C(),N("div",lb,G(e.tr("loading",{label:e.tabLabel(c)})),1)):c.state==="error"?(C(),N("div",cb,[Bt(G(e.tr("loadFailed",{label:e.tabLabel(c)})),1),t[7]||(t[7]=O("br",null,null,-1)),O("small",null,G(c.error),1)])):c.state==="idle"&&!c.scriptUrl&&e.manifestError?(C(),N("div",pb,[Bt(G(e.tr("loadFailed",{label:e.tabLabel(c)})),1),t[8]||(t[8]=O("br",null,null,-1)),O("small",null,G(e.manifestError),1),t[9]||(t[9]=O("br",null,null,-1)),O("small",null,G(e.tr("manifestHint")),1)])):se("",!0)],64)):se("",!0)],8,sb)),[[Xa,d===e.activeIndex]])),128)),e.disabledNotice?(C(),N("div",ub,G(e.disabledNotice),1)):se("",!0),e.helpOpen&&e.activeHelp?(C(),N("div",{key:1,class:"dms-help-scrim",onClick:t[3]||(t[3]=zo((...c)=>e.closeHelp&&e.closeHelp(...c),["self"])),onKeydown:t[4]||(t[4]=Qr(zo((...c)=>e.closeHelp&&e.closeHelp(...c),["stop","prevent"]),["esc"]))},[O("div",{class:"dms-help",role:"dialog","aria-modal":"true","aria-labelledby":"dms-help-title",onKeydown:t[2]||(t[2]=Qr(zo(c=>e.$refs.helpClose&&e.$refs.helpClose.focus(),["prevent"]),["tab"]))},[O("h2",db,G(e.tabLabel(e.tabs[e.activeIndex])),1),O("p",fb,[O("strong",null,G(e.activeHelp.what),1)]),O("p",gb,G(e.activeHelp.how),1),O("button",{ref:"helpClose",type:"button",class:"dms-help-close",onClick:t[1]||(t[1]=(...c)=>e.closeHelp&&e.closeHelp(...c))},G(e.tr("close")),513)],32)],32)):se("",!0),We(i,{target:e.activePaneEl,labels:{backToTop:e.tr("backToTop")}},null,8,["target","labels"])]),_:2},[e.showLocaleSwitcher?{name:"toolbar",fn:Fa(()=>[O("div",Xh,[O("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)},[O("span",Jh,G(e.activeLang.flag),1),O("span",Zh,G(e.activeLang.nativeName),1),t[6]||(t[6]=O("span",{class:"dms-dots","aria-hidden":"true"},"⋮",-1))],8,Yh),e.localeOpen?(C(),N("ul",Qh,[(C(!0),N(ne,null,Ye(e.switcherLangs,c=>(C(),N("li",{key:c.code,role:"option","aria-selected":String(c.code===e.locale)},[O("button",{type:"button",class:tt(["dms-locale-opt",{active:c.code===e.locale}]),onClick:d=>e.setLocale(c.code)},[O("span",ab,G(c.flag),1),O("span",ob,G(c.nativeName),1),O("span",nb,G(c.name),1)],10,tb)],8,eb))),128))])):se("",!0)])]),key:"0"}:void 0]),1032,["dir","lang","labels","home-href","home-label","title","nav-label","header","groups","active","onUpdate:active"])}const hb=zn(Kh,[["render",mb],["styles",[Wh]]]),bb=Pg(),vb=Bp(hb,{configureApp(e){e.provide("dmsTreeBase",bb)}});typeof customElements<"u"&&!customElements.get("doxa-maps-spa")&&customElements.define("doxa-maps-spa",vb)})(); +`,"map-info"),(x,Y)=>(C(),N("div",{ref_key:"rootEl",ref:Be,class:"mi",dir:y()?"rtl":"ltr",lang:n()},[Da(O("button",{ref_key:"btnEl",ref:V,type:"button",class:tt(["mi-btn",e.placement==="top-left"?"mi-at-left":"mi-at-right"]),"aria-label":Se(s)("mapInfo.open"),title:Se(s)("mapInfo.open"),"aria-haspopup":"dialog","aria-expanded":String(H.value),onClick:ke},[...Y[1]||(Y[1]=[O("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false"},[O("circle",{cx:"12",cy:"12",r:"10",fill:"none",stroke:"currentColor","stroke-width":"2"}),O("path",{d:"M9.1 9a3 3 0 0 1 5.8 1c0 2-3 3-3 3",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"}),O("circle",{cx:"12",cy:"17",r:"1.3",fill:"currentColor"})],-1)])],10,Um),[[Xa,$()]]),U.value&&!H.value&&$()?(C(),N("div",{key:0,class:tt(["mi-pointer",e.placement==="top-left"?"mi-at-left":"mi-at-right"]),"aria-hidden":"true"},[O("span",null,G(Se(s)("mapInfo.pointer")),1),(C(),N("svg",Hm,[e.placement==="top-left"?(C(),N("path",Vm)):(C(),N("path",Bm))]))],2)):se("",!0),U.value&&!H.value&&!$()&&g.value?(C(),N("div",{key:1,class:tt(["mi-pointer mi-ctl",["mi-ctl-"+g.value.side,{"mi-ctl-strip":g.value.strip}]]),style:Ta(w()),"aria-hidden":"true"},[O("span",{dir:y()?"rtl":"ltr"},G(Se(s)("mapInfo.pointer")),9,Gm),(C(),N("svg",Km,[g.value.side==="left"?(C(),N("path",Xm)):(C(),N("path",Ym))]))],6)):se("",!0),H.value?(C(),N("div",{key:2,class:"mi-scrim",onClick:zo(ot,["self"]),onKeydown:I},[O("div",{ref_key:"dialogEl",ref:k,class:"mi-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"mi-title-"+e.storageKey},[O("div",Zm,[O("h2",{id:"mi-title-"+e.storageKey,class:"mi-title"},G(Se(s)("mapInfo.title")),9,Qm),O("button",{ref_key:"closeEl",ref:me,type:"button",class:"mi-close","aria-label":Se(s)("mapInfo.close"),onClick:ot},"×",8,eh)]),O("div",th,[e.leadKey||e.lead?(C(),N("section",{key:0,class:"mi-bluf","aria-labelledby":"mi-bluf-"+e.storageKey},[O("h3",{id:"mi-bluf-"+e.storageKey,class:"mi-bluf-h"},G(Se(s)("mapInfo.shortDescription")),9,oh),O("p",nh,G(r(e.leadKey,e.lead)),1)],8,ah)):se("",!0),(e.takeawayKey||e.takeaway)&&!d()?(C(),N("p",sh,[O("b",null,G(Se(s)("mapInfo.takeaway")),1),Bt(" "+G(r(e.takeawayKey,e.takeaway)),1)])):se("",!0),d()?(C(),N("details",{key:"st-"+o.value,class:"mi-strategy"},[O("summary",rh,[O("span",null,G(Se(s)("mapInfo.tabStrategy")),1),Y[2]||(Y[2]=O("span",{class:"mi-chev","aria-hidden":"true"},"▾",-1))]),O("p",ih,G(l()),1),c().length?(C(),N("ul",lh,[(C(!0),N(ne,null,Ye(c(),(B,Q)=>(C(),N("li",{key:Q},G(B),1))),128))])):se("",!0)])):se("",!0),(C(!0),N(ne,null,Ye(e.examples,(B,Q)=>Da((C(),N("section",{key:Q,class:"mi-ex"},[O("h3",null,G(de(B)),1),B.kind==="image"?(C(),N(ne,{key:0},[O("img",{class:"mi-img mi-poster",src:X(B.src),alt:B.alt||de(B),decoding:"async",onError:le=>ee[Q]=!0},null,40,ch),B.full?(C(),N("div",ph,[O("a",{class:"mi-full",href:X(B.full),target:"_blank",rel:"noopener"},G(Se(s)("mapInfo.openFull")),9,uh)])):se("",!0)],64)):B.kind==="pages"&&(B.pages||[]).length?(C(),N(ne,{key:1},[we[Q]?(C(),N(ne,{key:1},[O("div",hh,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:le=>b(Q)},G(Se(s)("mapInfo.collapsePages")),9,bh)]),O("div",vh,[(C(!0),N(ne,null,Ye(B.pages,(le,xe)=>(C(),N("button",{key:xe,type:"button",class:"mi-hit mi-open mi-page","aria-label":Se(s)("mapInfo.collapsePages"),onClick:jt=>b(Q)},[O("img",{class:"mi-img",src:X(le),alt:de(B)+" "+m(xe+1),loading:"lazy",decoding:"async",onError:S},null,40,yh)],8,$h))),128))]),O("div",_h,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:le=>b(Q)},G(Se(s)("mapInfo.collapsePages")),9,wh)])],64)):(C(),N(ne,{key:0},[O("button",{type:"button",class:tt(["mi-hit mi-page",{"mi-stack":B.pages.length>1}]),"aria-label":Se(s)("mapInfo.expandPages",{n:m(B.pages.length)}),"aria-expanded":"false",onClick:le=>b(Q)},[O("img",{class:"mi-img",src:X(B.pages[0]),alt:de(B),decoding:"async",onError:le=>ee[Q]=!0},null,40,fh)],10,dh),B.pages.length>1?(C(),N("div",gh,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"false",onClick:le=>b(Q)},G(Se(s)("mapInfo.expandPages",{n:m(B.pages.length)})),9,mh)])):se("",!0)],64))],64)):B.kind==="deck"&&(B.cards||[]).length?(C(),N(ne,{key:2},[we[Q]?(C(),N(ne,{key:1},[O("div",Th,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:le=>b(Q)},G(Se(s)("mapInfo.collapseDeck")),9,Ph)]),O("div",Eh,[(C(!0),N(ne,null,Ye(B.cards,(le,xe)=>(C(),N("img",{key:xe,class:"mi-img",src:X(le),alt:de(B)+" "+m(xe+1),loading:"lazy",decoding:"async",onError:S},null,40,Oh))),128))]),O("div",Mh,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"true",onClick:le=>b(Q)},G(Se(s)("mapInfo.collapseDeck")),9,Ah)])],64)):(C(),N(ne,{key:0},[O("button",{type:"button",class:"mi-hit mi-deck","aria-label":Se(s)("mapInfo.expandDeck",{n:m(B.cards.length)}),"aria-expanded":"false",onClick:le=>b(Q)},[(C(!0),N(ne,null,Ye(je(B),(le,xe)=>(C(),N("img",{key:xe,class:"mi-card",src:X(le),alt:"",decoding:"async",onError:jt=>xe===0?ee[Q]=!0:S(jt),style:Ta({insetInlineStart:xe*36+"px",transform:"rotate("+(xe-2)*4+"deg)",zIndex:10-xe})},null,44,xh))),128))],8,kh),O("div",Sh,[O("button",{type:"button",class:"mi-toggle","aria-expanded":"false",onClick:le=>b(Q)},G(Se(s)("mapInfo.expandDeck",{n:m(B.cards.length)})),9,Lh)])],64))],64)):B.kind==="table"&&(B.columns||[]).length?(C(),N(ne,{key:3},[O("div",Ch,[O("table",Ih,[O("thead",null,[O("tr",null,[(C(!0),N(ne,null,Ye(B.columns,(le,xe)=>(C(),N("th",{key:xe,scope:"col"},G(Ie(le)),1))),128))])]),O("tbody",null,[(C(!0),N(ne,null,Ye(B.rows||[],(le,xe)=>(C(),N("tr",{key:xe},[(C(!0),N(ne,null,Ye(le,(jt,$b)=>(C(),N("td",{key:$b},G(typeof jt=="number"?m(jt):jt),1))),128))]))),128))])])]),B.total&&B.total>(B.rows||[]).length?(C(),N("p",Nh,G(Se(s)("mapInfo.moreRows",{n:m(B.total-(B.rows||[]).length)})),1)):se("",!0)],64)):se("",!0)])),[[Xa,!ee[Q]]])),128)),e.noteKey||e.note?(C(),N("p",Fh,G(r(e.noteKey,e.note)),1)):se("",!0)]),a()?se("",!0):(C(),N("div",Dh,[O("label",null,[O("input",{type:"checkbox",checked:_.value,onChange:Y[0]||(Y[0]=B=>F(B.target.checked))},null,40,Rh),O("span",null,G(Se(s)("mapInfo.pointerOff")),1)])]))],8,Jm)],32)):se("",!0)],8,jm))}},Wh=":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}.mi.dms-info-raise .mi-btn{z-index:60}.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 Ll(){try{const e=new URLSearchParams(location.search),t=(e.get("lang")||e.get("locale")||"").split("-")[0].toLowerCase();if(ls.includes(t))return t}catch{}try{const e=(document.documentElement.lang||"").split("-")[0].toLowerCase();if(ls.includes(e))return e}catch{}return""}const ps=[{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"},{id:"country-posters",icon:"poster"},{id:"poster-design",icon:"grid"}]},{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 qh(e){const t={},a=e&&Array.isArray(e.bundles)?e.bundles:[];for(const o of a)for(const n of Array.isArray(o&&o.profiles)?o.profiles:[])n&&(n.mobile==="desktop-only"||n.mobile==="larger-screens")&&(t[o.bundle+"/"+n.profile]=n.mobile);return t}const jh=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","posterverse","bible-posters"]),Tl={"prayer-walk-planner":1,"gospel-internet":2,"upg-neighbor":3,"key-cities":4,"all-people-groups":5,"doxa-vision-card":7},us=[{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 Posters",sub:"my unreached list + posters",emoji:"📋",bundle:"my-upg-100-list",profile:"upg-100-mfe"},{id:"country-posters",label:"Country Posters",sub:"a poster for every country",emoji:"🗺️",bundle:"country-posters",profile:"country-posters-mfe"},{id:"poster-design",label:"Poster Design",sub:"every poster style and size",emoji:"🎨",bundle:"poster-design",profile:"poster-design-mfe"}];Hh(ps);const Jo=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"]),Zo=new Set(["dashboard-plus-grid","research-map-plus-grid"]);function Uh(){const e=Object.fromEntries(us.map(a=>[a.id,a])),t=new Set;for(const a of ps)if(a.key!=="experimental")for(const o of a.tabs||[]){const n=e[o.id];n&&n.bundle&&t.add(n.bundle)}return t}function Pl(e,t){const a=[];for(const o of e)!o||t.has(o.key)||(t.add(o.key),a.push(o));return a}function Hh(e){const t=new Map,a=[];for(const o of e)if(o.key!=="experimental")for(const n of o.tabs||[]){if(!n||!n.id)continue;const s=t.get(n.id);if(s===void 0){t.set(n.id,o.key);continue}(s!==o.key||a.indexOf(n.id)===-1)&&a.push(n.id+" ("+s+" + "+o.key+")")}return a.length&&typeof console<"u"&&console.error("[doxa-maps-spa] duplicate tab key(s) across NAV_MODEL sections: "+a.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."),a}function Vh(e){return String(e).split(/[-_]/).filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}function Bh(e){const t=Uh(),a=e&&Array.isArray(e.bundles)?e.bundles:[],o=[];for(const n of a){const s=n&&n.bundle;if(!s||t.has(s)||jh.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&&o.push({id:s,label:i.title||Vh(s),sub:(i.description||"").trim().replace(/[,;]\s*$/,"")||"experimental bundle",emoji:"🧪",tag:l,bundle:s,profile:i.profile||s,scriptUrl:c,heavy:Jo.has(l)||Jo.has(s),scroll:Zo.has(l)||Zo.has(s),discovered:!0})}return o.sort((n,s)=>{const r=Tl[n.id]||999,i=Tl[s.id]||999;return r!==i?r-i:n.label.localeCompare(s.label)}),o}function Gh(e,t){const a=e&&Array.isArray(e.bundles)?e.bundles:[],o=Object.fromEntries(a.map(s=>[s.bundle,s])),n={};for(const s of t){const r=o[s.bundle];if(!r)continue;const i=Array.isArray(r.profiles)?r.profiles:[],l=i.find(L=>L.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 m=l&&Array.isArray(l.instances)?l.instances:[],y=!!(s.instance&&m.some(L=>(L&&(L.id||L.instance))===s.instance));n[s.id]={tag:c,scriptUrl:d,profile:l&&l.profile||s.profile,instance:y?s.instance:"",heavy:Jo.has(c)||Jo.has(s.bundle),scroll:Zo.has(c)||Zo.has(s.bundle)}}return n}const Kh=ma({name:"DoxaMapsSpa",inheritAttrs:!1,components:{VerticalTabsLayout:Am,BackToTopButton:oi,MapInfo:zh},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:""},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["tab-change"],setup(){return{injectedBase:ga("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:Nm(),hostLang:Ll(),localeOpen:!1,switcherLangs:Cm,tabs:us.map(e=>({...e,tag:"",scriptUrl:"",heavy:!1,scroll:!1,resolved:!1,mounted:!1,state:"idle",error:""}))}},computed:{largerScreenText(){return Zt("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?wl(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(a=>[a.id,a])),t=new Set;return ps.map(a=>{let o=Pl((a.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 a.key==="experimental"&&!this.showExperimental?{key:a.key,rows:[]}:(a.key==="experimental"&&(o=o.concat(Pl(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:a.key,label:a.i18n?this.tr(a.i18n):a.label,icon:a.icon,folder:!!a.folder,open:a.open,rows:o})}).filter(a=>a.rows.length)},showLocaleSwitcher(){return this.showHeader},activeLang(){return Im(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 ls.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","home"])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=(o,n)=>{try{const s=this._slots&&this._slots[o];s&&(s.innerHTML="")}catch{}n.mounted=!1,n.state="idle",n.error=""};this.tabs.forEach((o,n)=>{o.mounted&&n!==this.activeIndex&&e(n,o)});const t=this.activeIndex,a=this.tabs[t];!a||!a.mounted||(e(t,a),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())},infoProps(e){const{pos:t,...a}=this.infoFor(e)||{};return a},infoPos(e){const t=(this.infoFor(e)||{}).pos||{},{narrow:a,...o}=t;return this.narrow&&a?{...o,...a}:o},infoStyle(e){const t=this.infoPos(e),a={};return t.top&&(a["--map-info-top"]=t.top),t.side&&(a["--map-info-side"]=t.side),a},infoFor(e){const t=this.showInfo&&e&&Wm[e.id];return t&&(!t.leadKey||Zt(t.leadKey,"en"))?t:null},tabHasHelp(e){return!!(e&&e.discovered&&wl(e.id,this.uiLocale))},onHostedHelp(e){if(!this.activeHelp)return;e.stopPropagation();const t=e.composedPath?e.composedPath():[];this._helpReturn=t.find(a=>a&&a.tagName==="BUTTON")||null,this.openHelp()},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},tr(e,t){return Xo(this.uiLocale,e,t)},t(e,t){return Xo(this.uiLocale,e,t)},tabLabel(e){return!e.discovered||Dm("tab."+e.id)?Xo(this.uiLocale,"tab."+e.id):e.label},tabSub(e){return e.discovered?this.uiLocale==="en"?e.sub:this.tr("experimentalSub"):Xo(this.uiLocale,"sub."+e.id)},watchHostLang(){typeof MutationObserver>"u"||typeof document>"u"||(this._langObs=new MutationObserver(()=>{this.hostLang=Ll()}),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(a=>a.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 a of t.rows){const o=this.tabs.findIndex(n=>n.id===a.key);if(!(o<0)&&(e<0&&(e=o),!a.disabled))return o}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""}},a={url:e,root:t(e)},o={url:this.resolve("doxa-maps-spa/manifest.json"),root:a.root};let n=!1;try{n=new URL(e,location.href).origin!==location.origin}catch{}const s=n?[o,a]:[a,o],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:m}=s[c];return i.push(d),fetch(d,{credentials:"same-origin"}).then(y=>{if(!y||!y.ok)throw new Error(d+" → HTTP "+(y?y.status:"?"));return y.json()}).then(y=>{if(!y)throw new Error(d+" → empty");this.manifestError="",this.manifestBase=m||"",this.applyManifest(y)}).catch(()=>l(c+1))};try{l(0)}catch{}},applyManifest(e){this.runtime=e&&e.runtime&&typeof e.runtime=="object"?e.runtime:{},this.mobileFlags=qh(e),this.applyPageGlobals();const t=Gh(e,us),a=this.activeKey,o=[];for(const l of this.tabs){if(l.discovered){o.push(l);continue}const c=t[l.id];c&&(Object.assign(l,c,{resolved:!0}),o.push(l))}const n=new Set(o.map(l=>l.id));if(this.showExperimental)for(const l of Bh(e))n.has(l.id)||o.push({...l,resolved:!0,mounted:!1,state:"idle",error:""});this.tabs=o;const s=this.requestedTab(),r=s?this.tabs.findIndex(l=>l.id===s):-1,i=this.tabs.findIndex(l=>l.id===a);r>=0&&!this.isDesktopOnly(s)&&!this._honouredTab?this.select(r):this.select(i>=0&&!this.isDesktopOnly(a)?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(a=>a.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,Fm(e)},onSelect(e){if(this.isDesktopOnly(e)){const a=this.tabs.find(o=>o.id===e);this.disabledNotice=(Zt("messages.desktopOnlyNotice",this.uiLocale)||"{label} only supports desktop — open this page on a desktop to use it.").replace("{label}",a?this.tabLabel(a):e),clearTimeout(this._noticeTimer),this._noticeTimer=setTimeout(()=>{this.disabledNotice=""},4e3);return}const t=this.tabs.findIndex(a=>a.id===e);t!==-1&&this.select(t)},resolve(e){const t=String(e);if(/^(https?:)?\/\//.test(t)||t.startsWith("/"))return t;const a=t.replace(/^\.\//,"");return this.manifestBase?this.manifestBase.replace(/\/+$/,"")+"/"+a:this.base?this.base.replace(/\/+$/,"")+"/"+a:"../"+a},select(e){const t=this.activeIndex;if(this.activeIndex=e,t!==e&&t>=0){const o=this.tabs[t];o&&o.heavy&&o.mounted&&this.releaseTab(t,o)}const a=this.tabs[e];a&&((t!==e||!this._announced)&&(this._announced=!0,this.$emit("tab-change",{id:a.id,label:a.label})),a.scriptUrl&&(this.narrow&&this.mobileFlags===null||this.isDesktopOnly(a.id)||a.mounted||this.$nextTick(()=>{this.activeIndex===e&&this.mountElement(e)})))},releaseTab(e,t){try{const a=this._slots&&this._slots[e];a&&(a.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 a=this.tk||this.cfg.tk||this.runtime.token;return a&&(t.tk=a),(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.mapTitle=this.tabLabel(e),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 a=this.resolve(t.scriptUrl);vl(a).then(()=>Tg(t.tag)).then(()=>{try{if(t.heavy&&this.activeIndex!==e){t.mounted=!1,t.state="idle";return}const o=this._slots&&this._slots[e];if(!o){t.state="error",t.error="no slot";return}o.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;",o.appendChild(n),t.state="ready"}catch(o){t.state="error",t.error="mount failed: "+(o&&o.message||String(o))}}).catch(o=>{t.state="error",t.error=o&&o.message||String(o)})}}}),Xh={class:"dms-locale"},Yh=["aria-expanded"],Jh={class:"dms-flag"},Zh={class:"dms-locale-name"},Qh={key:0,class:"dms-locale-menu",role:"listbox"},eb=["aria-selected"],tb=["onClick"],ab={class:"dms-flag"},ob={class:"dms-locale-name"},nb={class:"dms-locale-en"},sb=["hidden","data-doxa-help"],rb={key:0,class:"dms-mobile-notice",role:"status"},ib=["aria-label","onClick"],lb={key:2,class:"dms-hint"},cb={key:3,class:"dms-hint err"},pb={key:4,class:"dms-hint err"},ub={key:0,class:"dms-notice",role:"status"},db={id:"dms-help-title",class:"dms-help-title"},fb={class:"dms-help-what"},gb={class:"dms-help-how"};function mb(e,t,a,o,n,s){const r=Eo("MapInfo"),i=Eo("BackToTopButton"),l=Eo("VerticalTabsLayout");return C(),$a(l,{dir:e.uiDir,lang:e.uiLocale,labels:e.layoutLabels,"home-href":e.homeHref||e.cfg.homeHref||"","home-label":e.homeLabel||e.cfg.homeLabel||"",title:e.headingText,"nav-label":e.t("navLabel"),header:e.showHeader,groups:e.navGroups,active:e.activeKey,"onUpdate:active":e.onSelect},Rc({brand:Fa(()=>[t[5]||(t[5]=O("span",{class:"dms-logo","aria-hidden":"true"},[O("svg",{viewBox:"0 0 24 24",width:"22",height:"22",fill:"none",stroke:"#92b195","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[O("circle",{cx:"12",cy:"12",r:"9"}),O("polygon",{points:"12 6 14 12 12 18 10 12",fill:"#92b195",stroke:"none"}),O("polygon",{points:"6 12 12 10 18 12 12 14",fill:"#92b195",opacity:"0.55",stroke:"none"})])],-1))]),meta:Fa(()=>[Bt(G(e.t("meta",{n:e.tabs.length})),1)]),default:Fa(()=>[(C(!0),N(ne,null,Ye(e.tabs,(c,d)=>Da((C(),N("section",{key:c.id,class:"dms-pane",ref_for:!0,ref:m=>{m?e.paneEls[d]=m:delete e.paneEls[d]},hidden:d!==e.activeIndex,"data-doxa-help":e.tabHasHelp(c)?"":null,"data-doxa-gallery":""},[!c.heavy||d===e.activeIndex?(C(),N(ne,{key:0},[e.showsMobileNotice(c.id)?(C(),N("div",rb,[O("span",null,G(e.largerScreenText),1),O("button",{type:"button",class:"dms-mobile-notice-x","aria-label":e.tr("dismiss"),onClick:m=>e.dismissMobileNotice(c.id)},"×",8,ib)])):se("",!0),O("div",{class:"dms-slot",ref_for:!0,ref:m=>e.setSlot(d,m)},null,512),e.infoFor(c)?(C(),$a(r,Ir({key:"info-"+c.id},{ref_for:!0},e.infoProps(c),{style:e.infoStyle(c),placement:e.infoPos(c).placement||"top-right",class:{"dms-info-raise":e.infoPos(c).raise},"assets-base":e.assetsBase,locale:e.effectiveLocale}),null,16,["style","placement","class","assets-base","locale"])):se("",!0),c.state==="loading"?(C(),N("div",lb,G(e.tr("loading",{label:e.tabLabel(c)})),1)):c.state==="error"?(C(),N("div",cb,[Bt(G(e.tr("loadFailed",{label:e.tabLabel(c)})),1),t[7]||(t[7]=O("br",null,null,-1)),O("small",null,G(c.error),1)])):c.state==="idle"&&!c.scriptUrl&&e.manifestError?(C(),N("div",pb,[Bt(G(e.tr("loadFailed",{label:e.tabLabel(c)})),1),t[8]||(t[8]=O("br",null,null,-1)),O("small",null,G(e.manifestError),1),t[9]||(t[9]=O("br",null,null,-1)),O("small",null,G(e.tr("manifestHint")),1)])):se("",!0)],64)):se("",!0)],8,sb)),[[Xa,d===e.activeIndex]])),128)),e.disabledNotice?(C(),N("div",ub,G(e.disabledNotice),1)):se("",!0),e.helpOpen&&e.activeHelp?(C(),N("div",{key:1,class:"dms-help-scrim",onClick:t[3]||(t[3]=zo((...c)=>e.closeHelp&&e.closeHelp(...c),["self"])),onKeydown:t[4]||(t[4]=Qr(zo((...c)=>e.closeHelp&&e.closeHelp(...c),["stop","prevent"]),["esc"]))},[O("div",{class:"dms-help",role:"dialog","aria-modal":"true","aria-labelledby":"dms-help-title",onKeydown:t[2]||(t[2]=Qr(zo(c=>e.$refs.helpClose&&e.$refs.helpClose.focus(),["prevent"]),["tab"]))},[O("h2",db,G(e.tabLabel(e.tabs[e.activeIndex])),1),O("p",fb,[O("strong",null,G(e.activeHelp.what),1)]),O("p",gb,G(e.activeHelp.how),1),O("button",{ref:"helpClose",type:"button",class:"dms-help-close",onClick:t[1]||(t[1]=(...c)=>e.closeHelp&&e.closeHelp(...c))},G(e.tr("close")),513)],32)],32)):se("",!0),We(i,{target:e.activePaneEl,labels:{backToTop:e.tr("backToTop")}},null,8,["target","labels"])]),_:2},[e.showLocaleSwitcher?{name:"toolbar",fn:Fa(()=>[O("div",Xh,[O("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)},[O("span",Jh,G(e.activeLang.flag),1),O("span",Zh,G(e.activeLang.nativeName),1),t[6]||(t[6]=O("span",{class:"dms-dots","aria-hidden":"true"},"⋮",-1))],8,Yh),e.localeOpen?(C(),N("ul",Qh,[(C(!0),N(ne,null,Ye(e.switcherLangs,c=>(C(),N("li",{key:c.code,role:"option","aria-selected":String(c.code===e.locale)},[O("button",{type:"button",class:tt(["dms-locale-opt",{active:c.code===e.locale}]),onClick:d=>e.setLocale(c.code)},[O("span",ab,G(c.flag),1),O("span",ob,G(c.nativeName),1),O("span",nb,G(c.name),1)],10,tb)],8,eb))),128))])):se("",!0)])]),key:"0"}:void 0]),1032,["dir","lang","labels","home-href","home-label","title","nav-label","header","groups","active","onUpdate:active"])}const hb=zn(Kh,[["render",mb],["styles",[Wh]]]),bb=Pg(),vb=Bp(hb,{configureApp(e){e.provide("dmsTreeBase",bb)}});typeof customElements<"u"&&!customElements.get("doxa-maps-spa")&&customElements.define("doxa-maps-spa",vb)})(); 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 1c8376b69..9833d218f 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 @@ -67,7 +67,7 @@ - + - + \n\n\n" + }, + "bundle": "bible-posters" + } + ] + }, { "bundle": "big-picture", "scriptUrl": "./big-picture/big-picture.js", @@ -361,7 +393,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-eMJnHI1Ed2HY5E2Zx0NpfPeu0upkZUhFg8sffdCZbsz9UP+rnWwQEtSTolFHcQxu", + "integrity": "sha384-XHR1mr4ln+rjjfizRrEKhU6y7/F35fb8gE/t7lmrTklC+E5ahrKp+dhhQFaaUPX6", "elements": [ "doxa-maps-spa" ], @@ -391,7 +423,7 @@ "scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { @@ -1134,7 +1166,7 @@ "bundle": "posterverse", "scriptUrl": "./posterverse/posterverse.js", "output": "dx-maps/posterverse/posterverse.js", - "integrity": "sha384-4JtSJ3JzXdoM1lWlRDeXMk8o5rwS76yF8Q6vf4OYtAhDziW4ZBKBfqvU09h6BLDR", + "integrity": "sha384-ln9GWhcuFxqkae3O6cotRVPmYfuwvxKtut6/mNJ7FCinDSlNqybkC8FGBQlGE0QV", "elements": [ "posterverse-app" ], @@ -1142,7 +1174,8 @@ "my-upg-100-list/upg-100-mfe", "country-posters/country-posters-mfe", "poster-design/poster-design-mfe", - "wall-of-people-groups/wall-of-people-groups" + "wall-of-people-groups/wall-of-people-groups", + "bible-posters/bible-posters" ], "stage": "experimental", "profiles": [ @@ -1159,7 +1192,7 @@ "scriptUrl": "./posterverse/posterverse.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { diff --git a/public/dx-maps/manifest.json b/public/dx-maps/manifest.json index f91a87fd0..48a5fa6d9 100644 --- a/public/dx-maps/manifest.json +++ b/public/dx-maps/manifest.json @@ -2,8 +2,8 @@ "schema": "doxa-maps-manifest@1", "generatedFrom": "plugin-designs/*/*.vue", "embedBase": ".", - "bundleCount": 27, - "profileCount": 41, + "bundleCount": 28, + "profileCount": 42, "runtime": { "apiBaseUrl": "https://pray.doxa.life" }, @@ -37,6 +37,38 @@ } ] }, + { + "bundle": "bible-posters", + "scriptUrl": "./bible-posters/bible-posters.js", + "output": "dx-maps/bible-posters/bible-posters.js", + "integrity": "sha384-x0qrqnzFOHxhCWZN4YYpnME08TLUQdfMI8oR5cAnQDtOVKu133/27BXcHCr0Ev7Q", + "elements": [ + "bible-posters" + ], + "stage": "experimental", + "profiles": [ + { + "profile": "bible-posters", + "stage": "experimental", + "label": "Bible Posters", + "targets": [ + "web" + ], + "file": "bible-posters.vue", + "description": "", + "element": "bible-posters", + "type": "single", + "isMap": false, + "iframeUrl": "./bible-posters/bible-posters/index.html", + "scriptUrl": "./bible-posters/bible-posters.js", + "embed": { + "iframe": "", + "script": "\n\n\n" + }, + "bundle": "bible-posters" + } + ] + }, { "bundle": "big-picture", "scriptUrl": "./big-picture/big-picture.js", @@ -361,7 +393,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-eMJnHI1Ed2HY5E2Zx0NpfPeu0upkZUhFg8sffdCZbsz9UP+rnWwQEtSTolFHcQxu", + "integrity": "sha384-XHR1mr4ln+rjjfizRrEKhU6y7/F35fb8gE/t7lmrTklC+E5ahrKp+dhhQFaaUPX6", "elements": [ "doxa-maps-spa" ], @@ -391,7 +423,7 @@ "scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { @@ -1134,7 +1166,7 @@ "bundle": "posterverse", "scriptUrl": "./posterverse/posterverse.js", "output": "dx-maps/posterverse/posterverse.js", - "integrity": "sha384-4JtSJ3JzXdoM1lWlRDeXMk8o5rwS76yF8Q6vf4OYtAhDziW4ZBKBfqvU09h6BLDR", + "integrity": "sha384-ln9GWhcuFxqkae3O6cotRVPmYfuwvxKtut6/mNJ7FCinDSlNqybkC8FGBQlGE0QV", "elements": [ "posterverse-app" ], @@ -1142,7 +1174,8 @@ "my-upg-100-list/upg-100-mfe", "country-posters/country-posters-mfe", "poster-design/poster-design-mfe", - "wall-of-people-groups/wall-of-people-groups" + "wall-of-people-groups/wall-of-people-groups", + "bible-posters/bible-posters" ], "stage": "experimental", "profiles": [ @@ -1159,7 +1192,7 @@ "scriptUrl": "./posterverse/posterverse.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { diff --git a/public/dx-maps/posterverse/posterverse.js b/public/dx-maps/posterverse/posterverse.js index 1f4dc4e95..e2d8d3e4f 100644 --- a/public/dx-maps/posterverse/posterverse.js +++ b/public/dx-maps/posterverse/posterverse.js @@ -159,4 +159,4 @@ @media (prefers-reduced-motion: reduce) { .vtl-nav, .vtl-collapse-ic, .vtl-tab, .vtl-tier, .vtl-pbar, .vtl-phone-menu, .vtl-rail-end, .vtl-scrim { transition: none !important; animation: none !important; } } -`,Al=Yo({name:"VerticalTabsLayout",components:{BackToTopButton:vr},props:{active:{type:String,default:""},title:{type:String,default:""},items:{type:Array,default:()=>[]},groups:{type:Array,default:()=>[]},navLabel:{type:String,default:"Sections"},labels:{type:Object,default:()=>({})},initialNavOpen:{type:Boolean,default:!0},header:{type:Boolean,default:!0},initialRailCollapsed:{type:Boolean,default:!1},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["update:active"],setup(){return vl(Pl,"vertical-tabs-layout"),{T:Ml}},data(){return{navOpen:this.initialNavOpen,railCollapsed:this.initialRailCollapsed,_tabEls:{},folderOverride:{},narrow:!1,_mql:null,_onMedia:null,activatedKeys:{},hostState:{},hostError:{},_hostSlots:{},_hostMounted:{},hostEls:{}}},computed:{phoneBarShown(){return this.narrow&&!this.header},railEndShown(){return!this.narrow&&!this.header},activeHostEl(){return this.hostEls[this.active]||null},railShown(){return this.narrow?this.navOpen:!0},homeLink(){const e=String(this.homeHref||"").trim();return!e||/^(javascript|data|vbscript):/i.test(e.replace(/[\u0000- ]/g,""))?"":e},homeText(){return this.homeLabel||this.label("home")},allRows(){if(this.groups&&this.groups.length){const e=[];for(const t of this.groups)for(const o of t.rows||[])e.push(o);return e}return this.items},orderedKeys(){return this.allRows.map(e=>e.key)},elementRows(){return this.allRows.filter(e=>e&&e.element)},mountedElementRows(){return this.elementRows.filter(e=>this.activatedKeys[e.key])}},watch:{active:{immediate:!0,handler(e){this.activateElement(e)}}},mounted(){try{window.matchMedia&&(this._mql=window.matchMedia("(max-width: 760px)"),this.narrow=this._mql.matches,this.reconcileForWidth(),this._onMedia=e=>{this.narrow=e.matches,this.reconcileForWidth()},this._mql.addEventListener?this._mql.addEventListener("change",this._onMedia):this._mql.addListener&&this._mql.addListener(this._onMedia))}catch{}this.$nextTick(()=>this.activateElement(this.active))},beforeUnmount(){try{this._mql&&this._onMedia&&(this._mql.removeEventListener?this._mql.removeEventListener("change",this._onMedia):this._mql.removeListener&&this._mql.removeListener(this._onMedia))}catch{}this._mql=null,this._onMedia=null},methods:{registerTab(e,t){t&&(this._tabEls[e]=t)},isNarrow(){return this.narrow},reconcileForWidth(){this.narrow?(this.navOpen=!1,this.railCollapsed=!1):this.navOpen=!0},label(e){const t={toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse",home:"Back to homepage"};return this.labels&&this.labels[e]||t[e]},expandRail(){!this.narrow&&this.railCollapsed&&(this.railCollapsed=!1)},toggleRail(){this.narrow?this.navOpen=!this.navOpen:this.railCollapsed=!this.railCollapsed},setHostSlot(e,t){t&&(this._hostSlots[e]=t,this.$nextTick(()=>this.mountHostElement(e)))},activateElement(e){!e||!this.elementRows.find(o=>o.key===e)||(this.activatedKeys[e]||(this.activatedKeys={...this.activatedKeys,[e]:!0},this.$nextTick(()=>this.watchContextLoss(e)),this.hostState={...this.hostState,[e]:"loading"}),this.$nextTick(()=>this.mountHostElement(e)))},deepCanvases(e,t=[]){if(!e)return t;for(const o of e.querySelectorAll("*"))o.tagName==="CANVAS"&&t.push(o),o.shadowRoot&&this.deepCanvases(o.shadowRoot,t);return t},watchContextLoss(e){const t=this._hostSlots[e];if(t)for(const o of this.deepCanvases(t))o.__vtlLossBound||(o.__vtlLossBound=!0,o.addEventListener("webglcontextlost",()=>{this.hostState={...this.hostState,[e]:"lost"}},{once:!0}))},reloadHostElement(e){const t=this._hostSlots[e];t&&(t.innerHTML=""),this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"loading"},this.$nextTick(()=>this.mountHostElement(e))},mountHostElement(e){if(this._hostMounted[e])return;const t=this.elementRows.find(n=>n.key===e),o=this._hostSlots[e];!t||!o||(this._hostMounted[e]=!0,this.hostState={...this.hostState,[e]:"loading"},Ll(t.src).then(()=>Ol(t.element)).then(()=>{xl(t.element,t.src),o.innerHTML="";const n=document.createElement(t.element),s=t.attrs||{};for(const r in s){const a=s[r],i=a!=null&&typeof a=="object"?JSON.stringify(a):String(a);try{n[r]=a}catch{}try{n.setAttribute(r,i)}catch{}}n.style.cssText="display:block;position:absolute;inset:0;width:100%;height:100%;",o.appendChild(n);for(const r of[0,250,1500])setTimeout(()=>this.watchContextLoss(e),r);this.hostState={...this.hostState,[e]:"ready"}}).catch(n=>{this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"error"},this.hostError={...this.hostError,[e]:n&&n.message||String(n)}}))},iconSvg(e){return e?yl(e):""},initial(e){const t=(e||"").trim();return t?t.charAt(0).toUpperCase():"•"},isFolderClosed(e){const t=this.folderOverride[e.key];return t!=null?!t:e.open!==!0},toggleFolder(e){const t=this.folderOverride[e],o=(this.groups||[]).find(s=>s.key===e),n=t??(o&&o.open===!0);this.folderOverride={...this.folderOverride,[e]:!n}},pick(e){this.$emit("update:active",e),this.narrow&&(this.navOpen=!1)},onKey(e){const t=this.orderedKeys;if(!t.length)return;const o=t.indexOf(this.active);let n=-1;if(e.key==="ArrowDown"||e.key==="ArrowRight")n=(o+1)%t.length;else if(e.key==="ArrowUp"||e.key==="ArrowLeft")n=(o-1+t.length)%t.length;else if(e.key==="Home")n=0;else if(e.key==="End")n=t.length-1;else return;e.preventDefault();const s=t[n];this.pick(s),this.$nextTick(()=>{const r=this._tabEls[s];r&&r.focus&&r.focus()})}}}),Cl={key:0,class:"vtl-top"},Fl=["aria-expanded","aria-label"],Il={class:"vtl-brand"},Nl={class:"vtl-title"},El={class:"vtl-meta"},Rl={key:1,class:"vtl-pbar"},Wl=["aria-expanded","aria-label"],Dl={class:"vtl-pbar-end"},zl={class:"vtl-body"},Hl=["aria-label","aria-hidden","role","aria-orientation"],Bl=["href","aria-label","title"],Ul=["innerHTML"],jl={class:"vtl-home-tx"},Vl=["aria-expanded","aria-label"],ql=["innerHTML"],Kl={class:"vtl-collapse-tx"},Gl=["aria-expanded","onClick"],Jl={key:0,class:"vtl-cap"},Xl={class:"vtl-tl"},Zl={key:1,class:"vtl-td"},Yl=["innerHTML"],Ql={key:1,class:"vtl-tier"},ec={key:0,class:"vtl-cap"},tc={class:"vtl-tl"},oc={key:1,class:"vtl-td"},nc={class:"vtl-rows"},sc=["aria-selected","aria-disabled","tabindex","onClick"],rc=["innerHTML"],ic={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},ac={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},lc={class:"vtl-tab-text"},cc={class:"vtl-tab-label"},pc={key:0,class:"vtl-tab-badge"},dc={key:0,class:"vtl-tab-sub"},uc=["innerHTML"],fc=["aria-selected","aria-disabled","tabindex","onClick"],hc=["innerHTML"],gc={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},mc={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},$c={class:"vtl-tab-text"},bc={class:"vtl-tab-label"},vc={key:0,class:"vtl-tab-sub"},_c={key:4,class:"vtl-rail-end"},yc={class:"vtl-main"},wc={class:"vtl-content"},xc=["hidden"],kc={key:0,class:"vtl-host-hint"},Tc={key:1,class:"vtl-host-hint"},Sc=["onClick"],Mc={key:2,class:"vtl-host-hint err"};function Lc(e,t,o,n,s,r){const a=tn("BackToTopButton");return A(),F("div",{class:Ke(["vtl",{"nav-open":e.navOpen,"rail-collapsed":e.railCollapsed,"no-header":!e.header,"has-phone-bar":e.phoneBarShown}])},[e.header?(A(),F("header",Cl,[I("button",{class:"vtl-menu",type:"button","aria-expanded":String(e.navOpen),onClick:t[0]||(t[0]=i=>e.navOpen=!e.navOpen),"aria-label":e.label("toggleList")},"☰",8,Fl),I("span",Il,[tt(e.$slots,"brand")]),I("b",Nl,D(e.title),1),I("span",El,[tt(e.$slots,"meta")])])):ie("",!0),e.phoneBarShown?(A(),F("div",Rl,[I("button",{class:"vtl-phone-menu",type:"button","aria-expanded":String(e.navOpen),onClick:t[1]||(t[1]=i=>e.navOpen=!e.navOpen),"aria-label":e.label("toggleList")},"☰",8,Wl),I("span",Dl,[tt(e.$slots,"phone-end")])])):ie("",!0),e.narrow?(A(),At(a,{key:2,target:e.activeHostEl,labels:{backToTop:e.T("actions.backToTop","Back to top")}},null,8,["target","labels"])):ie("",!0),I("div",zl,[I("nav",{class:Ke(["vtl-nav",{"has-rail-end":e.railEndShown&&!!e.$slots["rail-end"]}]),"aria-label":e.navLabel,"aria-hidden":String(!e.railShown),role:e.$slots.rail?null:"tablist","aria-orientation":e.$slots.rail?null:"vertical"},[e.homeLink?(A(),F("a",{key:0,class:"vtl-home",href:e.homeLink,target:"_top","aria-label":e.homeText,title:e.railCollapsed&&!e.narrow?e.homeText:null},[I("span",{class:"vtl-home-ic","aria-hidden":"true",innerHTML:e.iconSvg("home")},null,8,Ul),I("span",jl,D(e.homeText),1)],8,Bl)):ie("",!0),I("button",{type:"button",class:"vtl-collapse","aria-expanded":String(!e.railCollapsed),"aria-label":e.railCollapsed?e.label("expandList"):e.label("collapseList"),onClick:t[2]||(t[2]=(...i)=>e.toggleRail&&e.toggleRail(...i))},[I("span",{class:"vtl-collapse-ic","aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,8,ql),I("span",Kl,D(e.label("collapse")),1)],8,Vl),e.$slots.rail?tt(e.$slots,"rail",{collapsed:e.railCollapsed&&!e.narrow,expand:e.expandRail,pick:e.pick},void 0,void 0,1):e.groups&&e.groups.length?(A(!0),F(oe,{key:2},Mt(e.groups,i=>(A(),F("div",{class:"vtl-grp",key:i.key},[i.folder?(A(),F("button",{key:0,type:"button",class:"vtl-tier vtl-tier-btn","aria-expanded":String(!e.isFolderClosed(i)),onClick:l=>e.toggleFolder(i.key)},[i.badge?(A(),F("span",Jl,D(i.badge),1)):ie("",!0),I("span",Xl,D(i.label),1),i.count!=null?(A(),F("span",Zl,D(i.count),1)):ie("",!0),I("span",{class:Ke(["vtl-chev",{open:!e.isFolderClosed(i)}]),"aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,10,Yl)],8,Gl)):(A(),F("div",Ql,[i.badge?(A(),F("span",ec,D(i.badge),1)):ie("",!0),I("span",tc,D(i.label),1),i.count!=null?(A(),F("span",oc,D(i.count),1)):ie("",!0)])),Jo(I("div",nc,[(A(!0),F(oe,null,Mt(i.rows,l=>(A(),F("button",{key:l.key,type:"button",role:"tab",class:Ke(["vtl-tab",{active:l.key===e.active,disabled:l.disabled}]),"aria-selected":String(l.key===e.active),"aria-disabled":l.disabled?"true":null,tabindex:l.key===e.active?0:-1,ref_for:!0,ref:p=>e.registerTab(l.key,p),onClick:p=>e.pick(l.key),onKeydown:t[3]||(t[3]=p=>e.onKey(p))},[l.icon?(A(),F("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(l.icon)},null,8,rc)):l.emoji?(A(),F("span",ic,D(l.emoji),1)):(A(),F("span",ac,D(e.initial(l.label)),1)),I("span",lc,[I("span",cc,[gt(D(l.label),1),l.badge?(A(),F("span",pc,D(l.badge),1)):ie("",!0)]),l.sub?(A(),F("span",dc,[I("span",{innerHTML:l.sub},null,8,uc)])):ie("",!0)])],42,sc))),128))],512),[[gn,!i.folder||!e.isFolderClosed(i)]])]))),128)):(A(!0),F(oe,{key:3},Mt(e.items,i=>(A(),F("button",{key:i.key,type:"button",role:"tab",class:Ke(["vtl-tab",{active:i.key===e.active,disabled:i.disabled}]),"aria-selected":String(i.key===e.active),"aria-disabled":i.disabled?"true":null,tabindex:i.key===e.active?0:-1,ref_for:!0,ref:l=>e.registerTab(i.key,l),onClick:l=>e.pick(i.key),onKeydown:t[4]||(t[4]=l=>e.onKey(l))},[i.icon?(A(),F("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(i.icon)},null,8,hc)):i.emoji?(A(),F("span",gc,D(i.emoji),1)):(A(),F("span",mc,D(e.initial(i.label)),1)),I("span",$c,[I("span",bc,D(i.label),1),i.sub?(A(),F("span",vc,D(i.sub),1)):ie("",!0)])],42,fc))),128)),e.railEndShown&&e.$slots["rail-end"]?(A(),F("div",_c,[tt(e.$slots,"rail-end",{collapsed:e.railCollapsed})])):ie("",!0)],10,Hl),I("main",yc,[e.header?tt(e.$slots,"toolbar",{},void 0,void 0,0):ie("",!0),I("div",wc,[(A(!0),F(oe,null,Mt(e.mountedElementRows,i=>Jo((A(),F("section",{key:i.key,class:"vtl-host",hidden:i.key!==e.active,ref_for:!0,ref:l=>{l?e.hostEls[i.key]=l:delete e.hostEls[i.key]}},[I("div",{class:"vtl-host-slot",ref_for:!0,ref:l=>e.setHostSlot(i.key,l)},null,512),e.hostState[i.key]==="loading"?(A(),F("div",kc,D(e.T("messages.loadingNamed","Loading {name}…").replace("{name}",i.label)),1)):e.hostState[i.key]==="lost"?(A(),F("div",Tc,[gt(D(e.T("messages.mapContextLost","This map was unloaded to free graphics memory."))+" ",1),I("button",{type:"button",class:"vtl-host-reload",onClick:l=>e.reloadHostElement(i.key)},D(e.T("buttons.reloadMap","Reload Map")),9,Sc)])):e.hostState[i.key]==="error"?(A(),F("div",Mc,[gt(D(e.T("messages.couldNotLoadNamed","Could not load {name}.").replace("{name}",i.label)),1),t[5]||(t[5]=I("br",null,null,-1)),I("small",null,D(e.hostError[i.key]),1)])):ie("",!0)],8,xc)),[[gn,i.key===e.active]])),128)),tt(e.$slots,"default")])])])],2)}const Oc=vn(Al,[["render",Lc],["styles",[Sl]]]),_o={en:{"sec.posters":"Posters","sec.experimental":"Experimental","tab.upg-100":"UPG 100 List Posters","sub.upg-100":"my unreached list + posters","tab.country-posters":"Country Posters","sub.country-posters":"a poster for every country","tab.poster-design":"Poster Design","sub.poster-design":"every poster style and size","tab.wall-of-people-groups":"Wall of People Groups","tab.bible-posters":"Bible Posters",experimentalSub:"experimental bundle",lab:"lab",loading:"Loading {label}…",loadFailed:"Could not load {label}.",manifestHint:"This tab is composed from manifest.json — build the tree, or serve the built tree, to load it.",backToTop:"Back to top",home:"Back to homepage",toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse"},es:{"sec.posters":"Carteles","sec.experimental":"Experimental","tab.upg-100":"Carteles de la lista UPG 100","sub.upg-100":"mi lista de no alcanzados + carteles","tab.country-posters":"Carteles por país","sub.country-posters":"un cartel para cada país","tab.poster-design":"Diseño de carteles","sub.poster-design":"todos los estilos y tamaños de cartel","tab.wall-of-people-groups":"Muro de los pueblos","tab.bible-posters":"Carteles bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Cargando {label}…",loadFailed:"No se pudo cargar {label}.",manifestHint:"Esta pestaña se compone a partir de manifest.json: compila el árbol o sirve el árbol compilado para cargarla.",backToTop:"Volver arriba",home:"Volver a la página de inicio",toggleList:"Mostrar u ocultar la lista",openViews:"Abrir la lista de vistas",expandList:"Expandir la lista",collapseList:"Contraer la lista",collapse:"Contraer"},fr:{"sec.posters":"Affiches","sec.experimental":"Expérimental","tab.upg-100":"Affiches de la liste UPG 100","sub.upg-100":"ma liste des non atteints + affiches","tab.country-posters":"Affiches par pays","sub.country-posters":"une affiche pour chaque pays","tab.poster-design":"Conception d’affiches","sub.poster-design":"tous les styles et formats d’affiche","tab.wall-of-people-groups":"Mur des peuples","tab.bible-posters":"Affiches bibliques",experimentalSub:"carte expérimentale",lab:"bêta",loading:"Chargement de {label}…",loadFailed:"Impossible de charger {label}.",manifestHint:"Cet onglet est composé à partir de manifest.json : construisez l'arborescence ou servez l'arborescence construite pour le charger.",backToTop:"Retour en haut",home:"Retour à l’accueil",toggleList:"Afficher ou masquer la liste",openViews:"Ouvrir la liste des vues",expandList:"Déplier la liste",collapseList:"Replier la liste",collapse:"Replier"},de:{"sec.posters":"Poster","sec.experimental":"Experimentell","tab.upg-100":"Poster der UPG 100 Liste","sub.upg-100":"meine Liste der Unerreichten + Poster","tab.country-posters":"Länderposter","sub.country-posters":"ein Poster für jedes Land","tab.poster-design":"Postergestaltung","sub.poster-design":"alle Posterstile und -größen","tab.wall-of-people-groups":"Wand der Volksgruppen","tab.bible-posters":"Bibelposter",experimentalSub:"experimentelle Karte",lab:"Beta",loading:"{label} wird geladen…",loadFailed:"{label} konnte nicht geladen werden.",manifestHint:"Dieser Tab wird aus manifest.json zusammengesetzt – bauen Sie den Baum oder stellen Sie den gebauten Baum bereit, um ihn zu laden.",backToTop:"Nach oben",home:"Zurück zur Startseite",toggleList:"Liste ein-/ausblenden",openViews:"Ansichtsliste öffnen",expandList:"Liste ausklappen",collapseList:"Liste einklappen",collapse:"Einklappen"},pt:{"sec.posters":"Cartazes","sec.experimental":"Experimental","tab.upg-100":"Cartazes da lista UPG 100","sub.upg-100":"minha lista de não alcançados + cartazes","tab.country-posters":"Cartazes por país","sub.country-posters":"um cartaz para cada país","tab.poster-design":"Design de cartazes","sub.poster-design":"todos os estilos e tamanhos de cartaz","tab.wall-of-people-groups":"Mural dos povos","tab.bible-posters":"Cartazes bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Carregando {label}…",loadFailed:"Não foi possível carregar {label}.",manifestHint:"Esta aba é composta a partir do manifest.json — compile a árvore ou sirva a árvore compilada para carregá-la.",backToTop:"Voltar ao topo",home:"Voltar à página inicial",toggleList:"Mostrar ou ocultar a lista",openViews:"Abrir a lista de visualizações",expandList:"Expandir a lista",collapseList:"Recolher a lista",collapse:"Recolher"},it:{"sec.posters":"Poster","sec.experimental":"Sperimentale","tab.upg-100":"Poster della lista UPG 100","sub.upg-100":"la mia lista dei non raggiunti + poster","tab.country-posters":"Poster per paese","sub.country-posters":"un poster per ogni paese","tab.poster-design":"Design dei poster","sub.poster-design":"tutti gli stili e i formati dei poster","tab.wall-of-people-groups":"Muro dei popoli","tab.bible-posters":"Poster biblici",experimentalSub:"mappa sperimentale",lab:"beta",loading:"Caricamento di {label}…",loadFailed:"Impossibile caricare {label}.",manifestHint:"Questa scheda è composta da manifest.json: compila l'albero o pubblica l'albero compilato per caricarla.",backToTop:"Torna su",home:"Torna alla home page",toggleList:"Mostra o nascondi l’elenco",openViews:"Apri l’elenco delle viste",expandList:"Espandi l’elenco",collapseList:"Comprimi l’elenco",collapse:"Comprimi"},ro:{"sec.posters":"Afișe","sec.experimental":"Experimental","tab.upg-100":"Afișe din lista UPG 100","sub.upg-100":"lista mea de neatinși + afișe","tab.country-posters":"Afișe pe țări","sub.country-posters":"un afiș pentru fiecare țară","tab.poster-design":"Design de afișe","sub.poster-design":"toate stilurile și dimensiunile de afiș","tab.wall-of-people-groups":"Zidul popoarelor","tab.bible-posters":"Afișe biblice",experimentalSub:"hartă experimentală",lab:"beta",loading:"Se încarcă {label}…",loadFailed:"{label} nu a putut fi încărcat.",manifestHint:"Această filă este compusă din manifest.json — construiți arborele sau serviți arborele construit pentru a o încărca.",backToTop:"Sus",home:"Înapoi la pagina principală",toggleList:"Afișează sau ascunde lista",openViews:"Deschide lista de vizualizări",expandList:"Extinde lista",collapseList:"Restrânge lista",collapse:"Restrânge"},ru:{"sec.posters":"Плакаты","sec.experimental":"Экспериментальное","tab.upg-100":"Плакаты списка UPG 100","sub.upg-100":"мой список недостигнутых + плакаты","tab.country-posters":"Плакаты по странам","sub.country-posters":"плакат для каждой страны","tab.poster-design":"Дизайн плакатов","sub.poster-design":"все стили и размеры плакатов","tab.wall-of-people-groups":"Стена народов","tab.bible-posters":"Библейские плакаты",experimentalSub:"экспериментальная карта",lab:"бета",loading:"Загрузка: {label}…",loadFailed:"Не удалось загрузить: {label}.",manifestHint:"Эта вкладка собирается из manifest.json — соберите дерево или разместите собранное дерево, чтобы загрузить её.",backToTop:"Наверх",home:"На главную страницу",toggleList:"Показать или скрыть список",openViews:"Открыть список представлений",expandList:"Развернуть список",collapseList:"Свернуть список",collapse:"Свернуть"},ar:{"sec.posters":"ملصقات","sec.experimental":"تجريبي","tab.upg-100":"ملصقات قائمة UPG 100","sub.upg-100":"قائمتي لغير المُبشَّرين + ملصقات","tab.country-posters":"ملصقات الدول","sub.country-posters":"ملصق لكل دولة","tab.poster-design":"تصميم الملصقات","sub.poster-design":"كل أنماط الملصقات وأحجامها","tab.wall-of-people-groups":"جدار الشعوب","tab.bible-posters":"ملصقات الكتاب المقدس",experimentalSub:"خريطة تجريبية",lab:"تجريبي",loading:"جارٍ تحميل {label}…",loadFailed:"تعذّر تحميل {label}.",manifestHint:"تُبنى علامة التبويب هذه من manifest.json — ابنِ الشجرة أو قدّم الشجرة المبنية لتحميلها.",backToTop:"إلى الأعلى",home:"العودة إلى الصفحة الرئيسية",toggleList:"إظهار القائمة أو إخفاؤها",openViews:"فتح قائمة العروض",expandList:"توسيع القائمة",collapseList:"طي القائمة",collapse:"طي"},hi:{"sec.posters":"पोस्टर","sec.experimental":"प्रायोगिक","tab.upg-100":"UPG 100 सूची पोस्टर","sub.upg-100":"मेरी अप्राप्त सूची + पोस्टर","tab.country-posters":"देश पोस्टर","sub.country-posters":"हर देश के लिए एक पोस्टर","tab.poster-design":"पोस्टर डिज़ाइन","sub.poster-design":"हर पोस्टर शैली और आकार","tab.wall-of-people-groups":"जनसमूहों की दीवार","tab.bible-posters":"बाइबल पोस्टर",experimentalSub:"प्रायोगिक मानचित्र",lab:"बीटा",loading:"{label} लोड हो रहा है…",loadFailed:"{label} लोड नहीं हो सका।",manifestHint:"यह टैब manifest.json से बनता है — इसे लोड करने के लिए ट्री बनाएँ या बना हुआ ट्री सर्व करें।",backToTop:"ऊपर जाएँ",home:"होमपेज पर वापस जाएँ",toggleList:"सूची दिखाएँ या छिपाएँ",openViews:"दृश्यों की सूची खोलें",expandList:"सूची फैलाएँ",collapseList:"सूची संक्षिप्त करें",collapse:"संक्षिप्त करें"},zh:{"sec.posters":"海报","sec.experimental":"实验性","tab.upg-100":"UPG 100 名单海报","sub.upg-100":"我的未得之民名单 + 海报","tab.country-posters":"国家海报","sub.country-posters":"每个国家一张海报","tab.poster-design":"海报设计","sub.poster-design":"所有海报样式与尺寸","tab.wall-of-people-groups":"民族之墙","tab.bible-posters":"圣经海报",experimentalSub:"实验性地图",lab:"测试版",loading:"正在加载{label}…",loadFailed:"无法加载{label}。",manifestHint:"此标签页由 manifest.json 组成——请构建目录树或提供已构建的目录树以加载它。",backToTop:"回到顶部",home:"返回首页",toggleList:"显示或隐藏列表",openViews:"打开视图列表",expandList:"展开列表",collapseList:"折叠列表",collapse:"折叠"}},wn=Object.keys(_o);function Pc(e,t,o){let s=(_o[e]||_o.en)[t]??_o.en[t]??t;if(o)for(const r in o)s=s.split("{"+r+"}").join(String(o[r]));return s}const Ac=[{key:"posters",i18n:"sec.posters",icon:"poster"},{key:"experimental",i18n:"sec.experimental",icon:"flask",folder:!0,open:!1}],Or=[{id:"upg-100",section:"posters",icon:"list",bundle:"my-upg-100-list",profile:"upg-100-mfe"},{id:"country-posters",section:"posters",icon:"map",bundle:"country-posters",profile:"country-posters-mfe"},{id:"poster-design",section:"posters",icon:"poster",bundle:"poster-design",profile:"poster-design-mfe"},{id:"wall-of-people-groups",section:"experimental",icon:"flask",bundle:"wall-of-people-groups",profile:"wall-of-people-groups"},{id:"bible-posters",section:"experimental",icon:"flask",bundle:"bible-posters",profile:"bible-posters",provisional:!0}],Cc=new Set(["key-cities","posterverse","doxa-maps-spa","plugin-studio"]),Fc=new Set(["my-upg-100-list-map","country-posters-map"]);function Ic(e,t=()=>{}){const o=e&&Array.isArray(e.bundles)?e.bundles:[],n=Object.fromEntries(o.map(r=>[r&&r.bundle,r])),s=[];for(const r of Or){if(Cc.has(r.bundle))continue;const a=n[r.bundle];if(!a)continue;const i=Array.isArray(a.profiles)?a.profiles:[];let l=i.find(h=>h&&h.profile===r.profile);if(!l){if(l=i.find(h=>h&&h.profile===r.bundle)||i[0],!l)continue;t(`[posterverse] ${r.bundle} has no profile "${r.profile}"; row "${r.id}" opens "${l.profile}" instead`)}const p=l.element||Array.isArray(a.elements)&&a.elements[0]||r.bundle,d=a.scriptUrl||l.scriptUrl||"";d&&s.push({...r,tag:p,scriptUrl:d,profile:l.profile,heavy:Fc.has(p)||!!l.isMap})}return s}const Nc=":host{display:block;position:relative;height:var(--posterverse-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}.pv-pane{position:absolute;top:0;right:0;bottom:0;left:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;--profile-min-h: 0}.pv-slot{position:relative;min-height:100%}.pv-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}.pv-hint.err{color:#b3261e}.pv-hint small{color:#6d766e}";function Pr(){try{const e=new URLSearchParams(location.search),t=(e.get("lang")||e.get("locale")||"").split("-")[0].toLowerCase();if(wn.includes(t))return t}catch{}try{const e=(document.documentElement.lang||"").split("-")[0].toLowerCase();if(wn.includes(e))return e}catch{}return""}const Ar=e=>({...e,tag:e.tag||"",scriptUrl:e.scriptUrl||"",heavy:!!e.heavy,mounted:!1,state:"idle",error:""}),Ec=Yo({name:"Posterverse",inheritAttrs:!1,components:{VerticalTabsLayout:Oc,BackToTopButton:vr},props:{treeBase:{type:String,default:""},profileConfig:{type:[String,Object],default:""},heading:{type:String,default:"Posterverse"},tokenUrl:{type:String,default:""},tk:{type:String,default:""},language:{type:String,default:""},apiBaseUrl:{type:String,default:""},provider:{type:String,default:""},tab:{type:String,default:""},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["tab-change"],setup(){return{injectedBase:Tt("pvTreeBase","")}},data(){return{paneEls:{},activeIndex:0,manifestError:"",manifestBase:"",runtime:{},hostLang:Pr(),tabs:Or.filter(e=>!e.provisional).map(Ar)}},computed:{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=String(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":""},headingText(){return String(this.cfg.heading||this.heading||"").trim()||"Posterverse"},effectiveLocale(){return(String(this.language||this.cfg.language||this.cfg.locale||this.cfg.lang||"").trim()||this.hostLang||"en").split("-")[0].toLowerCase()},uiLocale(){return wn.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","home"])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:""},activePaneEl(){return this.paneEls[this.activeIndex]||null},navGroups(){return Ac.map(e=>({key:e.key,label:this.tr(e.i18n),icon:e.icon,folder:!!e.folder,open:e.open,rows:this.tabs.filter(t=>t.section===e.key).map(t=>({key:t.id,label:this.tabLabel(t),sub:this.tabSub(t),icon:t.icon,badge:e.folder?this.tr("lab"):void 0}))})).filter(e=>e.rows.length)}},watch:{effectiveLocale(){const e=(o,n)=>{try{const s=this._slots&&this._slots[o];s&&(s.innerHTML="")}catch{}n.mounted=!1,n.state="idle",n.error=""};this.tabs.forEach((o,n)=>{o.mounted&&n!==this.activeIndex&&e(n,o)});const t=this.tabs[this.activeIndex];!t||!t.mounted||(e(this.activeIndex,t),this.mountElement(this.activeIndex))},tab(e){e&&this.onSelect(e)}},mounted(){this.watchHostLang(),this.select(this.initialIndex()),this.loadManifest()},beforeUnmount(){this._langObs&&(this._langObs.disconnect(),this._langObs=null)},methods:{tr(e,t){return Pc(this.uiLocale,e,t)},tabLabel(e){return this.tr("tab."+e.id)},tabSub(e){return e.section==="experimental"?this.tr("experimentalSub"):this.tr("sub."+e.id)},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},watchHostLang(){typeof MutationObserver>"u"||typeof document>"u"||(this._langObs=new MutationObserver(()=>{this.hostLang=Pr()}),this._langObs.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]}))},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.tabs.findIndex(t=>t.id===this.requestedTab());return e>=0?e:0},loadManifest(){const e=p=>{try{return new URL(p,location.href).href.replace(/[^/]*$/,"")}catch{return""}},t=this.resolve("manifest.json"),o={url:t,root:e(t)},n={url:this.resolve("doxa-maps-spa/manifest.json"),root:o.root};let s=!1;try{s=new URL(t,location.href).origin!==location.origin}catch{}const r=s?[n,o]:[o,n],a="/public/dx-maps/manifest.json";r.some(p=>p.url===a)||r.push({url:a,root:e(a)});const i=[],l=p=>{if(p>=r.length){this.manifestError="manifest.json not found (tried "+i.join(", ")+")",console.error("[posterverse] "+this.manifestError+" — every tab is composed from it.");return}const{url:d,root:h}=r[p];return i.push(d),fetch(d,{credentials:"same-origin"}).then(w=>{if(!w||!w.ok)throw new Error(d+" → HTTP "+(w?w.status:"?"));return w.json()}).then(w=>{if(!w)throw new Error(d+" → empty");this.manifestError="",this.manifestBase=h||"",this.applyManifest(w)}).catch(()=>l(p+1))};try{l(0)}catch{}},applyManifest(e){this.runtime=e&&e.runtime&&typeof e.runtime=="object"?e.runtime:{},this.applyPageGlobals();const t=this.activeKey;this.tabs=Ic(e,r=>console.warn(r)).map(Ar);const o=this.requestedTab(),n=!this._honouredTab&&o?this.tabs.findIndex(r=>r.id===o):-1,s=this.tabs.findIndex(r=>r.id===t);this._honouredTab=!0,this.select(n>=0?n:s>=0?s:0)},onSelect(e){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 n=this.tabs[t];n&&n.heavy&&n.mounted&&this.releaseTab(t,n)}const o=this.tabs[e];o&&((t!==e||!this._announced)&&(this._announced=!0,this.$emit("tab-change",{id:o.id,label:this.tabLabel(o)})),o.scriptUrl&&(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:"pv-"+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.mapTitle=this.tabLabel(e),t},applyPageGlobals(){if(typeof window>"u")return;const e=String(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",Lr(this.resolve(t.scriptUrl)).then(()=>kl(t.tag)).then(()=>{try{if(t.heavy&&this.activeIndex!==e){t.mounted=!1,t.state="idle";return}const o=this._slots&&this._slots[e];if(!o){t.state="error",t.error="no slot";return}o.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="display:block;position:absolute;inset:0;width:100%;height:100%;min-height:0;",o.appendChild(n),t.state="ready"}catch(o){t.state="error",t.error="mount failed: "+(o&&o.message||String(o))}}).catch(o=>{t.state="error",t.error=o&&o.message||String(o)})}}}),Rc=["hidden"],Wc={key:0,class:"pv-hint"},Dc={key:1,class:"pv-hint err"},zc={key:2,class:"pv-hint err"};function Hc(e,t,o,n,s,r){const a=tn("BackToTopButton"),i=tn("VerticalTabsLayout");return A(),At(i,{dir:e.uiDir,lang:e.uiLocale,labels:e.layoutLabels,title:e.headingText,"nav-label":e.tr("sec.posters"),header:!1,"home-href":e.homeHref||e.cfg.homeHref||"","home-label":e.homeLabel||e.cfg.homeLabel||"",groups:e.navGroups,active:e.activeKey,"onUpdate:active":e.onSelect},{default:ds(()=>[(A(!0),F(oe,null,Mt(e.tabs,(l,p)=>Jo((A(),F("section",{key:l.id,class:"pv-pane",ref_for:!0,ref:d=>{d?e.paneEls[p]=d:delete e.paneEls[p]},hidden:p!==e.activeIndex},[!l.heavy||p===e.activeIndex?(A(),F(oe,{key:0},[I("div",{class:"pv-slot",ref_for:!0,ref:d=>e.setSlot(p,d)},null,512),l.state==="loading"?(A(),F("div",Wc,D(e.tr("loading",{label:e.tabLabel(l)})),1)):l.state==="error"?(A(),F("div",Dc,[gt(D(e.tr("loadFailed",{label:e.tabLabel(l)})),1),t[0]||(t[0]=I("br",null,null,-1)),I("small",null,D(l.error),1)])):l.state==="idle"&&!l.scriptUrl&&e.manifestError?(A(),F("div",zc,[gt(D(e.tr("loadFailed",{label:e.tabLabel(l)})),1),t[1]||(t[1]=I("br",null,null,-1)),I("small",null,D(e.manifestError),1),t[2]||(t[2]=I("br",null,null,-1)),I("small",null,D(e.tr("manifestHint")),1)])):ie("",!0)],64)):ie("",!0)],8,Rc)),[[gn,p===e.activeIndex]])),128)),be(a,{target:e.activePaneEl,labels:{backToTop:e.tr("backToTop")}},null,8,["target","labels"])]),_:1},8,["dir","lang","labels","title","nav-label","home-href","home-label","groups","active","onUpdate:active"])}const Bc=vn(Ec,[["render",Hc],["styles",[Nc]]]),Uc=Tl(),jc=nl(Bc,{configureApp(e){e.provide("pvTreeBase",Uc)}});typeof customElements<"u"&&!customElements.get("posterverse-app")&&customElements.define("posterverse-app",jc)})(); +`,Al=Yo({name:"VerticalTabsLayout",components:{BackToTopButton:vr},props:{active:{type:String,default:""},title:{type:String,default:""},items:{type:Array,default:()=>[]},groups:{type:Array,default:()=>[]},navLabel:{type:String,default:"Sections"},labels:{type:Object,default:()=>({})},initialNavOpen:{type:Boolean,default:!0},header:{type:Boolean,default:!0},initialRailCollapsed:{type:Boolean,default:!1},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["update:active"],setup(){return vl(Pl,"vertical-tabs-layout"),{T:Ml}},data(){return{navOpen:this.initialNavOpen,railCollapsed:this.initialRailCollapsed,_tabEls:{},folderOverride:{},narrow:!1,_mql:null,_onMedia:null,activatedKeys:{},hostState:{},hostError:{},_hostSlots:{},_hostMounted:{},hostEls:{}}},computed:{phoneBarShown(){return this.narrow&&!this.header},railEndShown(){return!this.narrow&&!this.header},activeHostEl(){return this.hostEls[this.active]||null},railShown(){return this.narrow?this.navOpen:!0},homeLink(){const e=String(this.homeHref||"").trim();return!e||/^(javascript|data|vbscript):/i.test(e.replace(/[\u0000- ]/g,""))?"":e},homeText(){return this.homeLabel||this.label("home")},allRows(){if(this.groups&&this.groups.length){const e=[];for(const t of this.groups)for(const o of t.rows||[])e.push(o);return e}return this.items},orderedKeys(){return this.allRows.map(e=>e.key)},elementRows(){return this.allRows.filter(e=>e&&e.element)},mountedElementRows(){return this.elementRows.filter(e=>this.activatedKeys[e.key])}},watch:{active:{immediate:!0,handler(e){this.activateElement(e)}}},mounted(){try{window.matchMedia&&(this._mql=window.matchMedia("(max-width: 760px)"),this.narrow=this._mql.matches,this.reconcileForWidth(),this._onMedia=e=>{this.narrow=e.matches,this.reconcileForWidth()},this._mql.addEventListener?this._mql.addEventListener("change",this._onMedia):this._mql.addListener&&this._mql.addListener(this._onMedia))}catch{}this.$nextTick(()=>this.activateElement(this.active))},beforeUnmount(){try{this._mql&&this._onMedia&&(this._mql.removeEventListener?this._mql.removeEventListener("change",this._onMedia):this._mql.removeListener&&this._mql.removeListener(this._onMedia))}catch{}this._mql=null,this._onMedia=null},methods:{registerTab(e,t){t&&(this._tabEls[e]=t)},isNarrow(){return this.narrow},reconcileForWidth(){this.narrow?(this.navOpen=!1,this.railCollapsed=!1):this.navOpen=!0},label(e){const t={toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse",home:"Back to homepage"};return this.labels&&this.labels[e]||t[e]},expandRail(){!this.narrow&&this.railCollapsed&&(this.railCollapsed=!1)},toggleRail(){this.narrow?this.navOpen=!this.navOpen:this.railCollapsed=!this.railCollapsed},setHostSlot(e,t){t&&(this._hostSlots[e]=t,this.$nextTick(()=>this.mountHostElement(e)))},activateElement(e){!e||!this.elementRows.find(o=>o.key===e)||(this.activatedKeys[e]||(this.activatedKeys={...this.activatedKeys,[e]:!0},this.$nextTick(()=>this.watchContextLoss(e)),this.hostState={...this.hostState,[e]:"loading"}),this.$nextTick(()=>this.mountHostElement(e)))},deepCanvases(e,t=[]){if(!e)return t;for(const o of e.querySelectorAll("*"))o.tagName==="CANVAS"&&t.push(o),o.shadowRoot&&this.deepCanvases(o.shadowRoot,t);return t},watchContextLoss(e){const t=this._hostSlots[e];if(t)for(const o of this.deepCanvases(t))o.__vtlLossBound||(o.__vtlLossBound=!0,o.addEventListener("webglcontextlost",()=>{this.hostState={...this.hostState,[e]:"lost"}},{once:!0}))},reloadHostElement(e){const t=this._hostSlots[e];t&&(t.innerHTML=""),this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"loading"},this.$nextTick(()=>this.mountHostElement(e))},mountHostElement(e){if(this._hostMounted[e])return;const t=this.elementRows.find(n=>n.key===e),o=this._hostSlots[e];!t||!o||(this._hostMounted[e]=!0,this.hostState={...this.hostState,[e]:"loading"},Ll(t.src).then(()=>Ol(t.element)).then(()=>{xl(t.element,t.src),o.innerHTML="";const n=document.createElement(t.element),s=t.attrs||{};for(const r in s){const a=s[r],i=a!=null&&typeof a=="object"?JSON.stringify(a):String(a);try{n[r]=a}catch{}try{n.setAttribute(r,i)}catch{}}n.style.cssText="display:block;position:absolute;inset:0;width:100%;height:100%;",o.appendChild(n);for(const r of[0,250,1500])setTimeout(()=>this.watchContextLoss(e),r);this.hostState={...this.hostState,[e]:"ready"}}).catch(n=>{this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"error"},this.hostError={...this.hostError,[e]:n&&n.message||String(n)}}))},iconSvg(e){return e?yl(e):""},initial(e){const t=(e||"").trim();return t?t.charAt(0).toUpperCase():"•"},isFolderClosed(e){const t=this.folderOverride[e.key];return t!=null?!t:e.open!==!0},toggleFolder(e){const t=this.folderOverride[e],o=(this.groups||[]).find(s=>s.key===e),n=t??(o&&o.open===!0);this.folderOverride={...this.folderOverride,[e]:!n}},pick(e){this.$emit("update:active",e),this.narrow&&(this.navOpen=!1)},onKey(e){const t=this.orderedKeys;if(!t.length)return;const o=t.indexOf(this.active);let n=-1;if(e.key==="ArrowDown"||e.key==="ArrowRight")n=(o+1)%t.length;else if(e.key==="ArrowUp"||e.key==="ArrowLeft")n=(o-1+t.length)%t.length;else if(e.key==="Home")n=0;else if(e.key==="End")n=t.length-1;else return;e.preventDefault();const s=t[n];this.pick(s),this.$nextTick(()=>{const r=this._tabEls[s];r&&r.focus&&r.focus()})}}}),Cl={key:0,class:"vtl-top"},Fl=["aria-expanded","aria-label"],Il={class:"vtl-brand"},Nl={class:"vtl-title"},El={class:"vtl-meta"},Rl={key:1,class:"vtl-pbar"},Wl=["aria-expanded","aria-label"],Dl={class:"vtl-pbar-end"},zl={class:"vtl-body"},Hl=["aria-label","aria-hidden","role","aria-orientation"],Bl=["href","aria-label","title"],Ul=["innerHTML"],jl={class:"vtl-home-tx"},Vl=["aria-expanded","aria-label"],ql=["innerHTML"],Kl={class:"vtl-collapse-tx"},Gl=["aria-expanded","onClick"],Jl={key:0,class:"vtl-cap"},Xl={class:"vtl-tl"},Zl={key:1,class:"vtl-td"},Yl=["innerHTML"],Ql={key:1,class:"vtl-tier"},ec={key:0,class:"vtl-cap"},tc={class:"vtl-tl"},oc={key:1,class:"vtl-td"},nc={class:"vtl-rows"},sc=["aria-selected","aria-disabled","tabindex","onClick"],rc=["innerHTML"],ic={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},ac={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},lc={class:"vtl-tab-text"},cc={class:"vtl-tab-label"},pc={key:0,class:"vtl-tab-badge"},dc={key:0,class:"vtl-tab-sub"},uc=["innerHTML"],fc=["aria-selected","aria-disabled","tabindex","onClick"],hc=["innerHTML"],gc={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},mc={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},$c={class:"vtl-tab-text"},bc={class:"vtl-tab-label"},vc={key:0,class:"vtl-tab-sub"},_c={key:4,class:"vtl-rail-end"},yc={class:"vtl-main"},wc={class:"vtl-content"},xc=["hidden"],kc={key:0,class:"vtl-host-hint"},Tc={key:1,class:"vtl-host-hint"},Sc=["onClick"],Mc={key:2,class:"vtl-host-hint err"};function Lc(e,t,o,n,s,r){const a=tn("BackToTopButton");return A(),F("div",{class:Ke(["vtl",{"nav-open":e.navOpen,"rail-collapsed":e.railCollapsed,"no-header":!e.header,"has-phone-bar":e.phoneBarShown}])},[e.header?(A(),F("header",Cl,[I("button",{class:"vtl-menu",type:"button","aria-expanded":String(e.navOpen),onClick:t[0]||(t[0]=i=>e.navOpen=!e.navOpen),"aria-label":e.label("toggleList")},"☰",8,Fl),I("span",Il,[tt(e.$slots,"brand")]),I("b",Nl,D(e.title),1),I("span",El,[tt(e.$slots,"meta")])])):ie("",!0),e.phoneBarShown?(A(),F("div",Rl,[I("button",{class:"vtl-phone-menu",type:"button","aria-expanded":String(e.navOpen),onClick:t[1]||(t[1]=i=>e.navOpen=!e.navOpen),"aria-label":e.label("toggleList")},"☰",8,Wl),I("span",Dl,[tt(e.$slots,"phone-end")])])):ie("",!0),e.narrow?(A(),At(a,{key:2,target:e.activeHostEl,labels:{backToTop:e.T("actions.backToTop","Back to top")}},null,8,["target","labels"])):ie("",!0),I("div",zl,[I("nav",{class:Ke(["vtl-nav",{"has-rail-end":e.railEndShown&&!!e.$slots["rail-end"]}]),"aria-label":e.navLabel,"aria-hidden":String(!e.railShown),role:e.$slots.rail?null:"tablist","aria-orientation":e.$slots.rail?null:"vertical"},[e.homeLink?(A(),F("a",{key:0,class:"vtl-home",href:e.homeLink,target:"_top","aria-label":e.homeText,title:e.railCollapsed&&!e.narrow?e.homeText:null},[I("span",{class:"vtl-home-ic","aria-hidden":"true",innerHTML:e.iconSvg("home")},null,8,Ul),I("span",jl,D(e.homeText),1)],8,Bl)):ie("",!0),I("button",{type:"button",class:"vtl-collapse","aria-expanded":String(!e.railCollapsed),"aria-label":e.railCollapsed?e.label("expandList"):e.label("collapseList"),onClick:t[2]||(t[2]=(...i)=>e.toggleRail&&e.toggleRail(...i))},[I("span",{class:"vtl-collapse-ic","aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,8,ql),I("span",Kl,D(e.label("collapse")),1)],8,Vl),e.$slots.rail?tt(e.$slots,"rail",{collapsed:e.railCollapsed&&!e.narrow,expand:e.expandRail,pick:e.pick},void 0,void 0,1):e.groups&&e.groups.length?(A(!0),F(oe,{key:2},Mt(e.groups,i=>(A(),F("div",{class:"vtl-grp",key:i.key},[i.folder?(A(),F("button",{key:0,type:"button",class:"vtl-tier vtl-tier-btn","aria-expanded":String(!e.isFolderClosed(i)),onClick:l=>e.toggleFolder(i.key)},[i.badge?(A(),F("span",Jl,D(i.badge),1)):ie("",!0),I("span",Xl,D(i.label),1),i.count!=null?(A(),F("span",Zl,D(i.count),1)):ie("",!0),I("span",{class:Ke(["vtl-chev",{open:!e.isFolderClosed(i)}]),"aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,10,Yl)],8,Gl)):(A(),F("div",Ql,[i.badge?(A(),F("span",ec,D(i.badge),1)):ie("",!0),I("span",tc,D(i.label),1),i.count!=null?(A(),F("span",oc,D(i.count),1)):ie("",!0)])),Jo(I("div",nc,[(A(!0),F(oe,null,Mt(i.rows,l=>(A(),F("button",{key:l.key,type:"button",role:"tab",class:Ke(["vtl-tab",{active:l.key===e.active,disabled:l.disabled}]),"aria-selected":String(l.key===e.active),"aria-disabled":l.disabled?"true":null,tabindex:l.key===e.active?0:-1,ref_for:!0,ref:p=>e.registerTab(l.key,p),onClick:p=>e.pick(l.key),onKeydown:t[3]||(t[3]=p=>e.onKey(p))},[l.icon?(A(),F("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(l.icon)},null,8,rc)):l.emoji?(A(),F("span",ic,D(l.emoji),1)):(A(),F("span",ac,D(e.initial(l.label)),1)),I("span",lc,[I("span",cc,[gt(D(l.label),1),l.badge?(A(),F("span",pc,D(l.badge),1)):ie("",!0)]),l.sub?(A(),F("span",dc,[I("span",{innerHTML:l.sub},null,8,uc)])):ie("",!0)])],42,sc))),128))],512),[[gn,!i.folder||!e.isFolderClosed(i)]])]))),128)):(A(!0),F(oe,{key:3},Mt(e.items,i=>(A(),F("button",{key:i.key,type:"button",role:"tab",class:Ke(["vtl-tab",{active:i.key===e.active,disabled:i.disabled}]),"aria-selected":String(i.key===e.active),"aria-disabled":i.disabled?"true":null,tabindex:i.key===e.active?0:-1,ref_for:!0,ref:l=>e.registerTab(i.key,l),onClick:l=>e.pick(i.key),onKeydown:t[4]||(t[4]=l=>e.onKey(l))},[i.icon?(A(),F("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(i.icon)},null,8,hc)):i.emoji?(A(),F("span",gc,D(i.emoji),1)):(A(),F("span",mc,D(e.initial(i.label)),1)),I("span",$c,[I("span",bc,D(i.label),1),i.sub?(A(),F("span",vc,D(i.sub),1)):ie("",!0)])],42,fc))),128)),e.railEndShown&&e.$slots["rail-end"]?(A(),F("div",_c,[tt(e.$slots,"rail-end",{collapsed:e.railCollapsed})])):ie("",!0)],10,Hl),I("main",yc,[e.header?tt(e.$slots,"toolbar",{},void 0,void 0,0):ie("",!0),I("div",wc,[(A(!0),F(oe,null,Mt(e.mountedElementRows,i=>Jo((A(),F("section",{key:i.key,class:"vtl-host",hidden:i.key!==e.active,ref_for:!0,ref:l=>{l?e.hostEls[i.key]=l:delete e.hostEls[i.key]}},[I("div",{class:"vtl-host-slot",ref_for:!0,ref:l=>e.setHostSlot(i.key,l)},null,512),e.hostState[i.key]==="loading"?(A(),F("div",kc,D(e.T("messages.loadingNamed","Loading {name}…").replace("{name}",i.label)),1)):e.hostState[i.key]==="lost"?(A(),F("div",Tc,[gt(D(e.T("messages.mapContextLost","This map was unloaded to free graphics memory."))+" ",1),I("button",{type:"button",class:"vtl-host-reload",onClick:l=>e.reloadHostElement(i.key)},D(e.T("buttons.reloadMap","Reload Map")),9,Sc)])):e.hostState[i.key]==="error"?(A(),F("div",Mc,[gt(D(e.T("messages.couldNotLoadNamed","Could not load {name}.").replace("{name}",i.label)),1),t[5]||(t[5]=I("br",null,null,-1)),I("small",null,D(e.hostError[i.key]),1)])):ie("",!0)],8,xc)),[[gn,i.key===e.active]])),128)),tt(e.$slots,"default")])])])],2)}const Oc=vn(Al,[["render",Lc],["styles",[Sl]]]),_o={en:{"sec.posters":"Posters","sec.experimental":"Experimental","tab.upg-100":"UPG 100 List Posters","sub.upg-100":"my unreached list + posters","tab.country-posters":"Country Posters","sub.country-posters":"a poster for every country","tab.poster-design":"Poster Design","sub.poster-design":"every poster style and size","tab.wall-of-people-groups":"Wall of People Groups","tab.bible-posters":"Bible Posters",experimentalSub:"experimental bundle",lab:"lab",loading:"Loading {label}…",loadFailed:"Could not load {label}.",manifestHint:"This tab is composed from manifest.json — build the tree, or serve the built tree, to load it.",backToTop:"Back to top",home:"Back to homepage",toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse"},es:{"sec.posters":"Carteles","sec.experimental":"Experimental","tab.upg-100":"Carteles de la lista UPG 100","sub.upg-100":"mi lista de no alcanzados + carteles","tab.country-posters":"Carteles por país","sub.country-posters":"un cartel para cada país","tab.poster-design":"Diseño de carteles","sub.poster-design":"todos los estilos y tamaños de cartel","tab.wall-of-people-groups":"Muro de los pueblos","tab.bible-posters":"Carteles bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Cargando {label}…",loadFailed:"No se pudo cargar {label}.",manifestHint:"Esta pestaña se compone a partir de manifest.json: compila el árbol o sirve el árbol compilado para cargarla.",backToTop:"Volver arriba",home:"Volver a la página de inicio",toggleList:"Mostrar u ocultar la lista",openViews:"Abrir la lista de vistas",expandList:"Expandir la lista",collapseList:"Contraer la lista",collapse:"Contraer"},fr:{"sec.posters":"Affiches","sec.experimental":"Expérimental","tab.upg-100":"Affiches de la liste UPG 100","sub.upg-100":"ma liste des non atteints + affiches","tab.country-posters":"Affiches par pays","sub.country-posters":"une affiche pour chaque pays","tab.poster-design":"Conception d’affiches","sub.poster-design":"tous les styles et formats d’affiche","tab.wall-of-people-groups":"Mur des peuples","tab.bible-posters":"Affiches bibliques",experimentalSub:"carte expérimentale",lab:"bêta",loading:"Chargement de {label}…",loadFailed:"Impossible de charger {label}.",manifestHint:"Cet onglet est composé à partir de manifest.json : construisez l'arborescence ou servez l'arborescence construite pour le charger.",backToTop:"Retour en haut",home:"Retour à l’accueil",toggleList:"Afficher ou masquer la liste",openViews:"Ouvrir la liste des vues",expandList:"Déplier la liste",collapseList:"Replier la liste",collapse:"Replier"},de:{"sec.posters":"Poster","sec.experimental":"Experimentell","tab.upg-100":"Poster der UPG 100 Liste","sub.upg-100":"meine Liste der Unerreichten + Poster","tab.country-posters":"Länderposter","sub.country-posters":"ein Poster für jedes Land","tab.poster-design":"Postergestaltung","sub.poster-design":"alle Posterstile und -größen","tab.wall-of-people-groups":"Wand der Volksgruppen","tab.bible-posters":"Bibelposter",experimentalSub:"experimentelle Karte",lab:"Beta",loading:"{label} wird geladen…",loadFailed:"{label} konnte nicht geladen werden.",manifestHint:"Dieser Tab wird aus manifest.json zusammengesetzt – bauen Sie den Baum oder stellen Sie den gebauten Baum bereit, um ihn zu laden.",backToTop:"Nach oben",home:"Zurück zur Startseite",toggleList:"Liste ein-/ausblenden",openViews:"Ansichtsliste öffnen",expandList:"Liste ausklappen",collapseList:"Liste einklappen",collapse:"Einklappen"},pt:{"sec.posters":"Cartazes","sec.experimental":"Experimental","tab.upg-100":"Cartazes da lista UPG 100","sub.upg-100":"minha lista de não alcançados + cartazes","tab.country-posters":"Cartazes por país","sub.country-posters":"um cartaz para cada país","tab.poster-design":"Design de cartazes","sub.poster-design":"todos os estilos e tamanhos de cartaz","tab.wall-of-people-groups":"Mural dos povos","tab.bible-posters":"Cartazes bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Carregando {label}…",loadFailed:"Não foi possível carregar {label}.",manifestHint:"Esta aba é composta a partir do manifest.json — compile a árvore ou sirva a árvore compilada para carregá-la.",backToTop:"Voltar ao topo",home:"Voltar à página inicial",toggleList:"Mostrar ou ocultar a lista",openViews:"Abrir a lista de visualizações",expandList:"Expandir a lista",collapseList:"Recolher a lista",collapse:"Recolher"},it:{"sec.posters":"Poster","sec.experimental":"Sperimentale","tab.upg-100":"Poster della lista UPG 100","sub.upg-100":"la mia lista dei non raggiunti + poster","tab.country-posters":"Poster per paese","sub.country-posters":"un poster per ogni paese","tab.poster-design":"Design dei poster","sub.poster-design":"tutti gli stili e i formati dei poster","tab.wall-of-people-groups":"Muro dei popoli","tab.bible-posters":"Poster biblici",experimentalSub:"mappa sperimentale",lab:"beta",loading:"Caricamento di {label}…",loadFailed:"Impossibile caricare {label}.",manifestHint:"Questa scheda è composta da manifest.json: compila l'albero o pubblica l'albero compilato per caricarla.",backToTop:"Torna su",home:"Torna alla home page",toggleList:"Mostra o nascondi l’elenco",openViews:"Apri l’elenco delle viste",expandList:"Espandi l’elenco",collapseList:"Comprimi l’elenco",collapse:"Comprimi"},ro:{"sec.posters":"Afișe","sec.experimental":"Experimental","tab.upg-100":"Afișe din lista UPG 100","sub.upg-100":"lista mea de neatinși + afișe","tab.country-posters":"Afișe pe țări","sub.country-posters":"un afiș pentru fiecare țară","tab.poster-design":"Design de afișe","sub.poster-design":"toate stilurile și dimensiunile de afiș","tab.wall-of-people-groups":"Zidul popoarelor","tab.bible-posters":"Afișe biblice",experimentalSub:"hartă experimentală",lab:"beta",loading:"Se încarcă {label}…",loadFailed:"{label} nu a putut fi încărcat.",manifestHint:"Această filă este compusă din manifest.json — construiți arborele sau serviți arborele construit pentru a o încărca.",backToTop:"Sus",home:"Înapoi la pagina principală",toggleList:"Afișează sau ascunde lista",openViews:"Deschide lista de vizualizări",expandList:"Extinde lista",collapseList:"Restrânge lista",collapse:"Restrânge"},ru:{"sec.posters":"Плакаты","sec.experimental":"Экспериментальное","tab.upg-100":"Плакаты списка UPG 100","sub.upg-100":"мой список недостигнутых + плакаты","tab.country-posters":"Плакаты по странам","sub.country-posters":"плакат для каждой страны","tab.poster-design":"Дизайн плакатов","sub.poster-design":"все стили и размеры плакатов","tab.wall-of-people-groups":"Стена народов","tab.bible-posters":"Библейские плакаты",experimentalSub:"экспериментальная карта",lab:"бета",loading:"Загрузка: {label}…",loadFailed:"Не удалось загрузить: {label}.",manifestHint:"Эта вкладка собирается из manifest.json — соберите дерево или разместите собранное дерево, чтобы загрузить её.",backToTop:"Наверх",home:"На главную страницу",toggleList:"Показать или скрыть список",openViews:"Открыть список представлений",expandList:"Развернуть список",collapseList:"Свернуть список",collapse:"Свернуть"},ar:{"sec.posters":"ملصقات","sec.experimental":"تجريبي","tab.upg-100":"ملصقات قائمة UPG 100","sub.upg-100":"قائمتي لغير المُبشَّرين + ملصقات","tab.country-posters":"ملصقات الدول","sub.country-posters":"ملصق لكل دولة","tab.poster-design":"تصميم الملصقات","sub.poster-design":"كل أنماط الملصقات وأحجامها","tab.wall-of-people-groups":"جدار الشعوب","tab.bible-posters":"ملصقات الكتاب المقدس",experimentalSub:"خريطة تجريبية",lab:"تجريبي",loading:"جارٍ تحميل {label}…",loadFailed:"تعذّر تحميل {label}.",manifestHint:"تُبنى علامة التبويب هذه من manifest.json — ابنِ الشجرة أو قدّم الشجرة المبنية لتحميلها.",backToTop:"إلى الأعلى",home:"العودة إلى الصفحة الرئيسية",toggleList:"إظهار القائمة أو إخفاؤها",openViews:"فتح قائمة العروض",expandList:"توسيع القائمة",collapseList:"طي القائمة",collapse:"طي"},hi:{"sec.posters":"पोस्टर","sec.experimental":"प्रायोगिक","tab.upg-100":"UPG 100 सूची पोस्टर","sub.upg-100":"मेरी अप्राप्त सूची + पोस्टर","tab.country-posters":"देश पोस्टर","sub.country-posters":"हर देश के लिए एक पोस्टर","tab.poster-design":"पोस्टर डिज़ाइन","sub.poster-design":"हर पोस्टर शैली और आकार","tab.wall-of-people-groups":"जनसमूहों की दीवार","tab.bible-posters":"बाइबल पोस्टर",experimentalSub:"प्रायोगिक मानचित्र",lab:"बीटा",loading:"{label} लोड हो रहा है…",loadFailed:"{label} लोड नहीं हो सका।",manifestHint:"यह टैब manifest.json से बनता है — इसे लोड करने के लिए ट्री बनाएँ या बना हुआ ट्री सर्व करें।",backToTop:"ऊपर जाएँ",home:"होमपेज पर वापस जाएँ",toggleList:"सूची दिखाएँ या छिपाएँ",openViews:"दृश्यों की सूची खोलें",expandList:"सूची फैलाएँ",collapseList:"सूची संक्षिप्त करें",collapse:"संक्षिप्त करें"},zh:{"sec.posters":"海报","sec.experimental":"实验性","tab.upg-100":"UPG 100 名单海报","sub.upg-100":"我的未得之民名单 + 海报","tab.country-posters":"国家海报","sub.country-posters":"每个国家一张海报","tab.poster-design":"海报设计","sub.poster-design":"所有海报样式与尺寸","tab.wall-of-people-groups":"民族之墙","tab.bible-posters":"圣经海报",experimentalSub:"实验性地图",lab:"测试版",loading:"正在加载{label}…",loadFailed:"无法加载{label}。",manifestHint:"此标签页由 manifest.json 组成——请构建目录树或提供已构建的目录树以加载它。",backToTop:"回到顶部",home:"返回首页",toggleList:"显示或隐藏列表",openViews:"打开视图列表",expandList:"展开列表",collapseList:"折叠列表",collapse:"折叠"}},wn=Object.keys(_o);function Pc(e,t,o){let s=(_o[e]||_o.en)[t]??_o.en[t]??t;if(o)for(const r in o)s=s.split("{"+r+"}").join(String(o[r]));return s}const Ac=[{key:"posters",i18n:"sec.posters",icon:"poster"},{key:"experimental",i18n:"sec.experimental",icon:"flask",folder:!0,open:!1}],Or=[{id:"upg-100",section:"posters",icon:"list",bundle:"my-upg-100-list",profile:"upg-100-mfe"},{id:"country-posters",section:"posters",icon:"map",bundle:"country-posters",profile:"country-posters-mfe"},{id:"poster-design",section:"posters",icon:"poster",bundle:"poster-design",profile:"poster-design-mfe"},{id:"wall-of-people-groups",section:"experimental",icon:"flask",bundle:"wall-of-people-groups",profile:"wall-of-people-groups"},{id:"bible-posters",section:"experimental",icon:"flask",bundle:"bible-posters",profile:"bible-posters"}],Cc=new Set(["key-cities","posterverse","doxa-maps-spa","plugin-studio"]),Fc=new Set(["my-upg-100-list-map","country-posters-map"]);function Ic(e,t=()=>{}){const o=e&&Array.isArray(e.bundles)?e.bundles:[],n=Object.fromEntries(o.map(r=>[r&&r.bundle,r])),s=[];for(const r of Or){if(Cc.has(r.bundle))continue;const a=n[r.bundle];if(!a)continue;const i=Array.isArray(a.profiles)?a.profiles:[];let l=i.find(h=>h&&h.profile===r.profile);if(!l){if(l=i.find(h=>h&&h.profile===r.bundle)||i[0],!l)continue;t(`[posterverse] ${r.bundle} has no profile "${r.profile}"; row "${r.id}" opens "${l.profile}" instead`)}const p=l.element||Array.isArray(a.elements)&&a.elements[0]||r.bundle,d=a.scriptUrl||l.scriptUrl||"";d&&s.push({...r,tag:p,scriptUrl:d,profile:l.profile,heavy:Fc.has(p)||!!l.isMap})}return s}const Nc=":host{display:block;position:relative;height:var(--posterverse-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}.pv-pane{position:absolute;top:0;right:0;bottom:0;left:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;--profile-min-h: 0}.pv-slot{position:relative;min-height:100%}.pv-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}.pv-hint.err{color:#b3261e}.pv-hint small{color:#6d766e}";function Pr(){try{const e=new URLSearchParams(location.search),t=(e.get("lang")||e.get("locale")||"").split("-")[0].toLowerCase();if(wn.includes(t))return t}catch{}try{const e=(document.documentElement.lang||"").split("-")[0].toLowerCase();if(wn.includes(e))return e}catch{}return""}const Ar=e=>({...e,tag:e.tag||"",scriptUrl:e.scriptUrl||"",heavy:!!e.heavy,mounted:!1,state:"idle",error:""}),Ec=Yo({name:"Posterverse",inheritAttrs:!1,components:{VerticalTabsLayout:Oc,BackToTopButton:vr},props:{treeBase:{type:String,default:""},profileConfig:{type:[String,Object],default:""},heading:{type:String,default:"Posterverse"},tokenUrl:{type:String,default:""},tk:{type:String,default:""},language:{type:String,default:""},apiBaseUrl:{type:String,default:""},provider:{type:String,default:""},tab:{type:String,default:""},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["tab-change"],setup(){return{injectedBase:Tt("pvTreeBase","")}},data(){return{paneEls:{},activeIndex:0,manifestError:"",manifestBase:"",runtime:{},hostLang:Pr(),tabs:Or.filter(e=>!e.provisional).map(Ar)}},computed:{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=String(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":""},headingText(){return String(this.cfg.heading||this.heading||"").trim()||"Posterverse"},effectiveLocale(){return(String(this.language||this.cfg.language||this.cfg.locale||this.cfg.lang||"").trim()||this.hostLang||"en").split("-")[0].toLowerCase()},uiLocale(){return wn.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","home"])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:""},activePaneEl(){return this.paneEls[this.activeIndex]||null},navGroups(){return Ac.map(e=>({key:e.key,label:this.tr(e.i18n),icon:e.icon,folder:!!e.folder,open:e.open,rows:this.tabs.filter(t=>t.section===e.key).map(t=>({key:t.id,label:this.tabLabel(t),sub:this.tabSub(t),icon:t.icon,badge:e.folder?this.tr("lab"):void 0}))})).filter(e=>e.rows.length)}},watch:{effectiveLocale(){const e=(o,n)=>{try{const s=this._slots&&this._slots[o];s&&(s.innerHTML="")}catch{}n.mounted=!1,n.state="idle",n.error=""};this.tabs.forEach((o,n)=>{o.mounted&&n!==this.activeIndex&&e(n,o)});const t=this.tabs[this.activeIndex];!t||!t.mounted||(e(this.activeIndex,t),this.mountElement(this.activeIndex))},tab(e){e&&this.onSelect(e)}},mounted(){this.watchHostLang(),this.select(this.initialIndex()),this.loadManifest()},beforeUnmount(){this._langObs&&(this._langObs.disconnect(),this._langObs=null)},methods:{tr(e,t){return Pc(this.uiLocale,e,t)},tabLabel(e){return this.tr("tab."+e.id)},tabSub(e){return e.section==="experimental"?this.tr("experimentalSub"):this.tr("sub."+e.id)},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},watchHostLang(){typeof MutationObserver>"u"||typeof document>"u"||(this._langObs=new MutationObserver(()=>{this.hostLang=Pr()}),this._langObs.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]}))},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.tabs.findIndex(t=>t.id===this.requestedTab());return e>=0?e:0},loadManifest(){const e=p=>{try{return new URL(p,location.href).href.replace(/[^/]*$/,"")}catch{return""}},t=this.resolve("manifest.json"),o={url:t,root:e(t)},n={url:this.resolve("doxa-maps-spa/manifest.json"),root:o.root};let s=!1;try{s=new URL(t,location.href).origin!==location.origin}catch{}const r=s?[n,o]:[o,n],a="/public/dx-maps/manifest.json";r.some(p=>p.url===a)||r.push({url:a,root:e(a)});const i=[],l=p=>{if(p>=r.length){this.manifestError="manifest.json not found (tried "+i.join(", ")+")",console.error("[posterverse] "+this.manifestError+" — every tab is composed from it.");return}const{url:d,root:h}=r[p];return i.push(d),fetch(d,{credentials:"same-origin"}).then(w=>{if(!w||!w.ok)throw new Error(d+" → HTTP "+(w?w.status:"?"));return w.json()}).then(w=>{if(!w)throw new Error(d+" → empty");this.manifestError="",this.manifestBase=h||"",this.applyManifest(w)}).catch(()=>l(p+1))};try{l(0)}catch{}},applyManifest(e){this.runtime=e&&e.runtime&&typeof e.runtime=="object"?e.runtime:{},this.applyPageGlobals();const t=this.activeKey;this.tabs=Ic(e,r=>console.warn(r)).map(Ar);const o=this.requestedTab(),n=!this._honouredTab&&o?this.tabs.findIndex(r=>r.id===o):-1,s=this.tabs.findIndex(r=>r.id===t);this._honouredTab=!0,this.select(n>=0?n:s>=0?s:0)},onSelect(e){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 n=this.tabs[t];n&&n.heavy&&n.mounted&&this.releaseTab(t,n)}const o=this.tabs[e];o&&((t!==e||!this._announced)&&(this._announced=!0,this.$emit("tab-change",{id:o.id,label:this.tabLabel(o)})),o.scriptUrl&&(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:"pv-"+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.mapTitle=this.tabLabel(e),t},applyPageGlobals(){if(typeof window>"u")return;const e=String(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",Lr(this.resolve(t.scriptUrl)).then(()=>kl(t.tag)).then(()=>{try{if(t.heavy&&this.activeIndex!==e){t.mounted=!1,t.state="idle";return}const o=this._slots&&this._slots[e];if(!o){t.state="error",t.error="no slot";return}o.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="display:block;position:absolute;inset:0;width:100%;height:100%;min-height:0;",o.appendChild(n),t.state="ready"}catch(o){t.state="error",t.error="mount failed: "+(o&&o.message||String(o))}}).catch(o=>{t.state="error",t.error=o&&o.message||String(o)})}}}),Rc=["hidden"],Wc={key:0,class:"pv-hint"},Dc={key:1,class:"pv-hint err"},zc={key:2,class:"pv-hint err"};function Hc(e,t,o,n,s,r){const a=tn("BackToTopButton"),i=tn("VerticalTabsLayout");return A(),At(i,{dir:e.uiDir,lang:e.uiLocale,labels:e.layoutLabels,title:e.headingText,"nav-label":e.tr("sec.posters"),header:!1,"home-href":e.homeHref||e.cfg.homeHref||"","home-label":e.homeLabel||e.cfg.homeLabel||"",groups:e.navGroups,active:e.activeKey,"onUpdate:active":e.onSelect},{default:ds(()=>[(A(!0),F(oe,null,Mt(e.tabs,(l,p)=>Jo((A(),F("section",{key:l.id,class:"pv-pane",ref_for:!0,ref:d=>{d?e.paneEls[p]=d:delete e.paneEls[p]},hidden:p!==e.activeIndex},[!l.heavy||p===e.activeIndex?(A(),F(oe,{key:0},[I("div",{class:"pv-slot",ref_for:!0,ref:d=>e.setSlot(p,d)},null,512),l.state==="loading"?(A(),F("div",Wc,D(e.tr("loading",{label:e.tabLabel(l)})),1)):l.state==="error"?(A(),F("div",Dc,[gt(D(e.tr("loadFailed",{label:e.tabLabel(l)})),1),t[0]||(t[0]=I("br",null,null,-1)),I("small",null,D(l.error),1)])):l.state==="idle"&&!l.scriptUrl&&e.manifestError?(A(),F("div",zc,[gt(D(e.tr("loadFailed",{label:e.tabLabel(l)})),1),t[1]||(t[1]=I("br",null,null,-1)),I("small",null,D(e.manifestError),1),t[2]||(t[2]=I("br",null,null,-1)),I("small",null,D(e.tr("manifestHint")),1)])):ie("",!0)],64)):ie("",!0)],8,Rc)),[[gn,p===e.activeIndex]])),128)),be(a,{target:e.activePaneEl,labels:{backToTop:e.tr("backToTop")}},null,8,["target","labels"])]),_:1},8,["dir","lang","labels","title","nav-label","home-href","home-label","groups","active","onUpdate:active"])}const Bc=vn(Ec,[["render",Hc],["styles",[Nc]]]),Uc=Tl(),jc=nl(Bc,{configureApp(e){e.provide("pvTreeBase",Uc)}});typeof customElements<"u"&&!customElements.get("posterverse-app")&&customElements.define("posterverse-app",jc)})(); diff --git a/public/dx-maps/posterverse/posterverse/app/index.html b/public/dx-maps/posterverse/posterverse/app/index.html index e6d286894..74743683a 100644 --- a/public/dx-maps/posterverse/posterverse/app/index.html +++ b/public/dx-maps/posterverse/posterverse/app/index.html @@ -67,7 +67,7 @@ - + - + \n\n\n" + }, + "bundle": "bible-posters" + } + ] + }, { "bundle": "big-picture", "scriptUrl": "./big-picture/big-picture.js", @@ -361,7 +393,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-eMJnHI1Ed2HY5E2Zx0NpfPeu0upkZUhFg8sffdCZbsz9UP+rnWwQEtSTolFHcQxu", + "integrity": "sha384-XHR1mr4ln+rjjfizRrEKhU6y7/F35fb8gE/t7lmrTklC+E5ahrKp+dhhQFaaUPX6", "elements": [ "doxa-maps-spa" ], @@ -391,7 +423,7 @@ "scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { @@ -1134,7 +1166,7 @@ "bundle": "posterverse", "scriptUrl": "./posterverse/posterverse.js", "output": "dx-maps/posterverse/posterverse.js", - "integrity": "sha384-+1IEWkJujDRDE7t/piXT6lq6T0QdhCYfT4pv4OURz6EKxDK8p8YcSZNZOv5uRi0W", + "integrity": "sha384-SHwg48KTIMJixoVevPoDmKMsuJ1tAKE2fa4WBS1bOmGeUawyWBt4n029N8itST7q", "elements": [ "posterverse-app" ], @@ -1142,7 +1174,8 @@ "my-upg-100-list/upg-100-mfe", "country-posters/country-posters-mfe", "poster-design/poster-design-mfe", - "wall-of-people-groups/wall-of-people-groups" + "wall-of-people-groups/wall-of-people-groups", + "bible-posters/bible-posters" ], "stage": "experimental", "profiles": [ @@ -1159,7 +1192,7 @@ "scriptUrl": "./posterverse/posterverse.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { diff --git a/public/dx-maps/manifest.json b/public/dx-maps/manifest.json index 82fb7f3a2..011e83992 100644 --- a/public/dx-maps/manifest.json +++ b/public/dx-maps/manifest.json @@ -2,8 +2,8 @@ "schema": "doxa-maps-manifest@1", "generatedFrom": "plugin-designs/*/*.vue", "embedBase": ".", - "bundleCount": 27, - "profileCount": 41, + "bundleCount": 28, + "profileCount": 42, "runtime": { "apiBaseUrl": "https://pray.doxa.life" }, @@ -37,6 +37,38 @@ } ] }, + { + "bundle": "bible-posters", + "scriptUrl": "./bible-posters/bible-posters.js", + "output": "dx-maps/bible-posters/bible-posters.js", + "integrity": "sha384-x0qrqnzFOHxhCWZN4YYpnME08TLUQdfMI8oR5cAnQDtOVKu133/27BXcHCr0Ev7Q", + "elements": [ + "bible-posters" + ], + "stage": "experimental", + "profiles": [ + { + "profile": "bible-posters", + "stage": "experimental", + "label": "Bible Posters", + "targets": [ + "web" + ], + "file": "bible-posters.vue", + "description": "A whole book of the Bible on one poster, in justified columns under a bold title, from a public-domain text.", + "element": "bible-posters", + "type": "single", + "isMap": false, + "iframeUrl": "./bible-posters/bible-posters/index.html", + "scriptUrl": "./bible-posters/bible-posters.js", + "embed": { + "iframe": "", + "script": "\n\n\n" + }, + "bundle": "bible-posters" + } + ] + }, { "bundle": "big-picture", "scriptUrl": "./big-picture/big-picture.js", @@ -361,7 +393,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-eMJnHI1Ed2HY5E2Zx0NpfPeu0upkZUhFg8sffdCZbsz9UP+rnWwQEtSTolFHcQxu", + "integrity": "sha384-XHR1mr4ln+rjjfizRrEKhU6y7/F35fb8gE/t7lmrTklC+E5ahrKp+dhhQFaaUPX6", "elements": [ "doxa-maps-spa" ], @@ -391,7 +423,7 @@ "scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { @@ -1134,7 +1166,7 @@ "bundle": "posterverse", "scriptUrl": "./posterverse/posterverse.js", "output": "dx-maps/posterverse/posterverse.js", - "integrity": "sha384-+1IEWkJujDRDE7t/piXT6lq6T0QdhCYfT4pv4OURz6EKxDK8p8YcSZNZOv5uRi0W", + "integrity": "sha384-SHwg48KTIMJixoVevPoDmKMsuJ1tAKE2fa4WBS1bOmGeUawyWBt4n029N8itST7q", "elements": [ "posterverse-app" ], @@ -1142,7 +1174,8 @@ "my-upg-100-list/upg-100-mfe", "country-posters/country-posters-mfe", "poster-design/poster-design-mfe", - "wall-of-people-groups/wall-of-people-groups" + "wall-of-people-groups/wall-of-people-groups", + "bible-posters/bible-posters" ], "stage": "experimental", "profiles": [ @@ -1159,7 +1192,7 @@ "scriptUrl": "./posterverse/posterverse.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { diff --git a/public/dx-maps/posterverse/posterverse.js b/public/dx-maps/posterverse/posterverse.js index 9c33e81b9..0ef78ba3a 100644 --- a/public/dx-maps/posterverse/posterverse.js +++ b/public/dx-maps/posterverse/posterverse.js @@ -159,4 +159,4 @@ @media (prefers-reduced-motion: reduce) { .vtl-nav, .vtl-collapse-ic, .vtl-tab, .vtl-tier, .vtl-pbar, .vtl-phone-menu, .vtl-rail-end, .vtl-scrim { transition: none !important; animation: none !important; } } -`,Fl=nn({name:"VerticalTabsLayout",components:{BackToTopButton:ba},props:{active:{type:String,default:""},title:{type:String,default:""},items:{type:Array,default:()=>[]},groups:{type:Array,default:()=>[]},navLabel:{type:String,default:"Sections"},labels:{type:Object,default:()=>({})},initialNavOpen:{type:Boolean,default:!0},header:{type:Boolean,default:!0},initialRailCollapsed:{type:Boolean,default:!1},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["update:active"],setup(){return wl(Cl,"vertical-tabs-layout"),{T:Ol}},data(){return{navOpen:this.initialNavOpen,railCollapsed:this.initialRailCollapsed,_tabEls:{},folderOverride:{},narrow:!1,_mql:null,_onMedia:null,activatedKeys:{},hostState:{},hostError:{},_hostSlots:{},_hostMounted:{},hostEls:{}}},computed:{phoneBarShown(){return this.narrow&&!this.header},railEndShown(){return!this.narrow&&!this.header},activeHostEl(){return this.hostEls[this.active]||null},railShown(){return this.narrow?this.navOpen:!0},homeLink(){const e=String(this.homeHref||"").trim();return!e||/^(javascript|data|vbscript):/i.test(e.replace(/[\u0000- ]/g,""))?"":e},homeText(){return this.homeLabel||this.label("home")},allRows(){if(this.groups&&this.groups.length){const e=[];for(const t of this.groups)for(const o of t.rows||[])e.push(o);return e}return this.items},orderedKeys(){return this.allRows.map(e=>e.key)},elementRows(){return this.allRows.filter(e=>e&&e.element)},mountedElementRows(){return this.elementRows.filter(e=>this.activatedKeys[e.key])}},watch:{active:{immediate:!0,handler(e){this.activateElement(e)}}},mounted(){try{window.matchMedia&&(this._mql=window.matchMedia("(max-width: 760px)"),this.narrow=this._mql.matches,this.reconcileForWidth(),this._onMedia=e=>{this.narrow=e.matches,this.reconcileForWidth()},this._mql.addEventListener?this._mql.addEventListener("change",this._onMedia):this._mql.addListener&&this._mql.addListener(this._onMedia))}catch{}this.$nextTick(()=>this.activateElement(this.active))},beforeUnmount(){try{this._mql&&this._onMedia&&(this._mql.removeEventListener?this._mql.removeEventListener("change",this._onMedia):this._mql.removeListener&&this._mql.removeListener(this._onMedia))}catch{}this._mql=null,this._onMedia=null},methods:{registerTab(e,t){t&&(this._tabEls[e]=t)},isNarrow(){return this.narrow},reconcileForWidth(){this.narrow?(this.navOpen=!1,this.railCollapsed=!1):this.navOpen=!0},label(e){const t={toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse",home:"Back to homepage"};return this.labels&&this.labels[e]||t[e]},expandRail(){!this.narrow&&this.railCollapsed&&(this.railCollapsed=!1)},toggleRail(){this.narrow?this.navOpen=!this.navOpen:this.railCollapsed=!this.railCollapsed},setHostSlot(e,t){t&&(this._hostSlots[e]=t,this.$nextTick(()=>this.mountHostElement(e)))},activateElement(e){!e||!this.elementRows.find(o=>o.key===e)||(this.activatedKeys[e]||(this.activatedKeys={...this.activatedKeys,[e]:!0},this.$nextTick(()=>this.watchContextLoss(e)),this.hostState={...this.hostState,[e]:"loading"}),this.$nextTick(()=>this.mountHostElement(e)))},deepCanvases(e,t=[]){if(!e)return t;for(const o of e.querySelectorAll("*"))o.tagName==="CANVAS"&&t.push(o),o.shadowRoot&&this.deepCanvases(o.shadowRoot,t);return t},watchContextLoss(e){const t=this._hostSlots[e];if(t)for(const o of this.deepCanvases(t))o.__vtlLossBound||(o.__vtlLossBound=!0,o.addEventListener("webglcontextlost",()=>{this.hostState={...this.hostState,[e]:"lost"}},{once:!0}))},reloadHostElement(e){const t=this._hostSlots[e];t&&(t.innerHTML=""),this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"loading"},this.$nextTick(()=>this.mountHostElement(e))},mountHostElement(e){if(this._hostMounted[e])return;const t=this.elementRows.find(n=>n.key===e),o=this._hostSlots[e];!t||!o||(this._hostMounted[e]=!0,this.hostState={...this.hostState,[e]:"loading"},Al(t.src).then(()=>Pl(t.element)).then(()=>{Tl(t.element,t.src),o.innerHTML="";const n=document.createElement(t.element),s=t.attrs||{};for(const a in s){const i=s[a],r=i!=null&&typeof i=="object"?JSON.stringify(i):String(i);try{n[a]=i}catch{}try{n.setAttribute(a,r)}catch{}}n.style.cssText="display:block;position:absolute;inset:0;width:100%;height:100%;",o.appendChild(n);for(const a of[0,250,1500])setTimeout(()=>this.watchContextLoss(e),a);this.hostState={...this.hostState,[e]:"ready"}}).catch(n=>{this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"error"},this.hostError={...this.hostError,[e]:n&&n.message||String(n)}}))},iconSvg(e){return e?Sa(e):""},initial(e){const t=(e||"").trim();return t?t.charAt(0).toUpperCase():"•"},isFolderClosed(e){const t=this.folderOverride[e.key];return t!=null?!t:e.open!==!0},toggleFolder(e){const t=this.folderOverride[e],o=(this.groups||[]).find(s=>s.key===e),n=t??(o&&o.open===!0);this.folderOverride={...this.folderOverride,[e]:!n}},pick(e){this.$emit("update:active",e),this.narrow&&(this.navOpen=!1)},onKey(e){const t=this.orderedKeys;if(!t.length)return;const o=t.indexOf(this.active);let n=-1;if(e.key==="ArrowDown"||e.key==="ArrowRight")n=(o+1)%t.length;else if(e.key==="ArrowUp"||e.key==="ArrowLeft")n=(o-1+t.length)%t.length;else if(e.key==="Home")n=0;else if(e.key==="End")n=t.length-1;else return;e.preventDefault();const s=t[n];this.pick(s),this.$nextTick(()=>{const a=this._tabEls[s];a&&a.focus&&a.focus()})}}}),Il={key:0,class:"vtl-top"},Nl=["aria-expanded","aria-label"],El={class:"vtl-brand"},Rl={class:"vtl-title"},Wl={class:"vtl-meta"},Dl={key:1,class:"vtl-pbar"},zl=["aria-expanded","aria-label"],Hl={class:"vtl-pbar-end"},Bl={class:"vtl-body"},Ul=["aria-label","aria-hidden","role","aria-orientation"],jl=["href","aria-label","title"],Vl=["innerHTML"],ql={class:"vtl-home-tx"},Kl=["aria-expanded","aria-label"],Gl=["innerHTML"],Jl={class:"vtl-collapse-tx"},Xl=["aria-expanded","onClick"],Zl={key:0,class:"vtl-cap"},Yl={class:"vtl-tl"},Ql={key:1,class:"vtl-td"},ec=["innerHTML"],tc={key:1,class:"vtl-tier"},oc={key:0,class:"vtl-cap"},nc={class:"vtl-tl"},sc={key:1,class:"vtl-td"},ac={class:"vtl-rows"},rc=["aria-selected","aria-disabled","tabindex","onClick"],ic=["innerHTML"],lc={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},cc={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},dc={class:"vtl-tab-text"},pc={class:"vtl-tab-label"},uc={key:0,class:"vtl-tab-badge"},fc={key:0,class:"vtl-tab-sub"},gc=["innerHTML"],hc=["aria-selected","aria-disabled","tabindex","onClick"],$c=["innerHTML"],mc={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},_c={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},bc={class:"vtl-tab-text"},vc={class:"vtl-tab-label"},yc={key:0,class:"vtl-tab-sub"},wc={key:4,class:"vtl-rail-end"},xc={class:"vtl-main"},kc={class:"vtl-content"},Tc=["hidden"],Sc={key:0,class:"vtl-host-hint"},Mc={key:1,class:"vtl-host-hint"},Lc=["onClick"],Oc={key:2,class:"vtl-host-hint err"};function Ac(e,t,o,n,s,a){const i=fo("BackToTopButton");return M(),C("div",{class:We(["vtl",{"nav-open":e.navOpen,"rail-collapsed":e.railCollapsed,"no-header":!e.header,"has-phone-bar":e.phoneBarShown}])},[e.header?(M(),C("header",Il,[I("button",{class:"vtl-menu",type:"button","aria-expanded":String(e.navOpen),onClick:t[0]||(t[0]=r=>e.navOpen=!e.navOpen),"aria-label":e.label("toggleList")},"☰",8,Nl),I("span",El,[tt(e.$slots,"brand")]),I("b",Rl,E(e.title),1),I("span",Wl,[tt(e.$slots,"meta")])])):ne("",!0),e.phoneBarShown?(M(),C("div",Dl,[I("button",{class:"vtl-phone-menu",type:"button","aria-expanded":String(e.navOpen),onClick:t[1]||(t[1]=r=>e.navOpen=!e.navOpen),"aria-label":e.label("toggleList")},"☰",8,zl),I("span",Hl,[tt(e.$slots,"phone-end")])])):ne("",!0),e.narrow?(M(),Pt(i,{key:2,target:e.activeHostEl,labels:{backToTop:e.T("actions.backToTop","Back to top")}},null,8,["target","labels"])):ne("",!0),I("div",Bl,[I("nav",{class:We(["vtl-nav",{"has-rail-end":e.railEndShown&&!!e.$slots["rail-end"]}]),"aria-label":e.navLabel,"aria-hidden":String(!e.railShown),role:e.$slots.rail?null:"tablist","aria-orientation":e.$slots.rail?null:"vertical"},[e.homeLink?(M(),C("a",{key:0,class:"vtl-home",href:e.homeLink,target:"_top","aria-label":e.homeText,title:e.railCollapsed&&!e.narrow?e.homeText:null},[I("span",{class:"vtl-home-ic","aria-hidden":"true",innerHTML:e.iconSvg("home")},null,8,Vl),I("span",ql,E(e.homeText),1)],8,jl)):ne("",!0),I("button",{type:"button",class:"vtl-collapse","aria-expanded":String(!e.railCollapsed),"aria-label":e.railCollapsed?e.label("expandList"):e.label("collapseList"),onClick:t[2]||(t[2]=(...r)=>e.toggleRail&&e.toggleRail(...r))},[I("span",{class:"vtl-collapse-ic","aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,8,Gl),I("span",Jl,E(e.label("collapse")),1)],8,Kl),e.$slots.rail?tt(e.$slots,"rail",{collapsed:e.railCollapsed&&!e.narrow,expand:e.expandRail,pick:e.pick},void 0,void 0,1):e.groups&&e.groups.length?(M(!0),C(ee,{key:2},ft(e.groups,r=>(M(),C("div",{class:"vtl-grp",key:r.key},[r.folder?(M(),C("button",{key:0,type:"button",class:"vtl-tier vtl-tier-btn","aria-expanded":String(!e.isFolderClosed(r)),onClick:l=>e.toggleFolder(r.key)},[r.badge?(M(),C("span",Zl,E(r.badge),1)):ne("",!0),I("span",Yl,E(r.label),1),r.count!=null?(M(),C("span",Ql,E(r.count),1)):ne("",!0),I("span",{class:We(["vtl-chev",{open:!e.isFolderClosed(r)}]),"aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,10,ec)],8,Xl)):(M(),C("div",tc,[r.badge?(M(),C("span",oc,E(r.badge),1)):ne("",!0),I("span",nc,E(r.label),1),r.count!=null?(M(),C("span",sc,E(r.count),1)):ne("",!0)])),en(I("div",ac,[(M(!0),C(ee,null,ft(r.rows,l=>(M(),C("button",{key:l.key,type:"button",role:"tab",class:We(["vtl-tab",{active:l.key===e.active,disabled:l.disabled}]),"aria-selected":String(l.key===e.active),"aria-disabled":l.disabled?"true":null,tabindex:l.key===e.active?0:-1,ref_for:!0,ref:d=>e.registerTab(l.key,d),onClick:d=>e.pick(l.key),onKeydown:t[3]||(t[3]=d=>e.onKey(d))},[l.icon?(M(),C("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(l.icon)},null,8,ic)):l.emoji?(M(),C("span",lc,E(l.emoji),1)):(M(),C("span",cc,E(e.initial(l.label)),1)),I("span",dc,[I("span",pc,[$t(E(l.label),1),l.badge?(M(),C("span",uc,E(l.badge),1)):ne("",!0)]),l.sub?(M(),C("span",fc,[I("span",{innerHTML:l.sub},null,8,gc)])):ne("",!0)])],42,rc))),128))],512),[[bn,!r.folder||!e.isFolderClosed(r)]])]))),128)):(M(!0),C(ee,{key:3},ft(e.items,r=>(M(),C("button",{key:r.key,type:"button",role:"tab",class:We(["vtl-tab",{active:r.key===e.active,disabled:r.disabled}]),"aria-selected":String(r.key===e.active),"aria-disabled":r.disabled?"true":null,tabindex:r.key===e.active?0:-1,ref_for:!0,ref:l=>e.registerTab(r.key,l),onClick:l=>e.pick(r.key),onKeydown:t[4]||(t[4]=l=>e.onKey(l))},[r.icon?(M(),C("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(r.icon)},null,8,$c)):r.emoji?(M(),C("span",mc,E(r.emoji),1)):(M(),C("span",_c,E(e.initial(r.label)),1)),I("span",bc,[I("span",vc,E(r.label),1),r.sub?(M(),C("span",yc,E(r.sub),1)):ne("",!0)])],42,hc))),128)),e.railEndShown&&e.$slots["rail-end"]?(M(),C("div",wc,[tt(e.$slots,"rail-end",{collapsed:e.railCollapsed})])):ne("",!0)],10,Ul),I("main",xc,[e.header?tt(e.$slots,"toolbar",{},void 0,void 0,0):ne("",!0),I("div",kc,[(M(!0),C(ee,null,ft(e.mountedElementRows,r=>en((M(),C("section",{key:r.key,class:"vtl-host",hidden:r.key!==e.active,ref_for:!0,ref:l=>{l?e.hostEls[r.key]=l:delete e.hostEls[r.key]}},[I("div",{class:"vtl-host-slot",ref_for:!0,ref:l=>e.setHostSlot(r.key,l)},null,512),e.hostState[r.key]==="loading"?(M(),C("div",Sc,E(e.T("messages.loadingNamed","Loading {name}…").replace("{name}",r.label)),1)):e.hostState[r.key]==="lost"?(M(),C("div",Mc,[$t(E(e.T("messages.mapContextLost","This map was unloaded to free graphics memory."))+" ",1),I("button",{type:"button",class:"vtl-host-reload",onClick:l=>e.reloadHostElement(r.key)},E(e.T("buttons.reloadMap","Reload Map")),9,Lc)])):e.hostState[r.key]==="error"?(M(),C("div",Oc,[$t(E(e.T("messages.couldNotLoadNamed","Could not load {name}.").replace("{name}",r.label)),1),t[5]||(t[5]=I("br",null,null,-1)),I("small",null,E(e.hostError[r.key]),1)])):ne("",!0)],8,Tc)),[[bn,r.key===e.active]])),128)),tt(e.$slots,"default")])])])],2)}const Pc=xo(Fl,[["render",Ac],["styles",[Ll]]]),Pa=[{code:"en",name:"English",nativeName:"English",flag:"🇺🇸"},{code:"es",name:"Spanish",nativeName:"Español",flag:"🇪🇸"},{code:"fr",name:"French",nativeName:"Français",flag:"🇫🇷"},{code:"pt",name:"Portuguese",nativeName:"Português",flag:"🇵🇹"},{code:"ar",name:"Arabic",nativeName:"العربية",flag:"🇸🇦",dir:"rtl"},{code:"ru",name:"Russian",nativeName:"Русский",flag:"🇷🇺"},{code:"de",name:"German",nativeName:"Deutsch",flag:"🇩🇪",hideFromSwitcher:!0},{code:"hi",name:"Hindi",nativeName:"हिन्दी",flag:"🇮🇳",hideFromSwitcher:!0},{code:"it",name:"Italian",nativeName:"Italiano",flag:"🇮🇹",hideFromSwitcher:!0},{code:"ro",name:"Romanian",nativeName:"Română",flag:"🇷🇴",hideFromSwitcher:!0},{code:"zh",name:"Chinese",nativeName:"中文",flag:"🇨🇳",hideFromSwitcher:!0}],Cc=Pa.filter(e=>!e.hideFromSwitcher);function Ca(e){return Pa.find(t=>t.code===e)}const Fc="doxa-maps:locale";function Ic(e){try{localStorage.setItem(Fc,e)}catch{}}const Nc="doxa-language-request";function Ec(e){try{const t=e&&e.getRootNode&&e.getRootNode();if(t&&t.host)return t.host}catch{}return e||null}function Rc(e,t){const o=Ec(e);return!o||typeof o.dispatchEvent!="function"?!0:o.dispatchEvent(new CustomEvent(Nc,{detail:{language:t},bubbles:!0,composed:!0,cancelable:!0}))}function Wc(e,t=typeof window<"u"?window:null){try{if(!t||t.MAP_OWNS_PAGE!==!0||!t.history||!t.location)return!1;const o=new URL(t.location.href);return o.searchParams.set("lang",e),t.history.replaceState(t.history.state,"",o.toString()),!0}catch{return!1}}const Dc=".slm[data-v-12760774]{position:relative;display:inline-flex;align-items:center;min-height:44px;max-width:100%;box-sizing:border-box;border-radius:8px;color:#3b463d}.slm-face[data-v-12760774]{display:inline-flex;align-items:center;gap:6px;padding-inline:10px;min-width:0;font-size:13px;font-weight:500;line-height:1.2}.slm-ic[data-v-12760774]{flex:0 0 auto;display:inline-flex;color:var(--vtl-muted, #6d766e)}.slm-ic[data-v-12760774] svg{width:18px;height:18px}.slm-name[data-v-12760774]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}.slm-code[data-v-12760774]{font-weight:600;font-size:12px;letter-spacing:.03em}.slm-caret[data-v-12760774]{flex:0 0 auto;color:var(--vtl-muted, #6d766e);font-size:11px}.slm.collapsed .slm-face[data-v-12760774]{flex-direction:column;gap:2px;padding-inline:4px}.slm-select[data-v-12760774]{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;opacity:0;margin:0;border:0;cursor:pointer;font-size:16px}.slm[data-v-12760774]:hover{background:var(--vtl-accented, #d1d4cd)}.slm[data-v-12760774]:focus-within{outline:2px solid var(--vtl-accent, #92b195);outline-offset:-2px}@media (prefers-reduced-motion: reduce){.slm[data-v-12760774]{transition:none}}",zc={class:"slm-face","aria-hidden":"true"},Hc=["innerHTML"],Bc={key:0,class:"slm-code"},Uc=["lang","dir"],jc={key:2,class:"slm-caret"},Vc=["value","aria-label","title"],qc=["value","lang","dir"],Kc=xo({__name:"ShellLanguageMenu",props:{current:{type:String,default:"en"},collapsed:{type:Boolean,default:!1}},emits:["switch"],setup(e,{emit:t}){const o=e,n=t,s=Et(()=>{const d=Cc.slice();if(o.current&&!d.some(p=>p.code===o.current)){const p=Ca(o.current);p&&d.push(p)}return d}),a=Et(()=>Ca(o.current)||{code:o.current,nativeName:o.current}),i=Et(()=>ka("controls.language",o.current)||"Language"),r=Sa("globe");function l(d){const p=d.target,f=p.value;!f||f===o.current||(Rc(p,f)?(n("switch",f),Wc(f)):p.value=o.current)}return(d,p)=>(M(),C("span",{class:We(["slm",{collapsed:e.collapsed}])},[I("span",zc,[I("span",{class:"slm-ic",innerHTML:Zo(r)},null,8,Hc),e.collapsed?(M(),C("span",Bc,E(String(e.current).toUpperCase()),1)):(M(),C("span",{key:1,class:"slm-name",lang:a.value.code,dir:a.value.dir||null},E(a.value.nativeName),9,Uc)),e.collapsed?ne("",!0):(M(),C("span",jc,"▾"))]),I("select",{class:"slm-select",value:e.current,"aria-label":i.value,title:i.value,onChange:l},[(M(!0),C(ee,null,ft(s.value,f=>(M(),C("option",{key:f.code,value:f.code,lang:f.code,dir:f.dir||null},E(f.nativeName),9,qc))),128))],40,Vc)],2))}},[["styles",[Dc]],["__scopeId","data-v-12760774"]]),ko={en:{"sec.posters":"Posters","sec.experimental":"Experimental","tab.upg-100":"UPG 100 List Posters","sub.upg-100":"my unreached list + posters","tab.country-posters":"Country Posters","sub.country-posters":"a poster for every country","tab.poster-design":"Poster Design","sub.poster-design":"every poster style and size","tab.wall-of-people-groups":"Wall of People Groups","tab.bible-posters":"Bible Posters",experimentalSub:"experimental bundle",lab:"lab",loading:"Loading {label}…",loadFailed:"Could not load {label}.",manifestHint:"This tab is composed from manifest.json — build the tree, or serve the built tree, to load it.",backToTop:"Back to top",home:"Back to homepage",toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse"},es:{"sec.posters":"Carteles","sec.experimental":"Experimental","tab.upg-100":"Carteles de la lista UPG 100","sub.upg-100":"mi lista de no alcanzados + carteles","tab.country-posters":"Carteles por país","sub.country-posters":"un cartel para cada país","tab.poster-design":"Diseño de carteles","sub.poster-design":"todos los estilos y tamaños de cartel","tab.wall-of-people-groups":"Muro de los pueblos","tab.bible-posters":"Carteles bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Cargando {label}…",loadFailed:"No se pudo cargar {label}.",manifestHint:"Esta pestaña se compone a partir de manifest.json: compila el árbol o sirve el árbol compilado para cargarla.",backToTop:"Volver arriba",home:"Volver a la página de inicio",toggleList:"Mostrar u ocultar la lista",openViews:"Abrir la lista de vistas",expandList:"Expandir la lista",collapseList:"Contraer la lista",collapse:"Contraer"},fr:{"sec.posters":"Affiches","sec.experimental":"Expérimental","tab.upg-100":"Affiches de la liste UPG 100","sub.upg-100":"ma liste des non atteints + affiches","tab.country-posters":"Affiches par pays","sub.country-posters":"une affiche pour chaque pays","tab.poster-design":"Conception d’affiches","sub.poster-design":"tous les styles et formats d’affiche","tab.wall-of-people-groups":"Mur des peuples","tab.bible-posters":"Affiches bibliques",experimentalSub:"carte expérimentale",lab:"bêta",loading:"Chargement de {label}…",loadFailed:"Impossible de charger {label}.",manifestHint:"Cet onglet est composé à partir de manifest.json : construisez l'arborescence ou servez l'arborescence construite pour le charger.",backToTop:"Retour en haut",home:"Retour à l’accueil",toggleList:"Afficher ou masquer la liste",openViews:"Ouvrir la liste des vues",expandList:"Déplier la liste",collapseList:"Replier la liste",collapse:"Replier"},de:{"sec.posters":"Poster","sec.experimental":"Experimentell","tab.upg-100":"Poster der UPG 100 Liste","sub.upg-100":"meine Liste der Unerreichten + Poster","tab.country-posters":"Länderposter","sub.country-posters":"ein Poster für jedes Land","tab.poster-design":"Postergestaltung","sub.poster-design":"alle Posterstile und -größen","tab.wall-of-people-groups":"Wand der Volksgruppen","tab.bible-posters":"Bibelposter",experimentalSub:"experimentelle Karte",lab:"Beta",loading:"{label} wird geladen…",loadFailed:"{label} konnte nicht geladen werden.",manifestHint:"Dieser Tab wird aus manifest.json zusammengesetzt – bauen Sie den Baum oder stellen Sie den gebauten Baum bereit, um ihn zu laden.",backToTop:"Nach oben",home:"Zurück zur Startseite",toggleList:"Liste ein-/ausblenden",openViews:"Ansichtsliste öffnen",expandList:"Liste ausklappen",collapseList:"Liste einklappen",collapse:"Einklappen"},pt:{"sec.posters":"Cartazes","sec.experimental":"Experimental","tab.upg-100":"Cartazes da lista UPG 100","sub.upg-100":"minha lista de não alcançados + cartazes","tab.country-posters":"Cartazes por país","sub.country-posters":"um cartaz para cada país","tab.poster-design":"Design de cartazes","sub.poster-design":"todos os estilos e tamanhos de cartaz","tab.wall-of-people-groups":"Mural dos povos","tab.bible-posters":"Cartazes bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Carregando {label}…",loadFailed:"Não foi possível carregar {label}.",manifestHint:"Esta aba é composta a partir do manifest.json — compile a árvore ou sirva a árvore compilada para carregá-la.",backToTop:"Voltar ao topo",home:"Voltar à página inicial",toggleList:"Mostrar ou ocultar a lista",openViews:"Abrir a lista de visualizações",expandList:"Expandir a lista",collapseList:"Recolher a lista",collapse:"Recolher"},it:{"sec.posters":"Poster","sec.experimental":"Sperimentale","tab.upg-100":"Poster della lista UPG 100","sub.upg-100":"la mia lista dei non raggiunti + poster","tab.country-posters":"Poster per paese","sub.country-posters":"un poster per ogni paese","tab.poster-design":"Design dei poster","sub.poster-design":"tutti gli stili e i formati dei poster","tab.wall-of-people-groups":"Muro dei popoli","tab.bible-posters":"Poster biblici",experimentalSub:"mappa sperimentale",lab:"beta",loading:"Caricamento di {label}…",loadFailed:"Impossibile caricare {label}.",manifestHint:"Questa scheda è composta da manifest.json: compila l'albero o pubblica l'albero compilato per caricarla.",backToTop:"Torna su",home:"Torna alla home page",toggleList:"Mostra o nascondi l’elenco",openViews:"Apri l’elenco delle viste",expandList:"Espandi l’elenco",collapseList:"Comprimi l’elenco",collapse:"Comprimi"},ro:{"sec.posters":"Afișe","sec.experimental":"Experimental","tab.upg-100":"Afișe din lista UPG 100","sub.upg-100":"lista mea de neatinși + afișe","tab.country-posters":"Afișe pe țări","sub.country-posters":"un afiș pentru fiecare țară","tab.poster-design":"Design de afișe","sub.poster-design":"toate stilurile și dimensiunile de afiș","tab.wall-of-people-groups":"Zidul popoarelor","tab.bible-posters":"Afișe biblice",experimentalSub:"hartă experimentală",lab:"beta",loading:"Se încarcă {label}…",loadFailed:"{label} nu a putut fi încărcat.",manifestHint:"Această filă este compusă din manifest.json — construiți arborele sau serviți arborele construit pentru a o încărca.",backToTop:"Sus",home:"Înapoi la pagina principală",toggleList:"Afișează sau ascunde lista",openViews:"Deschide lista de vizualizări",expandList:"Extinde lista",collapseList:"Restrânge lista",collapse:"Restrânge"},ru:{"sec.posters":"Плакаты","sec.experimental":"Экспериментальное","tab.upg-100":"Плакаты списка UPG 100","sub.upg-100":"мой список недостигнутых + плакаты","tab.country-posters":"Плакаты по странам","sub.country-posters":"плакат для каждой страны","tab.poster-design":"Дизайн плакатов","sub.poster-design":"все стили и размеры плакатов","tab.wall-of-people-groups":"Стена народов","tab.bible-posters":"Библейские плакаты",experimentalSub:"экспериментальная карта",lab:"бета",loading:"Загрузка: {label}…",loadFailed:"Не удалось загрузить: {label}.",manifestHint:"Эта вкладка собирается из manifest.json — соберите дерево или разместите собранное дерево, чтобы загрузить её.",backToTop:"Наверх",home:"На главную страницу",toggleList:"Показать или скрыть список",openViews:"Открыть список представлений",expandList:"Развернуть список",collapseList:"Свернуть список",collapse:"Свернуть"},ar:{"sec.posters":"ملصقات","sec.experimental":"تجريبي","tab.upg-100":"ملصقات قائمة UPG 100","sub.upg-100":"قائمتي لغير المُبشَّرين + ملصقات","tab.country-posters":"ملصقات الدول","sub.country-posters":"ملصق لكل دولة","tab.poster-design":"تصميم الملصقات","sub.poster-design":"كل أنماط الملصقات وأحجامها","tab.wall-of-people-groups":"جدار الشعوب","tab.bible-posters":"ملصقات الكتاب المقدس",experimentalSub:"خريطة تجريبية",lab:"تجريبي",loading:"جارٍ تحميل {label}…",loadFailed:"تعذّر تحميل {label}.",manifestHint:"تُبنى علامة التبويب هذه من manifest.json — ابنِ الشجرة أو قدّم الشجرة المبنية لتحميلها.",backToTop:"إلى الأعلى",home:"العودة إلى الصفحة الرئيسية",toggleList:"إظهار القائمة أو إخفاؤها",openViews:"فتح قائمة العروض",expandList:"توسيع القائمة",collapseList:"طي القائمة",collapse:"طي"},hi:{"sec.posters":"पोस्टर","sec.experimental":"प्रायोगिक","tab.upg-100":"UPG 100 सूची पोस्टर","sub.upg-100":"मेरी अप्राप्त सूची + पोस्टर","tab.country-posters":"देश पोस्टर","sub.country-posters":"हर देश के लिए एक पोस्टर","tab.poster-design":"पोस्टर डिज़ाइन","sub.poster-design":"हर पोस्टर शैली और आकार","tab.wall-of-people-groups":"जनसमूहों की दीवार","tab.bible-posters":"बाइबल पोस्टर",experimentalSub:"प्रायोगिक मानचित्र",lab:"बीटा",loading:"{label} लोड हो रहा है…",loadFailed:"{label} लोड नहीं हो सका।",manifestHint:"यह टैब manifest.json से बनता है — इसे लोड करने के लिए ट्री बनाएँ या बना हुआ ट्री सर्व करें।",backToTop:"ऊपर जाएँ",home:"होमपेज पर वापस जाएँ",toggleList:"सूची दिखाएँ या छिपाएँ",openViews:"दृश्यों की सूची खोलें",expandList:"सूची फैलाएँ",collapseList:"सूची संक्षिप्त करें",collapse:"संक्षिप्त करें"},zh:{"sec.posters":"海报","sec.experimental":"实验性","tab.upg-100":"UPG 100 名单海报","sub.upg-100":"我的未得之民名单 + 海报","tab.country-posters":"国家海报","sub.country-posters":"每个国家一张海报","tab.poster-design":"海报设计","sub.poster-design":"所有海报样式与尺寸","tab.wall-of-people-groups":"民族之墙","tab.bible-posters":"圣经海报",experimentalSub:"实验性地图",lab:"测试版",loading:"正在加载{label}…",loadFailed:"无法加载{label}。",manifestHint:"此标签页由 manifest.json 组成——请构建目录树或提供已构建的目录树以加载它。",backToTop:"回到顶部",home:"返回首页",toggleList:"显示或隐藏列表",openViews:"打开视图列表",expandList:"展开列表",collapseList:"折叠列表",collapse:"折叠"}},Tn=Object.keys(ko);function Gc(e,t,o){let s=(ko[e]||ko.en)[t]??ko.en[t]??t;if(o)for(const a in o)s=s.split("{"+a+"}").join(String(o[a]));return s}const Jc=[{key:"posters",i18n:"sec.posters",icon:"poster"},{key:"experimental",i18n:"sec.experimental",icon:"flask",folder:!0,open:!1}],Fa=[{id:"upg-100",section:"posters",icon:"list",bundle:"my-upg-100-list",profile:"upg-100-mfe"},{id:"country-posters",section:"posters",icon:"map",bundle:"country-posters",profile:"country-posters-mfe"},{id:"poster-design",section:"posters",icon:"poster",bundle:"poster-design",profile:"poster-design-mfe"},{id:"wall-of-people-groups",section:"experimental",icon:"flask",bundle:"wall-of-people-groups",profile:"wall-of-people-groups"},{id:"bible-posters",section:"experimental",icon:"flask",bundle:"bible-posters",profile:"bible-posters",provisional:!0}],Xc=new Set(["key-cities","posterverse","doxa-maps-spa","plugin-studio"]),Zc=new Set(["my-upg-100-list-map","country-posters-map"]);function Yc(e,t=()=>{}){const o=e&&Array.isArray(e.bundles)?e.bundles:[],n=Object.fromEntries(o.map(a=>[a&&a.bundle,a])),s=[];for(const a of Fa){if(Xc.has(a.bundle))continue;const i=n[a.bundle];if(!i)continue;const r=Array.isArray(i.profiles)?i.profiles:[];let l=r.find(f=>f&&f.profile===a.profile);if(!l){if(l=r.find(f=>f&&f.profile===a.bundle)||r[0],!l)continue;t(`[posterverse] ${a.bundle} has no profile "${a.profile}"; row "${a.id}" opens "${l.profile}" instead`)}const d=l.element||Array.isArray(i.elements)&&i.elements[0]||a.bundle,p=i.scriptUrl||l.scriptUrl||"";p&&s.push({...a,tag:d,scriptUrl:p,profile:l.profile,heavy:Zc.has(d)||!!l.isMap})}return s}const Qc=":host{display:block;position:relative;height:var(--posterverse-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}.pv-pane{position:absolute;top:0;right:0;bottom:0;left:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;--profile-min-h: 0}.pv-slot{position:relative;min-height:100%}.pv-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}.pv-hint.err{color:#b3261e}.pv-hint small{color:#6d766e}";function Ia(){try{const e=new URLSearchParams(location.search),t=(e.get("lang")||e.get("locale")||"").split("-")[0].toLowerCase();if(Tn.includes(t))return t}catch{}try{const e=(document.documentElement.lang||"").split("-")[0].toLowerCase();if(Tn.includes(e))return e}catch{}return""}const Na=e=>({...e,tag:e.tag||"",scriptUrl:e.scriptUrl||"",heavy:!!e.heavy,mounted:!1,state:"idle",error:""}),ed=nn({name:"Posterverse",inheritAttrs:!1,components:{VerticalTabsLayout:Pc,BackToTopButton:ba,ShellLanguageMenu:Kc},props:{treeBase:{type:String,default:""},profileConfig:{type:[String,Object],default:""},heading:{type:String,default:"Posterverse"},tokenUrl:{type:String,default:""},tk:{type:String,default:""},language:{type:String,default:""},apiBaseUrl:{type:String,default:""},provider:{type:String,default:""},tab:{type:String,default:""},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["tab-change"],setup(){return{injectedBase:St("pvTreeBase","")}},data(){return{paneEls:{},activeIndex:0,manifestError:"",manifestBase:"",runtime:{},hostLang:Ia(),localPick:"",pickBase:null,tabs:Fa.filter(e=>!e.provisional).map(Na)}},computed:{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=String(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":""},headingText(){return String(this.cfg.heading||this.heading||"").trim()||"Posterverse"},hostLanguage(){return String(this.language||this.cfg.language||this.cfg.locale||this.cfg.lang||"").trim()},effectiveLocale(){return this.localPick&&this.hostLanguage===this.pickBase?this.localPick:(this.hostLanguage||this.hostLang||"en").split("-")[0].toLowerCase()},uiLocale(){return Tn.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","home"])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:""},activePaneEl(){return this.paneEls[this.activeIndex]||null},navGroups(){return Jc.map(e=>({key:e.key,label:this.tr(e.i18n),icon:e.icon,folder:!!e.folder,open:e.open,rows:this.tabs.filter(t=>t.section===e.key).map(t=>({key:t.id,label:this.tabLabel(t),sub:this.tabSub(t),icon:t.icon,badge:e.folder?this.tr("lab"):void 0}))})).filter(e=>e.rows.length)}},watch:{effectiveLocale(){const e=(o,n)=>{try{const s=this._slots&&this._slots[o];s&&(s.innerHTML="")}catch{}n.mounted=!1,n.state="idle",n.error=""};this.tabs.forEach((o,n)=>{o.mounted&&n!==this.activeIndex&&e(n,o)});const t=this.tabs[this.activeIndex];!t||!t.mounted||(e(this.activeIndex,t),this.mountElement(this.activeIndex))},tab(e){e&&this.onSelect(e)},hostLanguage(e){e!==this.pickBase&&(this.localPick="",this.pickBase=null)}},mounted(){this.watchHostLang(),this.select(this.initialIndex()),this.loadManifest()},beforeUnmount(){this._langObs&&(this._langObs.disconnect(),this._langObs=null)},methods:{tr(e,t){return Gc(this.uiLocale,e,t)},setLocale(e){this.pickBase=this.hostLanguage,this.localPick=e,Ic(e)},tabLabel(e){return this.tr("tab."+e.id)},tabSub(e){return e.section==="experimental"?this.tr("experimentalSub"):this.tr("sub."+e.id)},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},watchHostLang(){typeof MutationObserver>"u"||typeof document>"u"||(this._langObs=new MutationObserver(()=>{this.hostLang=Ia()}),this._langObs.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]}))},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.tabs.findIndex(t=>t.id===this.requestedTab());return e>=0?e:0},loadManifest(){const e=d=>{try{return new URL(d,location.href).href.replace(/[^/]*$/,"")}catch{return""}},t=this.resolve("manifest.json"),o={url:t,root:e(t)},n={url:this.resolve("doxa-maps-spa/manifest.json"),root:o.root};let s=!1;try{s=new URL(t,location.href).origin!==location.origin}catch{}const a=s?[n,o]:[o,n],i="/public/dx-maps/manifest.json";a.some(d=>d.url===i)||a.push({url:i,root:e(i)});const r=[],l=d=>{if(d>=a.length){this.manifestError="manifest.json not found (tried "+r.join(", ")+")",console.error("[posterverse] "+this.manifestError+" — every tab is composed from it.");return}const{url:p,root:f}=a[d];return r.push(p),fetch(p,{credentials:"same-origin"}).then(w=>{if(!w||!w.ok)throw new Error(p+" → HTTP "+(w?w.status:"?"));return w.json()}).then(w=>{if(!w)throw new Error(p+" → empty");this.manifestError="",this.manifestBase=f||"",this.applyManifest(w)}).catch(()=>l(d+1))};try{l(0)}catch{}},applyManifest(e){this.runtime=e&&e.runtime&&typeof e.runtime=="object"?e.runtime:{},this.applyPageGlobals();const t=this.activeKey;this.tabs=Yc(e,a=>console.warn(a)).map(Na);const o=this.requestedTab(),n=!this._honouredTab&&o?this.tabs.findIndex(a=>a.id===o):-1,s=this.tabs.findIndex(a=>a.id===t);this._honouredTab=!0,this.select(n>=0?n:s>=0?s:0)},onSelect(e){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 n=this.tabs[t];n&&n.heavy&&n.mounted&&this.releaseTab(t,n)}const o=this.tabs[e];o&&((t!==e||!this._announced)&&(this._announced=!0,this.$emit("tab-change",{id:o.id,label:this.tabLabel(o)})),o.scriptUrl&&(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:"pv-"+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.mapTitle=this.tabLabel(e),t},applyPageGlobals(){if(typeof window>"u")return;const e=String(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",Aa(this.resolve(t.scriptUrl)).then(()=>Sl(t.tag)).then(()=>{try{if(t.heavy&&this.activeIndex!==e){t.mounted=!1,t.state="idle";return}const o=this._slots&&this._slots[e];if(!o){t.state="error",t.error="no slot";return}o.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="display:block;position:absolute;inset:0;width:100%;height:100%;min-height:0;",o.appendChild(n),t.state="ready"}catch(o){t.state="error",t.error="mount failed: "+(o&&o.message||String(o))}}).catch(o=>{t.state="error",t.error=o&&o.message||String(o)})}}}),td=["hidden"],od={key:0,class:"pv-hint"},nd={key:1,class:"pv-hint err"},sd={key:2,class:"pv-hint err"};function ad(e,t,o,n,s,a){const i=fo("ShellLanguageMenu"),r=fo("BackToTopButton"),l=fo("VerticalTabsLayout");return M(),Pt(l,{dir:e.uiDir,lang:e.uiLocale,labels:e.layoutLabels,title:e.headingText,"nav-label":e.tr("sec.posters"),header:!1,"home-href":e.homeHref||e.cfg.homeHref||"","home-label":e.homeLabel||e.cfg.homeLabel||"",groups:e.navGroups,active:e.activeKey,"onUpdate:active":e.onSelect},{"phone-end":io(()=>[ge(i,{current:e.uiLocale,onSwitch:e.setLocale},null,8,["current","onSwitch"])]),"rail-end":io(({collapsed:d})=>[ge(i,{current:e.uiLocale,collapsed:d,onSwitch:e.setLocale},null,8,["current","collapsed","onSwitch"])]),default:io(()=>[(M(!0),C(ee,null,ft(e.tabs,(d,p)=>en((M(),C("section",{key:d.id,class:"pv-pane",ref_for:!0,ref:f=>{f?e.paneEls[p]=f:delete e.paneEls[p]},hidden:p!==e.activeIndex},[!d.heavy||p===e.activeIndex?(M(),C(ee,{key:0},[I("div",{class:"pv-slot",ref_for:!0,ref:f=>e.setSlot(p,f)},null,512),d.state==="loading"?(M(),C("div",od,E(e.tr("loading",{label:e.tabLabel(d)})),1)):d.state==="error"?(M(),C("div",nd,[$t(E(e.tr("loadFailed",{label:e.tabLabel(d)})),1),t[0]||(t[0]=I("br",null,null,-1)),I("small",null,E(d.error),1)])):d.state==="idle"&&!d.scriptUrl&&e.manifestError?(M(),C("div",sd,[$t(E(e.tr("loadFailed",{label:e.tabLabel(d)})),1),t[1]||(t[1]=I("br",null,null,-1)),I("small",null,E(e.manifestError),1),t[2]||(t[2]=I("br",null,null,-1)),I("small",null,E(e.tr("manifestHint")),1)])):ne("",!0)],64)):ne("",!0)],8,td)),[[bn,p===e.activeIndex]])),128)),ge(r,{target:e.activePaneEl,labels:{backToTop:e.tr("backToTop")}},null,8,["target","labels"])]),_:1},8,["dir","lang","labels","title","nav-label","home-href","home-label","groups","active","onUpdate:active"])}const rd=xo(ed,[["render",ad],["styles",[Qc]]]),id=Ml(),ld=il(rd,{configureApp(e){e.provide("pvTreeBase",id)}});typeof customElements<"u"&&!customElements.get("posterverse-app")&&customElements.define("posterverse-app",ld)})(); +`,Fl=nn({name:"VerticalTabsLayout",components:{BackToTopButton:ba},props:{active:{type:String,default:""},title:{type:String,default:""},items:{type:Array,default:()=>[]},groups:{type:Array,default:()=>[]},navLabel:{type:String,default:"Sections"},labels:{type:Object,default:()=>({})},initialNavOpen:{type:Boolean,default:!0},header:{type:Boolean,default:!0},initialRailCollapsed:{type:Boolean,default:!1},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["update:active"],setup(){return wl(Cl,"vertical-tabs-layout"),{T:Ol}},data(){return{navOpen:this.initialNavOpen,railCollapsed:this.initialRailCollapsed,_tabEls:{},folderOverride:{},narrow:!1,_mql:null,_onMedia:null,activatedKeys:{},hostState:{},hostError:{},_hostSlots:{},_hostMounted:{},hostEls:{}}},computed:{phoneBarShown(){return this.narrow&&!this.header},railEndShown(){return!this.narrow&&!this.header},activeHostEl(){return this.hostEls[this.active]||null},railShown(){return this.narrow?this.navOpen:!0},homeLink(){const e=String(this.homeHref||"").trim();return!e||/^(javascript|data|vbscript):/i.test(e.replace(/[\u0000- ]/g,""))?"":e},homeText(){return this.homeLabel||this.label("home")},allRows(){if(this.groups&&this.groups.length){const e=[];for(const t of this.groups)for(const o of t.rows||[])e.push(o);return e}return this.items},orderedKeys(){return this.allRows.map(e=>e.key)},elementRows(){return this.allRows.filter(e=>e&&e.element)},mountedElementRows(){return this.elementRows.filter(e=>this.activatedKeys[e.key])}},watch:{active:{immediate:!0,handler(e){this.activateElement(e)}}},mounted(){try{window.matchMedia&&(this._mql=window.matchMedia("(max-width: 760px)"),this.narrow=this._mql.matches,this.reconcileForWidth(),this._onMedia=e=>{this.narrow=e.matches,this.reconcileForWidth()},this._mql.addEventListener?this._mql.addEventListener("change",this._onMedia):this._mql.addListener&&this._mql.addListener(this._onMedia))}catch{}this.$nextTick(()=>this.activateElement(this.active))},beforeUnmount(){try{this._mql&&this._onMedia&&(this._mql.removeEventListener?this._mql.removeEventListener("change",this._onMedia):this._mql.removeListener&&this._mql.removeListener(this._onMedia))}catch{}this._mql=null,this._onMedia=null},methods:{registerTab(e,t){t&&(this._tabEls[e]=t)},isNarrow(){return this.narrow},reconcileForWidth(){this.narrow?(this.navOpen=!1,this.railCollapsed=!1):this.navOpen=!0},label(e){const t={toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse",home:"Back to homepage"};return this.labels&&this.labels[e]||t[e]},expandRail(){!this.narrow&&this.railCollapsed&&(this.railCollapsed=!1)},toggleRail(){this.narrow?this.navOpen=!this.navOpen:this.railCollapsed=!this.railCollapsed},setHostSlot(e,t){t&&(this._hostSlots[e]=t,this.$nextTick(()=>this.mountHostElement(e)))},activateElement(e){!e||!this.elementRows.find(o=>o.key===e)||(this.activatedKeys[e]||(this.activatedKeys={...this.activatedKeys,[e]:!0},this.$nextTick(()=>this.watchContextLoss(e)),this.hostState={...this.hostState,[e]:"loading"}),this.$nextTick(()=>this.mountHostElement(e)))},deepCanvases(e,t=[]){if(!e)return t;for(const o of e.querySelectorAll("*"))o.tagName==="CANVAS"&&t.push(o),o.shadowRoot&&this.deepCanvases(o.shadowRoot,t);return t},watchContextLoss(e){const t=this._hostSlots[e];if(t)for(const o of this.deepCanvases(t))o.__vtlLossBound||(o.__vtlLossBound=!0,o.addEventListener("webglcontextlost",()=>{this.hostState={...this.hostState,[e]:"lost"}},{once:!0}))},reloadHostElement(e){const t=this._hostSlots[e];t&&(t.innerHTML=""),this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"loading"},this.$nextTick(()=>this.mountHostElement(e))},mountHostElement(e){if(this._hostMounted[e])return;const t=this.elementRows.find(n=>n.key===e),o=this._hostSlots[e];!t||!o||(this._hostMounted[e]=!0,this.hostState={...this.hostState,[e]:"loading"},Al(t.src).then(()=>Pl(t.element)).then(()=>{Tl(t.element,t.src),o.innerHTML="";const n=document.createElement(t.element),s=t.attrs||{};for(const a in s){const i=s[a],r=i!=null&&typeof i=="object"?JSON.stringify(i):String(i);try{n[a]=i}catch{}try{n.setAttribute(a,r)}catch{}}n.style.cssText="display:block;position:absolute;inset:0;width:100%;height:100%;",o.appendChild(n);for(const a of[0,250,1500])setTimeout(()=>this.watchContextLoss(e),a);this.hostState={...this.hostState,[e]:"ready"}}).catch(n=>{this._hostMounted[e]=!1,this.hostState={...this.hostState,[e]:"error"},this.hostError={...this.hostError,[e]:n&&n.message||String(n)}}))},iconSvg(e){return e?Sa(e):""},initial(e){const t=(e||"").trim();return t?t.charAt(0).toUpperCase():"•"},isFolderClosed(e){const t=this.folderOverride[e.key];return t!=null?!t:e.open!==!0},toggleFolder(e){const t=this.folderOverride[e],o=(this.groups||[]).find(s=>s.key===e),n=t??(o&&o.open===!0);this.folderOverride={...this.folderOverride,[e]:!n}},pick(e){this.$emit("update:active",e),this.narrow&&(this.navOpen=!1)},onKey(e){const t=this.orderedKeys;if(!t.length)return;const o=t.indexOf(this.active);let n=-1;if(e.key==="ArrowDown"||e.key==="ArrowRight")n=(o+1)%t.length;else if(e.key==="ArrowUp"||e.key==="ArrowLeft")n=(o-1+t.length)%t.length;else if(e.key==="Home")n=0;else if(e.key==="End")n=t.length-1;else return;e.preventDefault();const s=t[n];this.pick(s),this.$nextTick(()=>{const a=this._tabEls[s];a&&a.focus&&a.focus()})}}}),Il={key:0,class:"vtl-top"},Nl=["aria-expanded","aria-label"],El={class:"vtl-brand"},Rl={class:"vtl-title"},Wl={class:"vtl-meta"},Dl={key:1,class:"vtl-pbar"},zl=["aria-expanded","aria-label"],Hl={class:"vtl-pbar-end"},Bl={class:"vtl-body"},Ul=["aria-label","aria-hidden","role","aria-orientation"],jl=["href","aria-label","title"],Vl=["innerHTML"],ql={class:"vtl-home-tx"},Kl=["aria-expanded","aria-label"],Gl=["innerHTML"],Jl={class:"vtl-collapse-tx"},Xl=["aria-expanded","onClick"],Zl={key:0,class:"vtl-cap"},Yl={class:"vtl-tl"},Ql={key:1,class:"vtl-td"},ec=["innerHTML"],tc={key:1,class:"vtl-tier"},oc={key:0,class:"vtl-cap"},nc={class:"vtl-tl"},sc={key:1,class:"vtl-td"},ac={class:"vtl-rows"},rc=["aria-selected","aria-disabled","tabindex","onClick"],ic=["innerHTML"],lc={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},cc={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},dc={class:"vtl-tab-text"},pc={class:"vtl-tab-label"},uc={key:0,class:"vtl-tab-badge"},fc={key:0,class:"vtl-tab-sub"},gc=["innerHTML"],hc=["aria-selected","aria-disabled","tabindex","onClick"],$c=["innerHTML"],mc={key:1,class:"vtl-tab-emoji","aria-hidden":"true"},_c={key:2,class:"vtl-tab-fallback","aria-hidden":"true"},bc={class:"vtl-tab-text"},vc={class:"vtl-tab-label"},yc={key:0,class:"vtl-tab-sub"},wc={key:4,class:"vtl-rail-end"},xc={class:"vtl-main"},kc={class:"vtl-content"},Tc=["hidden"],Sc={key:0,class:"vtl-host-hint"},Mc={key:1,class:"vtl-host-hint"},Lc=["onClick"],Oc={key:2,class:"vtl-host-hint err"};function Ac(e,t,o,n,s,a){const i=fo("BackToTopButton");return M(),C("div",{class:We(["vtl",{"nav-open":e.navOpen,"rail-collapsed":e.railCollapsed,"no-header":!e.header,"has-phone-bar":e.phoneBarShown}])},[e.header?(M(),C("header",Il,[I("button",{class:"vtl-menu",type:"button","aria-expanded":String(e.navOpen),onClick:t[0]||(t[0]=r=>e.navOpen=!e.navOpen),"aria-label":e.label("toggleList")},"☰",8,Nl),I("span",El,[tt(e.$slots,"brand")]),I("b",Rl,E(e.title),1),I("span",Wl,[tt(e.$slots,"meta")])])):ne("",!0),e.phoneBarShown?(M(),C("div",Dl,[I("button",{class:"vtl-phone-menu",type:"button","aria-expanded":String(e.navOpen),onClick:t[1]||(t[1]=r=>e.navOpen=!e.navOpen),"aria-label":e.label("toggleList")},"☰",8,zl),I("span",Hl,[tt(e.$slots,"phone-end")])])):ne("",!0),e.narrow?(M(),Pt(i,{key:2,target:e.activeHostEl,labels:{backToTop:e.T("actions.backToTop","Back to top")}},null,8,["target","labels"])):ne("",!0),I("div",Bl,[I("nav",{class:We(["vtl-nav",{"has-rail-end":e.railEndShown&&!!e.$slots["rail-end"]}]),"aria-label":e.navLabel,"aria-hidden":String(!e.railShown),role:e.$slots.rail?null:"tablist","aria-orientation":e.$slots.rail?null:"vertical"},[e.homeLink?(M(),C("a",{key:0,class:"vtl-home",href:e.homeLink,target:"_top","aria-label":e.homeText,title:e.railCollapsed&&!e.narrow?e.homeText:null},[I("span",{class:"vtl-home-ic","aria-hidden":"true",innerHTML:e.iconSvg("home")},null,8,Vl),I("span",ql,E(e.homeText),1)],8,jl)):ne("",!0),I("button",{type:"button",class:"vtl-collapse","aria-expanded":String(!e.railCollapsed),"aria-label":e.railCollapsed?e.label("expandList"):e.label("collapseList"),onClick:t[2]||(t[2]=(...r)=>e.toggleRail&&e.toggleRail(...r))},[I("span",{class:"vtl-collapse-ic","aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,8,Gl),I("span",Jl,E(e.label("collapse")),1)],8,Kl),e.$slots.rail?tt(e.$slots,"rail",{collapsed:e.railCollapsed&&!e.narrow,expand:e.expandRail,pick:e.pick},void 0,void 0,1):e.groups&&e.groups.length?(M(!0),C(ee,{key:2},ft(e.groups,r=>(M(),C("div",{class:"vtl-grp",key:r.key},[r.folder?(M(),C("button",{key:0,type:"button",class:"vtl-tier vtl-tier-btn","aria-expanded":String(!e.isFolderClosed(r)),onClick:l=>e.toggleFolder(r.key)},[r.badge?(M(),C("span",Zl,E(r.badge),1)):ne("",!0),I("span",Yl,E(r.label),1),r.count!=null?(M(),C("span",Ql,E(r.count),1)):ne("",!0),I("span",{class:We(["vtl-chev",{open:!e.isFolderClosed(r)}]),"aria-hidden":"true",innerHTML:e.iconSvg("chevron")},null,10,ec)],8,Xl)):(M(),C("div",tc,[r.badge?(M(),C("span",oc,E(r.badge),1)):ne("",!0),I("span",nc,E(r.label),1),r.count!=null?(M(),C("span",sc,E(r.count),1)):ne("",!0)])),en(I("div",ac,[(M(!0),C(ee,null,ft(r.rows,l=>(M(),C("button",{key:l.key,type:"button",role:"tab",class:We(["vtl-tab",{active:l.key===e.active,disabled:l.disabled}]),"aria-selected":String(l.key===e.active),"aria-disabled":l.disabled?"true":null,tabindex:l.key===e.active?0:-1,ref_for:!0,ref:d=>e.registerTab(l.key,d),onClick:d=>e.pick(l.key),onKeydown:t[3]||(t[3]=d=>e.onKey(d))},[l.icon?(M(),C("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(l.icon)},null,8,ic)):l.emoji?(M(),C("span",lc,E(l.emoji),1)):(M(),C("span",cc,E(e.initial(l.label)),1)),I("span",dc,[I("span",pc,[$t(E(l.label),1),l.badge?(M(),C("span",uc,E(l.badge),1)):ne("",!0)]),l.sub?(M(),C("span",fc,[I("span",{innerHTML:l.sub},null,8,gc)])):ne("",!0)])],42,rc))),128))],512),[[bn,!r.folder||!e.isFolderClosed(r)]])]))),128)):(M(!0),C(ee,{key:3},ft(e.items,r=>(M(),C("button",{key:r.key,type:"button",role:"tab",class:We(["vtl-tab",{active:r.key===e.active,disabled:r.disabled}]),"aria-selected":String(r.key===e.active),"aria-disabled":r.disabled?"true":null,tabindex:r.key===e.active?0:-1,ref_for:!0,ref:l=>e.registerTab(r.key,l),onClick:l=>e.pick(r.key),onKeydown:t[4]||(t[4]=l=>e.onKey(l))},[r.icon?(M(),C("span",{key:0,class:"vtl-tab-ic","aria-hidden":"true",innerHTML:e.iconSvg(r.icon)},null,8,$c)):r.emoji?(M(),C("span",mc,E(r.emoji),1)):(M(),C("span",_c,E(e.initial(r.label)),1)),I("span",bc,[I("span",vc,E(r.label),1),r.sub?(M(),C("span",yc,E(r.sub),1)):ne("",!0)])],42,hc))),128)),e.railEndShown&&e.$slots["rail-end"]?(M(),C("div",wc,[tt(e.$slots,"rail-end",{collapsed:e.railCollapsed})])):ne("",!0)],10,Ul),I("main",xc,[e.header?tt(e.$slots,"toolbar",{},void 0,void 0,0):ne("",!0),I("div",kc,[(M(!0),C(ee,null,ft(e.mountedElementRows,r=>en((M(),C("section",{key:r.key,class:"vtl-host",hidden:r.key!==e.active,ref_for:!0,ref:l=>{l?e.hostEls[r.key]=l:delete e.hostEls[r.key]}},[I("div",{class:"vtl-host-slot",ref_for:!0,ref:l=>e.setHostSlot(r.key,l)},null,512),e.hostState[r.key]==="loading"?(M(),C("div",Sc,E(e.T("messages.loadingNamed","Loading {name}…").replace("{name}",r.label)),1)):e.hostState[r.key]==="lost"?(M(),C("div",Mc,[$t(E(e.T("messages.mapContextLost","This map was unloaded to free graphics memory."))+" ",1),I("button",{type:"button",class:"vtl-host-reload",onClick:l=>e.reloadHostElement(r.key)},E(e.T("buttons.reloadMap","Reload Map")),9,Lc)])):e.hostState[r.key]==="error"?(M(),C("div",Oc,[$t(E(e.T("messages.couldNotLoadNamed","Could not load {name}.").replace("{name}",r.label)),1),t[5]||(t[5]=I("br",null,null,-1)),I("small",null,E(e.hostError[r.key]),1)])):ne("",!0)],8,Tc)),[[bn,r.key===e.active]])),128)),tt(e.$slots,"default")])])])],2)}const Pc=xo(Fl,[["render",Ac],["styles",[Ll]]]),Pa=[{code:"en",name:"English",nativeName:"English",flag:"🇺🇸"},{code:"es",name:"Spanish",nativeName:"Español",flag:"🇪🇸"},{code:"fr",name:"French",nativeName:"Français",flag:"🇫🇷"},{code:"pt",name:"Portuguese",nativeName:"Português",flag:"🇵🇹"},{code:"ar",name:"Arabic",nativeName:"العربية",flag:"🇸🇦",dir:"rtl"},{code:"ru",name:"Russian",nativeName:"Русский",flag:"🇷🇺"},{code:"de",name:"German",nativeName:"Deutsch",flag:"🇩🇪",hideFromSwitcher:!0},{code:"hi",name:"Hindi",nativeName:"हिन्दी",flag:"🇮🇳",hideFromSwitcher:!0},{code:"it",name:"Italian",nativeName:"Italiano",flag:"🇮🇹",hideFromSwitcher:!0},{code:"ro",name:"Romanian",nativeName:"Română",flag:"🇷🇴",hideFromSwitcher:!0},{code:"zh",name:"Chinese",nativeName:"中文",flag:"🇨🇳",hideFromSwitcher:!0}],Cc=Pa.filter(e=>!e.hideFromSwitcher);function Ca(e){return Pa.find(t=>t.code===e)}const Fc="doxa-maps:locale";function Ic(e){try{localStorage.setItem(Fc,e)}catch{}}const Nc="doxa-language-request";function Ec(e){try{const t=e&&e.getRootNode&&e.getRootNode();if(t&&t.host)return t.host}catch{}return e||null}function Rc(e,t){const o=Ec(e);return!o||typeof o.dispatchEvent!="function"?!0:o.dispatchEvent(new CustomEvent(Nc,{detail:{language:t},bubbles:!0,composed:!0,cancelable:!0}))}function Wc(e,t=typeof window<"u"?window:null){try{if(!t||t.MAP_OWNS_PAGE!==!0||!t.history||!t.location)return!1;const o=new URL(t.location.href);return o.searchParams.set("lang",e),t.history.replaceState(t.history.state,"",o.toString()),!0}catch{return!1}}const Dc=".slm[data-v-12760774]{position:relative;display:inline-flex;align-items:center;min-height:44px;max-width:100%;box-sizing:border-box;border-radius:8px;color:#3b463d}.slm-face[data-v-12760774]{display:inline-flex;align-items:center;gap:6px;padding-inline:10px;min-width:0;font-size:13px;font-weight:500;line-height:1.2}.slm-ic[data-v-12760774]{flex:0 0 auto;display:inline-flex;color:var(--vtl-muted, #6d766e)}.slm-ic[data-v-12760774] svg{width:18px;height:18px}.slm-name[data-v-12760774]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}.slm-code[data-v-12760774]{font-weight:600;font-size:12px;letter-spacing:.03em}.slm-caret[data-v-12760774]{flex:0 0 auto;color:var(--vtl-muted, #6d766e);font-size:11px}.slm.collapsed .slm-face[data-v-12760774]{flex-direction:column;gap:2px;padding-inline:4px}.slm-select[data-v-12760774]{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;opacity:0;margin:0;border:0;cursor:pointer;font-size:16px}.slm[data-v-12760774]:hover{background:var(--vtl-accented, #d1d4cd)}.slm[data-v-12760774]:focus-within{outline:2px solid var(--vtl-accent, #92b195);outline-offset:-2px}@media (prefers-reduced-motion: reduce){.slm[data-v-12760774]{transition:none}}",zc={class:"slm-face","aria-hidden":"true"},Hc=["innerHTML"],Bc={key:0,class:"slm-code"},Uc=["lang","dir"],jc={key:2,class:"slm-caret"},Vc=["value","aria-label","title"],qc=["value","lang","dir"],Kc=xo({__name:"ShellLanguageMenu",props:{current:{type:String,default:"en"},collapsed:{type:Boolean,default:!1}},emits:["switch"],setup(e,{emit:t}){const o=e,n=t,s=Et(()=>{const d=Cc.slice();if(o.current&&!d.some(p=>p.code===o.current)){const p=Ca(o.current);p&&d.push(p)}return d}),a=Et(()=>Ca(o.current)||{code:o.current,nativeName:o.current}),i=Et(()=>ka("controls.language",o.current)||"Language"),r=Sa("globe");function l(d){const p=d.target,f=p.value;!f||f===o.current||(Rc(p,f)?(n("switch",f),Wc(f)):p.value=o.current)}return(d,p)=>(M(),C("span",{class:We(["slm",{collapsed:e.collapsed}])},[I("span",zc,[I("span",{class:"slm-ic",innerHTML:Zo(r)},null,8,Hc),e.collapsed?(M(),C("span",Bc,E(String(e.current).toUpperCase()),1)):(M(),C("span",{key:1,class:"slm-name",lang:a.value.code,dir:a.value.dir||null},E(a.value.nativeName),9,Uc)),e.collapsed?ne("",!0):(M(),C("span",jc,"▾"))]),I("select",{class:"slm-select",value:e.current,"aria-label":i.value,title:i.value,onChange:l},[(M(!0),C(ee,null,ft(s.value,f=>(M(),C("option",{key:f.code,value:f.code,lang:f.code,dir:f.dir||null},E(f.nativeName),9,qc))),128))],40,Vc)],2))}},[["styles",[Dc]],["__scopeId","data-v-12760774"]]),ko={en:{"sec.posters":"Posters","sec.experimental":"Experimental","tab.upg-100":"UPG 100 List Posters","sub.upg-100":"my unreached list + posters","tab.country-posters":"Country Posters","sub.country-posters":"a poster for every country","tab.poster-design":"Poster Design","sub.poster-design":"every poster style and size","tab.wall-of-people-groups":"Wall of People Groups","tab.bible-posters":"Bible Posters",experimentalSub:"experimental bundle",lab:"lab",loading:"Loading {label}…",loadFailed:"Could not load {label}.",manifestHint:"This tab is composed from manifest.json — build the tree, or serve the built tree, to load it.",backToTop:"Back to top",home:"Back to homepage",toggleList:"Toggle list",openViews:"Open the list of views",expandList:"Expand list",collapseList:"Collapse list",collapse:"Collapse"},es:{"sec.posters":"Carteles","sec.experimental":"Experimental","tab.upg-100":"Carteles de la lista UPG 100","sub.upg-100":"mi lista de no alcanzados + carteles","tab.country-posters":"Carteles por país","sub.country-posters":"un cartel para cada país","tab.poster-design":"Diseño de carteles","sub.poster-design":"todos los estilos y tamaños de cartel","tab.wall-of-people-groups":"Muro de los pueblos","tab.bible-posters":"Carteles bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Cargando {label}…",loadFailed:"No se pudo cargar {label}.",manifestHint:"Esta pestaña se compone a partir de manifest.json: compila el árbol o sirve el árbol compilado para cargarla.",backToTop:"Volver arriba",home:"Volver a la página de inicio",toggleList:"Mostrar u ocultar la lista",openViews:"Abrir la lista de vistas",expandList:"Expandir la lista",collapseList:"Contraer la lista",collapse:"Contraer"},fr:{"sec.posters":"Affiches","sec.experimental":"Expérimental","tab.upg-100":"Affiches de la liste UPG 100","sub.upg-100":"ma liste des non atteints + affiches","tab.country-posters":"Affiches par pays","sub.country-posters":"une affiche pour chaque pays","tab.poster-design":"Conception d’affiches","sub.poster-design":"tous les styles et formats d’affiche","tab.wall-of-people-groups":"Mur des peuples","tab.bible-posters":"Affiches bibliques",experimentalSub:"carte expérimentale",lab:"bêta",loading:"Chargement de {label}…",loadFailed:"Impossible de charger {label}.",manifestHint:"Cet onglet est composé à partir de manifest.json : construisez l'arborescence ou servez l'arborescence construite pour le charger.",backToTop:"Retour en haut",home:"Retour à l’accueil",toggleList:"Afficher ou masquer la liste",openViews:"Ouvrir la liste des vues",expandList:"Déplier la liste",collapseList:"Replier la liste",collapse:"Replier"},de:{"sec.posters":"Poster","sec.experimental":"Experimentell","tab.upg-100":"Poster der UPG 100 Liste","sub.upg-100":"meine Liste der Unerreichten + Poster","tab.country-posters":"Länderposter","sub.country-posters":"ein Poster für jedes Land","tab.poster-design":"Postergestaltung","sub.poster-design":"alle Posterstile und -größen","tab.wall-of-people-groups":"Wand der Volksgruppen","tab.bible-posters":"Bibelposter",experimentalSub:"experimentelle Karte",lab:"Beta",loading:"{label} wird geladen…",loadFailed:"{label} konnte nicht geladen werden.",manifestHint:"Dieser Tab wird aus manifest.json zusammengesetzt – bauen Sie den Baum oder stellen Sie den gebauten Baum bereit, um ihn zu laden.",backToTop:"Nach oben",home:"Zurück zur Startseite",toggleList:"Liste ein-/ausblenden",openViews:"Ansichtsliste öffnen",expandList:"Liste ausklappen",collapseList:"Liste einklappen",collapse:"Einklappen"},pt:{"sec.posters":"Cartazes","sec.experimental":"Experimental","tab.upg-100":"Cartazes da lista UPG 100","sub.upg-100":"minha lista de não alcançados + cartazes","tab.country-posters":"Cartazes por país","sub.country-posters":"um cartaz para cada país","tab.poster-design":"Design de cartazes","sub.poster-design":"todos os estilos e tamanhos de cartaz","tab.wall-of-people-groups":"Mural dos povos","tab.bible-posters":"Cartazes bíblicos",experimentalSub:"mapa experimental",lab:"beta",loading:"Carregando {label}…",loadFailed:"Não foi possível carregar {label}.",manifestHint:"Esta aba é composta a partir do manifest.json — compile a árvore ou sirva a árvore compilada para carregá-la.",backToTop:"Voltar ao topo",home:"Voltar à página inicial",toggleList:"Mostrar ou ocultar a lista",openViews:"Abrir a lista de visualizações",expandList:"Expandir a lista",collapseList:"Recolher a lista",collapse:"Recolher"},it:{"sec.posters":"Poster","sec.experimental":"Sperimentale","tab.upg-100":"Poster della lista UPG 100","sub.upg-100":"la mia lista dei non raggiunti + poster","tab.country-posters":"Poster per paese","sub.country-posters":"un poster per ogni paese","tab.poster-design":"Design dei poster","sub.poster-design":"tutti gli stili e i formati dei poster","tab.wall-of-people-groups":"Muro dei popoli","tab.bible-posters":"Poster biblici",experimentalSub:"mappa sperimentale",lab:"beta",loading:"Caricamento di {label}…",loadFailed:"Impossibile caricare {label}.",manifestHint:"Questa scheda è composta da manifest.json: compila l'albero o pubblica l'albero compilato per caricarla.",backToTop:"Torna su",home:"Torna alla home page",toggleList:"Mostra o nascondi l’elenco",openViews:"Apri l’elenco delle viste",expandList:"Espandi l’elenco",collapseList:"Comprimi l’elenco",collapse:"Comprimi"},ro:{"sec.posters":"Afișe","sec.experimental":"Experimental","tab.upg-100":"Afișe din lista UPG 100","sub.upg-100":"lista mea de neatinși + afișe","tab.country-posters":"Afișe pe țări","sub.country-posters":"un afiș pentru fiecare țară","tab.poster-design":"Design de afișe","sub.poster-design":"toate stilurile și dimensiunile de afiș","tab.wall-of-people-groups":"Zidul popoarelor","tab.bible-posters":"Afișe biblice",experimentalSub:"hartă experimentală",lab:"beta",loading:"Se încarcă {label}…",loadFailed:"{label} nu a putut fi încărcat.",manifestHint:"Această filă este compusă din manifest.json — construiți arborele sau serviți arborele construit pentru a o încărca.",backToTop:"Sus",home:"Înapoi la pagina principală",toggleList:"Afișează sau ascunde lista",openViews:"Deschide lista de vizualizări",expandList:"Extinde lista",collapseList:"Restrânge lista",collapse:"Restrânge"},ru:{"sec.posters":"Плакаты","sec.experimental":"Экспериментальное","tab.upg-100":"Плакаты списка UPG 100","sub.upg-100":"мой список недостигнутых + плакаты","tab.country-posters":"Плакаты по странам","sub.country-posters":"плакат для каждой страны","tab.poster-design":"Дизайн плакатов","sub.poster-design":"все стили и размеры плакатов","tab.wall-of-people-groups":"Стена народов","tab.bible-posters":"Библейские плакаты",experimentalSub:"экспериментальная карта",lab:"бета",loading:"Загрузка: {label}…",loadFailed:"Не удалось загрузить: {label}.",manifestHint:"Эта вкладка собирается из manifest.json — соберите дерево или разместите собранное дерево, чтобы загрузить её.",backToTop:"Наверх",home:"На главную страницу",toggleList:"Показать или скрыть список",openViews:"Открыть список представлений",expandList:"Развернуть список",collapseList:"Свернуть список",collapse:"Свернуть"},ar:{"sec.posters":"ملصقات","sec.experimental":"تجريبي","tab.upg-100":"ملصقات قائمة UPG 100","sub.upg-100":"قائمتي لغير المُبشَّرين + ملصقات","tab.country-posters":"ملصقات الدول","sub.country-posters":"ملصق لكل دولة","tab.poster-design":"تصميم الملصقات","sub.poster-design":"كل أنماط الملصقات وأحجامها","tab.wall-of-people-groups":"جدار الشعوب","tab.bible-posters":"ملصقات الكتاب المقدس",experimentalSub:"خريطة تجريبية",lab:"تجريبي",loading:"جارٍ تحميل {label}…",loadFailed:"تعذّر تحميل {label}.",manifestHint:"تُبنى علامة التبويب هذه من manifest.json — ابنِ الشجرة أو قدّم الشجرة المبنية لتحميلها.",backToTop:"إلى الأعلى",home:"العودة إلى الصفحة الرئيسية",toggleList:"إظهار القائمة أو إخفاؤها",openViews:"فتح قائمة العروض",expandList:"توسيع القائمة",collapseList:"طي القائمة",collapse:"طي"},hi:{"sec.posters":"पोस्टर","sec.experimental":"प्रायोगिक","tab.upg-100":"UPG 100 सूची पोस्टर","sub.upg-100":"मेरी अप्राप्त सूची + पोस्टर","tab.country-posters":"देश पोस्टर","sub.country-posters":"हर देश के लिए एक पोस्टर","tab.poster-design":"पोस्टर डिज़ाइन","sub.poster-design":"हर पोस्टर शैली और आकार","tab.wall-of-people-groups":"जनसमूहों की दीवार","tab.bible-posters":"बाइबल पोस्टर",experimentalSub:"प्रायोगिक मानचित्र",lab:"बीटा",loading:"{label} लोड हो रहा है…",loadFailed:"{label} लोड नहीं हो सका।",manifestHint:"यह टैब manifest.json से बनता है — इसे लोड करने के लिए ट्री बनाएँ या बना हुआ ट्री सर्व करें।",backToTop:"ऊपर जाएँ",home:"होमपेज पर वापस जाएँ",toggleList:"सूची दिखाएँ या छिपाएँ",openViews:"दृश्यों की सूची खोलें",expandList:"सूची फैलाएँ",collapseList:"सूची संक्षिप्त करें",collapse:"संक्षिप्त करें"},zh:{"sec.posters":"海报","sec.experimental":"实验性","tab.upg-100":"UPG 100 名单海报","sub.upg-100":"我的未得之民名单 + 海报","tab.country-posters":"国家海报","sub.country-posters":"每个国家一张海报","tab.poster-design":"海报设计","sub.poster-design":"所有海报样式与尺寸","tab.wall-of-people-groups":"民族之墙","tab.bible-posters":"圣经海报",experimentalSub:"实验性地图",lab:"测试版",loading:"正在加载{label}…",loadFailed:"无法加载{label}。",manifestHint:"此标签页由 manifest.json 组成——请构建目录树或提供已构建的目录树以加载它。",backToTop:"回到顶部",home:"返回首页",toggleList:"显示或隐藏列表",openViews:"打开视图列表",expandList:"展开列表",collapseList:"折叠列表",collapse:"折叠"}},Tn=Object.keys(ko);function Gc(e,t,o){let s=(ko[e]||ko.en)[t]??ko.en[t]??t;if(o)for(const a in o)s=s.split("{"+a+"}").join(String(o[a]));return s}const Jc=[{key:"posters",i18n:"sec.posters",icon:"poster"},{key:"experimental",i18n:"sec.experimental",icon:"flask",folder:!0,open:!1}],Fa=[{id:"upg-100",section:"posters",icon:"list",bundle:"my-upg-100-list",profile:"upg-100-mfe"},{id:"country-posters",section:"posters",icon:"map",bundle:"country-posters",profile:"country-posters-mfe"},{id:"poster-design",section:"posters",icon:"poster",bundle:"poster-design",profile:"poster-design-mfe"},{id:"wall-of-people-groups",section:"experimental",icon:"flask",bundle:"wall-of-people-groups",profile:"wall-of-people-groups"},{id:"bible-posters",section:"experimental",icon:"flask",bundle:"bible-posters",profile:"bible-posters"}],Xc=new Set(["key-cities","posterverse","doxa-maps-spa","plugin-studio"]),Zc=new Set(["my-upg-100-list-map","country-posters-map"]);function Yc(e,t=()=>{}){const o=e&&Array.isArray(e.bundles)?e.bundles:[],n=Object.fromEntries(o.map(a=>[a&&a.bundle,a])),s=[];for(const a of Fa){if(Xc.has(a.bundle))continue;const i=n[a.bundle];if(!i)continue;const r=Array.isArray(i.profiles)?i.profiles:[];let l=r.find(f=>f&&f.profile===a.profile);if(!l){if(l=r.find(f=>f&&f.profile===a.bundle)||r[0],!l)continue;t(`[posterverse] ${a.bundle} has no profile "${a.profile}"; row "${a.id}" opens "${l.profile}" instead`)}const d=l.element||Array.isArray(i.elements)&&i.elements[0]||a.bundle,p=i.scriptUrl||l.scriptUrl||"";p&&s.push({...a,tag:d,scriptUrl:p,profile:l.profile,heavy:Zc.has(d)||!!l.isMap})}return s}const Qc=":host{display:block;position:relative;height:var(--posterverse-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}.pv-pane{position:absolute;top:0;right:0;bottom:0;left:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;--profile-min-h: 0}.pv-slot{position:relative;min-height:100%}.pv-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}.pv-hint.err{color:#b3261e}.pv-hint small{color:#6d766e}";function Ia(){try{const e=new URLSearchParams(location.search),t=(e.get("lang")||e.get("locale")||"").split("-")[0].toLowerCase();if(Tn.includes(t))return t}catch{}try{const e=(document.documentElement.lang||"").split("-")[0].toLowerCase();if(Tn.includes(e))return e}catch{}return""}const Na=e=>({...e,tag:e.tag||"",scriptUrl:e.scriptUrl||"",heavy:!!e.heavy,mounted:!1,state:"idle",error:""}),ed=nn({name:"Posterverse",inheritAttrs:!1,components:{VerticalTabsLayout:Pc,BackToTopButton:ba,ShellLanguageMenu:Kc},props:{treeBase:{type:String,default:""},profileConfig:{type:[String,Object],default:""},heading:{type:String,default:"Posterverse"},tokenUrl:{type:String,default:""},tk:{type:String,default:""},language:{type:String,default:""},apiBaseUrl:{type:String,default:""},provider:{type:String,default:""},tab:{type:String,default:""},homeHref:{type:String,default:""},homeLabel:{type:String,default:""}},emits:["tab-change"],setup(){return{injectedBase:St("pvTreeBase","")}},data(){return{paneEls:{},activeIndex:0,manifestError:"",manifestBase:"",runtime:{},hostLang:Ia(),localPick:"",pickBase:null,tabs:Fa.filter(e=>!e.provisional).map(Na)}},computed:{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=String(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":""},headingText(){return String(this.cfg.heading||this.heading||"").trim()||"Posterverse"},hostLanguage(){return String(this.language||this.cfg.language||this.cfg.locale||this.cfg.lang||"").trim()},effectiveLocale(){return this.localPick&&this.hostLanguage===this.pickBase?this.localPick:(this.hostLanguage||this.hostLang||"en").split("-")[0].toLowerCase()},uiLocale(){return Tn.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","home"])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:""},activePaneEl(){return this.paneEls[this.activeIndex]||null},navGroups(){return Jc.map(e=>({key:e.key,label:this.tr(e.i18n),icon:e.icon,folder:!!e.folder,open:e.open,rows:this.tabs.filter(t=>t.section===e.key).map(t=>({key:t.id,label:this.tabLabel(t),sub:this.tabSub(t),icon:t.icon,badge:e.folder?this.tr("lab"):void 0}))})).filter(e=>e.rows.length)}},watch:{effectiveLocale(){const e=(o,n)=>{try{const s=this._slots&&this._slots[o];s&&(s.innerHTML="")}catch{}n.mounted=!1,n.state="idle",n.error=""};this.tabs.forEach((o,n)=>{o.mounted&&n!==this.activeIndex&&e(n,o)});const t=this.tabs[this.activeIndex];!t||!t.mounted||(e(this.activeIndex,t),this.mountElement(this.activeIndex))},tab(e){e&&this.onSelect(e)},hostLanguage(e){e!==this.pickBase&&(this.localPick="",this.pickBase=null)}},mounted(){this.watchHostLang(),this.select(this.initialIndex()),this.loadManifest()},beforeUnmount(){this._langObs&&(this._langObs.disconnect(),this._langObs=null)},methods:{tr(e,t){return Gc(this.uiLocale,e,t)},setLocale(e){this.pickBase=this.hostLanguage,this.localPick=e,Ic(e)},tabLabel(e){return this.tr("tab."+e.id)},tabSub(e){return e.section==="experimental"?this.tr("experimentalSub"):this.tr("sub."+e.id)},setSlot(e,t){t&&(this._slots=Object.assign(this._slots||{},{[e]:t}))},watchHostLang(){typeof MutationObserver>"u"||typeof document>"u"||(this._langObs=new MutationObserver(()=>{this.hostLang=Ia()}),this._langObs.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]}))},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.tabs.findIndex(t=>t.id===this.requestedTab());return e>=0?e:0},loadManifest(){const e=d=>{try{return new URL(d,location.href).href.replace(/[^/]*$/,"")}catch{return""}},t=this.resolve("manifest.json"),o={url:t,root:e(t)},n={url:this.resolve("doxa-maps-spa/manifest.json"),root:o.root};let s=!1;try{s=new URL(t,location.href).origin!==location.origin}catch{}const a=s?[n,o]:[o,n],i="/public/dx-maps/manifest.json";a.some(d=>d.url===i)||a.push({url:i,root:e(i)});const r=[],l=d=>{if(d>=a.length){this.manifestError="manifest.json not found (tried "+r.join(", ")+")",console.error("[posterverse] "+this.manifestError+" — every tab is composed from it.");return}const{url:p,root:f}=a[d];return r.push(p),fetch(p,{credentials:"same-origin"}).then(w=>{if(!w||!w.ok)throw new Error(p+" → HTTP "+(w?w.status:"?"));return w.json()}).then(w=>{if(!w)throw new Error(p+" → empty");this.manifestError="",this.manifestBase=f||"",this.applyManifest(w)}).catch(()=>l(d+1))};try{l(0)}catch{}},applyManifest(e){this.runtime=e&&e.runtime&&typeof e.runtime=="object"?e.runtime:{},this.applyPageGlobals();const t=this.activeKey;this.tabs=Yc(e,a=>console.warn(a)).map(Na);const o=this.requestedTab(),n=!this._honouredTab&&o?this.tabs.findIndex(a=>a.id===o):-1,s=this.tabs.findIndex(a=>a.id===t);this._honouredTab=!0,this.select(n>=0?n:s>=0?s:0)},onSelect(e){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 n=this.tabs[t];n&&n.heavy&&n.mounted&&this.releaseTab(t,n)}const o=this.tabs[e];o&&((t!==e||!this._announced)&&(this._announced=!0,this.$emit("tab-change",{id:o.id,label:this.tabLabel(o)})),o.scriptUrl&&(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:"pv-"+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.mapTitle=this.tabLabel(e),t},applyPageGlobals(){if(typeof window>"u")return;const e=String(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",Aa(this.resolve(t.scriptUrl)).then(()=>Sl(t.tag)).then(()=>{try{if(t.heavy&&this.activeIndex!==e){t.mounted=!1,t.state="idle";return}const o=this._slots&&this._slots[e];if(!o){t.state="error",t.error="no slot";return}o.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="display:block;position:absolute;inset:0;width:100%;height:100%;min-height:0;",o.appendChild(n),t.state="ready"}catch(o){t.state="error",t.error="mount failed: "+(o&&o.message||String(o))}}).catch(o=>{t.state="error",t.error=o&&o.message||String(o)})}}}),td=["hidden"],od={key:0,class:"pv-hint"},nd={key:1,class:"pv-hint err"},sd={key:2,class:"pv-hint err"};function ad(e,t,o,n,s,a){const i=fo("ShellLanguageMenu"),r=fo("BackToTopButton"),l=fo("VerticalTabsLayout");return M(),Pt(l,{dir:e.uiDir,lang:e.uiLocale,labels:e.layoutLabels,title:e.headingText,"nav-label":e.tr("sec.posters"),header:!1,"home-href":e.homeHref||e.cfg.homeHref||"","home-label":e.homeLabel||e.cfg.homeLabel||"",groups:e.navGroups,active:e.activeKey,"onUpdate:active":e.onSelect},{"phone-end":io(()=>[ge(i,{current:e.uiLocale,onSwitch:e.setLocale},null,8,["current","onSwitch"])]),"rail-end":io(({collapsed:d})=>[ge(i,{current:e.uiLocale,collapsed:d,onSwitch:e.setLocale},null,8,["current","collapsed","onSwitch"])]),default:io(()=>[(M(!0),C(ee,null,ft(e.tabs,(d,p)=>en((M(),C("section",{key:d.id,class:"pv-pane",ref_for:!0,ref:f=>{f?e.paneEls[p]=f:delete e.paneEls[p]},hidden:p!==e.activeIndex},[!d.heavy||p===e.activeIndex?(M(),C(ee,{key:0},[I("div",{class:"pv-slot",ref_for:!0,ref:f=>e.setSlot(p,f)},null,512),d.state==="loading"?(M(),C("div",od,E(e.tr("loading",{label:e.tabLabel(d)})),1)):d.state==="error"?(M(),C("div",nd,[$t(E(e.tr("loadFailed",{label:e.tabLabel(d)})),1),t[0]||(t[0]=I("br",null,null,-1)),I("small",null,E(d.error),1)])):d.state==="idle"&&!d.scriptUrl&&e.manifestError?(M(),C("div",sd,[$t(E(e.tr("loadFailed",{label:e.tabLabel(d)})),1),t[1]||(t[1]=I("br",null,null,-1)),I("small",null,E(e.manifestError),1),t[2]||(t[2]=I("br",null,null,-1)),I("small",null,E(e.tr("manifestHint")),1)])):ne("",!0)],64)):ne("",!0)],8,td)),[[bn,p===e.activeIndex]])),128)),ge(r,{target:e.activePaneEl,labels:{backToTop:e.tr("backToTop")}},null,8,["target","labels"])]),_:1},8,["dir","lang","labels","title","nav-label","home-href","home-label","groups","active","onUpdate:active"])}const rd=xo(ed,[["render",ad],["styles",[Qc]]]),id=Ml(),ld=il(rd,{configureApp(e){e.provide("pvTreeBase",id)}});typeof customElements<"u"&&!customElements.get("posterverse-app")&&customElements.define("posterverse-app",ld)})(); diff --git a/public/dx-maps/posterverse/posterverse/app/index.html b/public/dx-maps/posterverse/posterverse/app/index.html index 7ec8c0ecc..8f49bbb10 100644 --- a/public/dx-maps/posterverse/posterverse/app/index.html +++ b/public/dx-maps/posterverse/posterverse/app/index.html @@ -67,7 +67,7 @@ - + - + - + - + \n\n\n" + }, + "bundle": "bible-posters" + } + ] + }, { "bundle": "big-picture", "scriptUrl": "./big-picture/big-picture.js", @@ -361,7 +393,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-jJHY8JXkPZd8UQz7gDBNE4n+LX+DsK5MgcafqLChgSL5e1AUz+YaItO8LOX19VzO", + "integrity": "sha384-jvHzikM2VJQXpIlJwQVbEXFg/JOw67aiJsBaRBMkHKc4w080G41TsDc6Gt3y3GiH", "elements": [ "doxa-maps-spa" ], @@ -391,7 +423,7 @@ "scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { @@ -1134,7 +1166,7 @@ "bundle": "posterverse", "scriptUrl": "./posterverse/posterverse.js", "output": "dx-maps/posterverse/posterverse.js", - "integrity": "sha384-+1IEWkJujDRDE7t/piXT6lq6T0QdhCYfT4pv4OURz6EKxDK8p8YcSZNZOv5uRi0W", + "integrity": "sha384-SHwg48KTIMJixoVevPoDmKMsuJ1tAKE2fa4WBS1bOmGeUawyWBt4n029N8itST7q", "elements": [ "posterverse-app" ], @@ -1142,7 +1174,8 @@ "my-upg-100-list/upg-100-mfe", "country-posters/country-posters-mfe", "poster-design/poster-design-mfe", - "wall-of-people-groups/wall-of-people-groups" + "wall-of-people-groups/wall-of-people-groups", + "bible-posters/bible-posters" ], "stage": "experimental", "profiles": [ @@ -1159,7 +1192,7 @@ "scriptUrl": "./posterverse/posterverse.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { diff --git a/public/dx-maps/manifest.json b/public/dx-maps/manifest.json index 950e8a71c..52434fff0 100644 --- a/public/dx-maps/manifest.json +++ b/public/dx-maps/manifest.json @@ -2,8 +2,8 @@ "schema": "doxa-maps-manifest@1", "generatedFrom": "plugin-designs/*/*.vue", "embedBase": ".", - "bundleCount": 27, - "profileCount": 41, + "bundleCount": 28, + "profileCount": 42, "runtime": { "apiBaseUrl": "https://pray.doxa.life" }, @@ -37,6 +37,38 @@ } ] }, + { + "bundle": "bible-posters", + "scriptUrl": "./bible-posters/bible-posters.js", + "output": "dx-maps/bible-posters/bible-posters.js", + "integrity": "sha384-x0qrqnzFOHxhCWZN4YYpnME08TLUQdfMI8oR5cAnQDtOVKu133/27BXcHCr0Ev7Q", + "elements": [ + "bible-posters" + ], + "stage": "experimental", + "profiles": [ + { + "profile": "bible-posters", + "stage": "experimental", + "label": "Bible Posters", + "targets": [ + "web" + ], + "file": "bible-posters.vue", + "description": "A whole book of the Bible on one poster, in justified columns under a bold title, from a public-domain text.", + "element": "bible-posters", + "type": "single", + "isMap": false, + "iframeUrl": "./bible-posters/bible-posters/index.html", + "scriptUrl": "./bible-posters/bible-posters.js", + "embed": { + "iframe": "", + "script": "\n\n\n" + }, + "bundle": "bible-posters" + } + ] + }, { "bundle": "big-picture", "scriptUrl": "./big-picture/big-picture.js", @@ -361,7 +393,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-jJHY8JXkPZd8UQz7gDBNE4n+LX+DsK5MgcafqLChgSL5e1AUz+YaItO8LOX19VzO", + "integrity": "sha384-jvHzikM2VJQXpIlJwQVbEXFg/JOw67aiJsBaRBMkHKc4w080G41TsDc6Gt3y3GiH", "elements": [ "doxa-maps-spa" ], @@ -391,7 +423,7 @@ "scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ { @@ -1134,7 +1166,7 @@ "bundle": "posterverse", "scriptUrl": "./posterverse/posterverse.js", "output": "dx-maps/posterverse/posterverse.js", - "integrity": "sha384-+1IEWkJujDRDE7t/piXT6lq6T0QdhCYfT4pv4OURz6EKxDK8p8YcSZNZOv5uRi0W", + "integrity": "sha384-SHwg48KTIMJixoVevPoDmKMsuJ1tAKE2fa4WBS1bOmGeUawyWBt4n029N8itST7q", "elements": [ "posterverse-app" ], @@ -1142,7 +1174,8 @@ "my-upg-100-list/upg-100-mfe", "country-posters/country-posters-mfe", "poster-design/poster-design-mfe", - "wall-of-people-groups/wall-of-people-groups" + "wall-of-people-groups/wall-of-people-groups", + "bible-posters/bible-posters" ], "stage": "experimental", "profiles": [ @@ -1159,7 +1192,7 @@ "scriptUrl": "./posterverse/posterverse.js", "embed": { "iframe": "", - "script": "\n\n\n" + "script": "\n\n\n" }, "instances": [ {