W↗
WORLD ARCHITECTREGIONAL DEVELOPMENT ATLAS / V7.1
Connecting to atlas
LIVE ATLAS

Kuwait City

Checking access
Drag to explore · Scroll to zoom
2 km
Natural Earth · © OpenStreetMap contributors
WELCOME TO YOUR WORLD

Take your place.

Your PIN opens your country. This browser remembers you until you sign out or the owner changes your PIN.

Countries must be enabled by the host before players can enter.

E)&&(it=L(H,x,!0))&&(Y=0,h?(b.lineStart(),b.point(it[0][0],it[0][1]),b.point(it[1][0],it[1][1]),b.lineEnd()):(b.point(it[1][0],it[1][1]),b.lineEnd(),b.lineStart(),b.point(it[0][0],it[0][1],3)))}W&&(!x||!Pn(x,H))&&b.point(H[0],H[1]),x=H,C=W,E=$},lineEnd:function(){C&&b.lineEnd(),x=null},clean:function(){return Y|(P&&C)<<1}}}function L(b,x,E){var C=Je(b),P=Je(x),Y=[1,0,0],z=On(C,P),M=sr(z,z),H=z[0],V=M-H*H;if(!V)return!E&&b;var W=a*M/V,$=-a*H/V,it=On(Y,z),st=or(Y,W),nt=or(z,$);Ar(st,nt);var ft=it,gt=sr(st,ft),at=sr(ft,ft),_t=gt*gt-at*(sr(st,st)-1);if(!(_t<0)){var xt=Ke(_t),Et=or(ft,(-gt-xt)/at);if(Ar(Et,st),Et=ir(Et),!E)return Et;var Q=b[0],vt=x[0],Ft=b[1],ct=x[1],Wt;vt0^Et[1]<(qt(Et[0]-Q)St^(Q<=Et[0]&&Et[0]<=vt)){var ne=or(ft,(-gt+xt)/at);return Ar(ne,st),[Et,ir(ne)]}}}function w(b,x){var E=h?s:St-s,C=0;return b<-E?C|=1:b>E&&(C|=2),x<-E?C|=4:x>E&&(C|=8),C}return qr(v,_,c,h?[0,-s]:[-St,s-St])}function yo(s,a,u,h,m,c){var v=s[0],_=s[1],L=a[0],w=a[1],b=0,x=1,E=L-v,C=w-_,P;if(P=u-v,!(!E&&P>0)){if(P/=E,E<0){if(P0){if(P>x)return;P>b&&(b=P)}if(P=m-v,!(!E&&P<0)){if(P/=E,E<0){if(P>x)return;P>b&&(b=P)}else if(E>0){if(P0)){if(P/=C,C<0){if(P0){if(P>x)return;P>b&&(b=P)}if(P=c-_,!(!C&&P<0)){if(P/=C,C<0){if(P>x)return;P>b&&(b=P)}else if(C>0){if(P0&&(s[0]=v+b*E,s[1]=_+b*C),x<1&&(a[0]=v+x*E,a[1]=_+x*C),!0}}}}}var lr=1e9,Yr=-lr;function Ri(s,a,u,h){function m(w,b){return s<=w&&w<=u&&a<=b&&b<=h}function c(w,b,x,E){var C=0,P=0;if(w==null||(C=v(w,x))!==(P=v(b,x))||L(w,b)<0^x>0)do E.point(C===0||C===3?s:u,C>1?h:a);while((C=(C+x+4)%4)!==P);else E.point(b[0],b[1])}function v(w,b){return qt(w[0]-s)0?0:3:qt(w[0]-u)0?2:1:qt(w[1]-a)0?1:0:b>0?3:2}function _(w,b){return L(w.x,b.x)}function L(w,b){var x=v(w,1),E=v(b,1);return x!==E?x-E:x===0?b[1]-w[1]:x===1?w[0]-b[0]:x===2?w[1]-b[1]:b[0]-w[0]}return function(w){var b=w,x=Dr(),E,C,P,Y,z,M,H,V,W,$,it,st={point:nt,lineStart:_t,lineEnd:xt,polygonStart:gt,polygonEnd:at};function nt(Q,vt){m(Q,vt)&&b.point(Q,vt)}function ft(){for(var Q=0,vt=0,Ft=C.length;vth&&(tn-It)*(h-ne)>(Ce-ne)*(s-It)&&++Q:Ce<=h&&(tn-It)*(h-ne)<(Ce-ne)*(s-It)&&--Q;return Q}function gt(){b=x,E=[],C=[],it=!0}function at(){var Q=ft(),vt=it&&Q,Ft=(E=Mn(E)).length;(vt||Ft)&&(w.polygonStart(),vt&&(w.lineStart(),c(null,null,1,w),w.lineEnd()),Ft&&Gr(E,_,Q,c,w),w.polygonEnd()),b=w,E=C=P=null}function _t(){st.point=Et,C&&C.push(P=[]),$=!0,W=!1,H=V=NaN}function xt(){E&&(Et(Y,z),M&&W&&x.rejoin(),E.push(x.result())),st.point=nt,W&&b.lineEnd()}function Et(Q,vt){var Ft=m(Q,vt);if(C&&P.push([Q,vt]),$)Y=Q,z=vt,M=Ft,$=!1,Ft&&(b.lineStart(),b.point(Q,vt));else if(Ft&&W)b.point(Q,vt);else{var ct=[H=Math.max(Yr,Math.min(lr,H)),V=Math.max(Yr,Math.min(lr,V))],Wt=[Q=Math.max(Yr,Math.min(lr,Q)),vt=Math.max(Yr,Math.min(lr,vt))];yo(ct,Wt,s,a,u,h)?(W||(b.lineStart(),b.point(ct[0],ct[1])),b.point(Wt[0],Wt[1]),Ft||b.lineEnd(),it=!1):Ft&&(b.lineStart(),b.point(Q,vt),it=!1)}H=Q,V=vt,W=Ft}return st}}var Ti=s=>s;var An=1/0,Br=An,cr=-An,Ur=cr,Ru={point:Tu,lineStart:ln,lineEnd:ln,polygonStart:ln,polygonEnd:ln,result:function(){var s=[[An,Br],[cr,Ur]];return cr=Ur=-(Br=An=1/0),s}};function Tu(s,a){scr&&(cr=s),aUr&&(Ur=a)}var Mi=Ru;function hr(s){return function(a){var u=new Oi;for(var h in s)u[h]=s[h];return u.stream=a,u}}function Oi(){}Oi.prototype={constructor:Oi,point:function(s,a){this.stream.point(s,a)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};function Pi(s,a,u){var h=s.clipExtent&&s.clipExtent();return s.scale(150).translate([0,0]),h!=null&&s.clipExtent(null),ao(u,s.stream(Mi)),a(Mi.result()),h!=null&&s.clipExtent(h),s}function Ai(s,a,u){return Pi(s,function(h){var m=a[1][0]-a[0][0],c=a[1][1]-a[0][1],v=Math.min(m/(h[1][0]-h[0][0]),c/(h[1][1]-h[0][1])),_=+a[0][0]+(m-v*(h[1][0]+h[0][0]))/2,L=+a[0][1]+(c-v*(h[1][1]+h[0][1]))/2;s.scale(150*v).translate([_,L])},u)}function _o(s,a,u){return Ai(s,[[0,0],a],u)}function xo(s,a,u){return Pi(s,function(h){var m=+a,c=m/(h[1][0]-h[0][0]),v=(m-c*(h[1][0]+h[0][0]))/2,_=-c*h[0][1];s.scale(150*c).translate([v,_])},u)}function ko(s,a,u){return Pi(s,function(h){var m=+a,c=m/(h[1][1]-h[0][1]),v=-c*h[0][0],_=(m-c*(h[1][1]+h[0][1]))/2;s.scale(150*c).translate([v,_])},u)}var Eo=16,Mu=Pt(30*ee);function Di(s,a){return+a?Pu(s,a):Ou(s)}function Ou(s){return hr({point:function(a,u){a=s(a,u),this.stream.point(a[0],a[1])}})}function Pu(s,a){function u(h,m,c,v,_,L,w,b,x,E,C,P,Y,z){var M=w-h,H=b-m,V=M*M+H*H;if(V>4*a&&Y--){var W=v+E,$=_+C,it=L+P,st=Ke(W*W+$*$+it*it),nt=Ue(it/=st),ft=qt(qt(it)-1)a||qt((M*xt+H*Et)/V-.5)>.3||v*E+_*C+L*P2?Q[2]%360*ee:0,xt()):[_*Ae,L*Ae,w*Ae]},at.angle=function(Q){return arguments.length?(x=Q%360*ee,xt()):x*Ae},at.reflectX=function(Q){return arguments.length?(E=Q?-1:1,xt()):E<0},at.reflectY=function(Q){return arguments.length?(C=Q?-1:1,xt()):C<0},at.precision=function(Q){return arguments.length?(it=Di(st,$=Q*Q),Et()):Ke($)},at.fitExtent=function(Q,vt){return Ai(at,Q,vt)},at.fitSize=function(Q,vt){return _o(at,Q,vt)},at.fitWidth=function(Q,vt){return xo(at,Q,vt)},at.fitHeight=function(Q,vt){return ko(at,Q,vt)};function xt(){var Q=wo(u,0,0,E,C,x).apply(null,a(c,v)),vt=wo(u,h-Q[0],m-Q[1],E,C,x);return b=ho(_,L,w),st=ur(a,vt),nt=ur(b,st),it=Di(st,$),Et()}function Et(){return ft=gt=null,at}return function(){return a=s.apply(this,arguments),at.invert=a.invert&&_t,xt()}}function Io(s){return function(a,u){var h=Pt(a),m=Pt(u),c=s(h*m);return c===1/0?[2,0]:[c*m*At(a),c*At(u)]}}function No(s){return function(a,u){var h=Ke(a*a+u*u),m=s(h),c=At(m),v=Pt(m);return[Be(a*c,h*v),Ue(h&&u*c/h)]}}var Gi=Io(function(s){return(s=Or(s))&&s/At(s)});Gi.invert=No(function(s){return s});function qi(){return Fi(Gi).scale(79.4188).clipAngle(180-.001)}var{BufferOp:qu,GeoJSONReader:Yu,GeoJSONWriter:Bu}=bo.default;function Uu(s,a,u){u=u||{};var h=u.units||"kilometers",m=u.steps||8;if(!s)throw new Error("geojson is required");if(typeof u!="object")throw new Error("options must be an object");if(typeof m!="number")throw new Error("steps must be an number");if(a===void 0)throw new Error("radius is required");if(m<=0)throw new Error("steps must be greater than 0");var c=[];switch(s.type){case"GeometryCollection":return Mr(s,function(v){var _=Xr(v,a,h,m);_&&c.push(_)}),an(c);case"FeatureCollection":return ki(s,function(v){var _=Xr(v,a,h,m);_&&ki(_,function(L){L&&c.push(L)})}),an(c)}return Xr(s,a,h,m)}function Xr(s,a,u,h){var m=s.properties||{},c=s.type==="Feature"?s.geometry:s;if(c.type==="GeometryCollection"){var v=[];return Mr(s,function(Y){var z=Xr(Y,a,u,h);z&&v.push(z)}),an(v)}var _=Xu(c),L={type:c.type,coordinates:Lo(c.coordinates,_)},w=new Yu,b=w.read(L),x=Ks(Js(a,u),"meters"),E=qu.bufferOp(b,x,h),C=new Bu;if(E=C.write(E),!So(E.coordinates)){var P={type:E.type,coordinates:Co(E.coordinates,_)};return xe(P,m)}}function So(s){return Array.isArray(s[0])?So(s[0]):isNaN(s[0])}function Lo(s,a){return typeof s[0]!="object"?a(s):s.map(function(u){return Lo(u,a)})}function Co(s,a){return typeof s[0]!="object"?a.invert(s):s.map(function(u){return Co(u,a)})}function Xu(s){var a=$s(s).geometry.coordinates,u=[-a[0],-a[1]];return qi().rotate(u).scale(Ht)}var Ro=Uu;function zr(s){if(!s)throw new Error("coord is required");if(!Array.isArray(s)){if(s.type==="Feature"&&s.geometry!==null&&s.geometry.type==="Point")return[...s.geometry.coordinates];if(s.type==="Point")return[...s.coordinates]}if(Array.isArray(s)&&s.length>=2&&!Array.isArray(s[0])&&!Array.isArray(s[1]))return[...s];throw new Error("coord must be GeoJSON Point or an Array of numbers")}function vn(s){if(Array.isArray(s))return s;if(s.type==="Feature"){if(s.geometry!==null)return s.geometry.coordinates}else if(s.coordinates)return s.coordinates;throw new Error("coords must be GeoJSON Feature, Geometry Object or an Array")}function Ee(s){return s.type==="Feature"?s.geometry:s}function To(s,a){return s.type==="FeatureCollection"?"FeatureCollection":s.type==="GeometryCollection"?"GeometryCollection":s.type==="Feature"&&s.geometry!==null?s.geometry.type:s.type}var Mt=11102230246251565e-32,Kt=134217729,fr=(3+8*Mt)*Mt;function yn(s,a,u,h,m){let c,v,_,L,w=a[0],b=h[0],x=0,E=0;b>w==b>-w?(c=w,w=a[++x]):(c=b,b=h[++E]);let C=0;if(xw==b>-w?(v=w+c,_=c-(v-w),w=a[++x]):(v=b+c,_=c-(v-b),b=h[++E]),c=v,_!==0&&(m[C++]=_);xw==b>-w?(v=c+w,L=v-c,_=c-(v-L)+(w-L),w=a[++x]):(v=c+b,L=v-c,_=c-(v-L)+(b-L),b=h[++E]),c=v,_!==0&&(m[C++]=_);for(;x=Et||-xt>=Et||(x=s-ft,_=s-(ft+x)+(x-m),x=u-gt,w=u-(gt+x)+(x-m),x=a-at,L=a-(at+x)+(x-c),x=h-_t,b=h-(_t+x)+(x-c),_===0&&L===0&&w===0&&b===0)||(Et=Hu*v+fr*Math.abs(xt),xt+=ft*b+_t*_-(at*w+gt*L),xt>=Et||-xt>=Et))return xt;W=_*_t,E=Kt*_,C=E-(E-_),P=_-C,E=Kt*_t,Y=E-(E-_t),z=_t-Y,$=P*z-(W-C*Y-P*Y-C*z),it=L*gt,E=Kt*L,C=E-(E-L),P=L-C,E=Kt*gt,Y=E-(E-gt),z=gt-Y,st=P*z-(it-C*Y-P*Y-C*z),M=$-st,x=$-M,me[0]=$-(M+x)+(x-st),H=W+M,x=H-W,V=W-(H-x)+(M-x),M=V-it,x=V-M,me[1]=V-(M+x)+(x-it),nt=H+M,x=nt-H,me[2]=H-(nt-x)+(M-x),me[3]=nt;let Q=yn(4,Dn,4,me,Mo);W=ft*b,E=Kt*ft,C=E-(E-ft),P=ft-C,E=Kt*b,Y=E-(E-b),z=b-Y,$=P*z-(W-C*Y-P*Y-C*z),it=at*w,E=Kt*at,C=E-(E-at),P=at-C,E=Kt*w,Y=E-(E-w),z=w-Y,st=P*z-(it-C*Y-P*Y-C*z),M=$-st,x=$-M,me[0]=$-(M+x)+(x-st),H=W+M,x=H-W,V=W-(H-x)+(M-x),M=V-it,x=V-M,me[1]=V-(M+x)+(x-it),nt=H+M,x=nt-H,me[2]=H-(nt-x)+(M-x),me[3]=nt;let vt=yn(Q,Mo,4,me,Oo);W=_*b,E=Kt*_,C=E-(E-_),P=_-C,E=Kt*b,Y=E-(E-b),z=b-Y,$=P*z-(W-C*Y-P*Y-C*z),it=L*w,E=Kt*L,C=E-(E-L),P=L-C,E=Kt*w,Y=E-(E-w),z=w-Y,st=P*z-(it-C*Y-P*Y-C*z),M=$-st,x=$-M,me[0]=$-(M+x)+(x-st),H=W+M,x=H-W,V=W-(H-x)+(M-x),M=V-it,x=V-M,me[1]=V-(M+x)+(x-it),nt=H+M,x=nt-H,me[2]=H-(nt-x)+(M-x),me[3]=nt;let Ft=yn(vt,Oo,4,me,Po);return Po[Ft-1]}function Yi(s,a,u,h,m,c){let v=(a-c)*(u-m),_=(s-m)*(h-c),L=v-_,w=Math.abs(v+_);return Math.abs(L)>=zu*w?L:-ju(s,a,u,h,m,c,w)}var Eh=(7+56*Mt)*Mt,wh=(3+28*Mt)*Mt,Ih=(26+288*Mt)*Mt*Mt,Nh=K(4),bh=K(4),Sh=K(4),Lh=K(4),Ch=K(4),Rh=K(4),Th=K(4),Mh=K(4),Oh=K(4),Ph=K(8),Ah=K(8),Dh=K(8),Fh=K(4),Gh=K(8),qh=K(8),Yh=K(16),Bh=K(12),Uh=K(192),Xh=K(192);var Hh=(10+96*Mt)*Mt,jh=(4+48*Mt)*Mt,Wh=(44+576*Mt)*Mt*Mt,Zh=K(4),Kh=K(4),Jh=K(4),Qh=K(4),$h=K(4),tf=K(4),ef=K(4),nf=K(4),rf=K(8),sf=K(8),of=K(8),af=K(8),uf=K(8),lf=K(8),cf=K(8),hf=K(8),ff=K(8),gf=K(4),df=K(4),mf=K(4),pf=K(8),vf=K(16),yf=K(16),_f=K(16),xf=K(32),kf=K(32),Ef=K(48),wf=K(64),If=K(1152),Nf=K(1152);var Cf=(16+224*Mt)*Mt,Rf=(5+72*Mt)*Mt,Tf=(71+1408*Mt)*Mt*Mt,Mf=K(4),Of=K(4),Pf=K(4),Af=K(4),Df=K(4),Ff=K(4),Gf=K(4),qf=K(4),Yf=K(4),Bf=K(4),Uf=K(24),Xf=K(24),zf=K(24),Vf=K(24),Hf=K(24),jf=K(24),Wf=K(24),Zf=K(24),Kf=K(24),Jf=K(24),Qf=K(1152),$f=K(1152),tg=K(1152),eg=K(1152),ng=K(1152),rg=K(2304),ig=K(2304),sg=K(3456),og=K(5760),ag=K(8),ug=K(8),lg=K(8),cg=K(16),hg=K(24),fg=K(48),gg=K(48),dg=K(96),mg=K(192),pg=K(384),vg=K(384),yg=K(384),_g=K(768);var xg=K(96),kg=K(96),Eg=K(96),wg=K(1152);function Do(s,a){var u,h,m=0,c,v,_,L,w,b,x,E=s[0],C=s[1],P=a.length;for(u=0;u=0||v<=0&&L>=0)return 0}else if(w>=0&&_<=0||w<=0&&_>=0){if(c=Yi(v,L,_,w,0,0),c===0)return 0;(c>0&&w>0&&_<=0||c<0&&w<=0&&_>0)&&m++}b=x,_=w,v=L}}return m%2!==0}function cn(s,a,u={}){if(!s)throw new Error("point is required");if(!a)throw new Error("polygon is required");let h=zr(s),m=Ee(a),c=m.type,v=a.bbox,_=m.coordinates;if(v&&Zu(h,v)===!1)return!1;c==="Polygon"&&(_=[_]);for(var L=0;L<_.length;++L){let w=Do(h,_[L]);if(w===0&&!u.ignoreBoundary)return!0;if(w)return!0}return!1}function Zu(s,a){return a[0]<=s[0]&&a[1]<=s[1]&&a[2]>=s[0]&&a[3]>=s[1]}var Fn=class{constructor(a=[],u=Ku){if(this.data=a,this.length=this.data.length,this.compare=u,this.length>0)for(let h=(this.length>>1)-1;h>=0;h--)this._down(h)}push(a){this.data.push(a),this.length++,this._up(this.length-1)}pop(){if(this.length===0)return;let a=this.data[0],u=this.data.pop();return this.length--,this.length>0&&(this.data[0]=u,this._down(0)),a}peek(){return this.data[0]}_up(a){let{data:u,compare:h}=this,m=u[a];for(;a>0;){let c=a-1>>1,v=u[c];if(h(m,v)>=0)break;u[a]=v,a=c}u[a]=m}_down(a){let{data:u,compare:h}=this,m=this.length>>1,c=u[a];for(;a=0)break;u[a]=_,a=v}u[a]=c}};function Ku(s,a){return sa?1:0}var Ot=11102230246251565e-32,Jt=134217729,dr=(3+8*Ot)*Ot;function _n(s,a,u,h,m){let c,v,_,L,w=a[0],b=h[0],x=0,E=0;b>w==b>-w?(c=w,w=a[++x]):(c=b,b=h[++E]);let C=0;if(xw==b>-w?(v=w+c,_=c-(v-w),w=a[++x]):(v=b+c,_=c-(v-b),b=h[++E]),c=v,_!==0&&(m[C++]=_);xw==b>-w?(v=c+w,L=v-c,_=c-(v-L)+(w-L),w=a[++x]):(v=c+b,L=v-c,_=c-(v-L)+(b-L),b=h[++E]),c=v,_!==0&&(m[C++]=_);for(;x=Et||-xt>=Et||(x=s-ft,_=s-(ft+x)+(x-m),x=u-gt,w=u-(gt+x)+(x-m),x=a-at,L=a-(at+x)+(x-c),x=h-_t,b=h-(_t+x)+(x-c),_===0&&L===0&&w===0&&b===0)||(Et=$u*v+dr*Math.abs(xt),xt+=ft*b+_t*_-(at*w+gt*L),xt>=Et||-xt>=Et))return xt;W=_*_t,E=Jt*_,C=E-(E-_),P=_-C,E=Jt*_t,Y=E-(E-_t),z=_t-Y,$=P*z-(W-C*Y-P*Y-C*z),it=L*gt,E=Jt*L,C=E-(E-L),P=L-C,E=Jt*gt,Y=E-(E-gt),z=gt-Y,st=P*z-(it-C*Y-P*Y-C*z),M=$-st,x=$-M,pe[0]=$-(M+x)+(x-st),H=W+M,x=H-W,V=W-(H-x)+(M-x),M=V-it,x=V-M,pe[1]=V-(M+x)+(x-it),nt=H+M,x=nt-H,pe[2]=H-(nt-x)+(M-x),pe[3]=nt;let Q=_n(4,Gn,4,pe,Fo);W=ft*b,E=Jt*ft,C=E-(E-ft),P=ft-C,E=Jt*b,Y=E-(E-b),z=b-Y,$=P*z-(W-C*Y-P*Y-C*z),it=at*w,E=Jt*at,C=E-(E-at),P=at-C,E=Jt*w,Y=E-(E-w),z=w-Y,st=P*z-(it-C*Y-P*Y-C*z),M=$-st,x=$-M,pe[0]=$-(M+x)+(x-st),H=W+M,x=H-W,V=W-(H-x)+(M-x),M=V-it,x=V-M,pe[1]=V-(M+x)+(x-it),nt=H+M,x=nt-H,pe[2]=H-(nt-x)+(M-x),pe[3]=nt;let vt=_n(Q,Fo,4,pe,Go);W=_*b,E=Jt*_,C=E-(E-_),P=_-C,E=Jt*b,Y=E-(E-b),z=b-Y,$=P*z-(W-C*Y-P*Y-C*z),it=L*w,E=Jt*L,C=E-(E-L),P=L-C,E=Jt*w,Y=E-(E-w),z=w-Y,st=P*z-(it-C*Y-P*Y-C*z),M=$-st,x=$-M,pe[0]=$-(M+x)+(x-st),H=W+M,x=H-W,V=W-(H-x)+(M-x),M=V-it,x=V-M,pe[1]=V-(M+x)+(x-it),nt=H+M,x=nt-H,pe[2]=H-(nt-x)+(M-x),pe[3]=nt;let Ft=_n(vt,Go,4,pe,qo);return qo[Ft-1]}function Vr(s,a,u,h,m,c){let v=(a-c)*(u-m),_=(s-m)*(h-c),L=v-_;if(v===0||_===0||v>0!=_>0)return L;let w=Math.abs(v+_);return Math.abs(L)>=Ju*w?L:-tl(s,a,u,h,m,c,w)}var jg=(7+56*Ot)*Ot,Wg=(3+28*Ot)*Ot,Zg=(26+288*Ot)*Ot*Ot,Kg=J(4),Jg=J(4),Qg=J(4),$g=J(4),td=J(4),ed=J(4),nd=J(4),rd=J(4),id=J(4),sd=J(8),od=J(8),ad=J(8),ud=J(4),ld=J(8),cd=J(8),hd=J(8),fd=J(12),gd=J(192),dd=J(192);var vd=(10+96*Ot)*Ot,yd=(4+48*Ot)*Ot,_d=(44+576*Ot)*Ot*Ot,xd=J(4),kd=J(4),Ed=J(4),wd=J(4),Id=J(4),Nd=J(4),bd=J(4),Sd=J(4),Ld=J(8),Cd=J(8),Rd=J(8),Td=J(8),Md=J(8),Od=J(8),Pd=J(8),Ad=J(8),Dd=J(8),Fd=J(4),Gd=J(4),qd=J(4),Yd=J(8),Bd=J(16),Ud=J(16),Xd=J(16),zd=J(32),Vd=J(32),Hd=J(48),jd=J(64),Wd=J(1152),Zd=J(1152);var $d=(16+224*Ot)*Ot,tm=(5+72*Ot)*Ot,em=(71+1408*Ot)*Ot*Ot,nm=J(4),rm=J(4),im=J(4),sm=J(4),om=J(4),am=J(4),um=J(4),lm=J(4),cm=J(4),hm=J(4),fm=J(24),gm=J(24),dm=J(24),mm=J(24),pm=J(24),vm=J(24),ym=J(24),_m=J(24),xm=J(24),km=J(24),Em=J(1152),wm=J(1152),Im=J(1152),Nm=J(1152),bm=J(1152),Sm=J(2304),Lm=J(2304),Cm=J(3456),Rm=J(5760),Tm=J(8),Mm=J(8),Om=J(8),Pm=J(16),Am=J(24),Dm=J(48),Fm=J(48),Gm=J(96),qm=J(192),Ym=J(384),Bm=J(384),Um=J(384),Xm=J(768);var zm=J(96),Vm=J(96),Hm=J(96),jm=J(1152);function nl(s,a){let u=new Fn([],Xo);return il(s,u),sl(u,a)}function Xo(s,a){return s.p.x>a.p.x?1:s.p.xa.p.y?1:-1:1}function rl(s,a){return s.rightSweepEvent.p.x>a.rightSweepEvent.p.x?1:s.rightSweepEvent.p.x0?(b.isLeftEndpoint=!0,w.isLeftEndpoint=!1):(w.isLeftEndpoint=!0,b.isLeftEndpoint=!1),a.push(w),a.push(b),v=_,Wr=Wr+1}}Hr=Hr+1}var Uo=class{constructor(s,a,u,h){this.p={x:s[0],y:s[1]},this.featureId=a,this.ringId=u,this.eventId=h,this.otherEvent=null,this.isLeftEndpoint=null}isSamePoint(s){return this.p.x===s.p.x&&this.p.y===s.p.y}asNewXY(){return[this.p.x,this.p.y]}};function sl(s,a=!1){let u=[],h=new Fn([],rl);for(;s.length;){let m=s.pop();if(m.isLeftEndpoint){let c=new ol(m);for(let v=0;v0&&x>0)return!1;if(b<0&&x<0)return!1;if(s.leftSweepEvent.ringId===a.leftSweepEvent.ringId){if(s.rightSweepEvent.isSamePoint(a.leftSweepEvent)||s.rightSweepEvent.isSamePoint(a.rightSweepEvent)||s.leftSweepEvent.isSamePoint(a.leftSweepEvent)||s.leftSweepEvent.isSamePoint(a.rightSweepEvent))return!1}else{if(s.rightSweepEvent.isSamePoint(a.leftSweepEvent))return a.leftSweepEvent.asNewXY();if(s.rightSweepEvent.isSamePoint(a.rightSweepEvent))return a.rightSweepEvent.asNewXY();if(s.leftSweepEvent.isSamePoint(a.leftSweepEvent))return a.leftSweepEvent.asNewXY();if(s.leftSweepEvent.isSamePoint(a.rightSweepEvent))return a.rightSweepEvent.asNewXY()}let E=(w-_)*(m-u)-(L-v)*(c-h),C=(L-v)*(h-_)-(w-_)*(u-v),P=(m-u)*(h-_)-(c-h)*(u-v);if(E===0)return!1;let Y=C/E,z=P/E;if(Y>=0&&Y<=1&&z>=0&&z<=1){let M=u+Y*(m-u),H=h+Y*(c-h);return[M,H]}return!1}function Qe(s,a,u={}){let{removeDuplicates:h=!0,ignoreSelfIntersections:m=!0}=u,c=[];s.type==="FeatureCollection"?c=c.concat(s.features):s.type==="Feature"?c.push(s):(s.type==="LineString"||s.type==="Polygon"||s.type==="MultiLineString"||s.type==="MultiPolygon")&&c.push(xe(s)),a.type==="FeatureCollection"?c=c.concat(a.features):a.type==="Feature"?c.push(a):(a.type==="LineString"||a.type==="Polygon"||a.type==="MultiLineString"||a.type==="MultiPolygon")&&c.push(xe(a));let v=nl(an(c),m),_=[];if(h){let L={};v.forEach(w=>{let b=w.join(",");L[b]||(L[b]=!0,_.push(w))})}else _=v;return an(_.map(L=>Ye(L)))}function qn(s,a={}){let u=Ee(s);switch(!a.properties&&s.type==="Feature"&&(a.properties=s.properties),u.type){case"Polygon":return ul(u,a);case"MultiPolygon":return ll(u,a);default:throw new Error("invalid poly")}}function ul(s,a={}){let h=Ee(s).coordinates,m=a.properties?a.properties:s.type==="Feature"?s.properties:{};return zo(h,m)}function ll(s,a={}){let h=Ee(s).coordinates,m=a.properties?a.properties:s.type==="Feature"?s.properties:{},c=[];return h.forEach(v=>{c.push(zo(v,m))}),an(c)}function zo(s,a){return s.length>1?Zs(s,a):on(s[0],a)}function Ho(s,a,{ignoreSelfIntersections:u=!0}={ignoreSelfIntersections:!0}){let h=!0;return Ei(s,m=>{Ei(a,c=>{if(h===!1)return!1;h=cl(m.geometry,c.geometry,u)})}),h}function cl(s,a,u){switch(s.type){case"Point":switch(a.type){case"Point":return!dl(s.coordinates,a.coordinates);case"LineString":return!Zr(a,s);case"Polygon":return!cn(s,a)}break;case"LineString":switch(a.type){case"Point":return!Zr(s,a);case"LineString":return!hl(s,a,u);case"Polygon":return!Vo(a,s,u)}break;case"Polygon":switch(a.type){case"Point":return!cn(a,s);case"LineString":return!Vo(s,a,u);case"Polygon":return!fl(a,s,u)}}return!1}function Zr(s,a){for(let u=0;u0)return!0;for(let m of s.coordinates)if(Zr(a,{type:"Point",coordinates:m}))return!0;for(let m of a.coordinates)if(Zr(s,{type:"Point",coordinates:m}))return!0;return!1}function Vo(s,a,u){for(let m of a.coordinates)if(cn(m,s))return!0;return Qe(a,qn(s),{ignoreSelfIntersections:u}).features.length>0}function fl(s,a,u){for(let m of s.coordinates[0])if(cn(m,a))return!0;for(let m of a.coordinates[0])if(cn(m,s))return!0;return Qe(qn(s),qn(a),{ignoreSelfIntersections:u}).features.length>0}function gl(s,a,u){let h=u[0]-s[0],m=u[1]-s[1],c=a[0]-s[0],v=a[1]-s[1];return h*v-m*c!==0?!1:Math.abs(c)>=Math.abs(v)?c>0?s[0]<=u[0]&&u[0]<=a[0]:a[0]<=u[0]&&u[0]<=s[0]:v>0?s[1]<=u[1]&&u[1]<=a[1]:a[1]<=u[1]&&u[1]<=s[1]}function dl(s,a){return s[0]===a[0]&&s[1]===a[1]}var ml=Object.defineProperty,Yn=(s,a)=>ml(s,"name",{value:a,configurable:!0}),Wo=class{constructor(a){this.direction=!1,this.compareProperties=!0;var u,h,m;this.precision=10**-((u=a?.precision)!=null?u:17),this.direction=(h=a?.direction)!=null?h:!1,this.compareProperties=(m=a?.compareProperties)!=null?m:!0}compare(a,u){if(a.type!==u.type||!pr(a,u))return!1;switch(a.type){case"Point":return this.compareCoord(a.coordinates,u.coordinates);case"LineString":return this.compareLine(a.coordinates,u.coordinates);case"Polygon":return this.comparePolygon(a,u);case"GeometryCollection":return this.compareGeometryCollection(a,u);case"Feature":return this.compareFeature(a,u);case"FeatureCollection":return this.compareFeatureCollection(a,u);default:if(a.type.startsWith("Multi")){let h=Bi(a),m=Bi(u);return h.every(c=>m.some(v=>this.compare(c,v)))}}return!1}compareCoord(a,u){return a.length===u.length&&a.every((h,m)=>Math.abs(h-u[m])=0&&(h=[].concat(a.slice(m,a.length),a.slice(1,m+1))),h}comparePath(a,u){return a.every((h,m)=>this.compareCoord(h,u[m]))}comparePolygon(a,u){if(this.compareLine(a.coordinates[0],u.coordinates[0],1,!0)){let h=a.coordinates.slice(1,a.coordinates.length),m=u.coordinates.slice(1,u.coordinates.length);return h.every(c=>m.some(v=>this.compareLine(c,v,1,!0)))}return!1}compareGeometryCollection(a,u){return pr(a.geometries,u.geometries)&&this.compareBBox(a,u)&&a.geometries.every((h,m)=>this.compare(h,u.geometries[m]))}compareFeature(a,u){return a.id===u.id&&(this.compareProperties?Xi(a.properties,u.properties):!0)&&this.compareBBox(a,u)&&this.compare(a.geometry,u.geometry)}compareFeatureCollection(a,u){return pr(a.features,u.features)&&this.compareBBox(a,u)&&a.features.every((h,m)=>this.compare(h,u.features[m]))}compareBBox(a,u){return!a.bbox&&!u.bbox||(a.bbox&&u.bbox?this.compareCoord(a.bbox,u.bbox):!1)}};Yn(Wo,"GeojsonEquality");var pl=Wo;function pr(s,a){return s.coordinates?s.coordinates.length===a.coordinates.length:s.length===a.length}Yn(pr,"sameLength");function Bi(s){return s.coordinates.map(a=>({type:s.type.replace("Multi",""),coordinates:a}))}Yn(Bi,"explode");function Ui(s,a,u){return new pl(u).compare(s,a)}Yn(Ui,"geojsonEquality");function Xi(s,a){if(s===null&&a===null)return!0;if(s===null||a===null)return!1;let u=Object.keys(s),h=Object.keys(a);if(u.length!==h.length)return!1;for(var m of u){let c=s[m],v=a[m],_=jo(c)&&jo(v);if(_&&!Xi(c,v)||!_&&c!==v)return!1}return!0}Yn(Xi,"equal");var jo=Yn(s=>s!=null&&typeof s=="object","isObject");function vr(s,a,u={}){let h=zr(s),m=vn(a);for(let c=0;c"u"?null:u.epsilon))return!0}return!1}function vl(s,a,u,h,m){let c=u[0],v=u[1],_=s[0],L=s[1],w=a[0],b=a[1],x=u[0]-_,E=u[1]-L,C=w-_,P=b-L,Y=x*P-E*C;if(m!==null){if(Math.abs(Y)>m)return!1}else if(Y!==0)return!1;if(Math.abs(C)===Math.abs(P)&&Math.abs(C)===0)return h?!1:u[0]===s[0]&&u[1]===s[1];if(h){if(h==="start")return Math.abs(C)>=Math.abs(P)?C>0?_0?L=Math.abs(P)?C>0?_<=c&&c0?L<=v&&v=Math.abs(P)?C>0?_0?L=Math.abs(P)?C>0?_<=c&&c<=w:w<=c&&c<=_:P>0?L<=v&&v<=b:b<=v&&v<=L;return!1}function Vi(s,a={}){var u=typeof a=="object"?a.mutate:a;if(!s)throw new Error("geojson is required");var h=To(s),m=[];switch(h){case"LineString":m=zi(s,h);break;case"MultiLineString":case"Polygon":vn(s).forEach(function(v){m.push(zi(v,h))});break;case"MultiPolygon":vn(s).forEach(function(v){var _=[];v.forEach(function(L){_.push(zi(L,h))}),m.push(_)});break;case"Point":return s;case"MultiPoint":var c={};vn(s).forEach(function(v){var _=v.join("-");Object.prototype.hasOwnProperty.call(c,_)||(m.push(v),c[_]=!0)});break;default:throw new Error(h+" geometry not supported")}return s.coordinates?u===!0?(s.coordinates=m,s):{type:h,coordinates:m}:u===!0?(s.geometry.coordinates=m,s):xe({type:h,coordinates:m},s.properties,{bbox:s.bbox,id:s.id})}function zi(s,a){let u=vn(s);if(u.length===2&&!Zo(u[0],u[1]))return u;let h=[],m=0,c=1,v=2;for(h.push(u[m]);v=0))throw new Error("precision must be a positive number");let m=Ee(s).type,c=Ee(a).type;return m!==c?!1:Ui(Vi(s),Vi(a),{precision:h})}function $o(s,a){var u=Ee(s),h=Ee(a),m=u.type,c=h.type;switch(m){case"MultiPoint":switch(c){case"LineString":return Ko(u,h);case"Polygon":return Qo(u,h);default:throw new Error("feature2 "+c+" geometry not supported")}case"LineString":switch(c){case"MultiPoint":return Ko(h,u);case"LineString":return yl(u,h);case"Polygon":return Jo(u,h);default:throw new Error("feature2 "+c+" geometry not supported")}case"Polygon":switch(c){case"MultiPoint":return Qo(h,u);case"LineString":return Jo(h,u);default:throw new Error("feature2 "+c+" geometry not supported")}default:throw new Error("feature1 "+m+" geometry not supported")}}function Ko(s,a){for(var u=!1,h=!1,m=s.coordinates.length,c=0;c0}function Qo(s,a){var u=!1,h=!1,m=s.coordinates.length;for(let c=0;c=Math.abs(_)?v>0?s[0]<=u[0]&&u[0]<=a[0]:a[0]<=u[0]&&u[0]<=s[0]:_>0?s[1]<=u[1]&&u[1]<=a[1]:a[1]<=u[1]&&u[1]<=s[1]:Math.abs(v)>=Math.abs(_)?v>0?s[0]0?s[1]1;case"MultiPoint":for(var m=0;m0&&Qe(pn([h[0]]),pn([h[m]])).features.length>1)return!1;return!0;case"MultiPolygon":for(var m=0;m0&&Qe(pn([c[0]]),pn([c[v]])).features.length>1)return!1;return!0;case"GeometryCollection":return a.geometries?Array.isArray(a.geometries)&&a.geometries.length>0&&a.geometries.every(_=>xl.has(_.type)&&na(_)):!1;default:return!1}}function ta(s){return s[0][0]===s[s.length-1][0]&&s[0][1]===s[s.length-1][1]}function ea(s){for(var a=0;a[(s+180)/360,(1-Math.asinh(Math.tan(a*Math.PI/180))/Math.PI)/2],_r=([s,a])=>[s*360-180,Math.atan(Math.sinh(Math.PI*(1-2*a)))*180/Math.PI],Xn=s=>1/(40075016686e-3*Math.cos(_r([.5,s])[1]*Math.PI/180)),sa=(s,a)=>a?20:Math.log2(40075016686e-3*Math.cos(_r([.5,s])[1]*Math.PI/180)*120/(2e3*256));function Hi(s,a,u,h=48){return Array.from({length:h+1},(m,c)=>{let v=c/h,_=1-v;return[_*_*s[0]+2*_*v*a[0]+v*v*u[0],_*_*s[1]+2*_*v*a[1]+v*v*u[1]]})}function oa(s,a=25,u=20){let h=Xn(s[1]);return[[-a/2,-u/2],[a/2,-u/2],[a/2,u/2],[-a/2,u/2]].map(([m,c])=>[s[0]+m*h,s[1]+c*h])}function aa(s,a,u){if(!Bn.includes(s))throw Error("Select a country account to build.");if(!["road","building","park","district"].includes(a.kind))throw Error("Unknown construction.");let h=a.points;if(!Array.isArray(h)||h.length<(a.kind==="road"?2:3)||h.length>1e3||h.some(x=>!Array.isArray(x)||x.length!==2||x.some(E=>!Number.isFinite(E)||E<0||E>1)))throw Error("Invalid coordinates.");let m=Number(a.width??12),c=Number(a.levels??2);if(!Number.isFinite(m)||m<2||m>100||!Number.isFinite(c)||c<1||c>100)throw Error("Invalid width or floor count.");let v=h.map(_r),_;if(a.kind==="road")_=Ro({type:"Feature",properties:{},geometry:{type:"LineString",coordinates:v}},m/2e3,{units:"kilometers",steps:12})?.geometry;else if(!El(h)||(v=[...v,v[0]],_={type:"Polygon",coordinates:[v]},!ra(_)))throw Error("Footprint crosses itself or has no area.");if(!_)throw Error("Empty construction.");if(ia.default.difference(_.coordinates,u[s].coordinates).length)throw Error(`The entire construction must stay inside ${s}, including road width.`);let L=h.map(x=>x[0]),w=h.map(x=>x[1]),b=a.kind==="road"?m*Xn(h[0][1])/2:0;if(Math.max(...L)-Math.min(...L)>.03||Math.max(...w)-Math.min(...w)>.03)throw Error("Build a smaller section.");return{kind:a.kind,points:h,width:m,levels:c,name:String(a.name||"Untitled "+a.kind).slice(0,80),bounds:[Math.min(...L)-b,Math.min(...w)-b,Math.max(...L)+b,Math.max(...w)+b]}}function El(s){let a=(m,c,v)=>(c[0]-m[0])*(v[1]-m[1])-(c[1]-m[1])*(v[0]-m[0]),u=(m,c,v)=>Math.abs(a(m,c,v))<1e-20&&v[0]>=Math.min(m[0],c[0])&&v[0]<=Math.max(m[0],c[0])&&v[1]>=Math.min(m[1],c[1])&&v[1]<=Math.max(m[1],c[1]),h=0;for(let m=0;m1e-20}var lt=s=>document.getElementById(s),ve=lt("map"),rt=ve.getContext("2d",{alpha:!1}),D={account:null,detail:!1,admin:!1,radar:[],center:Un(Kr.Kuwait),zoom:11,tool:"navigate",points:[],features:[],coarse:!1,night:!1,demo:!1,token:localStorage.getItem("wa-token"),view:"Kuwait"},Qi,ma,$i,xr,ts,es,ue=0,ye=0,ji=!1,ua,Vn=0,wr,Se=null,Hn=null,la,Le=s=>{lt("toast").textContent=s,lt("toast").style.display="block",clearTimeout(la),la=setTimeout(()=>lt("toast").style.display="none",5e3)},$r=()=>JSON.parse(localStorage.getItem("wa-demo-world")||"[]");function pa(s){try{localStorage.setItem("wa-demo-world",JSON.stringify(s))}catch{throw Error("Browser storage is full. Export your demo before continuing.")}}async function $e(s,a={}){let u=await fetch(window.hostGate.apiUrl.replace(/\/$/,"")+s,{...a,headers:{"Content-Type":"application/json",Authorization:"Bearer "+D.token,...a.headers}}),h=await u.json();if(!u.ok)throw h.code==="unreleased"&&window.hostGate.unreleased(),h.code==="country_disabled"&&window.hostGate.block(D.account||lt("loginCountry").value),u.status===401&&(localStorage.removeItem("wa-token"),D.token=null,D.account=null,Xe?.close(),D.features=[],window.hostGate.canPlay&&!lt("login").open&<("login").showModal(),va()),Error(h.error||"Unable to connect.");return h}function ze(s){lt("connection").textContent=s}function Ve(){ji||(ji=!0,requestAnimationFrame(()=>{ji=!1,va()}))}function le(){return 256*2**D.zoom}function De(s){return[(s[0]-D.center[0])*le()+ue/2,(s[1]-D.center[1])*le()+ye/2]}function Ir(s,a){return[(s-ue/2)/le()+D.center[0],(a-ye/2)/le()+D.center[1]]}function Wn(){D.center[0]=Math.max(.52,Math.min(.7,D.center[0])),D.center[1]=Math.max(.32,Math.min(.49,D.center[1])),D.zoom=Math.max(5,Math.min(sa(D.center[1],D.detail),D.zoom)),Ve(),clearTimeout(ua),ua=setTimeout(xn,180);let s=120/(le()*Xn(D.center[1]));lt("scaleText").textContent=s>=1e3?(s/1e3).toFixed(s<1e4?1:0)+" km":Math.round(s)+" m",lt("accessBadge").textContent=D.detail?"FULL RESOLUTION \xB7 RADAR ACCESS":"RESTRICTED VIEW \xB7 2 KM LIMIT",lt("coords").textContent=_r(D.center).map(a=>a.toFixed(4)+"\xB0").join(" / ")}function ns(s){let a=D.zoom;D.zoom+=s,Wn(),s>0&&Math.abs(a-D.zoom)<.01&&!D.detail&&Le("2 km limit reached. Kuwait can share radar access.")}function Nr(){D.view=lt("country").value,D.center=Un(Kr[D.view]),D.zoom=D.detail?14:11,lt("viewTitle").textContent=D.view==="Kuwait"?"Kuwait City":D.view,Wn()}function kr(s,a=!0){rt.beginPath(),s.forEach((u,h)=>{let m=De(u);h?rt.lineTo(...m):rt.moveTo(...m)}),a&&rt.closePath()}function va(){if(!$i||!ue)return;rt.fillStyle=D.night?"#24332f":"#929f92",rt.fillRect(0,0,ue,ye);let s=De([xr[0],xr[1]]),a=De([xr[2],xr[3]]);rt.imageSmoothingEnabled=!0,D.zoom<=11?rt.drawImage($i,s[0],s[1],a[0]-s[0],a[1]-s[1]):(rt.fillStyle=D.night?"#162e3c":"#8da9ad",rt.fillRect(0,0,ue,ye)),D.night&&(rt.fillStyle="#081626aa",rt.fillRect(0,0,ue,ye)),rt.save(),rt.translate(ue/2-D.center[0]*le(),ye/2-D.center[1]*le()),rt.scale(le(),le()),rt.lineWidth=1/le(),rt.strokeStyle=D.night?"#d4c29e77":"#695f4966";for(let u of ya)D.zoom>11&&(rt.fillStyle=D.night?"#283732":"#dcd5bf",rt.fill(u,"evenodd")),rt.stroke(u);if(rt.restore(),wl(),D.zoom<11){rt.textAlign="center",rt.font="600 12px system-ui";for(let u of Bn){let h=De(Un(Kr[u]));rt.fillStyle="#eae7d5dd",rt.fillRect(h[0]-u.length*4-7,h[1]-15,u.length*8+14,23),rt.fillStyle="#34483e",rt.fillText(u.toUpperCase(),h[0],h[1])}}if(D.points.length){let u=D.points;D.tool==="road"&<("roadMode").value==="curve"&&u.length===2&&Hn?u=Hi(u[0],u[1],Hn):Hn&&(u=[...u,Hn]),kr(u,!1),rt.strokeStyle="#d3e8ae",rt.lineWidth=3,rt.setLineDash([7,5]),rt.stroke(),rt.setLineDash([]);for(let h of D.points)rt.beginPath(),rt.arc(...De(h),5,0,7),rt.fillStyle="#203c30",rt.fill(),rt.strokeStyle="#edffc9",rt.lineWidth=2,rt.stroke()}}var ya=[],zn=null,ca="",Wi;function wl(){let s=[D.zoom,D.night,D.coarse,ue,ye].join(":");if(!zn||ca!==s||ha!==D.features){zn=document.createElement("canvas"),zn.width=ue+512,zn.height=ye+512;let a=rt,u=ue,h=ye;rt=zn.getContext("2d"),ue+=512,ye+=512;for(let m of D.features)if(D.coarse){let c=De([m.x,m.y]);rt.fillStyle=m.owner===D.account?"#8ca567":"#596e65",rt.beginPath(),rt.arc(...c,Math.min(10,3+Math.log2(m.count+1)),0,7),rt.fill()}else Il(m);rt=a,ue=u,ye=h,Wi=[...D.center],ca=s,ha=D.features}rt.drawImage(zn,-256+(Wi[0]-D.center[0])*le(),-256+(Wi[1]-D.center[1])*le())}var ha;function Il(s){let a=s.points;if(!a?.length)return;let u=De(a[0]);if(s.kind==="road"){kr(a,!1);let w=Math.max(2,s.width*Xn(a[0][1])*le());rt.lineCap="round",rt.lineJoin="round",rt.strokeStyle=D.night?"#151c20":"#eee8d6",rt.lineWidth=w+3,rt.stroke(),rt.strokeStyle=D.night?"#384044":"#66716c",rt.lineWidth=w,rt.stroke(),w>7&&(rt.strokeStyle="#d9c99a",rt.lineWidth=1,rt.setLineDash([10,9]),rt.stroke(),rt.setLineDash([]));return}kr(a),rt.shadowColor="#142a2855",rt.shadowBlur=3,rt.shadowOffsetX=3,rt.shadowOffsetY=4,rt.fillStyle=s.kind==="park"?"#7c986a":s.kind==="district"?"#b7b694":D.night?"#4e5a57":"#d2c3a5",rt.fill(),rt.shadowColor="transparent",rt.shadowBlur=0,rt.shadowOffsetX=rt.shadowOffsetY=0,rt.strokeStyle="#677363",rt.lineWidth=1,rt.stroke();let h=a.map(w=>De(w)[0]),m=a.map(w=>De(w)[1]),c=Math.min(...h),v=Math.min(...m),_=Math.max(...h)-c,L=Math.max(...m)-v;if(s.kind==="building"&&_>12&&L>12&&(rt.save(),kr(a),rt.clip(),rt.drawImage(D.night?es:ts,c,v,_,L),rt.restore()),s.kind==="district"&&_>30){rt.save(),kr(a),rt.clip();let w=Math.max(12,40*Xn(a[0][1])*le()),b=0;for(let x=Math.max(v,0);x16&&s.name&&_>60&&(rt.font="10px system-ui",rt.fillStyle=D.night?"#eef0db":"#35473e",rt.textAlign="center",rt.fillText(s.name,c+_/2,v-5))}async function xn(){if(!D.account||!window.hostGate.canPlay)return;let s=++Vn;wr?.abort(),wr=new AbortController;try{if(D.demo){D.features=$r(),lt("buildCount").textContent=D.features.length.toLocaleString()+" local demo features",D.coarse=!1,ze("Local demo \xB7 saved in this browser"),Ve();return}let a=[...Ir(0,0),...Ir(ue,ye)].map(c=>Math.max(0,Math.min(1,c))),u="",h=[],m=!1;ze("Syncing shared world\u2026");do{let c=await $e("/features?"+new URLSearchParams({box:a.join(","),zoom:D.zoom,after:u}),{signal:wr.signal});if(s!==Vn)return;h.push(...c.features),m=!!c.coarse,u=c.next||""}while(u&&h.length<6e3);if(s!==Vn)return;D.features=h,D.coarse=m,ze(u?"Shared world \xB7 zoom closer for more detail":"Shared world \xB7 saved"),Ve()}catch(a){a.name!=="AbortError"&&(ze("Connection interrupted \xB7 retrying"),s===Vn&&Le(a.message))}}async function kn(){if(D.demo)return;let s=await $e("/me");D.detail&&!s.detail&&(D.features=[],D.points=[]),Object.assign(D,s),lt("countryTitle").textContent=s.account,lt("accountInfo").textContent=s.admin?"Owner access \xB7 manage your shared world":s.detail?"Radar connected. Your territory is ready.":"Standard access \xB7 2 km minimum scale.",lt("buildCount").textContent=s.counts.reduce((a,u)=>a+u.count,0).toLocaleString()+" saved developments",lt("accountBtn").textContent=s.account+" \xB7 Sign out",Wn()}async function jn(s,a=D.tool){try{if(!window.hostGate.canPlay)throw Error("The server is unavailable or not released.");if(!D.account)throw Error("Sign in first.");let u=D.admin?lt("country").value:D.account,h=aa(u,{kind:a,points:s,name:lt("buildName").value,width:Number(lt("roadWidth").value),levels:Number(lt("floors").value)},ma);ze("Saving development\u2026"),D.demo?pa([...$r(),{...h,id:`demo-${Date.now()}-${Math.random().toString(36).slice(2)}`,owner:u}]):await $e("/features",{method:"POST",body:JSON.stringify({...h,owner:u})}),D.points=[],Le("Development saved."),await xn(),D.demo||await kn()}catch(u){Le(u.message),ze("Not saved \xB7 "+u.message)}}var Nl=[["navigate","\u2196","Navigate"],["road","\u2301","Road"],["building","\u2302","House"],["tower","\u25A5","Tower"],["district","\u25A6","District"],["park","\u2667","Park"],["footprint","\u25C7","Footprint"],["erase","\u232B","Erase"]];function fa(s){D.tool=s,D.points=[],document.querySelectorAll("[data-tool]").forEach(a=>a.classList.toggle("active",a.dataset.tool===s)),lt("hint").textContent={navigate:"Drag to explore \xB7 Scroll to zoom",road:"Curve: click start, bend, then end \xB7 Esc cancels",building:"Click inside your country to place a house",tower:"Click inside your country to place a tower",district:"Click two opposite corners of a district",park:"Click corners \xB7 Enter to finish your park",footprint:"Click corners \xB7 Enter to finish your building",erase:"Click one of your builds to remove it"}[s],Ve()}async function bl(s){if(D.tool!=="navigate"){if(D.tool==="erase"){if(D.coarse){Le("Detailed selection needs radar access.");return}let a=D.features.filter(u=>D.admin||u.owner===D.account).map(u=>({f:u,d:Math.min(...u.points.map(h=>Math.hypot(...De(h).map((m,c)=>m-De(s)[c]))))})).sort((u,h)=>u.d-h.d)[0];if(a&&a.d<35)try{D.demo?pa($r().filter(u=>u.id!==a.f.id)):await $e("/features/"+a.f.id,{method:"DELETE"}),await xn(),Le("Build removed.")}catch(u){Le(u.message)}else Le("Zoom closer and click a corner of your build.");return}if(D.tool==="building"||D.tool==="tower"){D.tool==="tower"&&(lt("floors").value=20),await jn(oa(s,D.tool==="tower"?45:25,D.tool==="tower"?40:20),"building");return}if(D.points.push(s),D.tool==="road"&&(lt("roadMode").value==="straight"&&D.points.length===2&&await jn(D.points,"road"),lt("roadMode").value==="curve"&&D.points.length===3&&await jn(Hi(...D.points),"road")),D.tool==="district"&&D.points.length===2){let[a,u]=D.points;await jn([a,[u[0],a[1]],u,[a[0],u[1]]],"district")}Ve()}}ve.addEventListener("pointerdown",s=>{ve.setPointerCapture(s.pointerId);let a=ve.getBoundingClientRect();Se={x:s.clientX-a.left,y:s.clientY-a.top,center:[...D.center],moved:!1},D.tool==="road"&<("roadMode").value==="free"&&(D.points=[Ir(Se.x,Se.y)])});ve.addEventListener("pointermove",s=>{let a=ve.getBoundingClientRect(),u=s.clientX-a.left,h=s.clientY-a.top;if(Hn=Ir(u,h),Se){let m=u-Se.x,c=h-Se.y;Math.hypot(m,c)>4&&(Se.moved=!0),D.tool==="navigate"?(D.center=[Se.center[0]-m/le(),Se.center[1]-c/le()],Wn()):D.tool==="road"&<("roadMode").value==="free"&&D.points.length<999&&Math.hypot(...De(D.points.at(-1)).map((v,_)=>v-[u,h][_]))>6&&D.points.push(Hn)}Ve()});ve.addEventListener("pointerup",s=>{if(!Se)return;let a=ve.getBoundingClientRect(),u=Ir(s.clientX-a.left,s.clientY-a.top);D.tool==="road"&<("roadMode").value==="free"?D.points.length>=2&&jn([...D.points],"road"):Se.moved||bl(u),Se=null});ve.addEventListener("pointercancel",()=>{Se=null,D.points=[],Ve()});ve.addEventListener("wheel",s=>{s.preventDefault(),ns(s.deltaY<0?.35:-.35)},{passive:!1});function _a(){["park","footprint"].includes(D.tool)&&D.points.length>=3?jn([...D.points],D.tool==="park"?"park":"building"):Le("Add at least three corners for a footprint.")}lt("finish").onclick=_a;lt("cancel").onclick=()=>{D.points=[],Ve()};window.addEventListener("keydown",s=>{window.hostGate.canPlay&&(["INPUT","SELECT","TEXTAREA"].includes(s.target.tagName)||document.querySelector("dialog[open]")||(s.key==="Escape"&<("cancel").click(),s.key==="Enter"&&_a(),s.key.toLowerCase()==="h"&&Nr()))});lt("zoomIn").onclick=()=>ns(.5);lt("zoomOut").onclick=()=>ns(-.5);lt("home").onclick=Nr;lt("country").onchange=Nr;lt("roadMode").onchange=()=>{D.points=[],Ve()};lt("nightBtn").onclick=()=>{D.night=!D.night,lt("nightBtn").lastElementChild.textContent=D.night?"On":"Off",Ve()};function xa(s){return lt("panelTitle").textContent=s,lt("panelBody").replaceChildren(),lt("panel").showModal(),lt("panelBody")}lt("closePanel").onclick=()=>lt("panel").close();function Er(s,a,u,h=""){let m=document.createElement("button");return m.textContent=a,m.className=h,m.onclick=async()=>{m.disabled=!0;try{await u()}catch(c){Le(c.message)}finally{m.disabled=!1}},s.append(m),m}lt("radarBtn").onclick=()=>{let s=xa("Radar sharing");if(D.demo||!D.admin&&D.account!=="Kuwait"){s.textContent=D.detail?"Your account has full radar access.":"Kuwait can grant your country access beyond the 2 km scale.";return}let a=document.createElement("p");a.textContent="Grant closer zoom and detailed buildings. Revoking access takes effect on the next live update.",s.append(a);for(let u of Bn.filter(h=>h!=="Kuwait")){let h=document.createElement("div");h.className="radar-row";let m=document.createElement("span");m.textContent=u,h.append(m);let c=D.radar.includes(u);Er(h,c?"Revoke":"Share radar",async()=>{await $e("/radar",{method:"POST",body:JSON.stringify({account:u,enabled:!c})}),await kn(),lt("panel").close(),lt("radarBtn").click()}),s.append(h)}};function ga(s,a){let u=document.createElement("a"),h=URL.createObjectURL(new Blob([JSON.stringify(s)],{type:"application/json"}));u.href=h,u.download=a,u.click(),setTimeout(()=>URL.revokeObjectURL(h),2e3)}lt("ownerBtn").onclick=()=>{let s=xa("Owner controls");if(D.demo){Er(s,"Export local demo",()=>ga($r(),"world-demo.json"));return}if(!D.admin){s.textContent="Sign in with the Owner PIN to export, restore, or reset world data. Country PINs are managed in the private passwords.json file.";return}Er(s,"Download world backup",async()=>{let c=[],v="";do{let _=await $e("/admin/export?"+new URLSearchParams({after:v}));c.push(..._.features),v=_.next||""}while(v);ga(c,"world-backup.json")});let a=document.createElement("p");a.textContent="Restore adds validated builds. Export before resetting. Changing a PIN in your config/passwords.json on the host signs that account out without deleting its builds.",s.append(a);let u=document.createElement("input");u.type="file",u.accept=".json",s.append(u),Er(s,"Restore selected JSON backup",async()=>{if(!u.files[0])throw Error("Choose a backup.");let c=JSON.parse(await u.files[0].text());if(!Array.isArray(c))throw Error("Expected an array of developments.");let v=0;for(let _ of c)await $e("/features",{method:"POST",body:JSON.stringify(_)}),v++,ze(`Restoring ${v}/${c.length}`);Le(`Restored ${v} developments.`),xn()});let h=document.createElement("select");for(let c of[...Bn,"ALL"])h.add(new Option(c,c));s.append(h);let m=document.createElement("input");m.placeholder="Type RESET Kuwait (or chosen country)",s.append(m),Er(s,"Reset selected territory",async()=>{await $e("/admin/reset",{method:"POST",body:JSON.stringify({country:h.value,confirm:m.value})}),await xn(),await kn(),Le("Selected territory reset.")},"danger")};lt("loginForm").onsubmit=async s=>{if(s.preventDefault(),lt("loginError").textContent="",!Qi.apiUrl){lt("loginError").textContent="Enter the host server address on the connection screen.";return}let a=s.submitter;a.disabled=!0;try{let u=await $e("/login",{method:"POST",body:JSON.stringify({account:lt("loginCountry").value,pin:lt("pin").value})});D.token=u.token,Qr(),localStorage.setItem("wa-token",u.token),D.demo=!1,lt("pin").value="",await kn(),lt("country").value=D.admin?"Kuwait":D.account,Nr(),lt("login").close()}catch(u){lt("loginError").textContent=u.message}finally{a.disabled=!1}};lt("accountBtn").onclick=async()=>{if(D.token)try{await $e("/logout",{method:"POST"})}catch{}localStorage.removeItem("wa-token"),D.token=null,Xe?.close(),D.account=null,D.demo=!1,D.detail=!1,D.features=[],D.points=[],wr?.abort(),Vn++,Wn(),lt("login").showModal()};async function Jr(s,a){let u;for(let h=0;h<3;h++)try{let m=await fetch(s,{cache:h?"reload":"default",signal:AbortSignal.timeout(15e3)});if(!m.ok)throw Error("HTTP "+m.status);if(a==="json")return await m.json();let c=await m.blob(),v=URL.createObjectURL(c);try{let _=new Image;return _.src=v,await _.decode(),_}finally{URL.revokeObjectURL(v)}}catch(m){u=m}throw Error("Could not load "+s+" ("+u.message+"). Check your connection and retry.")}var Zi=s=>Jr(s,"image"),Xe=null,da=null,Ki=!1,Ji=!1;async function rs(){if(Ki){Ji=!0;return}if(!(!D.token||!window.hostGate.canPlay)){Ki=!0;try{await kn(),await xn()}catch(s){["Enter your country PIN."].includes(s.message)||Le(s.message)}finally{Ki=!1,Ji&&(Ji=!1,rs())}}}function Qr(){if(!D.token||!window.hostGate.canPlay||Xe&&[0,1].includes(Xe.readyState))return;let s=new URL(window.hostGate.apiUrl+"/live",location.href);s.protocol=s.protocol==="https:"?"wss:":"ws:";let a=new WebSocket(s);Xe=a,a.onopen=()=>a.send(JSON.stringify({token:D.token})),a.onmessage=u=>{try{let h=JSON.parse(u.data);["world","access","connected"].includes(h.type)&&(clearTimeout(da),da=setTimeout(async()=>{await window.hostGate.check(),rs()},120))}catch{}},a.onclose=()=>{Xe===a&&(Xe=null),D.token&&(ze("Live connection interrupted \xB7 reconnecting"),window.hostGate.check())},a.onerror=()=>a.close()}addEventListener("hoststate",s=>{if(s.detail.state==="ready")D.token?(Qr(),rs()):lt("login").open||lt("login").showModal();else{Xe?.close(),Xe=null;for(let a of document.querySelectorAll("dialog[open]"))a.close();wr?.abort(),Vn++,D.features=[],D.points=[],Ve()}});addEventListener("countrylist",s=>{for(let a of s.detail){let u=[...lt("loginCountry").options].find(h=>h.value===a.name);u&&(u.textContent=a.name+(a.enabled?"":" \u2014 needs enabling"))}});async function Sl(){try{for(let v of Bn)lt("country").add(new Option(v,v)),lt("loginCountry").add(new Option(v,v));lt("loginCountry").add(new Option("Owner","Owner")),lt("country").value="Kuwait";for(let[v,_,L]of Nl){let w=document.createElement("button");w.dataset.tool=v;let b=document.createElement("b");b.textContent=_,w.append(b,document.createTextNode(L)),w.onclick=()=>fa(v),lt("tools").append(w)}fa("navigate");let[s,a,u,h,m,c]=await Promise.all([Jr("config.json","json"),Jr("assets/borders.json","json"),Zi("assets/terrain.png"),Jr("assets/terrain.json","json"),Zi("assets/sprites/villa_0.png"),Zi("assets/sprites/villa_0_night.png")]);Qi={...s,apiUrl:window.hostGate.apiUrl},$i=u,xr=h.world_bounds,ts=m,es=c,ma=Object.fromEntries(a.features.map(v=>[v.properties.name,v.geometry]));for(let v of a.features){let _=new Path2D;for(let L of v.geometry.type==="Polygon"?[v.geometry.coordinates]:v.geometry.coordinates)for(let w of L)w.forEach((b,x)=>x?_.lineTo(...Un(b)):_.moveTo(...Un(b))),_.closePath();ya.push(_)}if(new ResizeObserver(()=>{ue=ve.clientWidth,ye=ve.clientHeight;let v=Math.min(devicePixelRatio,2);ve.width=ue*v,ve.height=ye*v,rt.setTransform(v,0,0,v,0,0),Wn()}).observe(ve),window.hostGate.assetsReady(),await window.hostGate.ready,D.token&&Qi.apiUrl)try{await kn(),Qr(),lt("country").value=D.admin?"Kuwait":D.account,Nr()}catch{window.hostGate.canPlay&&!lt("login").open&<("login").showModal()}else lt("login").open||lt("login").showModal(),ze("Ready \xB7 sign in to your country");setInterval(async()=>{if(!(document.hidden||!D.token||!window.hostGate.canPlay))try{(!Xe||Xe.readyState!==1)&&(Qr(),await kn(),await xn())}catch{ze("Connection interrupted \xB7 retrying")}},5e3)}catch(s){ze("Unable to load atlas"),window.hostGate.assetError(s.message)}}Sl();})(); /*! Bundled license information: polygon-clipping/dist/polygon-clipping.umd.js: (** * splaytree v3.1.2 * Fast Splay tree for Node and browser * * @author Alexander Milevski * @license MIT * @preserve *) (*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** *) */