diff --git a/README.md b/README.md index e7452c24..515a9c47 100644 --- a/README.md +++ b/README.md @@ -143,8 +143,8 @@ If you build with AI agents, this repo is made for you: Studio: look at a plugin, say what you see, and hand the text to your agent. Nothing leaves your computer (Linux today). - **One plugin, several outputs.** The same plugin ships as a web embed or a mobile app, and a plugin - can target the desktop: Rudder is the desktop example, running in the Studio today with its - desktop packaging next. + can target the desktop: Rudder is the desktop example, a corner widget in the Studio and its own + desktop app (`bun run desktop:build rudder-voice`, see [HOWTO-build-the-desktop-app](./documentation/HOWTO-build-the-desktop-app.md)). - **Build together.** [Run it in the cloud](#run-it-in-the-cloud) gives a whole team one shared dev server. diff --git a/documentation/HOWTO-which-gates-need-a-browser.md b/documentation/HOWTO-which-gates-need-a-browser.md new file mode 100644 index 00000000..48420256 --- /dev/null +++ b/documentation/HOWTO-which-gates-need-a-browser.md @@ -0,0 +1,139 @@ +# Which gates need a browser + +There are **238** checks in this repo. **97 need a real browser**; the rest run anywhere. If you are not +the person who owns the browser seat, that second group is not yours to run — and knowing which is +which saves you from a whole class of wrong answer. + +> **The short version.** A gate that reads *files* is headless. A gate that asks *what the page +> actually painted* needs a browser. Run the first kind freely; hand the second kind to whoever owns +> the browser. + +--- + +## Telling them apart + +**Ask the repo, don't grep:** + +```bash +bun run browser-gates # lists every script that launches a browser +``` + +That is the authoritative answer — the same detector `check:browser-gates-guarded` uses, so it +cannot drift from what is enforced. A grep for `playwright|chromium` also works today and is fine +for a quick look, but it is a heuristic: it finds files that *mention* the word, and it would miss a +file that reached the package by path. The name tells you nothing either. `check:packet-render` sounds like a file check and drives a browser; +`check:composites-mount` sounds like it needs one and does not (it mounts every composite through +Vite's SSR loader, no browser at all). + +### Measured on `main` (2026-09-28) + +| | Count | +|---|---:| +| headless — run these yourself | the remainder | +| **browser — not yours unless you own the seat** | **97** | +| neither (shells out to `bun`/`php`) | 3 — `check:mobile`, `check:wp-embed`, `smoke:playground` | + +The browser group is, broadly: everything that renders a map (`check:map-paints`, +`check:map-data-painted`, `check:auto-engine`, `check:maplibre-drops`), everything about layout +(`check:fits-screen`, `check:shell-scroll`, `check:filter-width`, `check:scrim-viewport`), +everything that prints (`check:poster-prints`, `check:print-geometry`, `check:packet-render`), +everything about right-to-left shaping (`check:rtl-shaping`, `check:embedded-rtl`), the English-leak +family (`check:english-leaks`, `check:leaf-english-leaks`, `check:host-locale-contract`), and every +`smoke:*`. + +## Why the split exists, and why it is not negotiable + +One machine, one browser seat. Two agents running Playwright at once fight over it, and the loser +does not fail — **it reports that it could not look**, which is a third outcome most people's mental +model does not have (see below). So the rule is: **one person runs the browser gates.** In this +repo that is the QA agent; ask them rather than starting a second browser. + +This is not a limitation to work around. A source read and a render are *different measurements*, +and confusing them is the most common way to report something false: + +- `check:leaf-english-leaks` can only find a leak by comparing what the catalogue says with **what + the page shows**. Four catalogue gates can all pass — keys exist, differ per locale, are reachable, + are in scope — while a page still paints English. Catalogue-green is not render-green. +- Equally, a headless check often settles a question people assume needs pixels. Of 16 cards parked + as "needs a browser", **7 turned out to be about markup, a path, a manifest field or a gate** — + all readable without one. + +**Ask what property the claim is about**, then pick the tool. Not the other way round. + +--- + +## The guard: you cannot launch a browser by accident any more + +The rule above used to be remembered. It is now **enforced**. Every browser gate reaches Playwright +through `internal/lib/playwright-guarded.mjs`, which refuses to launch unless +`internal/browser-slot.sh` has exported `DOXA_BROWSER_SLOT`: + +```bash +internal/browser-slot.sh bun run check:packet-render # the only way to run one +``` + +Run a browser gate outside the slot and it does not fail — **it exits 75 and tells you the command**: + +``` +this gate launches a browser. Browsers run only on the browser seat, inside the slot: + internal/browser-slot.sh bun run diff --git a/plugin-designs/gospel-resources/resources-map.vue b/plugin-designs/gospel-resources/resources-map.vue index a86cb910..1f2ff425 100644 --- a/plugin-designs/gospel-resources/resources-map.vue +++ b/plugin-designs/gospel-resources/resources-map.vue @@ -1956,7 +1956,7 @@ useShadowStyles( '.gm-key{display:flex;align-items:center;gap:5px;font-size:14px;white-space:nowrap}' + // This one label is a phrase, not a legend word, so it is allowed to wrap rather than // be clipped by the nowrap above. - '.gm-key.wide{white-space:normal;text-align:left;line-height:1.25}' + + '.gm-key.wide{white-space:normal;text-align:start;line-height:1.25}' + '.gm-sw{width:12px;height:12px;border-radius:3px;flex:none}' + '.gm-dot{width:10px;height:10px;border-radius:50%;flex:none;display:inline-block;' + 'border:1.4px solid #fff;box-shadow:0 0 0 1px rgba(0,0,0,.18);vertical-align:-1px}' + @@ -1971,7 +1971,7 @@ useShadowStyles( '.gm-filtered{margin-top:5px;font-size:13.5px;line-height:1.45;color:#3b463d}' + '.is-dark .gm-filtered{color:#e5e7eb}' + '.gm-kclear{border:1px solid #d1d4cd;background:#fff;color:#3b463d;font:600 10.5px inherit;' + - 'padding:3px 8px;border-radius:6px;cursor:pointer;margin-left:4px;min-height:24px}' + + 'padding:3px 8px;border-radius:6px;cursor:pointer;margin-inline-start:4px;min-height:24px}' + '.gm-pinkey-h{font-size:14px;font-weight:600;margin-bottom:4px}' + '.gm-caveat{margin-top:5px;font-size:13.5px;opacity:.72;line-height:1.4}' + '.gm-dot-hole{border:2.5px solid #7d3b30;box-sizing:border-box}' + @@ -2028,7 +2028,7 @@ useShadowStyles( '.gm-q:focus{outline:2px solid #92b195;outline-offset:1px}' + '.gm-qx{position:absolute;inset-inline-end:4px;top:50%;transform:translateY(-50%);border:0;background:transparent;color:#6d766e;font-size:19px;line-height:1;cursor:pointer;padding:4px 6px;min-height:24px}' + '.gm-qres{margin:-2px 0 7px;border:1px solid #d1d4cd;border-radius:8px;background:#fff;overflow:hidden}' + - '.gm-qrow{display:flex;align-items:baseline;gap:6px;width:100%;text-align:left;border:0;background:transparent;font:inherit;font-size:14px;color:#3b463d;padding:6px 8px;cursor:pointer;min-height:30px;border-bottom:1px solid #eceee9}' + + '.gm-qrow{display:flex;align-items:baseline;gap:6px;width:100%;text-align:start;border:0;background:transparent;font:inherit;font-size:14px;color:#3b463d;padding:6px 8px;cursor:pointer;min-height:30px;border-bottom:1px solid #eceee9}' + '.gm-qrow:last-child{border-bottom:0}' + '.gm-qrow:hover{background:#f3f3f1}' + '.gm-qn{font-weight:700}' + @@ -2081,19 +2081,19 @@ useShadowStyles( // must look identical, so the shell carries the box and .gm-pg-btn/.gm-pg-open carry // the interactive bits. cursor:pointer is NOT on the shell — on a resource row the // gaps between the name and the chips are not clickable, and saying otherwise lies. - '.gm-pg{width:100%;box-sizing:border-box;text-align:left;display:block;padding:8px 9px;' + + '.gm-pg{width:100%;box-sizing:border-box;text-align:start;display:block;padding:8px 9px;' + 'margin-bottom:6px;border-radius:8px;' + 'border:1px solid rgba(0,0,0,.10);background:rgba(0,0,0,.02);color:inherit;font:inherit}' + '.is-dark .gm-pg{border-color:rgba(255,255,255,.10);background:rgba(255,255,255,.03)}' + '.gm-pg-btn{cursor:pointer;text-decoration:none;color:inherit}' + // The drill-in control on a resource row: a bare button that inherits the shell's // look, so the row still reads as one tap-target for the name + language line. - '.gm-pg-open{display:block;width:100%;text-align:left;padding:0;margin:0;border:0;' + + '.gm-pg-open{display:block;width:100%;text-align:start;padding:0;margin:0;border:0;' + 'background:transparent;color:inherit;font:inherit;cursor:pointer}' + '.gm-pg-n{display:block;font-weight:700;font-size:15.5px}' + '.gm-pg-l{display:block;font-size:14px;opacity:.75;margin-top:1px}' + '.gm-code{display:inline-block;font:600 10px ui-monospace,SFMono-Regular,Menlo,monospace;' + - 'padding:1px 5px;border-radius:4px;background:rgba(0,0,0,.09);margin-left:5px;vertical-align:1px}' + + 'padding:1px 5px;border-radius:4px;background:rgba(0,0,0,.09);margin-inline-start:5px;vertical-align:1px}' + '.is-dark .gm-code{background:rgba(255,255,255,.12)}' + '.gm-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:5px}' + // nowrap keeps the short status chips ("Film - link checked") on one line, but a Door43 @@ -3099,7 +3099,7 @@ useShadowStyles(
",["to-number",["get","peoplePraying"],0],0],"#ffffff","#1f2937"],"circle-opacity":1,"circle-stroke-opacity":1,"circle-opacity-transition":{duration:250}}}),se.addLayer({id:"language-family-pins-hitbox",type:"circle",source:"language-families",paint:{"circle-radius":zl("touchTarget"),"circle-color":"rgba(0,0,0,0)","circle-stroke-width":0,"circle-opacity":0}}),i.value.languageFamilyPins=!0,r.attachLanguageFamilyEvents()}function u(B,V="doxa-regions"){const se=s();if(!se)return;se.getLayer("regions-fill")&&se.removeLayer("regions-fill"),se.getLayer("regions-border")&&se.removeLayer("regions-border"),se.getSource("regions")&&se.removeSource("regions");const _e={africa:"#ff2e2e",asia:"#1a8cff",europe:"#1ee05f","latin_america_&_caribbean":"#FFEB3B",middle_east:"#a83dff","north_america_&_non-spanish_caribbean":"#00e0bd",oceania:"#ff7f11"},E="#cccccc",N=B&&B.isoToRegion?B.isoToRegion:{},M=[],J={};for(const[ne,P]of Object.entries(N)){const A=_e[String(P).toLowerCase()];A&&M.push(ne,A),J[P]||(J[P]=[]),J[P].push(ne)}l.value=J;const oe=M.length?["match",["get","iso_3166_1_alpha_3"],...M,E]:E,D=se.getLayer("language-family-pins-shadow")?"language-family-pins-shadow":se.getLayer("language-family-pins")?"language-family-pins":void 0,le=(()=>{var ne,P,A;try{return!!((A=(P=(ne=se.getContainer)==null?void 0:ne.call(se))==null?void 0:P.classList)!=null&&A.contains("maplibregl-map"))}catch{return!1}})();le?(se.addSource("regions",{type:"geojson",data:{type:"FeatureCollection",features:[]}}),fetch(`${ll(null)}/boundaries/world-adm0-web.geojson`).then(ne=>ne.json()).then(ne=>{for(const A of ne.features||[])A.properties&&A.properties.iso3&&(A.properties.iso_3166_1_alpha_3=A.properties.iso3);const P=se.getSource("regions");P&&P.setData(ne)}).catch(ne=>console.warn("[map-layers] region boundaries failed to load",ne))):se.addSource("regions",{type:"vector",url:"mapbox://mapbox.country-boundaries-v1"}),se.addLayer({id:"regions-fill",type:"fill",source:"regions",...le?{}:{"source-layer":"country_boundaries"},paint:{"fill-color":oe,"fill-opacity":V==="none"?.1:.7,"fill-antialias":!0,...Oo(se,"fill"),"fill-opacity-transition":{duration:300}}},D),se.addLayer({id:"regions-border",type:"line",source:"regions",...le?{}:{"source-layer":"country_boundaries"},paint:{"line-color":oe,"line-width":1,"line-opacity":.9,...Oo(se,"line")}},D),i.value.regions=!0,r.attachRegionEvents()}function b(B,V){const se=s();if(!se||!B||!(V!=null&&V.length))return;m();const _e=V.filter(oe=>{var le;return(oe.languageFamily||((le=oe._normalized)==null?void 0:le.languageFamily)||"Unknown")===B});if(_e.length<2)return;const E=n(B),N=[],M=15,J=[..._e].sort((oe,D)=>(oe.longitude||oe.lng)-(D.longitude||D.lng));for(let oe=0;oe ",["to-number",["get","peoplePraying"],0],0],"#ffffff","#1f2937"],"circle-opacity":1,"circle-stroke-opacity":1,"circle-opacity-transition":{duration:250}}}),se.addLayer({id:"language-family-pins-hitbox",type:"circle",source:"language-families",paint:{"circle-radius":zl("touchTarget"),"circle-color":"rgba(0,0,0,0)","circle-stroke-width":0,"circle-opacity":0}}),i.value.languageFamilyPins=!0,r.attachLanguageFamilyEvents()}function u(B,V="doxa-regions"){const se=s();if(!se)return;se.getLayer("regions-fill")&&se.removeLayer("regions-fill"),se.getLayer("regions-border")&&se.removeLayer("regions-border"),se.getSource("regions")&&se.removeSource("regions");const _e={africa:"#ff2e2e",asia:"#1a8cff",europe:"#1ee05f","latin_america_&_caribbean":"#FFEB3B",middle_east:"#a83dff","north_america_&_non-spanish_caribbean":"#00e0bd",oceania:"#ff7f11"},E="#cccccc",N=B&&B.isoToRegion?B.isoToRegion:{},M=[],J={};for(const[ne,P]of Object.entries(N)){const A=_e[String(P).toLowerCase()];A&&M.push(ne,A),J[P]||(J[P]=[]),J[P].push(ne)}l.value=J;const oe=M.length?["match",["get","iso_3166_1_alpha_3"],...M,E]:E,D=se.getLayer("language-family-pins-shadow")?"language-family-pins-shadow":se.getLayer("language-family-pins")?"language-family-pins":void 0,le=(()=>{var ne,P,A;try{return!!((A=(P=(ne=se.getContainer)==null?void 0:ne.call(se))==null?void 0:P.classList)!=null&&A.contains("maplibregl-map"))}catch{return!1}})();le?(se.addSource("regions",{type:"geojson",data:{type:"FeatureCollection",features:[]}}),fetch(`${ll(null)}/boundaries/world-adm0-web.geojson`).then(ne=>ne.json()).then(ne=>{for(const A of ne.features||[])A.properties&&A.properties.iso3&&(A.properties.iso_3166_1_alpha_3=A.properties.iso3);const P=se.getSource("regions");P&&P.setData(ne)}).catch(ne=>console.warn("[map-layers] region boundaries failed to load",ne))):se.addSource("regions",{type:"vector",url:"mapbox://mapbox.country-boundaries-v1"}),se.addLayer({id:"regions-fill",type:"fill",source:"regions",...le?{}:{"source-layer":"country_boundaries"},paint:{"fill-color":oe,"fill-opacity":V==="none"?.1:.7,"fill-antialias":!0,...Oo(se,"fill"),"fill-opacity-transition":{duration:300}}},D),se.addLayer({id:"regions-border",type:"line",source:"regions",...le?{}:{"source-layer":"country_boundaries"},paint:{"line-color":oe,"line-width":1,"line-opacity":.9,...Oo(se,"line")}},D),i.value.regions=!0,r.attachRegionEvents()}function b(B,V){const se=s();if(!se||!B||!(V!=null&&V.length))return;m();const _e=V.filter(oe=>{var le;return(oe.languageFamily||((le=oe._normalized)==null?void 0:le.languageFamily)||"Unknown")===B});if(_e.length<2)return;const E=n(B),N=[],M=15,J=[..._e].sort((oe,D)=>(oe.longitude||oe.lng)-(D.longitude||D.lng));for(let oe=0;oete&&(te=J),z++)}if(z===0)return;if(z===1){l(T).flyTo({center:[be,$e],zoom:p,duration:h,essential:!0});return}const ge=R(j)||{center:0,minLng:0,maxLng:0,span:0},ue=[[ge.minLng,q],[ge.maxLng,te]];if(X(T,ue,ge.span)){U(T,ge.center,q,te);return}try{l(T).fitBounds(ue,{padding:d,maxZoom:y,duration:h,essential:!0})}catch{}}return{getOffsetCenter:u,slowFlyToFamily:b,slowFlyToRegion:m,flyTo:k,flyToCoords:_,fitBounds:g,resetView:$,zoomToLegendRow:ee,calculateRegionCenterFromPolygon:L}}const Tr="#1a1a1a",an="selected-pin-highlight";function px(e=Tr){const t=document.createElement("div");t.className="map-go-pin-wrapper";const o=`pinGrad-${Math.random().toString(36).slice(2,8)}`;return t.innerHTML=`
+ `}function b(h){const y=t();if(!y)return;const p=h||"language-family-pins";if(!y.getLayer(p))return;const w=f=>{try{const R=f.features[0],v=R.properties,U=R.geometry.coordinates.slice();for(;Math.abs(f.lngLat.lng-U[0])>180;)U[0]+=f.lngLat.lng>U[0]?360:-360;if(s&&s.legendMode!==void 0){s.selectPeopleGroup(R),s.isMobile&&s.legendState==="collapsed"&&s.setLegendState("open"),s.isMobile||window.dispatchEvent(new CustomEvent("dxm:openDesktopLegend",{detail:{mapId:o}}));return}new(kr(y)).Popup({maxWidth:"320px",className:"people-group-popup"}).setLngLat(U).setHTML(c(v)).addTo(y)}catch(R){console.error(` [${o}] Pin click handler error:`,R)}};y.on("click",p,w),l.value.push({event:"click",layer:p,handler:w})}function m(){const h=t();if(!h)return;const y="regions-fill";if(!h.getLayer(y))return;const p=w=>{const f=["language-family-pins","language-family-pins-hitbox","people-groups-pins"];for(const R of f)if(h.getLayer(R)){const v=h.queryRenderedFeatures(w.point,{layers:[R]});if(v&&v.length>0)return}if(w.features&&w.features.length>0){const R=w.features[0].properties;new(kr(h)).Popup().setLngLat(w.lngLat).setHTML(u(R)).addTo(h)}};h.on("click",y,p),l.value.push({event:"click",layer:y,handler:p})}function L(){const h=t();if(!h)return;const y="clusters";if(!h.getLayer(y))return;const p=w=>{const f=h.queryRenderedFeatures(w.point,{layers:[y]});if(!f.length)return;const R=f[0].properties.cluster_id,v=f[0].source;h.getSource(v).getClusterExpansionZoom(R,(U,X)=>{U||h.easeTo({center:f[0].geometry.coordinates,zoom:X})})};h.on("click",y,p),l.value.push({event:"click",layer:y,handler:p})}function k(h){const y=t();if(!y||!y.getLayer(h))return;const p=()=>{y.getCanvas().style.cursor="pointer"},w=()=>{y.getCanvas().style.cursor=""};y.on("mouseenter",h,p),y.on("mouseleave",h,w),l.value.push({event:"mouseenter",layer:h,handler:p}),l.value.push({event:"mouseleave",layer:h,handler:w})}function _(){b(),k("language-family-pins"),b("language-family-pins-hitbox"),k("language-family-pins-hitbox"),L(),k("clusters")}function g(){m(),k("regions-fill")}function $(){const h=t();h&&(h.getLayer("language-family-pins")&&_(),h.getLayer("regions-fill")&&g(),h.getLayer("people-groups-pins")&&(b(),k("people-groups-pins")))}function d(){const h=t();if(h){for(const{event:y,layer:p,handler:w}of l.value)try{h.off(y,p,w)}catch{}l.value=[]}}return{attachAllEventHandlers:$,attachLanguageFamilyEvents:_,attachRegionEvents:g,attachPinClickHandler:b,attachRegionClickHandler:m,attachClusterClickHandler:L,attachCursorHandlers:k,detachAllEventHandlers:d,generatePinPopupContent:c,generateRegionPopupContent:u,registeredHandlers:l}}const nt={Chamacoco:"Zamucoan",Ninam:"Yanomaman",Yagua:"Yaguan",Muinane:"Witotoan",Finnish:"Uralic","Hill Mari":"Uralic",Mansi:"Uralic","Meadow Mari":"Uralic","North Saami":"Uralic",Carabayo:"Unclassified",Kujarge:"Unclassified",Shabo:"Unclassified",Ainu:"Turkic",Kazakh:"Turkic","Khorasani Turkish":"Turkic",Kyrgyz:"Turkic","Northern Uzbek":"Turkic","South Azerbaijani":"Turkic",Turkish:"Turkic",Tuvan:"Turkic",Uyghur:"Turkic",Amundava:"Tupian",Araweté:"Tupian","Asurini of Xingú":"Tupian","Avá-Canoeiro":"Tupian",Awetí:"Tupian",Kamayurá:"Tupian",Karo:"Tupian",Morerebi:"Tupian",Tenharim:"Tupian","Uru-Eu-Wau-Wau":"Tupian","Uru-Pa-In":"Tupian",Wayampi:"Tupian","Zo’é":"Tupian",Evenki:"Tungusic",Xibe:"Tungusic",Carapana:"Tucanoan",Cubeo:"Tucanoan",Desano:"Tucanoan",Macuna:"Tucanoan",Piratapuyo:"Tucanoan",Siona:"Tucanoan",Siriano:"Tucanoan",Tucano:"Tucanoan",Tuyuca:"Tucanoan",Waimaha:"Tucanoan",Tay:"Trans-New Guinea",Adi:"Sino-Tibetan",Akha:"Sino-Tibetan","Amdo Tibetan":"Sino-Tibetan",Axi:"Sino-Tibetan",Biyo:"Sino-Tibetan","Boro (India)":"Sino-Tibetan",Brokkat:"Sino-Tibetan",Bugun:"Sino-Tibetan",Byangsi:"Sino-Tibetan","Central Lalo":"Sino-Tibetan","Central Tibetan":"Sino-Tibetan",Chak:"Sino-Tibetan",Chalikha:"Sino-Tibetan",Chaudangsi:"Sino-Tibetan",Chocangacakha:"Sino-Tibetan",Darlong:"Sino-Tibetan",Dhimal:"Sino-Tibetan","Digaro-Mishmi":"Sino-Tibetan",Dzalakha:"Sino-Tibetan","Eastern Nisu":"Sino-Tibetan",Ersu:"Sino-Tibetan",Gahri:"Sino-Tibetan",Gongduk:"Sino-Tibetan",Gyalsumdo:"Sino-Tibetan",Hani:"Sino-Tibetan","Idu-Mishmi":"Sino-Tibetan",Kaike:"Sino-Tibetan",Kanashi:"Sino-Tibetan",Katso:"Sino-Tibetan",Khamba:"Sino-Tibetan",Koireng:"Sino-Tibetan",Kucong:"Sino-Tibetan",Kurtokha:"Sino-Tibetan",Ladakhi:"Sino-Tibetan",Lakha:"Sino-Tibetan","Lang’e":"Sino-Tibetan",Lhokpu:"Sino-Tibetan",Lolopo:"Sino-Tibetan",Lunanakha:"Sino-Tibetan","Mandarin Chinese":"Sino-Tibetan",Meitei:"Sino-Tibetan","Miju-Mishmi":"Sino-Tibetan",Mpi:"Sino-Tibetan",Na:"Sino-Tibetan",Namuyi:"Sino-Tibetan",Narua:"Sino-Tibetan",Naxi:"Sino-Tibetan","Northern Muji":"Sino-Tibetan",Nuosu:"Sino-Tibetan",Nupbikha:"Sino-Tibetan",Nyenkha:"Sino-Tibetan",Olekha:"Sino-Tibetan",Pahari:"Sino-Tibetan",Pattani:"Sino-Tibetan","Phana’":"Sino-Tibetan",Phula:"Sino-Tibetan",Phunoi:"Sino-Tibetan",Puma:"Sino-Tibetan",Puroik:"Sino-Tibetan",Raji:"Sino-Tibetan",Rawat:"Sino-Tibetan",Sani:"Sino-Tibetan",Sherdukpen:"Sino-Tibetan",Sherpa:"Sino-Tibetan",Shuhi:"Sino-Tibetan",Sila:"Sino-Tibetan",Singpho:"Sino-Tibetan",Sunwar:"Sino-Tibetan","Tawang Monpa":"Sino-Tibetan",Tseku:"Sino-Tibetan",Tshangla:"Sino-Tibetan",Usoi:"Sino-Tibetan","Western Minyag":"Sino-Tibetan","Wusa Nasu":"Sino-Tibetan","Xiang Chinese":"Sino-Tibetan",Yakkha:"Sino-Tibetan","Youle Jinuo":"Sino-Tibetan","Yue Chinese":"Sino-Tibetan",Zakhring:"Sino-Tibetan","Afghan Sign Language":"Sign Language","Albanian Sign Language":"Sign Language","Algerian Sign Language":"Sign Language","American Sign Language":"Sign Language","Armenian Sign Language":"Sign Language","British Sign Language":"Sign Language","Bulgarian Sign Language":"Sign Language","Cambodian Sign Language":"Sign language","Cuban Sign Language":"Sign Language","Egyptian Sign Language":"Sign Language","Greek Sign Language":"Sign Language","Guinean Sign Language":"Sign Language","Hong Kong Sign Language":"Sign Language","Icelandic Sign Language":"Sign Language","Iranian Sign Language":"Sign Language","Israeli Sign Language":"Sign Language","Jamaican Sign Language":"Sign Language","Jordanian Sign Language":"Sign Language","Laos Sign Language":"Sign Language","Libyan Sign Language":"Sign Language","Maltese Sign Language":"Sign Language","Mauritian Sign Language":"Sign Language","Moroccan Sign Language":"Sign Language","Mozambican Sign Language":"Sign Language","Myanmar Sign Language":"Sign language","Natural Sign Language":"Sign Language","Pakistan Sign Language":"Sign Language","Papua New Guinean Sign Language":"Sign language","Russian Sign Language":"Sign Language","Saudi Arabian Sign Language":"Sign Language","Sign Language of the Netherlands":"Sign Language","Solomon Islands Sign Language":"Sign Language","Sri Lankan Sign Language":"Sign Language","Swedish Sign Language":"Sign Language","Turkish Sign Language":"Sign Language","Northern Conchucos Ancash Quechua":"Quechuan","Northern Pastaza Quichua":"Quechuan",Hupdë:"Puinavean",Amahuaca:"Panoan",Korubo:"Panoan",Sharanahua:"Panoan","Shipibo-Conibo":"Panoan",Yaminahua:"Panoan",Yawanawa:"Panoan",Afitti:"Nilo-Saharan",Assangori:"Nilo-Saharan","Beli (South Sudan)":"Nilo-Saharan",Berta:"Nilo-Saharan",Burun:"Nilo-Saharan","Dar Daju Daju":"Nilo-Saharan","Dar Fur Daju":"Nilo-Saharan","Dar Sila Daju":"Nilo-Saharan",Dazaga:"Nilo-Saharan","Dendi (Benin)":"Nilo-Saharan",Dilling:"Nilo-Saharan",Fur:"Nilo-Saharan",Gbaya:"Nilo-Saharan",Ghulfan:"Nilo-Saharan",Gwama:"Nilo-Saharan","Humburi Senni Songhay":"Nilo-Saharan",Jopadhola:"Nilo-Saharan",Kadaru:"Nilo-Saharan",Kanga:"Nilo-Saharan",Karanga:"Nilo-Saharan",Karko:"Nilo-Saharan",Kebu:"Nilo-Saharan",Keiga:"Nilo-Saharan",Keliko:"Nilo-Saharan",Kendeje:"Nilo-Saharan",Kibet:"Nilo-Saharan","Komo (Sudan)":"Nilo-Saharan",Korandje:"Nilo-Saharan",Kulfa:"Nilo-Saharan",Kwegu:"Nilo-Saharan",Laarim:"Nilo-Saharan",Logorik:"Nilo-Saharan",Majang:"Nilo-Saharan","Manga Kanuri":"Nilo-Saharan",Mango:"Nilo-Saharan",Mararit:"Nilo-Saharan",Marfa:"Nilo-Saharan",Midob:"Nilo-Saharan","Mo’da":"Nilo-Saharan",Morom:"Nilo-Saharan",Moru:"Nilo-Saharan",Naba:"Nilo-Saharan",Nara:"Nilo-Saharan",Njalgulgule:"Nilo-Saharan",Nuer:"Nilo-Saharan","Nyamusa-Molo":"Nilo-Saharan",Nyangatom:"Nilo-Saharan","Olu’bo":"Nilo-Saharan",Opo:"Nilo-Saharan",Päri:"Nilo-Saharan","Sara Kaba Naa":"Nilo-Saharan",Surbakhal:"Nilo-Saharan",Tadaksahak:"Nilo-Saharan","Tama (Chad)":"Nilo-Saharan",Temein:"Nilo-Saharan",Thuri:"Nilo-Saharan","Tirmaga-Chai Suri":"Nilo-Saharan",Toposa:"Nilo-Saharan",Tumtum:"Nilo-Saharan","Wali (Sudan)":"Nilo-Saharan","Yerwa Kanuri":"Nilo-Saharan",Yulu:"Nilo-Saharan",Zaghawa:"Nilo-Saharan","Adamawa Fulfulde":"Niger-Congo",Akaselem:"Niger-Congo","Amba (Uganda)":"Niger-Congo",Anii:"Niger-Congo",Baangi:"Niger-Congo",Badyara:"Niger-Congo","Bago-Kusuntu":"Niger-Congo",Bai:"Niger-Congo","Bainouk-Gunyaamolo":"Niger-Congo",Bamanankan:"Niger-Congo","Banda-Mbrès":"Niger-Congo",Bandial:"Niger-Congo",Bankagooma:"Niger-Congo","Belanda Viri":"Niger-Congo",Bemba:"Niger-Congo",Bolgo:"Niger-Congo","Bon Gula":"Niger-Congo",Bua:"Niger-Congo",Chichewa:"Niger-Congo","Chung (Cameroon)":"Niger-Congo","Ci Gbe":"Niger-Congo",Degema:"Niger-Congo",Dek:"Niger-Congo",Dhimba:"Niger-Congo",Dogoso:"Niger-Congo","East Limba":"Niger-Congo",Engenni:"Niger-Congo",Epie:"Niger-Congo",Éwé:"Niger-Congo",Fania:"Niger-Congo",Foodo:"Niger-Congo",Fwe:"Niger-Congo",Gciriku:"Niger-Congo",Gwa:"Niger-Congo",Herero:"Niger-Congo",Ibuoro:"Niger-Congo","Jenaama Bozo":"Niger-Congo",Jita:"Niger-Congo",Jula:"Niger-Congo",Kabiyè:"Niger-Congo",Kadung:"Niger-Congo",Kakabe:"Niger-Congo",Kalamsé:"Niger-Congo","Kami (Tanzania)":"Niger-Congo","Kango (Bas-Uélé District)":"Niger-Congo",Kasem:"Niger-Congo","Kelengaxo Bozo":"Niger-Congo",Khe:"Niger-Congo",Khisa:"Niger-Congo",Kim:"Niger-Congo",Kinyarwanda:"Niger-Congo",Kipfokomu:"Niger-Congo",Kitharaka:"Niger-Congo",Kiyombe:"Niger-Congo",Ko:"Niger-Congo",Koalib:"Niger-Congo",Koke:"Niger-Congo",Konongo:"Niger-Congo","Koro Nulu":"Niger-Congo","Koro Zuba":"Niger-Congo",Kuhane:"Niger-Congo",Kunda:"Niger-Congo",Kuranko:"Niger-Congo",Kuria:"Niger-Congo",Kwangali:"Niger-Congo",Lame:"Niger-Congo",Laru:"Niger-Congo",Lopa:"Niger-Congo","Makhuwa-Meetto":"Niger-Congo","Makhuwa-Shirima":"Niger-Congo","Malawi Nyiha":"Niger-Congo",Mandinka:"Niger-Congo",Mankanya:"Niger-Congo",Mansoanka:"Niger-Congo",Mbukushu:"Niger-Congo","Mende (Sierra Leone)":"Niger-Congo",Miyobe:"Niger-Congo",Mushungulu:"Niger-Congo","Mwali Comorian":"Niger-Congo","Mwera (Chimwera)":"Niger-Congo",Ndemli:"Niger-Congo",Ndengereko:"Niger-Congo",Ndumu:"Niger-Congo",Ndunga:"Niger-Congo","Ndzwani Comorian":"Niger-Congo",Ngile:"Niger-Congo","Northwest Gbaya":"Niger-Congo",Notre:"Niger-Congo",Nyamwanga:"Niger-Congo",Nyankore:"Niger-Congo",Nyengo:"Niger-Congo",Okpamheri:"Niger-Congo",Osatu:"Niger-Congo","Pana (Burkina Faso)":"Niger-Congo",Pulaar:"Niger-Congo",Pular:"Niger-Congo",Rufiji:"Niger-Congo","Sankaran Maninka":"Niger-Congo",Sapo:"Niger-Congo","Senara Sénoufo":"Niger-Congo",Shanga:"Niger-Congo",Sininkere:"Niger-Congo","Southern Ngbandi":"Niger-Congo",Swahili:"Niger-Congo","Syenara Sénoufo":"Niger-Congo",Tagbu:"Niger-Congo",Tagoi:"Niger-Congo",Tegali:"Niger-Congo",Tem:"Niger-Congo","Tiéyaxo Bozo":"Niger-Congo",Tiyaa:"Niger-Congo",Tocho:"Niger-Congo","Tonga (Zambia)":"Niger-Congo",Totela:"Niger-Congo","Toura (Côte d’Ivoire)":"Niger-Congo",Tswa:"Niger-Congo",Tumbuka:"Niger-Congo",Ukaan:"Niger-Congo",Uneme:"Niger-Congo",Vai:"Niger-Congo",Vute:"Niger-Congo",Waama:"Niger-Congo",Warnang:"Niger-Congo",Wolof:"Niger-Congo",Yao:"Niger-Congo",Yauma:"Niger-Congo",Yom:"Niger-Congo","Zan Gula":"Niger-Congo",Zande:"Niger-Congo",Zigula:"Niger-Congo",Mamaindê:"Nambikwara",Aghul:"Nakh-Daghestanian",Akhvakh:"Nakh-Daghestanian",Andi:"Nakh-Daghestanian",Avar:"Nakh-Daghestanian",Bagvalal:"Nakh-Daghestanian",Botlikh:"Nakh-Daghestanian",Chamalal:"Nakh-Daghestanian",Chechen:"Nakh-Daghestanian",Dargwa:"Nakh-Daghestanian",Kaitag:"Nakh-Daghestanian",Karata:"Nakh-Daghestanian",Khvarshi:"Nakh-Daghestanian",Tindi:"Nakh-Daghestanian",Pirahã:"Muran",Bonan:"Mongolic","China Buriat":"Mongolic",Daur:"Mongolic","Kalmyk-Oirat":"Mongolic","Peripheral Mongolian":"Mongolic","Russia Buriat":"Mongolic",Tagdal:"Mixed language",Wutunhua:"Mixed language","Ashéninka Perené":"Maipurean",Baniwa:"Maipurean",Cabiyarí:"Maipurean",Curripaco:"Maipurean","Enawené-Nawé":"Maipurean",Kanamarí:"Maipurean",Mehináku:"Maipurean","Pichis Ashéninka":"Maipurean",Waurá:"Maipurean",Bangime:"Language isolate",Burushaski:"Language isolate","Ai-Cham":"Kra-Dai",Aiton:"Kra-Dai","Dai Zhuang":"Kra-Dai",Duoluo:"Kra-Dai","Green Gelao":"Kra-Dai","Guibian Zhuang":"Kra-Dai",Hlai:"Kra-Dai",Jiamao:"Kra-Dai",Kang:"Kra-Dai",Khün:"Kra-Dai",Kuan:"Kra-Dai",Lachi:"Kra-Dai","Laha (Viet Nam)":"Kra-Dai",Lao:"Kra-Dai",Lü:"Kra-Dai","Mak (China)":"Kra-Dai","Northeastern Thai":"Kra-Dai","Northern Dong":"Kra-Dai","Northern Thai":"Kra-Dai",Nyaw:"Kra-Dai",Phake:"Kra-Dai","Phu Thai":"Kra-Dai",Qabiao:"Kra-Dai",Qau:"Kra-Dai","Qiubei Zhuang":"Kra-Dai",Shan:"Kra-Dai","Southern Dong":"Kra-Dai",Sui:"Kra-Dai","T’en":"Kra-Dai","Tai Daeng":"Kra-Dai","Tai Dam":"Kra-Dai","Tai Hongjin":"Kra-Dai","Tai Nüa":"Kra-Dai","Tai Ya":"Kra-Dai","Tai Yo":"Kra-Dai","Ts’ün-Lao":"Kra-Dai","Yang Zhuang":"Kra-Dai",Yerong:"Kra-Dai",Yong:"Kra-Dai",Yoy:"Kra-Dai",Khoekhoe:"Khoe-Kwadi",Karajá:"Karajá","Pará Gavião":"Jean",Suyá:"Jean",Japanese:"Japonic","Oki-No-Erabu":"Japonic","Toku-No-Shima":"Japonic",Yaeyama:"Japonic",Yoron:"Japonic","Adivasi Oriya":"Indo-European",Afrikaans:"Indo-European","Alviri-Vidari":"Indo-European",Angika:"Indo-European",Assamese:"Indo-European",Bagheli:"Indo-European",Bagri:"Indo-European",Bashkardi:"Indo-European",Bateri:"Indo-European",Bengali:"Indo-European",Bhojpuri:"Indo-European",Bhunjia:"Indo-European",Bilaspuri:"Indo-European",Bosnian:"Indo-European","Braj Bhasha":"Indo-European",Brokskat:"Indo-European",Bundeli:"Indo-European",Catalan:"Indo-European",Chambeali:"Indo-European",Chhattisgarhi:"Indo-European",Dameli:"Indo-European",Dari:"Indo-European",Dhundari:"Indo-European",Dogri:"Indo-European",Domari:"Indo-European",Dutch:"Indo-European","Eastern Balochi":"Indo-European","Eastern Panjabi":"Indo-European","Eastern Yiddish":"Indo-European",English:"Indo-European",French:"Indo-European",Gaddi:"Indo-European",Garhwali:"Indo-European",Gawri:"Indo-European",Gowro:"Indo-European",Gujarati:"Indo-European",Gujari:"Indo-European",Halbi:"Indo-European",Haroti:"Indo-European",Haryanvi:"Indo-European",Hindi:"Indo-European","Indus Kohistani":"Indo-European","Iranian Persian":"Indo-European",Ishkashimi:"Indo-European",Kacchi:"Indo-European",Kalkoti:"Indo-European",Kanauji:"Indo-European",Kangri:"Indo-European",Karingani:"Indo-European",Kashmiri:"Indo-European",Kati:"Indo-European",Khunsari:"Indo-European",Konkani:"Indo-European",Kudmali:"Indo-European",Kumaoni:"Indo-European",Kumzari:"Indo-European",Laki:"Indo-European",Lasi:"Indo-European",Luwati:"Indo-European",Magahi:"Indo-European",Maithili:"Indo-European",Maldivian:"Indo-European",Malvi:"Indo-European",Marathi:"Indo-European","Marwari (India)":"Indo-European",Mewari:"Indo-European",Munji:"Indo-European",Nepali:"Indo-European",Nimadi:"Indo-European","Northern Kurdish":"Indo-European",Odia:"Indo-European","Pahari-Potwari":"Indo-European",Palula:"Indo-European",Panchpargania:"Indo-European",Pangwali:"Indo-European",Parachi:"Indo-European",Portuguese:"Indo-European",Russian:"Indo-European",Sadri:"Indo-European",Sanglechi:"Indo-European",Sarikoli:"Indo-European",Savi:"Indo-European",Semnani:"Indo-European",Serbian:"Indo-European",Shabak:"Indo-European",Shahrudi:"Indo-European",Shekhawati:"Indo-European",Shina:"Indo-European",Shughni:"Indo-European",Shumashti:"Indo-European",Sindhi:"Indo-European",Sivandi:"Indo-European",Soi:"Indo-European","Southern Balochi":"Indo-European",Spanish:"Indo-European",Tajik:"Indo-European",Talysh:"Indo-European",Urdu:"Indo-European",Ushojo:"Indo-European",Vaghri:"Indo-European","Vlax Romani":"Indo-European",Wagdi:"Indo-European",Wakhi:"Indo-European",Waneci:"Indo-European","Western Balochi":"Indo-European",Yadgha:"Indo-European","Bu-Nao Bunu":"Hmong-Mien","Central Mashan Miao":"Hmong-Mien","Chuanqiandian Cluster Miao":"Hmong-Mien","Eastern Xiangxi Miao":"Hmong-Mien","Iu Mien":"Hmong-Mien","Luopohe Miao":"Hmong-Mien","Northern Qiandong Miao":"Hmong-Mien","Pa-Hng":"Hmong-Mien","Southwestern Huishui Miao":"Hmong-Mien","Wunai Bunu":"Hmong-Mien","Younuo Bunu":"Hmong-Mien",Amarakaeri:"Harákmbut",Huachipaeri:"Harákmbut",Cuiba:"Guajiboan",Macaguán:"Guajiboan",Tlicho:"Eyak-Athabaskan",Kannada:"Dravidian",Kodava:"Dravidian","Korra Koraga":"Dravidian","Kota (India)":"Dravidian",Kudiya:"Dravidian",Malapandaram:"Dravidian",Malayalam:"Dravidian",Muthuvan:"Dravidian",Ravula:"Dravidian",Sholaga:"Dravidian",Tamil:"Dravidian",Telugu:"Dravidian",Tulu:"Dravidian",Vishavan:"Dravidian","Andaman Hindi Creole":"Creole","Cocos Islands Malay":"Creole","Juba Arabic":"Creole",Nubi:"Creole",Barí:"Chibchan","Barro Negro Tunebo":"Chibchan","Western Tunebo":"Chibchan",Ikpeng:"Cariban","Kuikúro-Kalapálo":"Cariban",Pemon:"Cariban",Trió:"Cariban","Waimiri-Atroarí":"Cariban",Waiwai:"Cariban",Yukpa:"Cariban",Borôro:"Bororoan",Chachi:"Barbacoan","Abai Sungai":"Austronesian",Ambelau:"Austronesian",Asilulu:"Austronesian",Balaesang:"Austronesian","Batak Alas-Kluet":"Austronesian","Batak Dairi":"Austronesian","Batak Karo":"Austronesian",Bonerate:"Austronesian",Bonggi:"Austronesian",Brunei:"Austronesian","Brunei Bisaya":"Austronesian",Buol:"Austronesian","Central Malay":"Austronesian","Central Sama":"Austronesian","Coastal Konjo":"Austronesian",Dampelas:"Austronesian","Dibabawon Manobo":"Austronesian",Dondo:"Austronesian",Gane:"Austronesian","Geser-Gorom":"Austronesian","Highland Konjo":"Austronesian",Hitu:"Austronesian",Iban:"Austronesian",Indonesian:"Austronesian","Kadazan Dusun":"Austronesian",Kiput:"Austronesian",Komodo:"Austronesian",Kompane:"Austronesian",Lahanan:"Austronesian","Lampung Nyo":"Austronesian","Larike-Wakasihu":"Austronesian",Lola:"Austronesian",Luhu:"Austronesian",Malay:"Austronesian",Mariri:"Austronesian",Moronene:"Austronesian",Rukai:"Austronesian","Sabah Bisaya":"Austronesian","Seit-Kaitetu":"Austronesian",Sula:"Austronesian","Tae’":"Austronesian",Tajio:"Austronesian",Tomini:"Austronesian",Tutong:"Austronesian",Ujir:"Austronesian",Aheu:"Austro-Asiatic",Alak:"Austro-Asiatic",Bit:"Austro-Asiatic","Bo (Laos)":"Austro-Asiatic",Bondo:"Austro-Asiatic",Brao:"Austro-Asiatic",Bugan:"Austro-Asiatic",Chong:"Austro-Asiatic",Chut:"Austro-Asiatic",Danau:"Austro-Asiatic",Halang:"Austro-Asiatic","Halang Doan":"Austro-Asiatic",Hu:"Austro-Asiatic",Hung:"Austro-Asiatic",Ir:"Austro-Asiatic",Kensiu:"Austro-Asiatic",Khmu:"Austro-Asiatic",Khua:"Austro-Asiatic",Khuen:"Austro-Asiatic",Koda:"Austro-Asiatic","Kon Keu":"Austro-Asiatic",Kriang:"Austro-Asiatic",Kuay:"Austro-Asiatic",Laven:"Austro-Asiatic",Maleng:"Austro-Asiatic","Man Met":"Austro-Asiatic",Mang:"Austro-Asiatic",Minriq:"Austro-Asiatic",Mlabri:"Austro-Asiatic",Nguôn:"Austro-Asiatic",Nyaheun:"Austro-Asiatic",Nyahkur:"Austro-Asiatic","O’du":"Austro-Asiatic",Ong:"Austro-Asiatic",Oy:"Austro-Asiatic",Pacoh:"Austro-Asiatic","Phong-Kniang":"Austro-Asiatic",Prai:"Austro-Asiatic",Puoc:"Austro-Asiatic",Rengao:"Austro-Asiatic",Rmeet:"Austro-Asiatic","Rumai Palaung":"Austro-Asiatic",Sapuan:"Austro-Asiatic","Shwe Palaung":"Austro-Asiatic","So (Laos)":"Austro-Asiatic",Sou:"Austro-Asiatic","Tai Loi":"Austro-Asiatic",Talieng:"Austro-Asiatic",Tareng:"Austro-Asiatic",Tho:"Austro-Asiatic",U:"Austro-Asiatic","Upper Ta’oih":"Austro-Asiatic",Vietnamese:"Austro-Asiatic","Western Katu":"Austro-Asiatic",Suruahá:"Arauan",Jarawa:"Andamanese",Öñge:"Andamanese",Sentinel:"Andamanese",Afar:"Afro-Asiatic","Alaba-K’abeena":"Afro-Asiatic",Alagwa:"Afro-Asiatic",Ale:"Afro-Asiatic","Algerian Arabic":"Afro-Asiatic",Amharic:"Afro-Asiatic",Arbore:"Afro-Asiatic","Baharna Arabic":"Afro-Asiatic",Barein:"Afro-Asiatic",Bedawiyet:"Afro-Asiatic",Bidiyo:"Afro-Asiatic",Bilen:"Afro-Asiatic",Birgit:"Afro-Asiatic",Boor:"Afro-Asiatic","Borana-Arsi-Guji Oromo":"Afro-Asiatic",Buduma:"Afro-Asiatic","Central Atlas Tamazight":"Afro-Asiatic","Chadian Arabic":"Afro-Asiatic",Chenoua:"Afro-Asiatic",Ciwogai:"Afro-Asiatic",Daasanach:"Afro-Asiatic",Dabarre:"Afro-Asiatic",Dangaléat:"Afro-Asiatic",Deno:"Afro-Asiatic",Diri:"Afro-Asiatic",Duwai:"Afro-Asiatic","Eastern Egyptian Bedawi Arabic":"Afro-Asiatic","Eastern Oromo":"Afro-Asiatic",Garre:"Afro-Asiatic",Geruma:"Afro-Asiatic",Giiwo:"Afro-Asiatic",Gorowa:"Afro-Asiatic","Gulf Arabic":"Afro-Asiatic","Hadrami Arabic":"Afro-Asiatic",Harsusi:"Afro-Asiatic",Hassaniyya:"Afro-Asiatic",Hausa:"Afro-Asiatic",Hebrew:"Afro-Asiatic","Hijazi Arabic":"Afro-Asiatic",Hobyót:"Afro-Asiatic",Hozo:"Afro-Asiatic",Jiiddu:"Afro-Asiatic",Jimi:"Afro-Asiatic",Jina:"Afro-Asiatic","Jonkor Bourmataguil":"Afro-Asiatic","Judeo-Iraqi Arabic":"Afro-Asiatic","Judeo-Moroccan Arabic":"Afro-Asiatic",Kabalai:"Afro-Asiatic",Kajakse:"Afro-Asiatic",Kariya:"Afro-Asiatic","Karo (Ethiopia)":"Afro-Asiatic",Kutto:"Afro-Asiatic","Levantine Arabic":"Afro-Asiatic",Libido:"Afro-Asiatic","Libyan Arabic":"Afro-Asiatic","Lishana Deni":"Afro-Asiatic",Maaka:"Afro-Asiatic",Maay:"Afro-Asiatic",Majera:"Afro-Asiatic",Male:"Afro-Asiatic",Maslam:"Afro-Asiatic",Masmaje:"Afro-Asiatic",Mburku:"Afro-Asiatic",Mehri:"Afro-Asiatic","Mesopotamian Arabic":"Afro-Asiatic",Migaama:"Afro-Asiatic",Mogum:"Afro-Asiatic","Moroccan Arabic":"Afro-Asiatic",Mositacha:"Afro-Asiatic",Mubi:"Afro-Asiatic",Mukulu:"Afro-Asiatic",Nafusi:"Afro-Asiatic","Najdi Arabic":"Afro-Asiatic",Nyam:"Afro-Asiatic","Omani Arabic":"Afro-Asiatic","Pa’a":"Afro-Asiatic",Saba:"Afro-Asiatic",Saho:"Afro-Asiatic","Sanaani Arabic":"Afro-Asiatic",Seze:"Afro-Asiatic",Shehri:"Afro-Asiatic",Shekkacho:"Afro-Asiatic",Sheko:"Afro-Asiatic","Shihhi Arabic":"Afro-Asiatic",Siwi:"Afro-Asiatic",Sokoro:"Afro-Asiatic",Soqotri:"Afro-Asiatic","South Levantine Arabic":"Afro-Asiatic","Standard Arabic":"Afro-Asiatic","Sudanese Arabic":"Afro-Asiatic","Ta’izzi-Adeni Arabic":"Afro-Asiatic","Tahaggart Tamahaq":"Afro-Asiatic",Taznatit:"Afro-Asiatic",Tigré:"Afro-Asiatic",Toram:"Afro-Asiatic",Tsamai:"Afro-Asiatic",Tumzabt:"Afro-Asiatic",Tunni:"Afro-Asiatic",Waata:"Afro-Asiatic","West Central Oromo":"Afro-Asiatic",Xamtanga:"Afro-Asiatic",Zumbun:"Afro-Asiatic"},Gl=[">",["to-number",["get","peoplePraying"],0],0],Bl={0:.25,8:.4,14:.5},ga={0:.1,8:.18,14:.22},ha={0:1.2,8:1.6,14:2},qg=["interpolate",["linear"],["zoom"],0,["case",Gl,Bl[0],ga[0]],8,["case",Gl,Bl[8],ga[8]],14,["case",Gl,Bl[14],ga[14]]],ax=["interpolate",["linear"],["zoom"],0,ha[0],8,ha[8],14,ha[14]],Wg=["==",["to-number",["get","peoplePraying"],0],0],sx={prayer:[Wg],prayerProgress:[Wg],engagement:[["all",["!=",["get","engagementStatus"],!0],["!=",["get","engagementStatus"],1]]],adoption:[["all",["!=",["get","adoptionStatus"],!0],["!=",["get","adoptionStatus"],1]]]};function rx(e){const t=sx[e]||[];if(!t.length)return ax;const o=t.length===1?t[0]:["any",...t];return["interpolate",["linear"],["zoom"],0,["case",o,ga[0],ha[0]],8,["case",o,ga[8],ha[8]],14,["case",o,ga[14],ha[14]]]}const ix=[[/ sign language$/i,"Sign Language"]];function lx(e){if(!e||typeof e!="string")return null;const t=e.trim(),o=t.split(",").map(a=>a.trim()).filter(Boolean);if(o.length>=2){const a=[...o].reverse().join(" ");if(nt[a])return nt[a];if(o.length>=3){const s=[o[1],o[0]].join(" ");if(nt[s])return nt[s]}}if(nt[t])return nt[t];const n=t.replace(/\s*\(.*?\)\s*$/,"").trim();if(n!==t&&nt[n])return nt[n];for(const[a,s]of ix)if(a.test(t))return s;return null}function cx(e={}){const{getMap:t=()=>null,mapId:o="unknown",getLanguageFamilyColor:n=()=>"#999999",getNormalizedPeopleGroups:a=()=>[]}=e,s=()=>{const B=t();return B?Xe(B):null},r=Hg({getMap:s,mapId:o,getLanguageFamilyColor:n,getNormalizedPeopleGroups:a}),i=ke({languageFamilyPins:!1,regions:!1,peopleGroups:!1,familyConnections:!1}),l=ke({});function c(B,V="languageFamily"){const se=s();if(!se||!(B!=null&&B.length))return;const _e=Qk(V),E=B.map(D=>{var le,ne,P,A,W,Z,pe,re,Q,de,Pe,Ne,Ke,lt,et,Rt,Kt,Ee,Qe;return{type:"Feature",properties:{uniqueId:D.id||D.uniqueId,slug:D.slug||((le=D._normalized)==null?void 0:le.slug)||"",rop3:D.rop3||D.peopleGroupId,peopleId3:D.peopleId3||"",name:D.name,language:D.language,languageFamily:D.languageFamily||((ne=D._normalized)==null?void 0:ne.languageFamily)||lx(D.language)||"Unknown",affinityBlock:D.affinityBlock||D.affbloc||D.Affbloc||((P=D._normalized)==null?void 0:P.affinityBlock)||"Unknown",affinityBlockLabel:D.affinityBlockLabel||((A=D._normalized)==null?void 0:A.affinityBlockLabel)||"",cluster:D.cluster||((W=D._normalized)==null?void 0:W.cluster)||"",clusterLabel:D.clusterLabel||((Z=D._normalized)==null?void 0:Z.clusterLabel)||"",peopleGroup:D.peopleGroup||((pe=D._normalized)==null?void 0:pe.peopleGroup)||"",peopleGroupLabel:D.peopleGroupLabel||((re=D._normalized)==null?void 0:re.peopleGroupLabel)||"",doxaRegion:D.doxaRegion||((Q=D._normalized)==null?void 0:Q.doxaRegion)||"Unknown",wagfBlock:D.wagfBlock||((de=D._normalized)==null?void 0:de.wagfBlock)||"",wagfBlockLabel:D.wagfBlockLabel||((Pe=D._normalized)==null?void 0:Pe.wagfBlockLabel)||"",wagfRegionLabel:D.wagfRegionLabel||((Ne=D._normalized)==null?void 0:Ne.wagfRegionLabel)||"",country:D.country,countryIso:D.countryIso,countryIsoLabel:D.countryIsoLabel,countryName:D.countryName,religion:D.religion,religionCode:D.religionCode,religionLabel:D.religionLabel,religionName:D.religionName,population:D.population,status:D.status,description:D.description||"",imageUrl:D.imageUrl||"",peoplePraying:Number(D.peoplePraying??((Ke=D._normalized)==null?void 0:Ke.peoplePraying)??0),engagementStatus:D.engagementStatus===!0||D.engagementStatus===1||!1,adoptionStatus:D.adoptionStatus===!0||D.adoptionStatus===1||!1,bible:D.bible||((lt=D._normalized)==null?void 0:lt.bible)||"Not Available",jesusFilm:D.jesusFilm||((et=D._normalized)==null?void 0:et.jesusFilm)||"Not Available",radio:D.radio||((Rt=D._normalized)==null?void 0:Rt.radio)||"Not Available",gospel:D.gospel||((Kt=D._normalized)==null?void 0:Kt.gospel)||"Not Available",audio:D.audio||((Ee=D._normalized)==null?void 0:Ee.audio)||"Not Available",stories:D.stories||((Qe=D._normalized)==null?void 0:Qe.stories)||"Not Available",lng:parseFloat(D.longitude||D.lng)||0},geometry:{type:"Point",coordinates:[parseFloat(D.longitude||D.lng),parseFloat(D.latitude||D.lat)]}}}).filter(D=>!isNaN(D.geometry.coordinates[0])&&!isNaN(D.geometry.coordinates[1])),N=.04,M=D=>`${D.geometry.coordinates[0]},${D.geometry.coordinates[1]}`,J=new Map;for(const D of E){const le=M(D);J.has(le)||J.set(le,[]),J.get(le).push(D)}for(const D of J.values()){if(D.length<2)continue;const[le,ne]=D[0].geometry.coordinates,P=D.length;for(let A=0;A
te&&(te=J),z++)}if(z===0)return;if(z===1){l(T).flyTo({center:[be,$e],zoom:p,duration:h,essential:!0});return}const ge=R(j)||{center:0,minLng:0,maxLng:0,span:0},ue=[[ge.minLng,q],[ge.maxLng,te]];if(X(T,ue,ge.span)){U(T,ge.center,q,te);return}try{l(T).fitBounds(ue,{padding:d,maxZoom:y,duration:h,essential:!0})}catch{}}return{getOffsetCenter:u,slowFlyToFamily:b,slowFlyToRegion:m,flyTo:k,flyToCoords:_,fitBounds:g,resetView:$,zoomToLegendRow:ee,calculateRegionCenterFromPolygon:L}}const Tr="#1a1a1a",an="selected-pin-highlight";function gx(e=Tr){const t=document.createElement("div");t.className="map-go-pin-wrapper";const o=`pinGrad-${Math.random().toString(36).slice(2,8)}`;return t.innerHTML=`