404: This page could not be found.MapGenius – Explore maps for Tribes 2
404
This page could not be found.
\ No newline at end of file
+404: This page could not be found.MapGenius – Explore maps for Tribes 2
404
This page could not be found.
\ No newline at end of file
diff --git a/docs/404/index.html b/docs/404/index.html
index 3a1b27d1..5a4babc0 100644
--- a/docs/404/index.html
+++ b/docs/404/index.html
@@ -1 +1 @@
-404: This page could not be found.MapGenius – Explore maps for Tribes 2
404
This page could not be found.
\ No newline at end of file
+404: This page could not be found.MapGenius – Explore maps for Tribes 2
404
This page could not be found.
\ No newline at end of file
diff --git a/docs/__next.__PAGE__.txt b/docs/__next.__PAGE__.txt
index e53ec08b..b48bed34 100644
--- a/docs/__next.__PAGE__.txt
+++ b/docs/__next.__PAGE__.txt
@@ -1,9 +1,9 @@
1:"$Sreact.fragment"
2:I[47257,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ClientPageRoot"]
-3:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/74f04865c68de700.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
+3:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/15f5b04504a3a132.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
6:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
7:"$Sreact.suspense"
-0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/74f04865c68de700.js","async":true}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","async":true}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","async":true}],["$","script","script-4",{"src":"/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","async":true}],["$","script","script-5",{"src":"/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
+0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/15f5b04504a3a132.js","async":true}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","async":true}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","async":true}],["$","script","script-4",{"src":"/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","async":true}],["$","script","script-5",{"src":"/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
4:{}
5:"$0:rsc:props:children:0:props:serverProvidedParams:params"
8:null
diff --git a/docs/__next._full.txt b/docs/__next._full.txt
index 891df29f..549e3096 100644
--- a/docs/__next._full.txt
+++ b/docs/__next._full.txt
@@ -3,14 +3,14 @@
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
5:I[47257,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ClientPageRoot"]
-6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/74f04865c68de700.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
+6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/15f5b04504a3a132.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
9:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
a:"$Sreact.suspense"
c:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
e:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
10:I[68027,[],"default"]
-:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
-0:{"P":null,"b":"WsfG8iTCAMPA7qTCB_D8T","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L5",null,{"Component":"$6","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@7","$@8"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/74f04865c68de700.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","async":true,"nonce":"$undefined"}],["$","script","script-4",{"src":"/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","async":true,"nonce":"$undefined"}],["$","script","script-5",{"src":"/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lc",null,{"children":"$Ld"}],["$","div",null,{"hidden":true,"children":["$","$Le",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$Lf"}]}]}],null]}],false]],"m":"$undefined","G":["$10",[]],"S":true}
+:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
+0:{"P":null,"b":"-NrDAGL0vu_8RrgSU0FFY","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/284925ee1f24c201.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L5",null,{"Component":"$6","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@7","$@8"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/15f5b04504a3a132.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","async":true,"nonce":"$undefined"}],["$","script","script-4",{"src":"/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","async":true,"nonce":"$undefined"}],["$","script","script-5",{"src":"/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lc",null,{"children":"$Ld"}],["$","div",null,{"hidden":true,"children":["$","$Le",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$Lf"}]}]}],null]}],false]],"m":"$undefined","G":["$10",[]],"S":true}
7:{}
8:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
d:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
diff --git a/docs/__next._head.txt b/docs/__next._head.txt
index 1ada6f7b..bfcb8161 100644
--- a/docs/__next._head.txt
+++ b/docs/__next._head.txt
@@ -3,4 +3,4 @@
3:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
4:"$Sreact.suspense"
5:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
-0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"MapGenius – Explore maps for Tribes 2"}],["$","meta","1",{"name":"description","content":"Tribes 2 forever."}],["$","link","2",{"rel":"icon","href":"/t2-mapper/icon.png?icon.2911bba1.png","sizes":"108x128","type":"image/png"}],["$","$L5","3",{}]]}]}]}],null]}],"loading":null,"isPartial":false}
+0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"MapGenius – Explore maps for Tribes 2"}],["$","meta","1",{"name":"description","content":"Tribes 2 forever."}],["$","link","2",{"rel":"icon","href":"/t2-mapper/icon.png?icon.2911bba1.png","sizes":"108x128","type":"image/png"}],["$","$L5","3",{}]]}]}]}],null]}],"loading":null,"isPartial":false}
diff --git a/docs/__next._index.txt b/docs/__next._index.txt
index 8c39c785..eca24451 100644
--- a/docs/__next._index.txt
+++ b/docs/__next._index.txt
@@ -2,5 +2,5 @@
2:I[12985,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js"],"NuqsAdapter"]
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
-:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
-0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","precedence":"next"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]}]]}],"loading":null,"isPartial":false}
+:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
+0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/284925ee1f24c201.css","precedence":"next"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]}]]}],"loading":null,"isPartial":false}
diff --git a/docs/__next._tree.txt b/docs/__next._tree.txt
index 4d1e960c..ccabecd6 100644
--- a/docs/__next._tree.txt
+++ b/docs/__next._tree.txt
@@ -1,2 +1,2 @@
-:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
-0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
+:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
+0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
diff --git a/docs/_next/static/WsfG8iTCAMPA7qTCB_D8T/_buildManifest.js b/docs/_next/static/-NrDAGL0vu_8RrgSU0FFY/_buildManifest.js
similarity index 100%
rename from docs/_next/static/WsfG8iTCAMPA7qTCB_D8T/_buildManifest.js
rename to docs/_next/static/-NrDAGL0vu_8RrgSU0FFY/_buildManifest.js
diff --git a/docs/_next/static/WsfG8iTCAMPA7qTCB_D8T/_clientMiddlewareManifest.json b/docs/_next/static/-NrDAGL0vu_8RrgSU0FFY/_clientMiddlewareManifest.json
similarity index 100%
rename from docs/_next/static/WsfG8iTCAMPA7qTCB_D8T/_clientMiddlewareManifest.json
rename to docs/_next/static/-NrDAGL0vu_8RrgSU0FFY/_clientMiddlewareManifest.json
diff --git a/docs/_next/static/WsfG8iTCAMPA7qTCB_D8T/_ssgManifest.js b/docs/_next/static/-NrDAGL0vu_8RrgSU0FFY/_ssgManifest.js
similarity index 100%
rename from docs/_next/static/WsfG8iTCAMPA7qTCB_D8T/_ssgManifest.js
rename to docs/_next/static/-NrDAGL0vu_8RrgSU0FFY/_ssgManifest.js
diff --git a/docs/_next/static/chunks/0be79f7f5e0597a7.css b/docs/_next/static/chunks/0be79f7f5e0597a7.css
new file mode 100644
index 00000000..9103a7c8
--- /dev/null
+++ b/docs/_next/static/chunks/0be79f7f5e0597a7.css
@@ -0,0 +1,2 @@
+.GuiMarkup-module__CLgNnq__GuiMarkup{white-space:pre-wrap;font-size:14px;line-height:1.5}.GuiMarkup-module__CLgNnq__GuiMarkup a{color:inherit;text-decoration:underline}.GuiMarkup-module__CLgNnq__Bullet{margin-left:.5em;margin-right:.5em}
+.MapInfoDialog-module__m0lXla__Dialog{color:#bccec3;-webkit-user-select:text;user-select:text;-webkit-touch-callout:default;background:#142526cc;border:1px solid #41838b99;border-radius:4px;outline:none;grid-template-rows:1fr auto;grid-template-columns:100%;width:800px;max-width:calc(100dvw - 40px);height:600px;max-height:calc(100dvh - 40px);font-size:14px;line-height:1.5;display:grid;position:relative;overflow:hidden;box-shadow:0 0 50px #0006,inset 0 0 60px #01070d99}.MapInfoDialog-module__m0lXla__Overlay{z-index:10;background:#000000b3;justify-content:center;align-items:center;padding:20px;display:flex;position:fixed;inset:0}.MapInfoDialog-module__m0lXla__Body{grid-template-rows:100%;grid-template-columns:1fr auto;min-height:0;display:grid;overflow:hidden}.MapInfoDialog-module__m0lXla__Left{padding:24px 28px;overflow-y:auto}.MapInfoDialog-module__m0lXla__PreviewImage{border-left:1px solid #00bedc40;height:100%;display:block}.MapInfoDialog-module__m0lXla__PreviewImageFloating{float:right;clear:right;width:auto;max-width:30%;max-height:260px;margin:0 0 16px 20px;display:block}.MapInfoDialog-module__m0lXla__Title{color:#7dffff;text-shadow:0 1px 6px #0006;margin:0;font-size:26px;font-weight:500}.MapInfoDialog-module__m0lXla__MapMeta{flex-wrap:wrap;gap:8px 16px;margin-bottom:4px;font-size:15px;font-weight:400;display:flex}.MapInfoDialog-module__m0lXla__MapPlanet{color:#dbcaa8b3}.MapInfoDialog-module__m0lXla__MapQuote{border-left:2px solid #00bedc59;margin:16px 0;padding:0 0 0 14px;font-style:italic}.MapInfoDialog-module__m0lXla__MapQuote p{white-space:pre-line;margin:0 0 4px}.MapInfoDialog-module__m0lXla__MapQuote cite{color:#ffffff73;font-size:12px;font-style:normal;display:block}.MapInfoDialog-module__m0lXla__MapBlurb{margin:0 0 16px;font-size:13px}.MapInfoDialog-module__m0lXla__Section{margin-top:20px}.MapInfoDialog-module__m0lXla__SectionTitle{color:#7dffff;letter-spacing:.04em;text-transform:uppercase;text-shadow:0 0 16px #00d2f040;margin:0 0 8px;font-size:16px;font-weight:500}.MapInfoDialog-module__m0lXla__MusicTrack{color:#cad0ac80;align-items:center;gap:6px;margin-top:16px;font-size:14px;font-style:italic;display:flex}.MapInfoDialog-module__m0lXla__MusicTrack[data-playing=true]{color:#f7fdd8b3}.MapInfoDialog-module__m0lXla__MusicButton{cursor:pointer;color:#557663;opacity:.5;background:0 0;border:0;border-radius:20px;flex-shrink:0;place-content:center;width:32px;height:32px;padding:0;font-size:20px;font-style:normal;line-height:1;display:grid}.MapInfoDialog-module__m0lXla__MusicTrack[data-playing=true] .MapInfoDialog-module__m0lXla__MusicButton{color:#6dffaa;opacity:1}.MapInfoDialog-module__m0lXla__MusicTrack[data-playing=true] .MapInfoDialog-module__m0lXla__MusicButton:hover{opacity:.7}.MapInfoDialog-module__m0lXla__Footer{background:#021415b3;border-top:1px solid #00bedc40;flex-shrink:0;align-items:center;gap:16px;padding:10px 12px;display:flex}.MapInfoDialog-module__m0lXla__CloseButton{color:#9aefe1e6;text-shadow:0 -1px #00000080;cursor:pointer;background:linear-gradient(#29ac9cb3,#005041b3);border:1px solid #29615499;border-top-color:#65b9b080;border-radius:3px;padding:4px 18px;font-size:14px;font-weight:500;box-shadow:inset 0 1px #78dcc333,inset 0 -1px #0000004d,0 2px 4px #0006}.MapInfoDialog-module__m0lXla__CloseButton:active{transform:translateY(1px)}.MapInfoDialog-module__m0lXla__Hint{color:#c9dcd84d;margin-left:auto;font-size:12px}.MapInfoDialog-module__m0lXla__MusicTrackName{text-transform:capitalize}@media (max-width:719px){.MapInfoDialog-module__m0lXla__Body{display:block;overflow:auto}.MapInfoDialog-module__m0lXla__Hint{display:none}.MapInfoDialog-module__m0lXla__Left{width:100%;height:auto;margin:0;padding:16px 20px;overflow:auto}.MapInfoDialog-module__m0lXla__PreviewImage{width:auto;height:auto;margin:16px auto}.MapInfoDialog-module__m0lXla__CloseButton{width:220px;height:36px;margin:0 auto}}
diff --git a/docs/_next/static/chunks/74f04865c68de700.js b/docs/_next/static/chunks/15f5b04504a3a132.js
similarity index 99%
rename from docs/_next/static/chunks/74f04865c68de700.js
rename to docs/_next/static/chunks/15f5b04504a3a132.js
index c7087e7d..d8dbe501 100644
--- a/docs/_next/static/chunks/74f04865c68de700.js
+++ b/docs/_next/static/chunks/15f5b04504a3a132.js
@@ -208,4 +208,4 @@
void main() {
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
- `}),[P]);return a.createElement("group",(0,c.default)({},L,{ref:q}),E&&!et&&a.createElement("mesh",{castShadow:T,receiveShadow:w,ref:Q},D||a.createElement("planeGeometry",null),O||a.createElement("shaderMaterial",{side:s.DoubleSide,vertexShader:ea.vertexShader,fragmentShader:ea.fragmentShader})))});e.s(["Html",()=>b],60099);let F=[0,0,0],S=(0,a.memo)(function(e){let t,r,c,u,f,d=(0,o.c)(19),{children:m,color:g,position:h,opacity:v}=e,p=void 0===g?"white":g,x=void 0===h?F:h,y=void 0===v?"fadeWithDistance":v,S="fadeWithDistance"===y,M=(0,a.useRef)(null),P=function(e){let t,r,i=(0,o.c)(3),{camera:c}=(0,l.useThree)(),u=(0,a.useRef)(null),f=(r=(0,a.useRef)(null),(0,n.useFrame)(()=>{e.current&&(r.current??=new s.Vector3,e.current.getWorldPosition(r.current))}),r);return i[0]!==c||i[1]!==f?(t=()=>{f.current?u.current=c.position.distanceTo(f.current):u.current=null},i[0]=c,i[1]=f,i[2]=t):t=i[2],(0,n.useFrame)(t),u}(M),[E,_]=(0,a.useState)(0!==y),T=(0,a.useRef)(null);return d[0]!==P||d[1]!==S?(t=()=>{if(S&&T.current&&null!=P.current){let e=Math.max(0,Math.min(1,1-P.current/200));T.current.style.opacity=e.toString()}},d[0]=P,d[1]=S,d[2]=t):t=d[2],d[3]!==P||d[4]!==S||d[5]!==E?(r=[E,S,P],d[3]=P,d[4]=S,d[5]=E,d[6]=r):r=d[6],(0,a.useEffect)(t,r),d[7]!==P||d[8]!==S||d[9]!==E||d[10]!==y?(c=()=>{if(S){let e=P.current,t=null!=e&&e<200;if(E!==t&&_(t),T.current&&t){let t=Math.max(0,Math.min(1,1-e/200));T.current.style.opacity=t.toString()}}else _(0!==y),T.current&&(T.current.style.opacity=y.toString())},d[7]=P,d[8]=S,d[9]=E,d[10]=y,d[11]=c):c=d[11],(0,n.useFrame)(c),d[12]!==m||d[13]!==p||d[14]!==E||d[15]!==x?(u=E?(0,i.jsx)(b,{position:x,center:!0,children:(0,i.jsx)("div",{ref:T,className:"StaticShapeLabel",style:{color:p},children:m})}):null,d[12]=m,d[13]=p,d[14]=E,d[15]=x,d[16]=u):u=d[16],d[17]!==u?(f=(0,i.jsx)("group",{ref:M,children:u}),d[17]=u,d[18]=f):f=d[18],f});e.s(["FloatingLabel",0,S],89887)},51434,e=>{"use strict";var t=e.i(43476),r=e.i(932),i=e.i(71645),o=e.i(73949),a=e.i(90072);let n=(0,i.createContext)(void 0);function l(e){let l,c,u,f,d=(0,r.c)(7),{children:m}=e,{camera:g}=(0,o.useThree)();d[0]===Symbol.for("react.memo_cache_sentinel")?(l={audioLoader:null,audioListener:null},d[0]=l):l=d[0];let[h,v]=(0,i.useState)(l);return d[1]!==g?(c=()=>{let e=new a.AudioLoader,t=g.children.find(s);t||(t=new a.AudioListener,g.add(t)),v({audioLoader:e,audioListener:t})},u=[g],d[1]=g,d[2]=c,d[3]=u):(c=d[2],u=d[3]),(0,i.useEffect)(c,u),d[4]!==h||d[5]!==m?(f=(0,t.jsx)(n.Provider,{value:h,children:m}),d[4]=h,d[5]=m,d[6]=f):f=d[6],f}function s(e){return e instanceof a.AudioListener}function c(){let e=(0,i.useContext)(n);if(void 0===e)throw Error("useAudio must be used within AudioProvider");return e}e.s(["AudioProvider",()=>l,"useAudio",()=>c])},61921,e=>{e.v(t=>Promise.all(["static/chunks/cb4089eec9313f48.js"].map(t=>e.l(t))).then(()=>t(29055)))},25147,e=>{e.v(t=>Promise.all(["static/chunks/4e5626f3eeee0985.js"].map(t=>e.l(t))).then(()=>t(63724)))},18599,e=>{e.v(t=>Promise.all(["static/chunks/6e74e9455d83b68c.js"].map(t=>e.l(t))).then(()=>t(42585)))},84968,e=>{e.v(t=>Promise.all(["static/chunks/70bf3e06d5674fac.js"].map(t=>e.l(t))).then(()=>t(90208)))},59197,e=>{e.v(t=>Promise.all(["static/chunks/dd460a24fc1df5f8.js"].map(t=>e.l(t))).then(()=>t(94247)))}]);
\ No newline at end of file
+ `}),[P]);return a.createElement("group",(0,c.default)({},L,{ref:q}),E&&!et&&a.createElement("mesh",{castShadow:T,receiveShadow:w,ref:Q},D||a.createElement("planeGeometry",null),O||a.createElement("shaderMaterial",{side:s.DoubleSide,vertexShader:ea.vertexShader,fragmentShader:ea.fragmentShader})))});e.s(["Html",()=>b],60099);let F=[0,0,0],S=(0,a.memo)(function(e){let t,r,c,u,f,d=(0,o.c)(19),{children:m,color:g,position:h,opacity:v}=e,p=void 0===g?"white":g,x=void 0===h?F:h,y=void 0===v?"fadeWithDistance":v,S="fadeWithDistance"===y,M=(0,a.useRef)(null),P=function(e){let t,r,i=(0,o.c)(3),{camera:c}=(0,l.useThree)(),u=(0,a.useRef)(null),f=(r=(0,a.useRef)(null),(0,n.useFrame)(()=>{e.current&&(r.current??=new s.Vector3,e.current.getWorldPosition(r.current))}),r);return i[0]!==c||i[1]!==f?(t=()=>{f.current?u.current=c.position.distanceTo(f.current):u.current=null},i[0]=c,i[1]=f,i[2]=t):t=i[2],(0,n.useFrame)(t),u}(M),[E,_]=(0,a.useState)(0!==y),T=(0,a.useRef)(null);return d[0]!==P||d[1]!==S?(t=()=>{if(S&&T.current&&null!=P.current){let e=Math.max(0,Math.min(1,1-P.current/200));T.current.style.opacity=e.toString()}},d[0]=P,d[1]=S,d[2]=t):t=d[2],d[3]!==P||d[4]!==S||d[5]!==E?(r=[E,S,P],d[3]=P,d[4]=S,d[5]=E,d[6]=r):r=d[6],(0,a.useEffect)(t,r),d[7]!==P||d[8]!==S||d[9]!==E||d[10]!==y?(c=()=>{if(S){let e=P.current,t=null!=e&&e<200;if(E!==t&&_(t),T.current&&t){let t=Math.max(0,Math.min(1,1-e/200));T.current.style.opacity=t.toString()}}else _(0!==y),T.current&&(T.current.style.opacity=y.toString())},d[7]=P,d[8]=S,d[9]=E,d[10]=y,d[11]=c):c=d[11],(0,n.useFrame)(c),d[12]!==m||d[13]!==p||d[14]!==E||d[15]!==x?(u=E?(0,i.jsx)(b,{position:x,center:!0,children:(0,i.jsx)("div",{ref:T,className:"StaticShapeLabel",style:{color:p},children:m})}):null,d[12]=m,d[13]=p,d[14]=E,d[15]=x,d[16]=u):u=d[16],d[17]!==u?(f=(0,i.jsx)("group",{ref:M,children:u}),d[17]=u,d[18]=f):f=d[18],f});e.s(["FloatingLabel",0,S],89887)},51434,e=>{"use strict";var t=e.i(43476),r=e.i(932),i=e.i(71645),o=e.i(73949),a=e.i(90072);let n=(0,i.createContext)(void 0);function l(e){let l,c,u,f,d=(0,r.c)(7),{children:m}=e,{camera:g}=(0,o.useThree)();d[0]===Symbol.for("react.memo_cache_sentinel")?(l={audioLoader:null,audioListener:null},d[0]=l):l=d[0];let[h,v]=(0,i.useState)(l);return d[1]!==g?(c=()=>{let e=new a.AudioLoader,t=g.children.find(s);t||(t=new a.AudioListener,g.add(t)),v({audioLoader:e,audioListener:t})},u=[g],d[1]=g,d[2]=c,d[3]=u):(c=d[2],u=d[3]),(0,i.useEffect)(c,u),d[4]!==h||d[5]!==m?(f=(0,t.jsx)(n.Provider,{value:h,children:m}),d[4]=h,d[5]=m,d[6]=f):f=d[6],f}function s(e){return e instanceof a.AudioListener}function c(){let e=(0,i.useContext)(n);if(void 0===e)throw Error("useAudio must be used within AudioProvider");return e}e.s(["AudioProvider",()=>l,"useAudio",()=>c])},61921,e=>{e.v(t=>Promise.all(["static/chunks/cb4089eec9313f48.js"].map(t=>e.l(t))).then(()=>t(29055)))},25147,e=>{e.v(t=>Promise.all(["static/chunks/4e5626f3eeee0985.js"].map(t=>e.l(t))).then(()=>t(63724)))},18599,e=>{e.v(t=>Promise.all(["static/chunks/6e74e9455d83b68c.js"].map(t=>e.l(t))).then(()=>t(42585)))},84968,e=>{e.v(t=>Promise.all(["static/chunks/70bf3e06d5674fac.js"].map(t=>e.l(t))).then(()=>t(90208)))},59197,e=>{e.v(t=>Promise.all(["static/chunks/0be79f7f5e0597a7.css","static/chunks/1cf33c843f96e1c9.js"].map(t=>e.l(t))).then(()=>t(94247)))}]);
\ No newline at end of file
diff --git a/docs/_next/static/chunks/1cf33c843f96e1c9.js b/docs/_next/static/chunks/1cf33c843f96e1c9.js
new file mode 100644
index 00000000..f20da4c4
--- /dev/null
+++ b/docs/_next/static/chunks/1cf33c843f96e1c9.js
@@ -0,0 +1 @@
+(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,66438,e=>{e.v({Bullet:"GuiMarkup-module__CLgNnq__Bullet",GuiMarkup:"GuiMarkup-module__CLgNnq__GuiMarkup"})},41973,e=>{e.v({Body:"MapInfoDialog-module__m0lXla__Body",CloseButton:"MapInfoDialog-module__m0lXla__CloseButton",Dialog:"MapInfoDialog-module__m0lXla__Dialog",Footer:"MapInfoDialog-module__m0lXla__Footer",Hint:"MapInfoDialog-module__m0lXla__Hint",Left:"MapInfoDialog-module__m0lXla__Left",MapBlurb:"MapInfoDialog-module__m0lXla__MapBlurb",MapMeta:"MapInfoDialog-module__m0lXla__MapMeta",MapPlanet:"MapInfoDialog-module__m0lXla__MapPlanet",MapQuote:"MapInfoDialog-module__m0lXla__MapQuote",MusicButton:"MapInfoDialog-module__m0lXla__MusicButton",MusicTrack:"MapInfoDialog-module__m0lXla__MusicTrack",MusicTrackName:"MapInfoDialog-module__m0lXla__MusicTrackName",Overlay:"MapInfoDialog-module__m0lXla__Overlay",PreviewImage:"MapInfoDialog-module__m0lXla__PreviewImage",PreviewImageFloating:"MapInfoDialog-module__m0lXla__PreviewImageFloating",Section:"MapInfoDialog-module__m0lXla__Section",SectionTitle:"MapInfoDialog-module__m0lXla__SectionTitle",Title:"MapInfoDialog-module__m0lXla__Title"})},94247,e=>{"use strict";var t=e.i(43476),a=e.i(932),l=e.i(71645),n=e.i(11152),r=e.i(66027),i=e.i(12979),s=e.i(91996),o=e.i(66438);let u=new Set(["spop","spush","lmargin","font","color","bitmap","a","/a"]),c=new Map;function m(e){let l,n=(0,a.c)(5),{name:r}=e;n[0]!==r?(l=function(e){let t;if(c.has(e))return c.get(e);try{t=(0,i.getUrlForPath)((0,s.getStandardTextureResourceKey)(`textures/gui/${e}`))}catch{t=null}return c.set(e,t),t}(r),n[0]=r,n[1]=l):l=n[1];let u=l;if(u){let e;return n[2]!==u?(e=(0,t.jsx)("img",{src:u,alt:"",className:o.default.Bitmap}),n[2]=u,n[3]=e):e=n[3],e}if(/bullet/i.test(r)){let e;return n[4]===Symbol.for("react.memo_cache_sentinel")?(e=(0,t.jsx)("span",{className:o.default.Bullet,children:"•"}),n[4]=e):e=n[4],e}return null}let p=/<(?:font|color|bitmap|just|lmargin|a):/i;function d(e){let n,r,i=(0,a.c)(4),{markup:s}=e;i[0]!==s?(n=function(e){let a=e.split(/<([^><]+)>/g).map((e,t)=>{if(t%2==0)return e?{type:"text",value:e}:null;{let[t,...a]=e.split(":");return u.has(t.toLowerCase())?{type:"tag",name:t,args:a}:{type:"text",value:`<${e}>`}}}).filter(e=>null!=e),n={type:"span",source:"root",style:{},children:[]},r=n,i=[r],s=e=>null!=e.children&&e.children.some(e=>"string"==typeof e||s(e));for(let e of a)switch(e.type){case"text":r.children.push(e.value);break;case"tag":switch(e.name){case"spush":{let e={type:"span",source:"spush",style:{},children:[]};r.children.push(e),r=e,i.push(r);break}case"spop":if("root"!==r.source){let e=i.pop();for(;"spush"!==e.source;)e=i.pop();r=i[i.length-1]}break;case"lmargin":break;case"font":{let t=function(e){let[t,a]=e;return{fontDescription:t,fontSize:a?Math.max(11,Math.min(parseInt(a.trim(),10),16)):void 0}}(e.args).fontSize;if(s(r)){let e={type:"span",source:"spush",style:{fontSize:t},children:[]};r.children.push(e),r=e,i.push(r)}else r.style.fontSize=t;break}case"color":if(s(r)){let t={type:"span",source:"spush",style:{color:`#${e.args[0].trim()}`},children:[]};r.children.push(t),r=t,i.push(r)}else r.style.color=`#${e.args[0].trim()}`;break;case"bitmap":{let t={type:"bitmap",value:e.args[0]};r.children.push(t);break}case"a":{let t=e.args[0].trim().split(" "),a=2===t.length&&"wwwlink"===t[0]?t[1]:t[0],l={type:"a",source:"a",value:`http://${a}`,style:{},children:[]};r.children.push(l),r=l,i.push(r);break}case"/a":{let e=i.pop();for(;"a"!==e.source;)e=i.pop();r=i[i.length-1]}}}return function e(a){switch(a.type){case"span":return l.default.createElement("span",{style:0===Object.keys(a.style).length?void 0:a.style},...a.children.map(t=>"string"==typeof t?t:e(t)));case"a":return l.default.createElement("a",{href:a.value,style:0===Object.keys(a.style).length?void 0:a.style,rel:"noopener noreferrer",target:"_blank"},...a.children.map(t=>"string"==typeof t?t:e(t)));case"bitmap":return(0,t.jsx)(m,{name:a.value})}}(n)}(s),i[0]=s,i[1]=n):n=i[1];let c=n;return i[2]!==c?(r=(0,t.jsx)("div",{className:o.default.GuiMarkup,children:c}),i[2]=c,i[3]=r):r=i[3],r}var f=e.i(41973);function h(e){let n,r,i,s=(0,a.c)(7),{src:o,alt:u,className:c}=e,m=void 0===c?f.default.PreviewImage:c,[p,d]=(0,l.useState)(null);return(s[0]!==o?(n=()=>{let e,t=!1;return fetch(o).then(M).then(y).then(g).then(a=>{!t&&a&&d(e=URL.createObjectURL(a))}).catch(_),()=>{t=!0,e&&URL.revokeObjectURL(e)}},r=[o],s[0]=o,s[1]=n,s[2]=r):(n=s[1],r=s[2]),(0,l.useEffect)(n,r),p)?(s[3]!==u||s[4]!==m||s[5]!==p?(i=(0,t.jsx)("img",{src:p,alt:u,className:m}),s[3]=u,s[4]=m,s[5]=p,s[6]=i):i=s[6],i):null}function _(){}function g(e){return new Promise(t=>{let a=document.createElement("canvas");a.width=e.width,a.height=e.height,a.getContext("2d")?.drawImage(e,0,0),e.close(),a.toBlob(t)})}function y(e){return createImageBitmap(e,{colorSpaceConversion:"none"})}function M(e){return e.blob()}function v(e){let r,s,o,u,c,m,p,d,h,_,g,y=(0,a.c)(22),{track:M}=e,[v,x]=(0,l.useState)(!1),[b,j]=(0,l.useState)(!0),k=(0,l.useRef)(null);y[0]!==M?(r=M.toLowerCase(),y[0]=M,y[1]=r):r=y[1];let I=`${i.RESOURCE_ROOT_URL}music/${r}.mp3`;y[2]===Symbol.for("react.memo_cache_sentinel")?(s=()=>()=>{k.current?.pause()},o=[],y[2]=s,y[3]=o):(s=y[2],o=y[3]),(0,l.useEffect)(s,o),y[4]!==v?(u=()=>{let e=k.current;e&&(v?e.pause():e.play().catch(()=>j(!1)))},y[4]=v,y[5]=u):u=y[5];let w=u;return y[6]===Symbol.for("react.memo_cache_sentinel")?(c=()=>x(!0),m=()=>x(!1),p=()=>j(!1),y[6]=c,y[7]=m,y[8]=p):(c=y[6],m=y[7],p=y[8]),y[9]!==I?(d=(0,t.jsx)("audio",{ref:k,src:I,loop:!0,onPlay:c,onPause:m,onError:p}),y[9]=I,y[10]=d):d=y[10],y[11]!==M?(h=(0,t.jsx)("span",{className:f.default.MusicTrackName,children:M}),y[11]=M,y[12]=h):h=y[12],y[13]!==b||y[14]!==v||y[15]!==w?(_=b&&(0,t.jsx)("button",{className:f.default.MusicButton,onClick:w,"aria-label":v?"Pause music":"Play music",children:v?(0,t.jsx)(n.FaVolumeUp,{}):(0,t.jsx)(n.FaVolumeMute,{})}),y[13]=b,y[14]=v,y[15]=w,y[16]=_):_=y[16],y[17]!==v||y[18]!==_||y[19]!==d||y[20]!==h?(g=(0,t.jsxs)("div",{className:f.default.MusicTrack,"data-playing":v,children:[d,h,_]}),y[17]=v,y[18]=_,y[19]=d,y[20]=h,y[21]=g):g=y[21],g}function x(e){var n,o,u;let c,m,_,g,y,M,x,I,w,N,B,S,D,P,C,L,T,X,E,R,U,O,F,$,K,Q,q,G,z,A,H,V,J,W,Y,Z,ee,et=(0,a.c)(102),{open:ea,onClose:el,missionName:en,missionType:er}=e,{data:ei}=((ee=(0,a.c)(2))[0]!==en?(Z={queryKey:["parsedMission",en],queryFn:()=>(0,i.loadMission)(en)},ee[0]=en,ee[1]=Z):Z=ee[1],(0,r.useQuery)(Z)),es=(0,l.useRef)(null);if(et[0]!==ea?(c=()=>{if(ea){es.current?.focus();try{document.exitPointerLock()}catch{}}},m=[ea],et[0]=ea,et[1]=c,et[2]=m):(c=et[1],m=et[2]),(0,l.useEffect)(c,m),et[3]!==el||et[4]!==ea?(_=()=>{if(!ea)return;let e=e=>{if("KeyI"===e.code||"Escape"===e.key)el();else if("k"===e.key&&(e.metaKey||e.ctrlKey))return void el();e.stopImmediatePropagation()};return window.addEventListener("keydown",e,{capture:!0}),window.addEventListener("keyup",k,{capture:!0}),()=>{window.removeEventListener("keydown",e,{capture:!0}),window.removeEventListener("keyup",k,{capture:!0})}},g=[ea,el],et[3]=el,et[4]=ea,et[5]=_,et[6]=g):(_=et[5],g=et[6]),(0,l.useEffect)(_,g),!ea)return null;et[7]!==ei?(y=ei?function(e){for(let t of e.body){if("ObjectDeclaration"!==t.type)continue;let{instanceName:e,body:a}=t;if(e&&"Identifier"===e.type&&"missiongroup"===e.name.toLowerCase()){let e={};for(let t of a){if("Assignment"!==t.type)continue;let{target:a,value:l}=t;"Identifier"===a.type&&"StringLiteral"===l.type&&(e[a.name.toLowerCase()]=l.value)}return e}}return{}}(ei.ast):{},et[7]=ei,et[8]=y):y=et[8];let eo=y;et[9]!==en||et[10]!==ei?(M=ei?function(e,t){if(e)try{let t=(0,s.getStandardTextureResourceKey)(`textures/gui/${e}`);return(0,i.getUrlForPath)(t)}catch{}try{let e=(0,s.getStandardTextureResourceKey)(`textures/gui/Load_${t}`);return(0,i.getUrlForPath)(e)}catch{}return null}(ei.bitmap,en):null,et[9]=en,et[10]=ei,et[11]=M):M=et[11];let eu=M,ec=ei?.displayName??en;et[12]!==er?(x=er.toLowerCase(),et[12]=er,et[13]=x):x=et[13];let em="singleplayer"===x,ep=eo.musictrack;if(et[14]!==eu||et[15]!==ec||et[16]!==em||et[17]!==er||et[18]!==el||et[19]!==ei){let e,a,l,r,i,s,c=ei?.missionString?(n=ei.missionString,s=er.toUpperCase(),n.split("\n").flatMap(e=>{let t=e.match(/^\[([^\]]+)\]/);return t&&!t[1].toUpperCase().split(/\s+/).includes(s)?[]:[e.replace(/^\[[^\]]+\]/,"")]}).join("\n")):null;if(et[38]!==ei?.missionQuote){if(o=r=ei?.missionQuote?.trim()??"",l="",e="",!(a=p.test(o)))for(let t of r.split("\n")){let a=t.trim();a.match(/^--[^-]/)?e=a.replace(/^-+\s*/,"").trim():a&&(l+=(l?"\n":"")+a)}et[38]=ei?.missionQuote,et[39]=e,et[40]=a,et[41]=l,et[42]=r}else e=et[39],a=et[40],l=et[41],r=et[42];(O=f.default.Overlay,F=el,P=es,C=f.default.Dialog,L=j,T=b,X="dialog",E="true",R="Map Information",U=-1,D=f.default.Body,$=f.default.Left,et[43]!==eu||et[44]!==ec||et[45]!==em?(K=eu&&em&&(0,t.jsx)(h,{className:f.default.PreviewImageFloating,src:eu,alt:`${ec} preview`},eu),et[43]=eu,et[44]=ec,et[45]=em,et[46]=K):K=et[46],et[47]!==ec?(I=(0,t.jsx)("h1",{className:f.default.Title,children:ec}),et[47]=ec,et[48]=I):I=et[48],et[49]!==ei?(i=ei?.planetName&&(0,t.jsx)("span",{className:f.default.MapPlanet,children:ei.planetName}),et[49]=ei,et[50]=i):i=et[50],et[51]!==i?(w=(0,t.jsx)("div",{className:f.default.MapMeta,children:i}),et[51]=i,et[52]=w):w=et[52],et[53]!==e||et[54]!==a||et[55]!==l||et[56]!==r?(N=a?(0,t.jsx)("blockquote",{className:f.default.MapQuote,children:(0,t.jsx)(d,{markup:r})}):l?(0,t.jsxs)("blockquote",{className:f.default.MapQuote,children:[(0,t.jsx)("p",{children:l}),e&&(0,t.jsxs)("cite",{children:["— ",e]})]}):null,et[53]=e,et[54]=a,et[55]=l,et[56]=r,et[57]=N):N=et[57],et[58]!==ei)?(B=ei?.missionBlurb&&(0,t.jsx)("div",{className:f.default.MapBlurb,children:(u=ei.missionBlurb,p.test(u))?(0,t.jsx)(d,{markup:ei.missionBlurb.trim()}):ei.missionBlurb.trim()}),et[58]=ei,et[59]=B):B=et[59],S=c&&c.trim()&&(0,t.jsx)("div",{className:f.default.Section,children:(0,t.jsx)(d,{markup:c})}),et[14]=eu,et[15]=ec,et[16]=em,et[17]=er,et[18]=el,et[19]=ei,et[20]=I,et[21]=w,et[22]=N,et[23]=B,et[24]=S,et[25]=D,et[26]=P,et[27]=C,et[28]=L,et[29]=T,et[30]=X,et[31]=E,et[32]=R,et[33]=U,et[34]=O,et[35]=F,et[36]=$,et[37]=K}else I=et[20],w=et[21],N=et[22],B=et[23],S=et[24],D=et[25],P=et[26],C=et[27],L=et[28],T=et[29],X=et[30],E=et[31],R=et[32],U=et[33],O=et[34],F=et[35],$=et[36],K=et[37];return et[60]!==ei?(Q=ei?.missionBriefing&&(0,t.jsxs)("div",{className:f.default.Section,children:[(0,t.jsx)("h2",{className:f.default.SectionTitle,children:"Mission Briefing"}),(0,t.jsx)(d,{markup:ei.missionBriefing})]}),et[60]=ei,et[61]=Q):Q=et[61],et[62]!==ep?(q=ep&&(0,t.jsx)(v,{track:ep}),et[62]=ep,et[63]=q):q=et[63],et[64]!==I||et[65]!==w||et[66]!==N||et[67]!==B||et[68]!==S||et[69]!==Q||et[70]!==q||et[71]!==$||et[72]!==K?(G=(0,t.jsxs)("div",{className:$,children:[K,I,w,N,B,S,Q,q]}),et[64]=I,et[65]=w,et[66]=N,et[67]=B,et[68]=S,et[69]=Q,et[70]=q,et[71]=$,et[72]=K,et[73]=G):G=et[73],et[74]!==eu||et[75]!==ec||et[76]!==em?(z=eu&&!em&&(0,t.jsx)(h,{src:eu,alt:`${ec} preview`},eu),et[74]=eu,et[75]=ec,et[76]=em,et[77]=z):z=et[77],et[78]!==D||et[79]!==G||et[80]!==z?(A=(0,t.jsxs)("div",{className:D,children:[G,z]}),et[78]=D,et[79]=G,et[80]=z,et[81]=A):A=et[81],et[82]!==el?(H=(0,t.jsx)("button",{className:f.default.CloseButton,onClick:el,children:"Close"}),et[82]=el,et[83]=H):H=et[83],et[84]===Symbol.for("react.memo_cache_sentinel")?(V=(0,t.jsx)("span",{className:f.default.Hint,children:"I or Esc to close"}),et[84]=V):V=et[84],et[85]!==H?(J=(0,t.jsxs)("div",{className:f.default.Footer,children:[H,V]}),et[85]=H,et[86]=J):J=et[86],et[87]!==P||et[88]!==C||et[89]!==L||et[90]!==T||et[91]!==X||et[92]!==E||et[93]!==R||et[94]!==U||et[95]!==A||et[96]!==J?(W=(0,t.jsxs)("div",{ref:P,className:C,onClick:L,onKeyDown:T,role:X,"aria-modal":E,"aria-label":R,tabIndex:U,children:[A,J]}),et[87]=P,et[88]=C,et[89]=L,et[90]=T,et[91]=X,et[92]=E,et[93]=R,et[94]=U,et[95]=A,et[96]=J,et[97]=W):W=et[97],et[98]!==O||et[99]!==F||et[100]!==W?(Y=(0,t.jsx)("div",{className:O,onClick:F,children:W}),et[98]=O,et[99]=F,et[100]=W,et[101]=Y):Y=et[101],Y}function b(e){return e.stopPropagation()}function j(e){return e.stopPropagation()}function k(e){e.stopImmediatePropagation()}e.s(["MapInfoDialog",()=>x],94247)}]);
\ No newline at end of file
diff --git a/docs/_next/static/chunks/f9ef36e323faaaed.css b/docs/_next/static/chunks/284925ee1f24c201.css
similarity index 61%
rename from docs/_next/static/chunks/f9ef36e323faaaed.css
rename to docs/_next/static/chunks/284925ee1f24c201.css
index 9a7e832f..b20560df 100644
--- a/docs/_next/static/chunks/f9ef36e323faaaed.css
+++ b/docs/_next/static/chunks/284925ee1f24c201.css
@@ -1 +1 @@
-html{box-sizing:border-box;background:#000;margin:0;padding:0;overflow:hidden}*,:before,:after{box-sizing:inherit}body{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;font-size:100%}body{margin:0;padding:0;overflow:hidden}main{width:100dvw;height:100dvh}#canvasContainer{z-index:0;position:absolute;inset:0}#controls{color:#fff;z-index:2;background:#00000080;border-radius:0 0 4px;padding:8px 12px 8px 8px;font-size:13px;position:fixed;top:0;left:0}input[type=range]{max-width:80px}.CheckboxField,.LabelledButton,.Field{align-items:center;gap:6px;display:flex}#controls,.Controls-dropdown,.Controls-group{justify-content:center;align-items:center;gap:20px;display:flex}@media (max-width:1279px){.Controls-dropdown[data-open=false]{display:none}.Controls-dropdown{background:#000c;border:1px solid #fff3;border-radius:4px;flex-direction:column;align-items:center;gap:12px;max-height:calc(100dvh - 56px);padding:12px;display:flex;position:absolute;top:calc(100% + 2px);left:2px;right:2px;overflow:auto;box-shadow:0 0 12px #0006}.Controls-group{flex-wrap:wrap;gap:12px 20px}}@media (max-width:639px){#controls{border-radius:0;right:0}#controls>.MissionSelect-inputWrapper{flex:1 1 0;min-width:0}#controls>.MissionSelect-inputWrapper .MissionSelect-input{width:100%}.Controls-toggle{flex:none}}.IconButton{color:#fff;cursor:pointer;background:#03529399;border:1px solid #c8c8c84d;border-color:#ffffff4d #c8c8c84d #c8c8c84d #ffffff4d;border-radius:4px;justify-content:center;align-items:center;width:28px;height:28px;margin:0 0 0 -12px;padding:0;font-size:15px;transition:background .2s,border-color .2s;display:flex;position:relative;transform:translate(0);box-shadow:0 1px 2px #0006}.ButtonLabel{font-size:12px}.IconButton svg{pointer-events:none}@media (hover:hover){.IconButton:hover{background:#0062b3cc;border-color:#fff6}}.IconButton:active,.IconButton[aria-expanded=true]{background:#0062b3b3;border-color:#ffffff4d;transform:translateY(1px)}.Controls-toggle{margin:0}@media (max-width:1279px){.LabelledButton{width:auto;padding:0 10px}}@media (min-width:1280px){.Controls-toggle,.LabelledButton .ButtonLabel,.MapInfoButton{display:none}}.CopyCoordinatesButton[data-copied=true]{background:#0075d5e6;border-color:#fff6}.CopyCoordinatesButton .ClipboardCheck{opacity:1;display:none}.CopyCoordinatesButton[data-copied=true] .ClipboardCheck{animation:.22s linear infinite showClipboardCheck;display:block}.CopyCoordinatesButton[data-copied=true] .MapPin{display:none}.StaticShapeLabel{color:#fff;white-space:nowrap;text-align:center;background:#00000080;border-radius:1px;padding:1px 3px;font-size:11px}.StatsPanel{bottom:0;right:0;top:auto!important;left:auto!important}.AxisLabel{pointer-events:none;font-size:12px}.AxisLabel[data-axis=x]{color:#f90}.AxisLabel[data-axis=y]{color:#9f0}.AxisLabel[data-axis=z]{color:#09f}.MissionSelect-inputWrapper{align-items:center;display:flex;position:relative}.MissionSelect-shortcut{color:#fff9;pointer-events:none;background:#ffffff26;border-radius:3px;padding:1px 4px;font-family:system-ui,sans-serif;font-size:11px;position:absolute;right:7px}.MissionSelect-input[aria-expanded=true]~.MissionSelect-shortcut{display:none}.MissionSelect-input{color:#fff;-webkit-user-select:text;user-select:text;background:#0009;border:1px solid #ffffff4d;border-radius:3px;outline:none;width:280px;padding:6px 36px 6px 8px;font-size:14px}.MissionSelect-input[aria-expanded=true]{padding-right:8px}.MissionSelect-input:focus{border-color:#fff9}.MissionSelect-input::placeholder{color:#0000}.MissionSelect-selectedValue{pointer-events:none;align-items:center;gap:6px;display:flex;position:absolute;left:8px;right:36px;overflow:hidden}.MissionSelect-input[aria-expanded=true]~.MissionSelect-selectedValue{display:none}.MissionSelect-selectedName{color:#fff;white-space:nowrap;text-overflow:ellipsis;flex-shrink:1;min-width:0;font-size:14px;font-weight:600;overflow:hidden}.MissionSelect-selectedValue>.MissionSelect-itemType{flex-shrink:0}.MissionSelect-popover{z-index:100;min-width:320px;max-height:var(--popover-available-height,90vh);overscroll-behavior:contain;background:#141414f2;border:1px solid #ffffff80;border-radius:3px;overflow-y:auto;box-shadow:0 8px 24px #0009}.MissionSelect-list{padding:4px 0}.MissionSelect-list:has(>.MissionSelect-group:first-child){padding-top:0}.MissionSelect-group{padding-bottom:4px}.MissionSelect-groupLabel{color:#c6caca;z-index:1;background:#3a4548f2;border-bottom:1px solid #ffffff4d;padding:6px 8px 6px 12px;font-size:13px;font-weight:600;position:sticky;top:0}.MissionSelect-group:not(:last-child){border-bottom:1px solid #ffffff4d}.MissionSelect-item{cursor:pointer;border-radius:4px;outline:none;flex-direction:column;gap:1px;margin:4px 4px 0;padding:6px 8px;scroll-margin-top:32px;display:flex}.MissionSelect-list>.MissionSelect-item:first-child{margin-top:0}.MissionSelect-item[data-active-item]{background:#ffffff26}.MissionSelect-item[aria-selected=true]{background:#6496ff4d}.MissionSelect-itemHeader{align-items:center;gap:6px;display:flex}.MissionSelect-itemName{color:#fff;font-size:14px;font-weight:600}.MissionSelect-itemTypes{gap:3px;display:flex}.MissionSelect-itemType{color:#fff;background:#ff9d0066;border-radius:3px;padding:2px 5px;font-size:10px;font-weight:600}.MissionSelect-itemType:hover{background:#ff9d00b3}.MissionSelect-itemMissionName{color:#ffffff80;font-size:12px}.MissionSelect-noResults{color:#ffffff80;text-align:center;padding:12px 8px;font-size:13px}.LoadingSpinner{border:4px solid #fff3;border-top-color:#fff;border-radius:50%;width:48px;height:48px;animation:1s linear infinite LoadingSpinner-spin}@keyframes LoadingSpinner-spin{to{transform:rotate(360deg)}}#loadingIndicator{pointer-events:none;z-index:1;opacity:.8;flex-direction:column;align-items:center;gap:16px;display:flex;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}#loadingIndicator[data-complete=true]{animation:.3s ease-out forwards loadingComplete}@keyframes loadingComplete{0%{opacity:1}to{opacity:0}}.LoadingProgress{background:#fff3;border-radius:2px;width:200px;height:4px;overflow:hidden}.LoadingProgress-bar{background:#fff;border-radius:2px;height:100%;transition:width .1s ease-out}.LoadingProgress-text{color:#ffffffb3;font-variant-numeric:tabular-nums;font-size:14px}@keyframes showClipboardCheck{0%{opacity:1}to{opacity:.2}}.KeyboardOverlay{pointer-events:none;z-index:1;align-items:flex-end;gap:10px;display:flex;position:fixed;bottom:16px;left:50%;transform:translate(-50%)}.KeyboardOverlay-column{flex-direction:column;justify-content:center;gap:4px;display:flex}.KeyboardOverlay-row{justify-content:stretch;gap:4px;display:flex}.KeyboardOverlay-spacer{width:32px}.KeyboardOverlay-key{color:#ffffff80;white-space:nowrap;background:#0006;border:1px solid #fff3;border-radius:4px;flex:1 0 0;justify-content:center;align-items:center;min-width:32px;height:32px;padding:0 8px;font-size:11px;font-weight:600;display:flex}.KeyboardOverlay-key[data-pressed=true]{color:#fff;background:#34bbab99;border-color:#23fddc80}.KeyboardOverlay-arrow{margin-right:3px}.MapInfoDialog-overlay{z-index:10;background:#000000b3;justify-content:center;align-items:center;padding:20px;display:flex;position:fixed;inset:0}.MapInfoDialog{color:#bccec3;-webkit-user-select:text;user-select:text;-webkit-touch-callout:default;background:#142526cc;border:1px solid #41838b99;border-radius:3px;outline:none;grid-template-rows:1fr auto;grid-template-columns:100%;width:800px;max-width:calc(100dvw - 40px);height:600px;max-height:calc(100dvh - 40px);font-size:14px;line-height:1.5;display:grid;position:relative;box-shadow:0 0 0 1px #00bedc1f,0 0 60px #008cb41f,inset 0 0 60px #01070d99}.MapInfoDialog-inner{grid-template-rows:100%;grid-template-columns:1fr auto;min-height:0;display:grid;overflow:hidden}.MapInfoDialog-left{width:100%;padding:24px 28px;overflow-y:auto}.MapInfoDialog-right{border-left:1px solid #00bedc4d;width:auto;height:100%;margin-left:auto;margin-right:0;display:flex}.MapInfoDialog-preview{width:auto;height:100%;overflow:hidden}.MapInfoDialog-preview--floated{float:right;clear:right;width:auto;max-width:30%;max-height:260px;margin:0 0 16px 20px;display:block}.MapInfoDialog-title{color:#7dffff;text-shadow:0 1px 6px #0006;margin:0;font-size:26px;font-weight:500}.MapInfoDialog-meta{flex-wrap:wrap;gap:8px 16px;margin-bottom:4px;font-size:15px;font-weight:400;display:flex}.MapInfoDialog-planet{color:#dbcaa8b3}.MapInfoDialog-quote{border-left:2px solid #00bedc59;margin:16px 0;padding:0 0 0 14px;font-style:italic}.MapInfoDialog-quote p{white-space:pre-line;margin:0 0 4px}.MapInfoDialog-quote cite{color:#ffffff73;font-size:12px;font-style:normal;display:block}.MapInfoDialog-blurb{margin:0 0 16px;font-size:13px}.MapInfoDialog-section{margin-top:20px}.MapInfoDialog-sectionTitle{color:#7dffff;letter-spacing:.04em;text-transform:uppercase;text-shadow:0 0 16px #00d2f040;margin:0 0 8px;font-size:16px;font-weight:500}.MapInfoDialog-musicTrack{color:#cad0ac80;align-items:center;gap:6px;margin-top:16px;font-size:14px;font-style:italic;display:flex}.MapInfoDialog-musicTrack[data-playing=true]{color:#f7fdd8b3}.MapInfoDialog-musicBtn{cursor:pointer;color:#557663;opacity:.5;background:0 0;border:0;border-radius:20px;flex-shrink:0;place-content:center;width:32px;height:32px;padding:0;font-size:20px;font-style:normal;line-height:1;display:grid}.MapInfoDialog-musicTrack[data-playing=true] .MapInfoDialog-musicBtn{color:#6dffaa;opacity:1}.MapInfoDialog-musicTrack[data-playing=true] .MapInfoDialog-musicBtn:hover{opacity:.7}.MapInfoDialog-footer{background:#021415b3;border-top:1px solid #00bedc40;flex-shrink:0;align-items:center;gap:16px;padding:10px 12px;display:flex}.MapInfoDialog-closeBtn{color:#9aefe1e6;text-shadow:0 -1px #00000080;cursor:pointer;background:linear-gradient(#29ac9cb3,#005041b3);border:1px solid #29615499;border-top-color:#65b9b080;border-radius:3px;padding:4px 18px;font-size:14px;font-weight:500;box-shadow:inset 0 1px #78dcc333,inset 0 -1px #0000004d,0 2px 4px #0006}.MapInfoDialog-closeBtn:active{transform:translateY(1px)}.MapInfoDialog-hint{color:#c9dcd84d;margin-left:auto;font-size:12px}@media (max-width:719px){.MapInfoDialog-inner{display:block;overflow:auto}.MapInfoDialog-hint{display:none}.MapInfoDialog-left{width:100%;height:auto;margin:0;padding:16px 20px;overflow:auto}.MapInfoDialog-right{border-left:0;width:100%;height:auto;margin:0;overflow:auto}.MapInfoDialog-preview{width:auto;height:auto;margin:16px auto}.MapInfoDialog-closeBtn{width:220px;height:36px;margin:0 auto}}.GuiMarkup-line{margin-bottom:1px}.GuiMarkup-spacer{height:.6em}.GuiMarkup-bulletLine{align-items:baseline;gap:5px;margin-bottom:3px;display:flex}.GuiMarkup-bulletIcon{flex-shrink:0;align-items:center;display:flex}.GuiMarkup-bulletText{flex:1;min-width:0}.GuiMarkup-bitmap{vertical-align:middle;max-height:1em}.GuiMarkup-bullet{opacity:.8}.TouchJoystick{z-index:1;width:140px;height:140px;position:fixed;bottom:20px;left:50%;transform:translate(-50%)}.TouchJoystick--left{left:20px;transform:none}.TouchJoystick--right{left:auto;right:20px;transform:none}.TouchJoystick .back{background:#034f4c99!important;border:1px solid #00dbdf80!important;box-shadow:inset 0 0 10px #000000b3!important}.TouchJoystick .front{background:radial-gradient(circle,#17f7c6e6 0%,#09b8aaf2 100%)!important;border:2px solid #fff6!important;box-shadow:0 2px 4px #00000080,0 1px 1px #0000004d,inset 0 1px #ffffff26,inset 0 -1px 2px #0000004d!important}.MusicTrackName{text-transform:capitalize}
+html{box-sizing:border-box;background:#000;margin:0;padding:0;overflow:hidden}*,:before,:after{box-sizing:inherit}body{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;font-size:100%}body{margin:0;padding:0;overflow:hidden}main{width:100dvw;height:100dvh}#canvasContainer{z-index:0;position:absolute;inset:0}#controls{color:#fff;z-index:2;background:#00000080;border-radius:0 0 4px;padding:8px 12px 8px 8px;font-size:13px;position:fixed;top:0;left:0}input[type=range]{max-width:80px}.CheckboxField,.LabelledButton,.Field{align-items:center;gap:6px;display:flex}#controls,.Controls-dropdown,.Controls-group{justify-content:center;align-items:center;gap:20px;display:flex}@media (max-width:1279px){.Controls-dropdown[data-open=false]{display:none}.Controls-dropdown{background:#000c;border:1px solid #fff3;border-radius:4px;flex-direction:column;align-items:center;gap:12px;max-height:calc(100dvh - 56px);padding:12px;display:flex;position:absolute;top:calc(100% + 2px);left:2px;right:2px;overflow:auto;box-shadow:0 0 12px #0006}.Controls-group{flex-wrap:wrap;gap:12px 20px}}@media (max-width:639px){#controls{border-radius:0;right:0}#controls>.MissionSelect-inputWrapper{flex:1 1 0;min-width:0}#controls>.MissionSelect-inputWrapper .MissionSelect-input{width:100%}.Controls-toggle{flex:none}}.IconButton{color:#fff;cursor:pointer;background:#03529399;border:1px solid #c8c8c84d;border-color:#ffffff4d #c8c8c84d #c8c8c84d #ffffff4d;border-radius:4px;justify-content:center;align-items:center;width:28px;height:28px;margin:0 0 0 -12px;padding:0;font-size:15px;transition:background .2s,border-color .2s;display:flex;position:relative;transform:translate(0);box-shadow:0 1px 2px #0006}.ButtonLabel{font-size:12px}.IconButton svg{pointer-events:none}@media (hover:hover){.IconButton:hover{background:#0062b3cc;border-color:#fff6}}.IconButton:active,.IconButton[aria-expanded=true]{background:#0062b3b3;border-color:#ffffff4d;transform:translateY(1px)}.Controls-toggle{margin:0}@media (max-width:1279px){.LabelledButton{width:auto;padding:0 10px}}@media (min-width:1280px){.Controls-toggle,.LabelledButton .ButtonLabel,.MapInfoButton{display:none}}.CopyCoordinatesButton[data-copied=true]{background:#0075d5e6;border-color:#fff6}.CopyCoordinatesButton .ClipboardCheck{opacity:1;display:none}.CopyCoordinatesButton[data-copied=true] .ClipboardCheck{animation:.22s linear infinite showClipboardCheck;display:block}.CopyCoordinatesButton[data-copied=true] .MapPin{display:none}.StaticShapeLabel{color:#fff;white-space:nowrap;text-align:center;background:#00000080;border-radius:1px;padding:1px 3px;font-size:11px}.StatsPanel{bottom:0;right:0;top:auto!important;left:auto!important}.AxisLabel{pointer-events:none;font-size:12px}.AxisLabel[data-axis=x]{color:#f90}.AxisLabel[data-axis=y]{color:#9f0}.AxisLabel[data-axis=z]{color:#09f}.MissionSelect-inputWrapper{align-items:center;display:flex;position:relative}.MissionSelect-shortcut{color:#fff9;pointer-events:none;background:#ffffff26;border-radius:3px;padding:1px 4px;font-family:system-ui,sans-serif;font-size:11px;position:absolute;right:7px}.MissionSelect-input[aria-expanded=true]~.MissionSelect-shortcut{display:none}.MissionSelect-input{color:#fff;-webkit-user-select:text;user-select:text;background:#0009;border:1px solid #ffffff4d;border-radius:3px;outline:none;width:280px;padding:6px 36px 6px 8px;font-size:14px}.MissionSelect-input[aria-expanded=true]{padding-right:8px}.MissionSelect-input:focus{border-color:#fff9}.MissionSelect-input::placeholder{color:#0000}.MissionSelect-selectedValue{pointer-events:none;align-items:center;gap:6px;display:flex;position:absolute;left:8px;right:36px;overflow:hidden}.MissionSelect-input[aria-expanded=true]~.MissionSelect-selectedValue{display:none}.MissionSelect-selectedName{color:#fff;white-space:nowrap;text-overflow:ellipsis;flex-shrink:1;min-width:0;font-size:14px;font-weight:600;overflow:hidden}.MissionSelect-selectedValue>.MissionSelect-itemType{flex-shrink:0}.MissionSelect-popover{z-index:100;min-width:320px;max-height:var(--popover-available-height,90vh);overscroll-behavior:contain;background:#141414f2;border:1px solid #ffffff80;border-radius:3px;overflow-y:auto;box-shadow:0 8px 24px #0009}.MissionSelect-list{padding:4px 0}.MissionSelect-list:has(>.MissionSelect-group:first-child){padding-top:0}.MissionSelect-group{padding-bottom:4px}.MissionSelect-groupLabel{color:#c6caca;z-index:1;background:#3a4548f2;border-bottom:1px solid #ffffff4d;padding:6px 8px 6px 12px;font-size:13px;font-weight:600;position:sticky;top:0}.MissionSelect-group:not(:last-child){border-bottom:1px solid #ffffff4d}.MissionSelect-item{cursor:pointer;border-radius:4px;outline:none;flex-direction:column;gap:1px;margin:4px 4px 0;padding:6px 8px;scroll-margin-top:32px;display:flex}.MissionSelect-list>.MissionSelect-item:first-child{margin-top:0}.MissionSelect-item[data-active-item]{background:#ffffff26}.MissionSelect-item[aria-selected=true]{background:#6496ff4d}.MissionSelect-itemHeader{align-items:center;gap:6px;display:flex}.MissionSelect-itemName{color:#fff;font-size:14px;font-weight:600}.MissionSelect-itemTypes{gap:3px;display:flex}.MissionSelect-itemType{color:#fff;background:#ff9d0066;border-radius:3px;padding:2px 5px;font-size:10px;font-weight:600}.MissionSelect-itemType:hover{background:#ff9d00b3}.MissionSelect-itemMissionName{color:#ffffff80;font-size:12px}.MissionSelect-noResults{color:#ffffff80;text-align:center;padding:12px 8px;font-size:13px}.LoadingSpinner{border:4px solid #fff3;border-top-color:#fff;border-radius:50%;width:48px;height:48px;animation:1s linear infinite LoadingSpinner-spin}@keyframes LoadingSpinner-spin{to{transform:rotate(360deg)}}#loadingIndicator{pointer-events:none;z-index:1;opacity:.8;flex-direction:column;align-items:center;gap:16px;display:flex;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}#loadingIndicator[data-complete=true]{animation:.3s ease-out forwards loadingComplete}@keyframes loadingComplete{0%{opacity:1}to{opacity:0}}.LoadingProgress{background:#fff3;border-radius:2px;width:200px;height:4px;overflow:hidden}.LoadingProgress-bar{background:#fff;border-radius:2px;height:100%;transition:width .1s ease-out}.LoadingProgress-text{color:#ffffffb3;font-variant-numeric:tabular-nums;font-size:14px}@keyframes showClipboardCheck{0%{opacity:1}to{opacity:.2}}.KeyboardOverlay{pointer-events:none;z-index:1;align-items:flex-end;gap:10px;display:flex;position:fixed;bottom:16px;left:50%;transform:translate(-50%)}.KeyboardOverlay-column{flex-direction:column;justify-content:center;gap:4px;display:flex}.KeyboardOverlay-row{justify-content:stretch;gap:4px;display:flex}.KeyboardOverlay-spacer{width:32px}.KeyboardOverlay-key{color:#ffffff80;white-space:nowrap;background:#0006;border:1px solid #fff3;border-radius:4px;flex:1 0 0;justify-content:center;align-items:center;min-width:32px;height:32px;padding:0 8px;font-size:11px;font-weight:600;display:flex}.KeyboardOverlay-key[data-pressed=true]{color:#fff;background:#34bbab99;border-color:#23fddc80}.KeyboardOverlay-arrow{margin-right:3px}.TouchJoystick{z-index:1;width:140px;height:140px;position:fixed;bottom:20px;left:50%;transform:translate(-50%)}.TouchJoystick--left{left:20px;transform:none}.TouchJoystick--right{left:auto;right:20px;transform:none}.TouchJoystick .back{background:#034f4c99!important;border:1px solid #00dbdf80!important;box-shadow:inset 0 0 10px #000000b3!important}.TouchJoystick .front{background:radial-gradient(circle,#17f7c6e6 0%,#09b8aaf2 100%)!important;border:2px solid #fff6!important;box-shadow:0 2px 4px #00000080,0 1px 1px #0000004d,inset 0 1px #ffffff26,inset 0 -1px 2px #0000004d!important}
diff --git a/docs/_next/static/chunks/dd460a24fc1df5f8.js b/docs/_next/static/chunks/dd460a24fc1df5f8.js
deleted file mode 100644
index f6f06299..00000000
--- a/docs/_next/static/chunks/dd460a24fc1df5f8.js
+++ /dev/null
@@ -1 +0,0 @@
-(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,94247,e=>{"use strict";var t=e.i(43476),n=e.i(932),a=e.i(71645),i=e.i(11152),s=e.i(66027),l=e.i(12979),r=e.i(91996);let o=new Map;function c(e){let a,i=(0,n.c)(5),{name:s}=e;i[0]!==s?(a=function(e){let t;if(o.has(e))return o.get(e);try{t=(0,l.getUrlForPath)((0,r.getStandardTextureResourceKey)(`textures/gui/${e}`))}catch{t=null}return o.set(e,t),t}(s),i[0]=s,i[1]=a):a=i[1];let c=a;if(c){let e;return i[2]!==c?(e=(0,t.jsx)("img",{src:c,alt:"",className:"GuiMarkup-bitmap"}),i[2]=c,i[3]=e):e=i[3],e}if(/bullet/i.test(s)){let e;return i[4]===Symbol.for("react.memo_cache_sentinel")?(e=(0,t.jsx)("span",{className:"GuiMarkup-bullet",children:"•"}),i[4]=e):e=i[4],e}return null}function u(e){let a,i,s=(0,n.c)(8),{span:l}=e,{color:r,fontSize:o}=l.style;if(!r&&!o){let e;return s[0]!==l.text?(e=(0,t.jsx)(t.Fragment,{children:l.text}),s[0]=l.text,s[1]=e):e=s[1],e}let c=null!=o?`${o}px`:void 0;return s[2]!==r||s[3]!==c?(a={color:r,fontSize:c},s[2]=r,s[3]=c,s[4]=a):a=s[4],s[5]!==l.text||s[6]!==a?(i=(0,t.jsx)("span",{style:a,children:l.text}),s[5]=l.text,s[6]=a,s[7]=i):i=s[7],i}let p=/<(?:font|color|bitmap|just|lmargin):/i;function m(e){let a,i,s,l=(0,n.c)(6),{markup:r}=e;l[0]!==r?(a=function(e){let t=function(e){let t,n=[],a=/<([^>]*)>/g,i=0,s=e=>{let t=e.split("\n");t.forEach((e,a)=>{e&&n.push({type:"text",value:e}),ai&&s(e.slice(i,t.index)),i=t.index+t[0].length;let a=t[1].trim(),l=a.indexOf(":"),r=(-1===l?a:a.slice(0,l)).toLowerCase(),o=-1===l?"":a.slice(l+1);n.push({type:"tag",name:r,arg:o})}return i{p.push({align:r,lmargin:o,textIndent:u,items:l}),l=[],r=i,o=s,c=!1,u=0},f=e=>{if(!e)return;let t=l[l.length-1];t?.type==="span"&&t.style.color===a.color&&t.style.fontSize===a.fontSize?t.text+=e:l.push({type:"span",text:e,style:{...a}})};for(let e of t){if("newline"===e.type){m();continue}if("text"===e.type){f(e.value.replace(/\t/g," "));continue}let{name:t,arg:p}=e;switch(t){case"spush":n.push({...a});break;case"spop":n.length>0&&(a=n.pop());break;case"color":a={...a,color:`#${p.trim()}`};break;case"font":a={...a,fontSize:function(e){let t=e.lastIndexOf(":");return Math.min(parseInt(-1===t?e:e.slice(t+1),10)||14,16)}(p)};break;case"lmargin":{let e=parseInt(p,10)||0;s=e,c&&e>0?u=e:0===l.length&&(o=e);break}case"just":{let e=p.trim().toLowerCase();("left"===e||"center"===e||"right"===e)&&(i=e,0===l.length&&(r=e));break}case"bitmap":c=!0,l.push({type:"bitmap",name:p.trim()});break;case"br":m();break;case"sbreak":l.length>0&&m(),m()}}return l.length>0&&m(),p}(r),l[0]=r,l[1]=a):a=l[1];let o=a;return l[2]!==o?(i=o.map(f),l[2]=o,l[3]=i):i=l[3],l[4]!==i?(s=(0,t.jsx)("div",{className:"GuiMarkup",children:i}),l[4]=i,l[5]=s):s=l[5],s}function f(e,n){let{align:a,lmargin:i,textIndent:s,items:l}=e,r=l.filter(j),o=l.filter(y),c=o.some(x);return r.length>0&&s>0&&c?(0,t.jsxs)("div",{className:"GuiMarkup-bulletLine",children:[(0,t.jsx)("div",{className:"GuiMarkup-bulletIcon",children:r.map(g)}),(0,t.jsx)("div",{className:"GuiMarkup-bulletText",children:o.map(h)})]},n):c||0!==r.length?(0,t.jsx)("div",{className:"GuiMarkup-line",style:{textAlign:"left"!==a?a:void 0,paddingLeft:i>0?`${i}px`:void 0},children:l.map(d)},n):(0,t.jsx)("div",{className:"GuiMarkup-spacer"},n)}function d(e,n){return"bitmap"===e.type?(0,t.jsx)(c,{name:e.name},n):(0,t.jsx)(u,{span:e},n)}function h(e,n){return(0,t.jsx)(u,{span:e},n)}function g(e,n){return(0,t.jsx)(c,{name:e.name},n)}function x(e){return e.text.trim().length>0}function y(e){return"span"===e.type}function j(e){return"bitmap"===e.type}function b(e){let i,s,l,r,o=(0,n.c)(9),{src:c,alt:u,className:p}=e,m=void 0===p?"MapInfoDialog-preview":p,f=(0,a.useRef)(null),[d,h]=(0,a.useState)(!1);o[0]!==c?(i=()=>{let e=!1;return fetch(c).then(M).then(k).then(t=>{if(e)return void t.close();let n=f.current;n?(n.width=t.width,n.height=t.height,n.getContext("2d")?.drawImage(t,0,0),t.close(),h(!0)):t.close()}).catch(v),()=>{e=!0}},s=[c],o[0]=c,o[1]=i,o[2]=s):(i=o[1],s=o[2]),(0,a.useEffect)(i,s);let g=d?"block":"none";return o[3]!==g?(l={display:g},o[3]=g,o[4]=l):l=o[4],o[5]!==u||o[6]!==m||o[7]!==l?(r=(0,t.jsx)("canvas",{ref:f,className:m,"aria-label":u,style:l}),o[5]=u,o[6]=m,o[7]=l,o[8]=r):r=o[8],r}function v(){}function k(e){return createImageBitmap(e,{colorSpaceConversion:"none"})}function M(e){return e.blob()}function I(e){let s,r,o,c,u,p,m,f,d,h,g,x=(0,n.c)(22),{track:y}=e,[j,b]=(0,a.useState)(!1),[v,k]=(0,a.useState)(!0),M=(0,a.useRef)(null);x[0]!==y?(s=y.toLowerCase(),x[0]=y,x[1]=s):s=x[1];let I=`${l.RESOURCE_ROOT_URL}music/${s}.mp3`;x[2]===Symbol.for("react.memo_cache_sentinel")?(r=()=>()=>{M.current?.pause()},o=[],x[2]=r,x[3]=o):(r=x[2],o=x[3]),(0,a.useEffect)(r,o),x[4]!==j?(c=()=>{let e=M.current;e&&(j?e.pause():e.play().catch(()=>k(!1)))},x[4]=j,x[5]=c):c=x[5];let N=c;return x[6]===Symbol.for("react.memo_cache_sentinel")?(u=()=>b(!0),p=()=>b(!1),m=()=>k(!1),x[6]=u,x[7]=p,x[8]=m):(u=x[6],p=x[7],m=x[8]),x[9]!==I?(f=(0,t.jsx)("audio",{ref:M,src:I,loop:!0,onPlay:u,onPause:p,onError:m}),x[9]=I,x[10]=f):f=x[10],x[11]!==y?(d=(0,t.jsx)("span",{className:"MusicTrackName",children:y}),x[11]=y,x[12]=d):d=x[12],x[13]!==v||x[14]!==j||x[15]!==N?(h=v&&(0,t.jsx)("button",{className:"MapInfoDialog-musicBtn",onClick:N,"aria-label":j?"Pause music":"Play music",children:j?(0,t.jsx)(i.FaVolumeUp,{}):(0,t.jsx)(i.FaVolumeMute,{})}),x[13]=v,x[14]=j,x[15]=N,x[16]=h):h=x[16],x[17]!==j||x[18]!==h||x[19]!==f||x[20]!==d?(g=(0,t.jsxs)("div",{className:"MapInfoDialog-musicTrack","data-playing":j,children:[f,d,h]}),x[17]=j,x[18]=h,x[19]=f,x[20]=d,x[21]=g):g=x[21],g}function N(e){var i,o,c;let u,f,d,h,g,x,y,j,v,k,M,N,C,L,E,P,B,R,T,_,K,U,$,G,O,F,q,z,A,Q,V,H,J,W,X,Y,Z,ee=(0,n.c)(102),{open:et,onClose:en,missionName:ea,missionType:ei}=e,{data:es}=((Z=(0,n.c)(2))[0]!==ea?(Y={queryKey:["parsedMission",ea],queryFn:()=>(0,l.loadMission)(ea)},Z[0]=ea,Z[1]=Y):Y=Z[1],(0,s.useQuery)(Y)),el=(0,a.useRef)(null);if(ee[0]!==et?(u=()=>{if(et){el.current?.focus();try{document.exitPointerLock()}catch{}}},f=[et],ee[0]=et,ee[1]=u,ee[2]=f):(u=ee[1],f=ee[2]),(0,a.useEffect)(u,f),ee[3]!==en||ee[4]!==et?(d=()=>{if(!et)return;let e=e=>{if("KeyI"===e.code||"Escape"===e.key)en();else if("k"===e.key&&(e.metaKey||e.ctrlKey))return void en();e.stopImmediatePropagation()};return window.addEventListener("keydown",e,{capture:!0}),window.addEventListener("keyup",S,{capture:!0}),()=>{window.removeEventListener("keydown",e,{capture:!0}),window.removeEventListener("keyup",S,{capture:!0})}},h=[et,en],ee[3]=en,ee[4]=et,ee[5]=d,ee[6]=h):(d=ee[5],h=ee[6]),(0,a.useEffect)(d,h),!et)return null;ee[7]!==es?(g=es?function(e){for(let t of e.body){if("ObjectDeclaration"!==t.type)continue;let{instanceName:e,body:n}=t;if(e&&"Identifier"===e.type&&"missiongroup"===e.name.toLowerCase()){let e={};for(let t of n){if("Assignment"!==t.type)continue;let{target:n,value:a}=t;"Identifier"===n.type&&"StringLiteral"===a.type&&(e[n.name.toLowerCase()]=a.value)}return e}}return{}}(es.ast):{},ee[7]=es,ee[8]=g):g=ee[8];let er=g;ee[9]!==ea||ee[10]!==es?(x=es?function(e,t){if(e)try{let t=(0,r.getStandardTextureResourceKey)(`textures/gui/${e}`);return(0,l.getUrlForPath)(t)}catch{}try{let e=(0,r.getStandardTextureResourceKey)(`textures/gui/Load_${t}`);return(0,l.getUrlForPath)(e)}catch{}return null}(es.bitmap,ea):null,ee[9]=ea,ee[10]=es,ee[11]=x):x=ee[11];let eo=x,ec=es?.displayName??ea;ee[12]!==ei?(y=ei.toLowerCase(),ee[12]=ei,ee[13]=y):y=ee[13];let eu="singleplayer"===y,ep=er.musictrack;if(ee[14]!==eo||ee[15]!==ec||ee[16]!==eu||ee[17]!==ei||ee[18]!==en||ee[19]!==es){let e,n,a,s,l,r,u=es?.missionString?(i=es.missionString,r=ei.toUpperCase(),i.split("\n").flatMap(e=>{let t=e.match(/^\[([^\]]+)\]/);return t&&!t[1].toUpperCase().split(/\s+/).includes(r)?[]:[e.replace(/^\[[^\]]+\]/,"")]}).join("\n")):null;if(ee[38]!==es?.missionQuote){if(o=s=es?.missionQuote?.trim()??"",a="",e="",!(n=p.test(o)))for(let t of s.split("\n")){let n=t.trim();n.match(/^-+\s/)?e=n.replace(/^-+\s*/,"").trim():n&&(a+=(a?"\n":"")+n)}ee[38]=es?.missionQuote,ee[39]=e,ee[40]=n,ee[41]=a,ee[42]=s}else e=ee[39],n=ee[40],a=ee[41],s=ee[42];(U="MapInfoDialog-overlay",$=en,L=el,E="MapInfoDialog",P=D,B=w,R="dialog",T="true",_="Map Information",K=-1,C="MapInfoDialog-inner",G="MapInfoDialog-left",ee[43]!==eo||ee[44]!==ec||ee[45]!==eu?(O=eo&&eu&&(0,t.jsx)(b,{className:"MapInfoDialog-preview--floated",src:eo,alt:`${ec} preview`},eo),ee[43]=eo,ee[44]=ec,ee[45]=eu,ee[46]=O):O=ee[46],ee[47]!==ec?(j=(0,t.jsx)("h1",{className:"MapInfoDialog-title",children:ec}),ee[47]=ec,ee[48]=j):j=ee[48],ee[49]!==es?(l=es?.planetName&&(0,t.jsx)("span",{className:"MapInfoDialog-planet",children:es.planetName}),ee[49]=es,ee[50]=l):l=ee[50],ee[51]!==l?(v=(0,t.jsx)("div",{className:"MapInfoDialog-meta",children:l}),ee[51]=l,ee[52]=v):v=ee[52],ee[53]!==e||ee[54]!==n||ee[55]!==a||ee[56]!==s?(k=n?(0,t.jsx)("blockquote",{className:"MapInfoDialog-quote",children:(0,t.jsx)(m,{markup:s})}):a?(0,t.jsxs)("blockquote",{className:"MapInfoDialog-quote",children:[(0,t.jsx)("p",{children:a}),e&&(0,t.jsxs)("cite",{children:["— ",e]})]}):null,ee[53]=e,ee[54]=n,ee[55]=a,ee[56]=s,ee[57]=k):k=ee[57],ee[58]!==es)?(M=es?.missionBlurb&&(0,t.jsx)("div",{className:"MapInfoDialog-blurb",children:(c=es.missionBlurb,p.test(c))?(0,t.jsx)(m,{markup:es.missionBlurb.trim()}):(0,t.jsx)("p",{children:es.missionBlurb.trim()})}),ee[58]=es,ee[59]=M):M=ee[59],N=u&&u.trim()&&(0,t.jsx)("div",{className:"MapInfoDialog-section",children:(0,t.jsx)(m,{markup:u})}),ee[14]=eo,ee[15]=ec,ee[16]=eu,ee[17]=ei,ee[18]=en,ee[19]=es,ee[20]=j,ee[21]=v,ee[22]=k,ee[23]=M,ee[24]=N,ee[25]=C,ee[26]=L,ee[27]=E,ee[28]=P,ee[29]=B,ee[30]=R,ee[31]=T,ee[32]=_,ee[33]=K,ee[34]=U,ee[35]=$,ee[36]=G,ee[37]=O}else j=ee[20],v=ee[21],k=ee[22],M=ee[23],N=ee[24],C=ee[25],L=ee[26],E=ee[27],P=ee[28],B=ee[29],R=ee[30],T=ee[31],_=ee[32],K=ee[33],U=ee[34],$=ee[35],G=ee[36],O=ee[37];return ee[60]!==es?(F=es?.missionBriefing&&(0,t.jsxs)("div",{className:"MapInfoDialog-section",children:[(0,t.jsx)("h2",{className:"MapInfoDialog-sectionTitle",children:"Mission Briefing"}),(0,t.jsx)(m,{markup:es.missionBriefing})]}),ee[60]=es,ee[61]=F):F=ee[61],ee[62]!==ep?(q=ep&&(0,t.jsx)(I,{track:ep}),ee[62]=ep,ee[63]=q):q=ee[63],ee[64]!==j||ee[65]!==v||ee[66]!==k||ee[67]!==M||ee[68]!==N||ee[69]!==F||ee[70]!==q||ee[71]!==G||ee[72]!==O?(z=(0,t.jsxs)("div",{className:G,children:[O,j,v,k,M,N,F,q]}),ee[64]=j,ee[65]=v,ee[66]=k,ee[67]=M,ee[68]=N,ee[69]=F,ee[70]=q,ee[71]=G,ee[72]=O,ee[73]=z):z=ee[73],ee[74]!==eo||ee[75]!==ec||ee[76]!==eu?(A=eo&&!eu&&(0,t.jsx)("div",{className:"MapInfoDialog-right",children:(0,t.jsx)(b,{src:eo,alt:`${ec} preview`},eo)}),ee[74]=eo,ee[75]=ec,ee[76]=eu,ee[77]=A):A=ee[77],ee[78]!==C||ee[79]!==z||ee[80]!==A?(Q=(0,t.jsxs)("div",{className:C,children:[z,A]}),ee[78]=C,ee[79]=z,ee[80]=A,ee[81]=Q):Q=ee[81],ee[82]!==en?(V=(0,t.jsx)("button",{className:"MapInfoDialog-closeBtn",onClick:en,children:"Close"}),ee[82]=en,ee[83]=V):V=ee[83],ee[84]===Symbol.for("react.memo_cache_sentinel")?(H=(0,t.jsx)("span",{className:"MapInfoDialog-hint",children:"I or Esc to close"}),ee[84]=H):H=ee[84],ee[85]!==V?(J=(0,t.jsxs)("div",{className:"MapInfoDialog-footer",children:[V,H]}),ee[85]=V,ee[86]=J):J=ee[86],ee[87]!==L||ee[88]!==E||ee[89]!==P||ee[90]!==B||ee[91]!==R||ee[92]!==T||ee[93]!==_||ee[94]!==K||ee[95]!==Q||ee[96]!==J?(W=(0,t.jsxs)("div",{ref:L,className:E,onClick:P,onKeyDown:B,role:R,"aria-modal":T,"aria-label":_,tabIndex:K,children:[Q,J]}),ee[87]=L,ee[88]=E,ee[89]=P,ee[90]=B,ee[91]=R,ee[92]=T,ee[93]=_,ee[94]=K,ee[95]=Q,ee[96]=J,ee[97]=W):W=ee[97],ee[98]!==U||ee[99]!==$||ee[100]!==W?(X=(0,t.jsx)("div",{className:U,onClick:$,children:W}),ee[98]=U,ee[99]=$,ee[100]=W,ee[101]=X):X=ee[101],X}function w(e){return e.stopPropagation()}function D(e){return e.stopPropagation()}function S(e){e.stopImmediatePropagation()}e.s(["MapInfoDialog",()=>N],94247)}]);
\ No newline at end of file
diff --git a/docs/_not-found/__next._full.txt b/docs/_not-found/__next._full.txt
index 5eb98920..c6f69fec 100644
--- a/docs/_not-found/__next._full.txt
+++ b/docs/_not-found/__next._full.txt
@@ -7,8 +7,8 @@
8:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
a:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
c:I[68027,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
-:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
-0:{"P":null,"b":"WsfG8iTCAMPA7qTCB_D8T","c":["","_not-found",""],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L5",null,{"children":["$","$6",null,{"name":"Next.MetadataOutlet","children":"$@7"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$6",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],null]}],false]],"m":"$undefined","G":["$c","$undefined"],"S":true}
+:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
+0:{"P":null,"b":"-NrDAGL0vu_8RrgSU0FFY","c":["","_not-found",""],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/284925ee1f24c201.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L5",null,{"children":["$","$6",null,{"name":"Next.MetadataOutlet","children":"$@7"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$6",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],null]}],false]],"m":"$undefined","G":["$c","$undefined"],"S":true}
9:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
d:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
7:null
diff --git a/docs/_not-found/__next._head.txt b/docs/_not-found/__next._head.txt
index 6d4275b7..e04cbb69 100644
--- a/docs/_not-found/__next._head.txt
+++ b/docs/_not-found/__next._head.txt
@@ -3,4 +3,4 @@
3:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
4:"$Sreact.suspense"
5:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
-0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"MapGenius – Explore maps for Tribes 2"}],["$","meta","1",{"name":"description","content":"Tribes 2 forever."}],["$","link","2",{"rel":"icon","href":"/t2-mapper/icon.png?icon.2911bba1.png","sizes":"108x128","type":"image/png"}],["$","$L5","3",{}]]}]}]}],null]}],"loading":null,"isPartial":false}
+0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"MapGenius – Explore maps for Tribes 2"}],["$","meta","1",{"name":"description","content":"Tribes 2 forever."}],["$","link","2",{"rel":"icon","href":"/t2-mapper/icon.png?icon.2911bba1.png","sizes":"108x128","type":"image/png"}],["$","$L5","3",{}]]}]}]}],null]}],"loading":null,"isPartial":false}
diff --git a/docs/_not-found/__next._index.txt b/docs/_not-found/__next._index.txt
index 8c39c785..eca24451 100644
--- a/docs/_not-found/__next._index.txt
+++ b/docs/_not-found/__next._index.txt
@@ -2,5 +2,5 @@
2:I[12985,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js"],"NuqsAdapter"]
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
-:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
-0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","precedence":"next"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]}]]}],"loading":null,"isPartial":false}
+:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
+0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/284925ee1f24c201.css","precedence":"next"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]}]]}],"loading":null,"isPartial":false}
diff --git a/docs/_not-found/__next._not-found.__PAGE__.txt b/docs/_not-found/__next._not-found.__PAGE__.txt
index e3346884..b84d612f 100644
--- a/docs/_not-found/__next._not-found.__PAGE__.txt
+++ b/docs/_not-found/__next._not-found.__PAGE__.txt
@@ -1,5 +1,5 @@
1:"$Sreact.fragment"
2:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
3:"$Sreact.suspense"
-0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],null,["$","$L2",null,{"children":["$","$3",null,{"name":"Next.MetadataOutlet","children":"$@4"}]}]]}],"loading":null,"isPartial":false}
+0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],null,["$","$L2",null,{"children":["$","$3",null,{"name":"Next.MetadataOutlet","children":"$@4"}]}]]}],"loading":null,"isPartial":false}
4:null
diff --git a/docs/_not-found/__next._not-found.txt b/docs/_not-found/__next._not-found.txt
index ec693ab4..1154e0b1 100644
--- a/docs/_not-found/__next._not-found.txt
+++ b/docs/_not-found/__next._not-found.txt
@@ -1,4 +1,4 @@
1:"$Sreact.fragment"
2:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
3:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
-0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"loading":null,"isPartial":false}
+0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"loading":null,"isPartial":false}
diff --git a/docs/_not-found/__next._tree.txt b/docs/_not-found/__next._tree.txt
index b744b78f..54243166 100644
--- a/docs/_not-found/__next._tree.txt
+++ b/docs/_not-found/__next._tree.txt
@@ -1,2 +1,2 @@
-:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
-0:{"buildId":"WsfG8iTCAMPA7qTCB_D8T","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"/_not-found","paramType":null,"paramKey":"/_not-found","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
+:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
+0:{"buildId":"-NrDAGL0vu_8RrgSU0FFY","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"/_not-found","paramType":null,"paramKey":"/_not-found","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
diff --git a/docs/_not-found/index.html b/docs/_not-found/index.html
index 3a1b27d1..5a4babc0 100644
--- a/docs/_not-found/index.html
+++ b/docs/_not-found/index.html
@@ -1 +1 @@
-404: This page could not be found.MapGenius – Explore maps for Tribes 2
404
This page could not be found.
\ No newline at end of file
+404: This page could not be found.MapGenius – Explore maps for Tribes 2
404
This page could not be found.
\ No newline at end of file
diff --git a/docs/_not-found/index.txt b/docs/_not-found/index.txt
index 5eb98920..c6f69fec 100644
--- a/docs/_not-found/index.txt
+++ b/docs/_not-found/index.txt
@@ -7,8 +7,8 @@
8:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
a:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
c:I[68027,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
-:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
-0:{"P":null,"b":"WsfG8iTCAMPA7qTCB_D8T","c":["","_not-found",""],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L5",null,{"children":["$","$6",null,{"name":"Next.MetadataOutlet","children":"$@7"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$6",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],null]}],false]],"m":"$undefined","G":["$c","$undefined"],"S":true}
+:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
+0:{"P":null,"b":"-NrDAGL0vu_8RrgSU0FFY","c":["","_not-found",""],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/284925ee1f24c201.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L5",null,{"children":["$","$6",null,{"name":"Next.MetadataOutlet","children":"$@7"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$6",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],null]}],false]],"m":"$undefined","G":["$c","$undefined"],"S":true}
9:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
d:I[27201,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"IconMark"]
7:null
diff --git a/docs/index.html b/docs/index.html
index 8db3c94c..8f0edca1 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1 +1 @@
-MapGenius – Explore maps for Tribes 2
\ No newline at end of file
+MapGenius – Explore maps for Tribes 2
\ No newline at end of file
diff --git a/docs/index.txt b/docs/index.txt
index 891df29f..549e3096 100644
--- a/docs/index.txt
+++ b/docs/index.txt
@@ -3,14 +3,14 @@
3:I[39756,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
4:I[37457,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"default"]
5:I[47257,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ClientPageRoot"]
-6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/74f04865c68de700.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
+6:I[31713,["/t2-mapper/_next/static/chunks/e6da73430a674f20.js","/t2-mapper/_next/static/chunks/15f5b04504a3a132.js","/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js"],"default"]
9:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"OutletBoundary"]
a:"$Sreact.suspense"
c:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"ViewportBoundary"]
e:I[97367,["/t2-mapper/_next/static/chunks/4fd93823156e59e8.js"],"MetadataBoundary"]
10:I[68027,[],"default"]
-:HL["/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","style"]
-0:{"P":null,"b":"WsfG8iTCAMPA7qTCB_D8T","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/f9ef36e323faaaed.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L5",null,{"Component":"$6","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@7","$@8"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/74f04865c68de700.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","async":true,"nonce":"$undefined"}],["$","script","script-4",{"src":"/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","async":true,"nonce":"$undefined"}],["$","script","script-5",{"src":"/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lc",null,{"children":"$Ld"}],["$","div",null,{"hidden":true,"children":["$","$Le",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$Lf"}]}]}],null]}],false]],"m":"$undefined","G":["$10",[]],"S":true}
+:HL["/t2-mapper/_next/static/chunks/284925ee1f24c201.css","style"]
+0:{"P":null,"b":"-NrDAGL0vu_8RrgSU0FFY","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/284925ee1f24c201.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/e6da73430a674f20.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"defaultOptions":{"clearOnDefault":false},"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L5",null,{"Component":"$6","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@7","$@8"]}}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/15f5b04504a3a132.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/93b588fa7f31935c.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/5619c5b2b1355f74.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/eced4fe19bc9da99.js","async":true,"nonce":"$undefined"}],["$","script","script-4",{"src":"/t2-mapper/_next/static/chunks/fcdc907286f09d63.js","async":true,"nonce":"$undefined"}],["$","script","script-5",{"src":"/t2-mapper/_next/static/chunks/bb0aa1c978feffed.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lc",null,{"children":"$Ld"}],["$","div",null,{"hidden":true,"children":["$","$Le",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$Lf"}]}]}],null]}],false]],"m":"$undefined","G":["$10",[]],"S":true}
7:{}
8:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
d:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"}]]
diff --git a/src/components/GuiMarkup.module.css b/src/components/GuiMarkup.module.css
new file mode 100644
index 00000000..bd20c959
--- /dev/null
+++ b/src/components/GuiMarkup.module.css
@@ -0,0 +1,15 @@
+.GuiMarkup {
+ font-size: 14px;
+ line-height: 1.5;
+ white-space: pre-wrap;
+}
+
+.GuiMarkup a {
+ color: inherit;
+ text-decoration: underline;
+}
+
+.Bullet {
+ margin-left: 0.5em;
+ margin-right: 0.5em;
+}
diff --git a/src/components/GuiMarkup.spec.tsx b/src/components/GuiMarkup.spec.tsx
new file mode 100644
index 00000000..16430f9e
--- /dev/null
+++ b/src/components/GuiMarkup.spec.tsx
@@ -0,0 +1,30 @@
+import { describe, expect, it } from "vitest";
+import { parseMarkup } from "./GuiMarkup";
+
+const s1 = `Map by: FlyingElmo
+Flyersfan leave me alone now pls
+Website:Part of the Double Threat Pack`;
+
+describe("GuiMarkup", () => {
+ describe("parseMarkup", () => {
+ it("converts markup to JSX", () => {
+ expect(parseMarkup(s1)).toEqual(
+
+
+ {`Map by: FlyingElmo\nFlyersfan leave me alone now pls\nWebsite:`}
+ {" "}
+
+
+ {`Part of the `}
+ Double Threat Pack
+
+
+ ,
+ );
+ });
+ });
+});
diff --git a/src/components/GuiMarkup.tsx b/src/components/GuiMarkup.tsx
new file mode 100644
index 00000000..eb6f2861
--- /dev/null
+++ b/src/components/GuiMarkup.tsx
@@ -0,0 +1,289 @@
+import React, { useMemo } from "react";
+import { getUrlForPath } from "../loaders";
+import { getStandardTextureResourceKey } from "../manifest";
+import styles from "./GuiMarkup.module.css";
+
+// Tokenizer
+
+type Token =
+ | { type: "text"; value: string }
+ | { type: "tag"; name: string; args: string[] };
+
+// spop, spush, lmargin, font, color, bitmap, a, a:wwwlink\t
+const validTagNames = new Set([
+ "spop",
+ "spush",
+ "lmargin",
+ "font",
+ "color",
+ "bitmap",
+ "a",
+ "/a",
+]);
+
+export function tokenize(input: string): Token[] {
+ const pattern = /<([^><]+)>/g;
+ const tokens = input
+ .split(pattern)
+ .map((text, i) => {
+ if (i % 2 === 0) {
+ return text ? ({ type: "text", value: text } as Token) : null;
+ } else {
+ const [name, ...args] = text.split(":");
+ if (validTagNames.has(name.toLowerCase())) {
+ return { type: "tag", name, args } as Token;
+ } else {
+ return { type: "text", value: `<${text}>` } as Token;
+ }
+ }
+ })
+ .filter((token) => token != null);
+ return tokens;
+}
+
+// Parser
+
+function parseFontArgs(args: string[]): {
+ fontDescription: string;
+ fontSize?: number;
+} {
+ // arg is "FontName:size" — size is after the last colon
+ const [fontDescription, fontSizeString] = args;
+ const fontSize = fontSizeString
+ ? Math.max(11, Math.min(parseInt(fontSizeString.trim(), 10), 16))
+ : undefined;
+ return {
+ fontDescription,
+ fontSize,
+ };
+}
+
+type Node = {
+ type: string;
+ source?: string;
+ style?: Record;
+ children?: Array;
+ value?: any;
+};
+
+export function parseMarkup(input: string) {
+ const tokens = tokenize(input);
+ const rootEl: Node = {
+ type: "span",
+ source: "root",
+ style: {},
+ children: [],
+ };
+ let topEl = rootEl;
+ const stack = [topEl];
+ const isUsed = (node: Node): boolean => {
+ return (
+ node.children != null &&
+ node.children.some((child) => typeof child === "string" || isUsed(child))
+ );
+ };
+ for (const token of tokens) {
+ switch (token.type) {
+ case "text":
+ topEl.children.push(token.value);
+ break;
+ case "tag":
+ switch (token.name) {
+ case "spush": {
+ const span = {
+ type: "span",
+ source: "spush",
+ style: {},
+ children: [],
+ };
+ topEl.children.push(span);
+ topEl = span;
+ stack.push(topEl);
+ break;
+ }
+ case "spop": {
+ if (topEl.source !== "root") {
+ let lastPop = stack.pop();
+ while (lastPop.source !== "spush") {
+ lastPop = stack.pop();
+ }
+ topEl = stack[stack.length - 1];
+ }
+ break;
+ }
+ case "lmargin": {
+ // const marginLeft = parseInt(token.args[0].trim(), 10) || 0;
+ // if (topEl.children.length) {
+ // topEl.style.marginLeft = marginLeft;
+ // } else {
+ // const marginNode: Node = {
+ // type: "span",
+ // source: "spush",
+ // style: { marginLeft },
+ // children: [],
+ // };
+ // topEl.children.push(marginNode);
+ // topEl = marginNode;
+ // stack.push(topEl);
+ // }
+ break;
+ }
+ case "font": {
+ const fontSize = parseFontArgs(token.args).fontSize;
+ if (!isUsed(topEl)) {
+ topEl.style.fontSize = fontSize;
+ } else {
+ const fontNode: Node = {
+ type: "span",
+ source: "spush",
+ style: { fontSize },
+ children: [],
+ };
+ topEl.children.push(fontNode);
+ topEl = fontNode;
+ stack.push(topEl);
+ }
+ break;
+ }
+ case "color":
+ if (!isUsed(topEl)) {
+ topEl.style.color = `#${token.args[0].trim()}`;
+ } else {
+ const colorNode: Node = {
+ type: "span",
+ source: "spush",
+ style: { color: `#${token.args[0].trim()}` },
+ children: [],
+ };
+ topEl.children.push(colorNode);
+ topEl = colorNode;
+ stack.push(topEl);
+ }
+ break;
+ case "bitmap": {
+ const bitmap: Node = {
+ type: "bitmap",
+ value: token.args[0],
+ };
+ topEl.children.push(bitmap);
+ break;
+ }
+ case "a": {
+ const arg = token.args[0].trim().split("\t");
+ const href =
+ arg.length === 2 && arg[0] === "wwwlink" ? arg[1] : arg[0];
+ const link: Node = {
+ type: "a",
+ source: "a",
+ value: `http://${href}`,
+ style: {},
+ children: [],
+ };
+ topEl.children.push(link);
+ topEl = link;
+ stack.push(topEl);
+ break;
+ }
+ case "/a": {
+ let lastPop = stack.pop();
+ while (lastPop.source !== "a") {
+ lastPop = stack.pop();
+ }
+ topEl = stack[stack.length - 1];
+ break;
+ }
+ }
+ }
+ }
+ return nodeToJsx(rootEl);
+}
+
+function nodeToJsx(node: Node): React.ReactNode {
+ switch (node.type) {
+ case "span":
+ return React.createElement(
+ "span",
+ {
+ style: Object.keys(node.style).length === 0 ? undefined : node.style,
+ },
+ ...node.children.map((child) =>
+ typeof child === "string" ? child : nodeToJsx(child),
+ ),
+ );
+ case "a":
+ return React.createElement(
+ "a",
+ {
+ href: node.value,
+ style: Object.keys(node.style).length === 0 ? undefined : node.style,
+ rel: "noopener noreferrer",
+ target: "_blank",
+ },
+ ...node.children.map((child) =>
+ typeof child === "string" ? child : nodeToJsx(child),
+ ),
+ );
+ case "bitmap":
+ return ;
+ }
+}
+
+// Bitmap rendering
+
+const bitmapUrlCache = new Map();
+
+function getBitmapUrl(name: string): string | null {
+ if (bitmapUrlCache.has(name)) return bitmapUrlCache.get(name)!;
+ let url: string | null;
+ try {
+ url = getUrlForPath(getStandardTextureResourceKey(`textures/gui/${name}`));
+ } catch {
+ url = null;
+ }
+ bitmapUrlCache.set(name, url);
+ return url;
+}
+
+function GuiBitmap({ name }: { name: string }) {
+ const url = getBitmapUrl(name);
+ if (url) {
+ return ;
+ }
+ if (/bullet/i.test(name)) {
+ return •;
+ }
+ return null;
+}
+
+const guiMarkupTagPattern = /<(?:font|color|bitmap|just|lmargin|a):/i;
+
+/** Whether a string contains Torque GUI markup tags. */
+export function hasGuiMarkup(text: string): boolean {
+ return guiMarkupTagPattern.test(text);
+}
+
+/**
+ * Filter a mission string by game mode prefix, e.g. `[CTF]`, `[DM Bounty]`.
+ * Lines without a prefix are shown for all modes.
+ */
+export function filterMissionStringByMode(
+ str: string,
+ missionType: string,
+): string {
+ const type = missionType.toUpperCase();
+ return str
+ .split("\n")
+ .flatMap((line) => {
+ const m = line.match(/^\[([^\]]+)\]/);
+ if (m && !m[1].toUpperCase().split(/\s+/).includes(type)) return [];
+ return [line.replace(/^\[[^\]]+\]/, "")];
+ })
+ .join("\n");
+}
+
+/** Renders Torque `GuiMLTextCtrl` markup as React elements. */
+export function GuiMarkup({ markup }: { markup: string }) {
+ const children = useMemo(() => parseMarkup(markup), [markup]);
+
+ return