~starkingdoms/starkingdoms

1314012768def43442090d9d34e7a315c533c994 — core 2 hours ago eabc84c core/netcode-round-three
feat: native
39 files changed, 59 insertions(+), 1653 deletions(-)

M Cargo.lock
M crates/unified/Cargo.toml
M crates/unified/src/cli.rs
D crates/unified/src/client/interpolation.rs
M crates/unified/src/client/mod.rs
M crates/unified/src/client/parts.rs
M crates/unified/src/client/planet/incoming_planets.rs
D crates/unified/src/client/server_clock.rs
M crates/unified/src/main.rs
M crates/unified/src/server/mod.rs
M crates/unified/src/server/planets.rs
M crates/unified/src/shared/attachment.rs
M crates/unified/src/shared/config/planet.rs
M crates/unified/src/shared/ecs.rs
M crates/unified/src/shared/ecs/thruster.rs
M crates/unified/src/shared/mod.rs
M crates/unified/src/shared/net.rs
A crates/unified/src/shared/network/mod.rs
M crates/xtask/src/main.rs
D crates/xtask/src/unified_web.rs
M crates/xtask/src/util.rs
D web/.gitignore
D web/.npmrc
D web/.vscode/extensions.json
D web/.vscode/settings.json
D web/README.md
D web/bun.lock
D web/package.json
D web/src/app.d.ts
D web/src/app.html
D web/src/lib/index.ts
D web/src/routes/+layout.svelte
D web/src/routes/+page.svelte
D web/src/routes/layout.css
D web/static/assets
D web/static/robots.txt
D web/svelte.config.js
D web/tsconfig.json
D web/vite.config.ts
M Cargo.lock => Cargo.lock +4 -834
@@ 236,45 236,6 @@ dependencies = [
]

[[package]]
name = "asn1-rs"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f43a50ac4fdca5df8e885c21b835997f0a1cdee65494a6847694a98652d9d8"
dependencies = [
 "asn1-rs-derive",
 "asn1-rs-impl",
 "displaydoc",
 "nom",
 "num-traits",
 "rusticata-macros",
 "thiserror 2.0.18",
 "time",
]

[[package]]
name = "asn1-rs-derive"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c"
dependencies = [
 "proc-macro2",
 "quote",
 "syn 2.0.117",
 "synstructure",
]

[[package]]
name = "asn1-rs-impl"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
dependencies = [
 "proc-macro2",
 "quote",
 "syn 2.0.117",
]

[[package]]
name = "assert_type_match"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 447,28 408,6 @@ dependencies = [
]

[[package]]
name = "aws-lc-rs"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00"
dependencies = [
 "aws-lc-sys",
 "zeroize",
]

[[package]]
name = "aws-lc-sys"
version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4"
dependencies = [
 "cc",
 "cmake",
 "dunce",
 "fs_extra",
]

[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 821,36 760,6 @@ dependencies = [
]

[[package]]
name = "bevy_feathers"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cb29be8f8443c5cc44e1c4710bbe02877e73703c60228ca043f20529a5496c6"
dependencies = [
 "accesskit",
 "bevy_a11y",
 "bevy_app",
 "bevy_asset",
 "bevy_camera",
 "bevy_color",
 "bevy_derive",
 "bevy_ecs",
 "bevy_input_focus",
 "bevy_log",
 "bevy_math",
 "bevy_picking",
 "bevy_platform",
 "bevy_reflect",
 "bevy_render",
 "bevy_shader",
 "bevy_text",
 "bevy_ui",
 "bevy_ui_render",
 "bevy_ui_widgets",
 "bevy_window",
 "smol_str",
]

[[package]]
name = "bevy_gilrs"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1014,7 923,6 @@ dependencies = [
 "bevy_dev_tools",
 "bevy_diagnostic",
 "bevy_ecs",
 "bevy_feathers",
 "bevy_gilrs",
 "bevy_gizmos",
 "bevy_gizmos_render",


@@ 1024,7 932,6 @@ dependencies = [
 "bevy_log",
 "bevy_math",
 "bevy_mesh",
 "bevy_pbr",
 "bevy_picking",
 "bevy_platform",
 "bevy_post_process",


@@ 1048,27 955,6 @@ dependencies = [
]

[[package]]
name = "bevy_light"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d9d2ac64390a9baacb3c0fa0f5456ac1553959d5a387874c102a09aab8b92cc"
dependencies = [
 "bevy_app",
 "bevy_asset",
 "bevy_camera",
 "bevy_color",
 "bevy_ecs",
 "bevy_image",
 "bevy_math",
 "bevy_mesh",
 "bevy_platform",
 "bevy_reflect",
 "bevy_transform",
 "bevy_utils",
 "tracing",
]

[[package]]
name = "bevy_log"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1128,9 1014,7 @@ dependencies = [
 "bevy_asset",
 "bevy_derive",
 "bevy_ecs",
 "bevy_image",
 "bevy_math",
 "bevy_mikktspace",
 "bevy_platform",
 "bevy_reflect",
 "bevy_transform",


@@ 1145,49 1029,6 @@ dependencies = [
]

[[package]]
name = "bevy_mikktspace"
version = "0.17.0-dev"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef8e4b7e61dfe7719bb03c884dc270cd46a82efb40f93e9933b990c5c190c59"

[[package]]
name = "bevy_pbr"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5ab6944ffc6fd71604c0fbca68cc3e2a3654edfcdbfd232f9d8b88e3d20fdc0"
dependencies = [
 "bevy_app",
 "bevy_asset",
 "bevy_camera",
 "bevy_color",
 "bevy_core_pipeline",
 "bevy_derive",
 "bevy_diagnostic",
 "bevy_ecs",
 "bevy_image",
 "bevy_light",
 "bevy_log",
 "bevy_math",
 "bevy_mesh",
 "bevy_platform",
 "bevy_reflect",
 "bevy_render",
 "bevy_shader",
 "bevy_transform",
 "bevy_utils",
 "bitflags 2.11.1",
 "bytemuck",
 "derive_more",
 "fixedbitset",
 "nonmax",
 "offset-allocator",
 "smallvec",
 "static_assertions",
 "thiserror 2.0.18",
 "tracing",
]

[[package]]
name = "bevy_picking"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1645,7 1486,6 @@ dependencies = [
 "bevy_input",
 "bevy_input_focus",
 "bevy_math",
 "bevy_picking",
 "bevy_platform",
 "bevy_reflect",
 "bevy_sprite",


@@ 1659,7 1499,6 @@ dependencies = [
 "taffy",
 "thiserror 2.0.18",
 "tracing",
 "uuid",
]

[[package]]


@@ 1694,26 1533,6 @@ dependencies = [
]

[[package]]
name = "bevy_ui_widgets"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6a63cb818b0de41bdb14990e0ce1aaaa347f871750ab280f80c427e83d72712"
dependencies = [
 "accesskit",
 "bevy_a11y",
 "bevy_app",
 "bevy_camera",
 "bevy_ecs",
 "bevy_input",
 "bevy_input_focus",
 "bevy_log",
 "bevy_math",
 "bevy_picking",
 "bevy_reflect",
 "bevy_ui",
]

[[package]]
name = "bevy_utils"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1798,7 1617,6 @@ version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
dependencies = [
 "bytemuck",
 "serde_core",
]



@@ 2103,15 1921,6 @@ dependencies = [
]

[[package]]
name = "cmake"
version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
dependencies = [
 "cc",
]

[[package]]
name = "cobs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2406,19 2215,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"

[[package]]
name = "crossbeam"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
dependencies = [
 "crossbeam-channel",
 "crossbeam-deque",
 "crossbeam-epoch",
 "crossbeam-queue",
 "crossbeam-utils",
]

[[package]]
name = "crossbeam-channel"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2574,29 2370,6 @@ dependencies = [
]

[[package]]
name = "der-parser"
version = "10.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6"
dependencies = [
 "asn1-rs",
 "displaydoc",
 "nom",
 "num-bigint",
 "num-traits",
 "rusticata-macros",
]

[[package]]
name = "deranged"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
dependencies = [
 "powerfmt",
]

[[package]]
name = "derive_builder"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2817,12 2590,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"

[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"

[[package]]
name = "dyn-clone"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3151,21 2918,6 @@ dependencies = [
]

[[package]]
name = "fragile"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8878864ba14bb86e818a412bfd6f18f9eabd4ec0f008a28e8f7eb61db532fcf9"
dependencies = [
 "futures-core",
]

[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"

[[package]]
name = "fsevent-sys"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3175,28 2927,12 @@ dependencies = [
]

[[package]]
name = "futures"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
dependencies = [
 "futures-channel",
 "futures-core",
 "futures-executor",
 "futures-io",
 "futures-sink",
 "futures-task",
 "futures-util",
]

[[package]]
name = "futures-channel"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
dependencies = [
 "futures-core",
 "futures-sink",
]

[[package]]


@@ 3206,17 2942,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"

[[package]]
name = "futures-executor"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
dependencies = [
 "futures-core",
 "futures-task",
 "futures-util",
]

[[package]]
name = "futures-io"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3247,12 2972,6 @@ dependencies = [
]

[[package]]
name = "futures-sink"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"

[[package]]
name = "futures-task"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3264,13 2983,9 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
dependencies = [
 "futures-channel",
 "futures-core",
 "futures-io",
 "futures-macro",
 "futures-sink",
 "futures-task",
 "memchr",
 "pin-project-lite",
 "slab",
]


@@ 3312,10 3027,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
 "cfg-if",
 "js-sys",
 "libc",
 "wasi",
 "wasm-bindgen",
]

[[package]]


@@ 3325,11 3038,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
dependencies = [
 "cfg-if",
 "js-sys",
 "libc",
 "r-efi 5.3.0",
 "wasip2",
 "wasm-bindgen",
]

[[package]]


@@ 3339,13 3050,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [
 "cfg-if",
 "js-sys",
 "libc",
 "r-efi 6.0.0",
 "rand_core 0.10.1",
 "wasip2",
 "wasip3",
 "wasm-bindgen",
]

[[package]]


@@ 3383,17 3092,6 @@ dependencies = [
]

[[package]]
name = "gl_generator"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
dependencies = [
 "khronos_api",
 "log",
 "xml-rs",
]

[[package]]
name = "glam"
version = "0.30.10"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3442,27 3140,6 @@ dependencies = [
]

[[package]]
name = "glow"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08"
dependencies = [
 "js-sys",
 "slotmap",
 "wasm-bindgen",
 "web-sys",
]

[[package]]
name = "glutin_wgl_sys"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e"
dependencies = [
 "gl_generator",
]

[[package]]
name = "good_lp"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3671,12 3348,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec9d92d097f4749b64e8cc33d924d9f40a2d4eb91402b458014b781f5733d60f"

[[package]]
name = "httlib-huffman"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a9fcbcc408c5526c3ab80d534e5c86e7967c1fb7aa0a8c76abd1edc27deb877"

[[package]]
name = "http"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4002,29 3673,12 @@ dependencies = [
]

[[package]]
name = "khronos-egl"
version = "6.0.0"
name = "konst"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76"
checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb"
dependencies = [
 "libc",
 "libloading",
 "pkg-config",
]

[[package]]
name = "khronos_api"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"

[[package]]
name = "konst"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb"
dependencies = [
 "konst_macro_rules",
 "konst_macro_rules",
]

[[package]]


@@ 4198,12 3852,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86"

[[package]]
name = "lru-slab"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"

[[package]]
name = "malloc_buf"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4261,12 3909,6 @@ dependencies = [
]

[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"

[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4409,16 4051,6 @@ dependencies = [
]

[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
 "memchr",
 "minimal-lexical",
]

[[package]]
name = "nonmax"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4474,16 4106,6 @@ dependencies = [
]

[[package]]
name = "num-bigint"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
dependencies = [
 "num-integer",
 "num-traits",
]

[[package]]
name = "num-complex"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4493,12 4115,6 @@ dependencies = [
]

[[package]]
name = "num-conv"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"

[[package]]
name = "num-derive"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4510,15 4126,6 @@ dependencies = [
]

[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
 "num-traits",
]

[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4822,15 4429,6 @@ dependencies = [
]

[[package]]
name = "oid-registry"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7"
dependencies = [
 "asn1-rs",
]

[[package]]
name = "once_cell"
version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4849,12 4447,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"

[[package]]
name = "openssl-probe"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"

[[package]]
name = "orbclient"
version = "0.3.53"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4984,16 4576,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"

[[package]]
name = "pem"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be"
dependencies = [
 "base64",
 "serde_core",
]

[[package]]
name = "percent-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5192,12 4774,6 @@ dependencies = [
]

[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"

[[package]]
name = "pp-rs"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5302,61 4878,6 @@ dependencies = [
]

[[package]]
name = "quinn"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
dependencies = [
 "bytes",
 "cfg_aliases",
 "pin-project-lite",
 "quinn-proto",
 "quinn-udp",
 "rustc-hash 2.1.2",
 "rustls",
 "socket2 0.6.4",
 "thiserror 2.0.18",
 "tokio",
 "tracing",
 "web-time 1.1.0",
]

[[package]]
name = "quinn-proto"
version = "0.11.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
dependencies = [
 "bytes",
 "getrandom 0.3.4",
 "lru-slab",
 "rand 0.9.4",
 "ring",
 "rustc-hash 2.1.2",
 "rustls",
 "rustls-pki-types",
 "slab",
 "thiserror 2.0.18",
 "tinyvec",
 "tracing",
 "web-time 1.1.0",
]

[[package]]
name = "quinn-udp"
version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
dependencies = [
 "cfg_aliases",
 "libc",
 "once_cell",
 "socket2 0.6.4",
 "tracing",
 "windows-sys 0.60.2",
]

[[package]]
name = "quote"
version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5487,19 5008,6 @@ dependencies = [
]

[[package]]
name = "rcgen"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2"
dependencies = [
 "pem",
 "ring",
 "rustls-pki-types",
 "time",
 "yasna",
]

[[package]]
name = "rdst"
version = "0.20.14"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5620,33 5128,14 @@ version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bda5b3ebbfacba2976a9825dac8cd57efadc2a55a98fc334fb504fa714d1200"
dependencies = [
 "anyhow",
 "async-channel",
 "bevy_ecs",
 "bytes",
 "crossbeam",
 "fragile",
 "futures",
 "hmac-sha256",
 "http",
 "js-sys",
 "log",
 "octets",
 "quinn",
 "rcgen",
 "renet2",
 "renetcode2",
 "rustls",
 "rustls-pki-types",
 "send_wrapper",
 "time",
 "tokio",
 "url",
 "urlencoding",
 "wasm-bindgen",
 "wasm-bindgen-futures",
 "web-sys",
 "wtransport",
]

[[package]]


@@ 5660,20 5149,6 @@ dependencies = [
]

[[package]]
name = "ring"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
 "cc",
 "cfg-if",
 "getrandom 0.2.17",
 "libc",
 "untrusted",
 "windows-sys 0.52.0",
]

[[package]]
name = "robust"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5721,15 5196,6 @@ dependencies = [
]

[[package]]
name = "rusticata-macros"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
dependencies = [
 "nom",
]

[[package]]
name = "rustix"
version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5756,65 5222,6 @@ dependencies = [
]

[[package]]
name = "rustls"
version = "0.23.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
dependencies = [
 "aws-lc-rs",
 "log",
 "once_cell",
 "ring",
 "rustls-pki-types",
 "rustls-webpki",
 "subtle",
 "zeroize",
]

[[package]]
name = "rustls-native-certs"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d"
dependencies = [
 "openssl-probe",
 "rustls-pki-types",
 "schannel",
 "security-framework",
]

[[package]]
name = "rustls-pemfile"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
 "rustls-pki-types",
]

[[package]]
name = "rustls-pki-types"
version = "1.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9"
dependencies = [
 "web-time 1.1.0",
 "zeroize",
]

[[package]]
name = "rustls-webpki"
version = "0.103.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
dependencies = [
 "aws-lc-rs",
 "ring",
 "rustls-pki-types",
 "untrusted",
]

[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5848,15 5255,6 @@ dependencies = [
]

[[package]]
name = "schannel"
version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939"
dependencies = [
 "windows-sys 0.61.2",
]

[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5882,29 5280,6 @@ dependencies = [
]

[[package]]
name = "security-framework"
version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
 "bitflags 2.11.1",
 "core-foundation 0.10.1",
 "core-foundation-sys",
 "libc",
 "security-framework-sys",
]

[[package]]
name = "security-framework-sys"
version = "2.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
dependencies = [
 "core-foundation-sys",
 "libc",
]

[[package]]
name = "self_cell"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5921,9 5296,6 @@ name = "send_wrapper"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
dependencies = [
 "futures-core",
]

[[package]]
name = "serde"


@@ 6043,16 5415,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"

[[package]]
name = "signal-hook-registry"
version = "1.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
dependencies = [
 "errno",
 "libc",
]

[[package]]
name = "signature"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 6183,26 5545,6 @@ dependencies = [
]

[[package]]
name = "socket2"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
dependencies = [
 "libc",
 "windows-sys 0.52.0",
]

[[package]]
name = "socket2"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
dependencies = [
 "libc",
 "windows-sys 0.61.2",
]

[[package]]
name = "spade"
version = "2.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 6276,10 5618,6 @@ dependencies = [
 "bevy_common_assets",
 "bevy_replicon",
 "bevy_replicon_renet2",
 "console_error_panic_hook",
 "ctrlc",
 "getrandom 0.2.17",
 "getrandom 0.4.2",
 "good_lp",
 "leafwing-input-manager",
 "pico-args",


@@ 6288,11 5626,7 @@ dependencies = [
 "serde_json",
 "tokio",
 "tracing-subscriber",
 "tracing-web",
 "url",
 "wasm-bindgen",
 "wasm-bindgen-futures",
 "web-sys",
 "web-time 1.1.0",
]



@@ 6521,37 5855,6 @@ dependencies = [
]

[[package]]
name = "time"
version = "0.3.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
dependencies = [
 "deranged",
 "itoa",
 "num-conv",
 "powerfmt",
 "serde_core",
 "time-core",
 "time-macros",
]

[[package]]
name = "time-core"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"

[[package]]
name = "time-macros"
version = "0.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
dependencies = [
 "num-conv",
 "time-core",
]

[[package]]
name = "tiny-skia"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 6617,26 5920,7 @@ version = "1.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
dependencies = [
 "bytes",
 "libc",
 "mio",
 "parking_lot",
 "pin-project-lite",
 "signal-hook-registry",
 "socket2 0.6.4",
 "tokio-macros",
 "windows-sys 0.61.2",
]

[[package]]
name = "tokio-macros"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
dependencies = [
 "proc-macro2",
 "quote",
 "syn 2.0.117",
]

[[package]]


@@ 6796,19 6080,6 @@ dependencies = [
]

[[package]]
name = "tracing-web"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e6a141feebd51f8d91ebfd785af50fca223c570b86852166caa3b141defe7c"
dependencies = [
 "js-sys",
 "tracing-core",
 "tracing-subscriber",
 "wasm-bindgen",
 "web-sys",
]

[[package]]
name = "ttf-parser"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 6922,12 6193,6 @@ dependencies = [
]

[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"

[[package]]
name = "url"
version = "2.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 6940,12 6205,6 @@ dependencies = [
]

[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"

[[package]]
name = "utf-8"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 7312,7 6571,6 @@ dependencies = [
 "cfg_aliases",
 "document-features",
 "hashbrown 0.16.1",
 "js-sys",
 "log",
 "naga",
 "portable-atomic",


@@ 7320,8 6578,6 @@ dependencies = [
 "raw-window-handle",
 "smallvec",
 "static_assertions",
 "wasm-bindgen",
 "web-sys",
 "wgpu-core",
 "wgpu-hal",
 "wgpu-types",


@@ 7353,7 6609,6 @@ dependencies = [
 "smallvec",
 "thiserror 2.0.18",
 "wgpu-core-deps-apple",
 "wgpu-core-deps-wasm",
 "wgpu-core-deps-windows-linux-android",
 "wgpu-hal",
 "wgpu-types",


@@ 7369,15 6624,6 @@ dependencies = [
]

[[package]]
name = "wgpu-core-deps-wasm"
version = "27.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b1027dcf3b027a877e44819df7ceb0e2e98578830f8cd34cd6c3c7c2a7a50b7"
dependencies = [
 "wgpu-hal",
]

[[package]]
name = "wgpu-core-deps-windows-linux-android"
version = "27.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 7402,20 6648,15 @@ dependencies = [
 "cfg-if",
 "cfg_aliases",
 "core-graphics-types 0.2.0",
 "glow",
 "glutin_wgl_sys",
 "gpu-alloc",
 "gpu-allocator",
 "gpu-descriptor",
 "hashbrown 0.16.1",
 "js-sys",
 "khronos-egl",
 "libc",
 "libloading",
 "log",
 "metal",
 "naga",
 "ndk-sys",
 "objc",
 "once_cell",
 "ordered-float",


@@ 7428,8 6669,6 @@ dependencies = [
 "renderdoc-sys",
 "smallvec",
 "thiserror 2.0.18",
 "wasm-bindgen",
 "web-sys",
 "wgpu-types",
 "windows 0.58.0",
 "windows-core 0.58.0",


@@ 8068,43 7307,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"

[[package]]
name = "wtransport"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e5e745c8789c20095c9061d292098d4106660efe2d172efd8ae7a369fe28e3e"
dependencies = [
 "bytes",
 "pem",
 "quinn",
 "rcgen",
 "rustls",
 "rustls-native-certs",
 "rustls-pemfile",
 "rustls-pki-types",
 "sha2",
 "socket2 0.5.10",
 "thiserror 2.0.18",
 "time",
 "tokio",
 "tracing",
 "url",
 "wtransport-proto",
 "x509-parser",
]

[[package]]
name = "wtransport-proto"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a09d89a8dba201c2439d9d5eca55a0faa08909d69da50decdb5ec00be0ac504"
dependencies = [
 "httlib-huffman",
 "octets",
 "thiserror 2.0.18",
 "url",
]

[[package]]
name = "x11-dl"
version = "2.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 8137,23 7339,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"

[[package]]
name = "x509-parser"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460"
dependencies = [
 "asn1-rs",
 "data-encoding",
 "der-parser",
 "lazy_static",
 "nom",
 "oid-registry",
 "rusticata-macros",
 "thiserror 2.0.18",
 "time",
]

[[package]]
name = "xcursor"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 8179,12 7364,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"

[[package]]
name = "xml-rs"
version = "0.8.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f"

[[package]]
name = "xtask"
version = "0.1.0"
dependencies = [


@@ 8199,15 7378,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3"

[[package]]
name = "yasna"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd"
dependencies = [
 "time",
]

[[package]]
name = "yazi"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

M crates/unified/Cargo.toml => crates/unified/Cargo.toml +4 -27
@@ 4,49 4,26 @@ description = "A game about floating through space"
edition = "2024"
version = "0.1.0"


[dependencies]
bevy = { workspace = true }
bevy = { workspace = true, features = ["x11", "wayland"] }
avian2d = { workspace = true }
bevy_common_assets = { workspace = true }
tracing-subscriber = { workspace = true }
serde = { workspace = true }
rand = { workspace = true }
getrandom = { workspace = true }
pico-args = { workspace = true }
leafwing-input-manager = { workspace = true }
good_lp = { workspace = true }
web-time = { workspace = true }
bevy_replicon = { workspace = true, features = ["client"] }
bevy_replicon_renet2 = { workspace = true, features = ["client", "netcode"] }
bevy_replicon = { workspace = true, features = ["client", "server"] }
bevy_replicon_renet2 = { workspace = true, features = ["client", "netcode", "server", "native_transport"] }
url = { workspace = true }
serde_json = { workspace = true }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
ctrlc = { workspace = true }
tokio = { version = "1", features = ["rt-multi-thread"] }

[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = { workspace = true }
wasm-bindgen-futures = { workspace = true }
tracing-web = { workspace = true }
console_error_panic_hook = { workspace = true }
getrandom02 = { package = "getrandom", version = "0.2", features = ["js"] }
web-sys = { workspace = true, features = ["Window", "Response"] }

[features]
native_dev = [
    "bevy/file_watcher",
    "bevy/hotpatching",
    "bevy/dynamic_linking",
    "native"
]
native = [
    "bevy/x11",
    "bevy/wayland",
    "bevy_replicon/server",
    "bevy_replicon_renet2/server",
    "bevy_replicon_renet2/native_transport",
    "bevy_replicon_renet2/wt_server_transport"
]
wasm = ["getrandom/wasm_js", "bevy/webgl2", "bevy_replicon_renet2/wt_client_transport"]
]
\ No newline at end of file

M crates/unified/src/cli.rs => crates/unified/src/cli.rs +0 -8
@@ 1,13 1,7 @@
#[cfg(not(any(feature = "native", feature = "wasm")))]
compile_error!("You need to enable one of native, wasm features");
#[cfg(all(feature = "native", feature = "wasm"))]
compile_error!("You cannot enable both native and wasm features");

pub enum StkArgs {
    Client {
        server: String,
    },
    #[cfg(not(target_arch = "wasm32"))]
    Server {
        management_bind: std::net::SocketAddr,
        native_bind: std::net::SocketAddr,


@@ 16,7 10,6 @@ pub enum StkArgs {
    },
}

#[cfg(not(target_arch = "wasm32"))]
pub fn parse_args() -> StkArgs {
    let mut pargs = pico_args::Arguments::from_env();



@@ 42,7 35,6 @@ pub fn parse_args() -> StkArgs {
                server: pargs.value_from_str(["-s", "--server"]).unwrap(),
            }
        },
        #[cfg(not(target_arch = "wasm32"))]
        "server" => {
            StkArgs::Server {
                management_bind: pargs.value_from_str("--management-bind").unwrap(),

D crates/unified/src/client/interpolation.rs => crates/unified/src/client/interpolation.rs +0 -125
@@ 1,125 0,0 @@
use std::collections::VecDeque;
use std::f64::consts::PI;
use std::time::{Duration};
use avian2d::parry::transformation::utils::transform;
use bevy_replicon::client::confirm_history::ConfirmHistory;
use crate::client::components::{ServerClock, ServerTimeOffset};
use crate::prelude::*;
use crate::shared::plugins::TICK_RATE;

/// interpolation period in seconds
const INTERP: f64 = 0.150;

pub fn interpolation_plugin(app: &mut App) {
    app
        .add_systems(Update, update_interpolation_info)
        .add_systems(Update, sync_non_interpolated_transforms)
        .add_systems(Update, do_interpolation);
}

#[derive(Component, Debug)]
pub struct TranslationInterpolationInfo {
    pub positions: VecDeque<(f64, Vec2)>,
}
#[derive(Component, Debug)]
pub struct RotationInterpolationInfo {
    pub rotations: VecDeque<(f64, f64)> // time and rotation
}

fn update_interpolation_info(
    mut interpolation_pos_query: Query<(Entity, &Position, &mut TranslationInterpolationInfo, &ConfirmHistory), Changed<Position>>,
    mut interpolation_rot_query: Query<(&Rotation, &AngularVelocity, &mut RotationInterpolationInfo, &ConfirmHistory), Changed<Rotation>>,
    server_clock: Res<ServerClock>,
    server_time_offset: Res<ServerTimeOffset>,
) {
    for (entity, position, mut info, confirm_history) in interpolation_pos_query.iter_mut() {
        let now = confirm_history.last_tick().get() as f64 / TICK_RATE - **server_time_offset;
        info.positions.push_back((now, position.as_vec2()));

        let mut last_over_time = 0;
        for (i, (time, _)) in info.positions.iter().enumerate() {
            if *time < now - INTERP {
                last_over_time = i;
            }
        }
        if last_over_time > 0 {
            info.positions.drain(..last_over_time);
        }
    }
    for (rotation, angular_velocity, mut info, confirm_history) in interpolation_rot_query.iter_mut() {
        let now = confirm_history.last_tick().get() as f64 / TICK_RATE - **server_time_offset;
        let delta_rotation = angular_velocity.0.to_radians() / TICK_RATE;
        let num_revolutions = (delta_rotation / (2.0*PI)).round();
        let mut rotation_offset = 0.0;
        let rotation = rotation.as_radians() as f64;
        if let Some((_, rotation)) = info.rotations.back() {
            if delta_rotation + rotation >= PI {
                rotation_offset = 2.0 * PI;
            } else if delta_rotation + rotation < -PI {
                rotation_offset = -2.0 * PI;
            }
        }
        info.rotations.push_back((now, rotation + rotation_offset + num_revolutions*2.0*PI));

        let mut last_over_time = 0;
        for (i, (time, _)) in info.rotations.iter().enumerate() {
            if *time < now - INTERP {
                last_over_time = i;
            }
        }
        if last_over_time > 0 {
            info.rotations.drain(..last_over_time);
        }
    }
}
fn sync_non_interpolated_transforms(
    mut query: Query<(&mut Transform, &Position), (Changed<Position>, Without<TranslationInterpolationInfo>)>,
) {
    for (mut transform, position) in &mut query {
        transform.translation = position.as_vec2().extend(0.0);
    }
}
fn do_interpolation(
    mut interpolation_query: Query<(Entity, &mut Transform, &mut TranslationInterpolationInfo, &RotationInterpolationInfo)>,
    time: Res<Time>,
) {
    for (entity, mut transform, mut pos_info, rot_info) in &mut interpolation_query {
        let now = time.elapsed().as_secs_f64();

        let mut time_after_now = 0;
        for (i, (time, _)) in pos_info.positions.iter().enumerate() {
            if *time > now - INTERP {
                time_after_now = i;
                break;
            }
        }
        // this should not happen, but is necessary to prevent a panic
        if time_after_now == 0 { continue }
        // we need to have 2 packets to reference, so continuing if we don't have that is a-ok
        let Some(first_time) = pos_info.positions.get(time_after_now-1) else { continue };
        let Some(second_time) = pos_info.positions.get(time_after_now) else { continue };
        let elapsed = now - INTERP - first_time.0;
        let dt = second_time.0 - first_time.0;
        let progress = elapsed / dt; // should be between 0.0 and 1.0
        if progress < 0.0 || progress > 1.0 { continue }
        transform.translation = (first_time.1 + progress as f32 * (second_time.1 - first_time.1)).extend(0.0);

        let mut time_after_now = 0;
        for (i, (time, _)) in rot_info.rotations.iter().enumerate() {
            if *time > now - INTERP {
                time_after_now = i;
                break;
            }
        }
        // this should not happen, but is necessary to prevent a panic
        if time_after_now == 0 { continue }
        // we need to have 2 packets to reference, so continuing if we don't have that is a-ok
        let Some(first_time) = rot_info.rotations.get(time_after_now-1) else { continue };
        let Some(second_time) = rot_info.rotations.get(time_after_now) else { continue };
        let elapsed = now - INTERP - first_time.0;
        let dt = second_time.0 - first_time.0;
        let progress = elapsed / dt; // should be between 0.0 and 1.0
        if progress < 0.0 || progress > 1.0 { continue }
        transform.rotation = Quat::from_rotation_z((first_time.1 + progress * (second_time.1 - first_time.1)) as f32);
    }
}
\ No newline at end of file

M crates/unified/src/client/mod.rs => crates/unified/src/client/mod.rs +0 -6
@@ 42,8 42,6 @@ use std::rc::Rc;
use wasm_bindgen::JsCast;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_futures::JsFuture;
use crate::client::interpolation::interpolation_plugin;
use crate::client::server_clock::server_clock_plugin;
use crate::shared::config::planet::Planet;

pub mod colors;


@@ 60,8 58,6 @@ pub mod starguide;
pub mod crafting;
pub mod components;
pub mod plugins;
pub mod interpolation;
pub mod server_clock;

pub struct ClientPlugin {
    pub server: Option<String>


@@ 85,8 81,6 @@ impl Plugin for ClientPlugin {
            .add_plugins(starguide_input_plugin)
            //.add_plugins(starguide_orbit_plugin)
            .add_plugins(crafting_ui_plugin)
            .add_plugins(interpolation_plugin)
            .add_plugins(server_clock_plugin)
            .add_systems(Update, find_me)
            .insert_state(GameplayState::Main)
            .insert_resource(DebugPickingMode::Disabled)

M crates/unified/src/client/parts.rs => crates/unified/src/client/parts.rs +0 -7
@@ 12,7 12,6 @@ use crate::client::components::Me;
use crate::client::ship::attachment::AttachmentDebugRes;
use crate::prelude::*;
use bevy_replicon::client::confirm_history::ConfirmHistory;
use crate::client::interpolation::{RotationInterpolationInfo, TranslationInterpolationInfo};

pub fn parts_plugin(app: &mut App) {
    app.insert_resource(DragResource { dragged: None });


@@ 61,12 60,6 @@ fn handle_incoming_parts(
            .insert(MAIN_LAYER)
            .insert(sprite)
            .insert(Pickable::default())
            .insert(TranslationInterpolationInfo {
                positions: VecDeque::new(),
            })
            .insert(RotationInterpolationInfo {
                rotations: VecDeque::new(),
            })
            .observe(on_part_click)
            .observe(open_crafting_ui);
    }

M crates/unified/src/client/planet/incoming_planets.rs => crates/unified/src/client/planet/incoming_planets.rs +1 -8
@@ 4,7 4,6 @@ use crate::shared::config::planet::{Planet, SpecialSpriteProperties};
use crate::prelude::*;
use crate::shared::ecs::{MAIN_STAR_LAYERS};
use bevy_replicon::client::confirm_history::ConfirmHistory;
use crate::client::interpolation::{RotationInterpolationInfo, TranslationInterpolationInfo};

pub fn incoming_planets_plugin(app: &mut App) {
    app.add_systems(Update, (handle_incoming_planets, handle_updated_planets));


@@ 27,13 26,7 @@ fn handle_incoming_planets(
    for (new_entity, new_planet, transform, confirm_history) in new_planets.iter() {
        commands.entity(new_entity)
            .insert(MAIN_STAR_LAYERS.clone())
            .insert(build_planet_sprite(new_planet, &asset_server))
            .insert(TranslationInterpolationInfo {
                positions: VecDeque::new(),
            })
            .insert(RotationInterpolationInfo {
                rotations: VecDeque::new(),
            });
            .insert(build_planet_sprite(new_planet, &asset_server));
        trace!(?new_planet, "prepared new planet");
    }
}

D crates/unified/src/client/server_clock.rs => crates/unified/src/client/server_clock.rs +0 -67
@@ 1,67 0,0 @@
use std::collections::VecDeque;
use crate::client::components::{ServerClock, ServerTimeOffset};
use crate::prelude::*;
use crate::shared::ecs::clock_sync::{ClientTiming, ServerTiming};

pub fn server_clock_plugin(app: &mut App) {
    app
        .insert_resource(SyncTimer(Timer::from_seconds(1.0, TimerMode::Repeating)))
        .insert_resource(ServerClock {
            rtt_queue: VecDeque::with_capacity(10), // 10 seconds
            time_offset_queue: VecDeque::with_capacity(10),
            ..default()
        })
        .add_systems(Update, send_timing)
        .add_systems(Update, recv_timing);
}

#[derive(Resource)]
struct SyncTimer(Timer);

fn send_timing(
    mut sync_timer: ResMut<SyncTimer>,
    mut client_timing: MessageWriter<ClientTiming>,
    time: Res<Time>,
) {
    if !sync_timer.0.tick(time.delta()).is_finished() {
        return
    }
    sync_timer.0.reset();

    let Ok(now) = web_time::SystemTime::now().duration_since(web_time::UNIX_EPOCH) else {
        warn!("Could not get system time");
        return
    };
    client_timing.write(ClientTiming {
        time: now.as_secs_f64(),
    });
}

fn recv_timing(
    mut server_timings: MessageReader<ServerTiming>,
    mut server_clock: ResMut<ServerClock>,
    mut server_time_offset: ResMut<ServerTimeOffset>,
    time: Res<Time>,
) {
    for ServerTiming { client_tx, server, server_time_elapsed } in server_timings.read() {
        let Ok(now) = web_time::SystemTime::now().duration_since(web_time::UNIX_EPOCH) else {
            warn!("Could not get system time");
            return
        };
        let client_rx = now.as_secs_f64();
        let time_offset = 2.0*server - client_tx - client_rx;
        let rtt = client_rx - client_tx;

        if server_clock.rtt_queue.len() >= 10 {
            server_clock.rtt_queue.drain(10..);
        }
        if server_clock.time_offset_queue.len() >= 10 {
            server_clock.time_offset_queue.drain(10..);
        }
        server_clock.rtt_queue.push_back(rtt);
        server_clock.time_offset_queue.push_back(time_offset);
        server_clock.rtt = server_clock.rtt_queue.iter().sum::<f64>() / server_clock.rtt_queue.len() as f64;
        server_clock.time_offset = server_clock.time_offset_queue.iter().sum::<f64>() / server_clock.time_offset_queue.len() as f64;
        **server_time_offset = *server_time_elapsed - time.elapsed_secs_f64();
    }
}
\ No newline at end of file

M crates/unified/src/main.rs => crates/unified/src/main.rs +2 -14
@@ 18,34 18,22 @@
#![allow(dead_code, unused, reason = "We have a lot of this and it's getting annoying")]

pub mod client;
#[cfg(not(target_arch = "wasm32"))]
pub mod server;

pub mod prelude;

#[cfg(target_arch = "wasm32")]
pub mod wasm_entrypoint;
pub mod cli;
pub mod shared;
pub mod universal_entrypoint;

use std::str::FromStr;
#[cfg(target_arch = "wasm32")]
pub use wasm_entrypoint::*;

use crate::prelude::*;
use crate::universal_entrypoint::run;
use tracing_subscriber::util::SubscriberInitExt;
use bevy::log::tracing_subscriber;

#[cfg(feature = "wasm")]
fn main() {
    // noop on webassembly
}

#[cfg(feature = "native")]
fn main() -> AppExit {
    use tracing_subscriber::util::SubscriberInitExt;
    use bevy::log::tracing_subscriber;

    let cli = cli::parse_args();

    tracing_subscriber::fmt()

M crates/unified/src/server/mod.rs => crates/unified/src/server/mod.rs +5 -13
@@ 22,7 22,6 @@ use bevy_replicon::server::AuthorizedClient;
use bevy_replicon_renet2::RenetChannelsExt;
use bevy_replicon_renet2::netcode::{
    BoxedSocket, NativeSocket, NetcodeServerTransport, ServerAuthentication, ServerSetupConfig,
    WebTransportServer, WebTransportServerConfig,
};
use bevy_replicon_renet2::renet2::{ConnectionConfig, RenetServer};
use web_time::SystemTime;


@@ 42,6 41,7 @@ use crate::server::client_timing::client_timing_plugin;
use crate::server::orbit::OrbitPlugin;
use crate::server::player::thrust::server_thrust_plugin;
use crate::shared::net::{encode_cert_hash, ManagementInfo, STARKINGDOMS_PROTOCOL_MAGIC};
use crate::shared::network::ReplicateAndInterpolate;

const MAX_CLIENTS: usize = 32;



@@ 83,34 83,26 @@ impl Plugin for ServerPlugin {
            let native_socket = NativeSocket::new(UdpSocket::bind(native_bind).expect("failed to bind server UDP socket"))
                .expect("failed to create native socket");

            let (wt_config, cert_hash) = WebTransportServerConfig::new_selfsigned(wt_bind, MAX_CLIENTS)
                .expect("failed to create self-signed WebTransport server config");
            let runtime = tokio::runtime::Runtime::new().expect("failed to create tokio runtime");
            let wt_socket = WebTransportServer::new(wt_config, runtime.handle().clone())
                .expect("failed to create WebTransport server socket");

            let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
            let server_config = ServerSetupConfig {
                current_time,
                max_clients: MAX_CLIENTS,
                protocol_id: STARKINGDOMS_PROTOCOL_MAGIC,
                socket_addresses: vec![vec![native_bind], vec![wt_bind]],
                socket_addresses: vec![vec![native_bind]],
                authentication: ServerAuthentication::Unsecure,
            };
            let transport = NetcodeServerTransport::new_with_sockets(server_config, vec![
                BoxedSocket::new(native_socket),
                BoxedSocket::new(wt_socket),
            ]).expect("failed to create server transport");

            spawn_management_server(management_bind, ManagementInfo {
                native_port: native_bind.port(),
                wt_port: wt_bind.port(),
                cert_hash: encode_cert_hash(&cert_hash.hash),
                cert_hash: "".to_string(),
            });

            commands.insert_resource(server);
            commands.insert_resource(transport);
            commands.insert_resource(TokioRuntime(runtime));
        });
    }
}


@@ 133,13 125,13 @@ fn handle_authorized(
) {
    for client in newly_authorized_clients.iter() {
        let player = commands
            .spawn((Replicated, ConnectedGameEntity {
            .spawn((ReplicateAndInterpolate, ConnectedGameEntity {
                network_entity: client,
            }))
            .id();

        commands.entity(client).insert((
            Replicated,
            ReplicateAndInterpolate,
            ConnectedNetworkEntity {
                game_entity: player,
            },

M crates/unified/src/server/planets.rs => crates/unified/src/server/planets.rs +2 -1
@@ 4,6 4,7 @@ use bevy_replicon::prelude::Replicated;
use crate::prelude::*;
use crate::shared::config::planet::{PlanetSpring, PlanetSpringJoint};
use crate::shared::config::planet::{Planet, PlanetBundle, PlanetConfigCollection};
use crate::shared::network::ReplicateAndInterpolate;
use crate::shared::world_config::WorldConfigResource;

const PLANET_SENSOR_PADDING: f64 = 2.0;


@@ 91,7 92,7 @@ pub fn update_planets(
                                },
                                Transform::from_translation(planet.default_position),
                                RigidBody::Kinematic,
                                Replicated,
                                ReplicateAndInterpolate,
                            )).id();
                            commands.spawn((
                                PlanetSpringJoint {

M crates/unified/src/shared/attachment.rs => crates/unified/src/shared/attachment.rs +4 -3
@@ 19,9 19,10 @@ use crate::prelude::*;
use serde::{Deserialize, Serialize};
use std::ops::Deref;
use bevy_replicon::shared::replication::Replicated;
use crate::shared::network::ReplicateAndInterpolate;

#[derive(Component, Serialize, Deserialize)]
#[require(Replicated)]
#[require(ReplicateAndInterpolate)]
/// The primary component for a ship structure. Will be present on Hearty
pub struct Ship;



@@ 39,7 40,7 @@ pub struct Parts(#[entities] Vec<Entity>);
pub struct PartInShip(#[entities] pub Entity);

#[derive(Component, Serialize, Deserialize)]
#[require(Transform, Replicated)]
#[require(Transform, ReplicateAndInterpolate)]
/// A `Joint` is a separate entity (child of a part) that represents a single possible attachment
/// point for that part.
pub struct Joint {


@@ 73,7 74,7 @@ impl Deref for Joints {
}

#[derive(Component, Serialize, Deserialize, MapEntities)]
#[require(Replicated)]
#[require(ReplicateAndInterpolate)]
#[relationship(relationship_target = Snaps)]
/// The `Part` that this Snap belongs to. A Snap is an internal entity used for snapping during
/// the attachment routine. Managed automatically.

M crates/unified/src/shared/config/planet.rs => crates/unified/src/shared/config/planet.rs +2 -1
@@ 3,11 3,12 @@ use bevy::color::Color;
use crate::prelude::*;
use serde::{Deserialize, Serialize};
use bevy_replicon::prelude::Replicated;
use crate::shared::network::ReplicateAndInterpolate;

#[derive(Deserialize, Asset, TypePath, Component, Serialize, Clone, Debug)]
#[require(
    RigidBody::Dynamic,
    Replicated
    ReplicateAndInterpolate
)]
pub struct Planet {
    pub name: String,

M crates/unified/src/shared/ecs.rs => crates/unified/src/shared/ecs.rs +2 -1
@@ 8,6 8,7 @@ use crate::prelude::*;
use avian2d::prelude::*;
use std::collections::HashMap;
use std::sync::LazyLock;
use crate::shared::network::ReplicateAndInterpolate;
use bevy::ecs::entity::MapEntities;
use bevy_replicon::prelude::Replicated;



@@ 30,7 31,7 @@ pub const ORBIT_LAYER: RenderLayers = RenderLayers::layer(2);
    LinearVelocity,
    AngularVelocity,
    ConstantForce,
    Replicated
    ReplicateAndInterpolate
)]
pub struct Part {
    pub config: PartConfig,

M crates/unified/src/shared/ecs/thruster.rs => crates/unified/src/shared/ecs/thruster.rs +2 -1
@@ 5,6 5,7 @@ use bevy::prelude::Bundle;
use serde::{Deserialize, Serialize};
use crate::prelude::{ChildOf, Component, Entity, Transform};
use bevy_replicon::shared::replication::Replicated;
use crate::shared::network::ReplicateAndInterpolate;

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct ThrusterId(pub String);


@@ 31,7 32,7 @@ impl Deref for PartThrusters {
pub struct ThrusterOfPart(#[entities] pub Entity);

#[derive(Component, Serialize, Deserialize)]
#[require(Replicated)]
#[require(ReplicateAndInterpolate)]
pub struct Thruster {
    pub id: ThrusterId,
    pub thrust_vector: Vec2,

M crates/unified/src/shared/mod.rs => crates/unified/src/shared/mod.rs +2 -1
@@ 5,4 5,5 @@ pub mod thrust;
pub mod world_config;
pub mod plugins;
pub mod ecs;
pub mod net;
\ No newline at end of file
pub mod net;
pub mod network;
\ No newline at end of file

M crates/unified/src/shared/net.rs => crates/unified/src/shared/net.rs +2 -2
@@ 11,6 11,7 @@ use crate::shared::config::planet::{Planet, PlanetSpring, PlanetSpringJoint};
use crate::shared::ecs::{CanCraft, CraftPartRequest, DragRequestEvent, Drill, Part, Player, PlayerStorage, SingleStorage, Temperature, ToggleDrillEvent};
use crate::shared::ecs::clock_sync::{ClientTiming, ServerTiming};
use crate::shared::ecs::thruster::{Thruster, ThrusterOfPart};
use crate::shared::network::Tick;
use crate::shared::thrust::ThrustSolution;

pub const STARKINGDOMS_PROTOCOL_MAGIC: u64 = 0x5a5a_e37e_4aaa;


@@ 26,8 27,7 @@ pub fn register_replication(app: &mut App) {
        .add_mapped_client_message::<ToggleDrillEvent>(Channel::Ordered)
        .add_mapped_client_message::<CraftPartRequest>(Channel::Ordered)

        .replicate_once::<Transform>()
        .replicate_once::<GlobalTransform>()
        .replicate::<Transform>()

        .replicate::<Position>()
        .replicate::<Rotation>()

A crates/unified/src/shared/network/mod.rs => crates/unified/src/shared/network/mod.rs +27 -0
@@ 0,0 1,27 @@
use bevy::app::FixedPreUpdate;
use bevy::prelude::Resource;
use crate::prelude::{App, Component, Query, ResMut};
use bevy_replicon::shared::replication::Replicated;

#[derive(Resource)]
pub struct Tick(pub u64);
#[derive(Component, Default)]
pub struct ServerTick(pub u64);

#[derive(Component, Default)]
#[require(Replicated, ServerTick)]
pub struct ReplicateAndInterpolate;


pub fn tick_update_plugin(app: &mut App) {
    app
        .insert_resource(Tick(0))
        .add_systems(FixedPreUpdate, tick);
}

fn tick(mut tick_counter: ResMut<Tick>, mut entities: Query<&mut ServerTick>) {
    tick_counter.0 += 1;
    for mut entity in entities.iter_mut() {
        entity.0 = tick_counter.0;
    }
}
\ No newline at end of file

M crates/xtask/src/main.rs => crates/xtask/src/main.rs +0 -3
@@ 2,10 2,8 @@ use std::io::{stdout, Write};
use colored::Colorize;
use qsv_tabwriter::TabWriter;
use crate::unified::{RunClientNative, RunListenServerNative, RunServerNative};
use crate::unified_web::RunClientWeb;

mod unified;
mod unified_web;
mod util;

fn main() {


@@ 38,7 36,6 @@ fn tasks() -> Vec<Box<dyn Task>> {

    v.push(Box::new(RunClientNative));
    v.push(Box::new(RunServerNative));
    v.push(Box::new(RunClientWeb));
    v.push(Box::new(RunListenServerNative));

    v

D crates/xtask/src/unified_web.rs => crates/xtask/src/unified_web.rs +0 -29
@@ 1,29 0,0 @@
use std::env::set_current_dir;
use crate::Task;
use crate::util::{cargo, wasmopt, wbg, workspace_dir};

#[derive(Default)]
pub struct RunClientWeb;
impl Task for RunClientWeb {
    fn name(&self) -> &'static str {
        "unified:web:client"
    }
    fn help(&self) -> &'static str {
        "Build the client (web)"
    }

    fn run(&self, _args: Vec<String>) {
        set_current_dir(workspace_dir().join("crates/unified/")).unwrap();
        cargo("build --profile wasm-release -F wasm --package starkingdoms --target wasm32-unknown-unknown".to_string());

        let wks = workspace_dir();
        let target_dir = wks.join("target/").join("wasm32-unknown-unknown/").join("wasm-release/");

        let unopt = target_dir.join("starkingdoms.wasm");
        let opt = target_dir.join("starkingdoms-opt.wasm");
        let bundle = wks.join("web/src/lib/bundle");

        wasmopt(format!("{} -O -o {}", unopt.display(), opt.display()));
        wbg(format!("--out-dir {} {} --target web", bundle.display(), opt.display()))
    }
}
\ No newline at end of file

M crates/xtask/src/util.rs => crates/xtask/src/util.rs +0 -30
@@ 64,33 64,3 @@ impl SanitizedEnvVars {
}

static SANITIZED_ENV_VARS: SanitizedEnvVars = SanitizedEnvVars::new();

pub fn wasmopt(cmd: String) {
    println!("{} wasm-opt {}", "[wasm-opt]".bold().cyan(), cmd);
    let mut output = std::process::Command::new("wasm-opt");

    for command in cmd.split(" ") {
        output.arg(command);
    }
    let output = output.spawn().unwrap().wait().unwrap();

    if !output.success() {
        println!("{}", "============ TASK FAILED".bold().red());
        exit(1);
    }
}

pub fn wbg(cmd: String) {
    println!("{} wasm-bindgen {}", "[wasm-bindgen]".bold().cyan(), cmd);
    let mut output = std::process::Command::new("wasm-bindgen");

    for command in cmd.split(" ") {
        output.arg(command);
    }
    let output = output.spawn().unwrap().wait().unwrap();

    if !output.success() {
        println!("{}", "============ TASK FAILED".bold().red());
        exit(1);
    }
}
\ No newline at end of file

D web/.gitignore => web/.gitignore +0 -23
@@ 1,23 0,0 @@
node_modules

# Output
.output
.vercel
.netlify
.wrangler
/.svelte-kit
/build

# OS
.DS_Store
Thumbs.db

# Env
.env
.env.*
!.env.example
!.env.test

# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*

D web/.npmrc => web/.npmrc +0 -1
@@ 1,1 0,0 @@
engine-strict=true

D web/.vscode/extensions.json => web/.vscode/extensions.json +0 -6
@@ 1,6 0,0 @@
{
	"recommendations": [
		"svelte.svelte-vscode",
		"bradlc.vscode-tailwindcss"
	]
}

D web/.vscode/settings.json => web/.vscode/settings.json +0 -5
@@ 1,5 0,0 @@
{
	"files.associations": {
		"*.css": "tailwindcss"
	}
}

D web/README.md => web/README.md +0 -42
@@ 1,42 0,0 @@
# sv

Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).

## Creating a project

If you're seeing this, you've probably already done this step. Congrats!

```sh
# create a new project
npx sv create my-app
```

To recreate this project with the same configuration:

```sh
# recreate this project
bun x sv@0.15.1 create --template minimal --types ts --install bun web
```

## Developing

Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:

```sh
npm run dev

# or start the server and open the app in a new browser tab
npm run dev -- --open
```

## Building

To create a production version of your app:

```sh
npm run build
```

You can preview the production build with `npm run preview`.

> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.

D web/bun.lock => web/bun.lock +0 -247
@@ 1,247 0,0 @@
{
  "lockfileVersion": 1,
  "configVersion": 1,
  "workspaces": {
    "": {
      "name": "web",
      "devDependencies": {
        "@sveltejs/adapter-auto": "^7.0.1",
        "@sveltejs/kit": "^2.57.0",
        "@sveltejs/vite-plugin-svelte": "^7.0.0",
        "@tailwindcss/vite": "^4.2.2",
        "svelte": "^5.55.2",
        "svelte-check": "^4.4.6",
        "tailwindcss": "^4.2.2",
        "typescript": "^6.0.2",
        "vite": "^8.0.7",
      },
    },
  },
  "packages": {
    "@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],

    "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],

    "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],

    "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],

    "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],

    "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],

    "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],

    "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],

    "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="],

    "@oxc-project/types": ["@oxc-project/types@0.127.0", "", {}, "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ=="],

    "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],

    "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.17", "", { "os": "android", "cpu": "arm64" }, "sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ=="],

    "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.17", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw=="],

    "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.17", "", { "os": "darwin", "cpu": "x64" }, "sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw=="],

    "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.17", "", { "os": "freebsd", "cpu": "x64" }, "sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw=="],

    "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17", "", { "os": "linux", "cpu": "arm" }, "sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ=="],

    "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q=="],

    "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg=="],

    "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "ppc64" }, "sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA=="],

    "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "s390x" }, "sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA=="],

    "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.17", "", { "os": "linux", "cpu": "x64" }, "sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA=="],

    "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.17", "", { "os": "linux", "cpu": "x64" }, "sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw=="],

    "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.17", "", { "os": "none", "cpu": "arm64" }, "sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA=="],

    "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.17", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA=="],

    "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17", "", { "os": "win32", "cpu": "arm64" }, "sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA=="],

    "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.17", "", { "os": "win32", "cpu": "x64" }, "sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg=="],

    "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.17", "", {}, "sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg=="],

    "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],

    "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.9", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA=="],

    "@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@7.0.1", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-dvuPm1E7M9NI/+canIQ6KKQDU2AkEefEZ2Dp7cY6uKoPq9Z/PhOXABe526UdW2mN986gjVkuSLkOYIBnS/M2LQ=="],

    "@sveltejs/kit": ["@sveltejs/kit@2.58.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.6.4", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "set-cookie-parser": "^3.0.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3 || ^6.0.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-kT9GCN8yJTkCK1W+Gi/bvGooWAM7y7WXP+yd+rf6QOIjyoK1ERPrMwSufXJUNu2pMWIqruhFvmz+LbOqsEmKmA=="],

    "@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@7.0.0", "", { "dependencies": { "deepmerge": "^4.3.1", "magic-string": "^0.30.21", "obug": "^2.1.0", "vitefu": "^1.1.2" }, "peerDependencies": { "svelte": "^5.46.4", "vite": "^8.0.0-beta.7 || ^8.0.0" } }, "sha512-ILXmxC7HAsnkK2eslgPetrqqW1BKSL7LktsFgqzNj83MaivMGZzluWq32m25j2mDOjmSKX7GGWahePhuEs7P/g=="],

    "@tailwindcss/node": ["@tailwindcss/node@4.2.4", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.4" } }, "sha512-Ai7+yQPxz3ddrDQzFfBKdHEVBg0w3Zl83jnjuwxnZOsnH9pGn93QHQtpU0p/8rYWxvbFZHneni6p1BSLK4DkGA=="],

    "@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.4", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.4", "@tailwindcss/oxide-darwin-arm64": "4.2.4", "@tailwindcss/oxide-darwin-x64": "4.2.4", "@tailwindcss/oxide-freebsd-x64": "4.2.4", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.4", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.4", "@tailwindcss/oxide-linux-arm64-musl": "4.2.4", "@tailwindcss/oxide-linux-x64-gnu": "4.2.4", "@tailwindcss/oxide-linux-x64-musl": "4.2.4", "@tailwindcss/oxide-wasm32-wasi": "4.2.4", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.4", "@tailwindcss/oxide-win32-x64-msvc": "4.2.4" } }, "sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q=="],

    "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.4", "", { "os": "android", "cpu": "arm64" }, "sha512-e7MOr1SAn9U8KlZzPi1ZXGZHeC5anY36qjNwmZv9pOJ8E4Q6jmD1vyEHkQFmNOIN7twGPEMXRHmitN4zCMN03g=="],

    "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tSC/Kbqpz/5/o/C2sG7QvOxAKqyd10bq+ypZNf+9Fi2TvbVbv1zNpcEptcsU7DPROaSbVgUXmrzKhurFvo5eDg=="],

    "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-yPyUXn3yO/ufR6+Kzv0t4fCg2qNr90jxXc5QqBpjlPNd0NqyDXcmQb/6weunH/MEDXW5dhyEi+agTDiqa3WsGg=="],

    "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-BoMIB4vMQtZsXdGLVc2z+P9DbETkiopogfWZKbWwM8b/1Vinbs4YcUwo+kM/KeLkX3Ygrf4/PsRndKaYhS8Eiw=="],

    "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-7pIHBLTHYRAlS7V22JNuTh33yLH4VElwKtB3bwchK/UaKUPpQ0lPQiOWcbm4V3WP2I6fNIJ23vABIvoy2izdwA=="],

    "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-+E4wxJ0ZGOzSH325reXTWB48l42i93kQqMvDyz5gqfRzRZ7faNhnmvlV4EPGJU3QJM/3Ab5jhJ5pCRUsKn6OQw=="],

    "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g=="],

    "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA=="],

    "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA=="],

    "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.4", "", { "dependencies": { "@emnapi/core": "^1.8.1", "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw=="],

    "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-L9BXqxC4ToVgwMFqj3pmZRqyHEztulpUJzCxUtLjobMCzTPsGt1Fa9enKbOpY2iIyVtaHNeNvAK8ERP/64sqGQ=="],

    "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.4", "", { "os": "win32", "cpu": "x64" }, "sha512-ESlKG0EpVJQwRjXDDa9rLvhEAh0mhP1sF7sap9dNZT0yyl9SAG6T7gdP09EH0vIv0UNTlo6jPWyujD6559fZvw=="],

    "@tailwindcss/vite": ["@tailwindcss/vite@4.2.4", "", { "dependencies": { "@tailwindcss/node": "4.2.4", "@tailwindcss/oxide": "4.2.4", "tailwindcss": "4.2.4" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-pCvohwOCspk3ZFn6eJzrrX3g4n2JY73H6MmYC87XfGPyTty4YsCjYTMArRZm/zOI8dIt3+EcrLHAFPe5A4bgtw=="],

    "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],

    "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],

    "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],

    "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],

    "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],

    "aria-query": ["aria-query@5.3.1", "", {}, "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g=="],

    "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],

    "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],

    "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],

    "cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],

    "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],

    "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],

    "devalue": ["devalue@5.7.1", "", {}, "sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA=="],

    "enhanced-resolve": ["enhanced-resolve@5.21.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA=="],

    "esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="],

    "esrap": ["esrap@2.2.5", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, "peerDependencies": { "@typescript-eslint/types": "^8.2.0" }, "optionalPeers": ["@typescript-eslint/types"] }, "sha512-/yLB1538mag+dn0wsePTe8C0rDIjUOaJpMs2McodSzmM2msWcZsBSdRtg6HOBt0A/r82BN+Md3pgwSc/uWt2Ig=="],

    "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],

    "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],

    "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],

    "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="],

    "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],

    "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],

    "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],

    "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],

    "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],

    "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],

    "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],

    "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],

    "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],

    "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],

    "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],

    "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],

    "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],

    "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],

    "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="],

    "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],

    "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],

    "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],

    "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],

    "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="],

    "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],

    "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],

    "postcss": ["postcss@8.5.12", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA=="],

    "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],

    "rolldown": ["rolldown@1.0.0-rc.17", "", { "dependencies": { "@oxc-project/types": "=0.127.0", "@rolldown/pluginutils": "1.0.0-rc.17" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.17", "@rolldown/binding-darwin-arm64": "1.0.0-rc.17", "@rolldown/binding-darwin-x64": "1.0.0-rc.17", "@rolldown/binding-freebsd-x64": "1.0.0-rc.17", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA=="],

    "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],

    "set-cookie-parser": ["set-cookie-parser@3.1.0", "", {}, "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw=="],

    "sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],

    "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],

    "svelte": ["svelte@5.55.5", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.6.4", "esm-env": "^1.2.1", "esrap": "^2.2.4", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-2uCs/LZ9us+AktdzYJM8OcxQ8qnPS1kpaO7syGT/MgO+6Qr1Ybl+TqPq+97u7PHqmmMlye5ZkoyXONy5mjjAbw=="],

    "svelte-check": ["svelte-check@4.4.6", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-kP1zG81EWaFe9ZyTv4ZXv44Csi6Pkdpb7S3oj6m+K2ec/IcDg/a8LsFsnVLqm2nxtkSwsd5xPj/qFkTBgXHXjg=="],

    "tailwindcss": ["tailwindcss@4.2.4", "", {}, "sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA=="],

    "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],

    "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="],

    "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],

    "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],

    "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],

    "vite": ["vite@8.0.10", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.10", "rolldown": "1.0.0-rc.17", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw=="],

    "vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="],

    "zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],

    "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],

    "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],

    "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],

    "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="],

    "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],

    "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
  }
}

D web/package.json => web/package.json +0 -25
@@ 1,25 0,0 @@
{
	"name": "web",
	"private": true,
	"version": "0.0.1",
	"type": "module",
	"scripts": {
		"dev": "vite dev",
		"build": "vite build",
		"preview": "vite preview",
		"prepare": "svelte-kit sync || echo ''",
		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
	},
	"devDependencies": {
		"@sveltejs/adapter-auto": "^7.0.1",
		"@sveltejs/kit": "^2.57.0",
		"@sveltejs/vite-plugin-svelte": "^7.0.0",
		"@tailwindcss/vite": "^4.2.2",
		"svelte": "^5.55.2",
		"svelte-check": "^4.4.6",
		"tailwindcss": "^4.2.2",
		"typescript": "^6.0.2",
		"vite": "^8.0.7"
	}
}

D web/src/app.d.ts => web/src/app.d.ts +0 -13
@@ 1,13 0,0 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
	namespace App {
		// interface Error {}
		// interface Locals {}
		// interface PageData {}
		// interface PageState {}
		// interface Platform {}
	}
}

export {};

D web/src/app.html => web/src/app.html +0 -12
@@ 1,12 0,0 @@
<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		<meta name="text-scale" content="scale" />
		%sveltekit.head%
	</head>
	<body data-sveltekit-preload-data="hover">
		<div style="display: contents">%sveltekit.body%</div>
	</body>
</html>

D web/src/lib/index.ts => web/src/lib/index.ts +0 -9
@@ 1,9 0,0 @@
// place files you want to import through the `$lib` alias in this folder.
export const config = {
    environments: [
        { name: 'Live',     url: 'wss://stk.e3t.cc',          isPrimary: true,  isTesting: false, isDisabled: false },
        { name: 'Beta',     url: 'wss://beta.stk.e3t.cc',     isPrimary: false, isTesting: true,  isDisabled: false },
        { name: 'Bleeding', url: 'wss://bleeding.stk.e3t.cc', isPrimary: false, isTesting: true,  isDisabled: true  },
        { name: 'Local',    url: 'ws://localhost:5151',       isPrimary: false, isTesting: true,  isDisabled: false },
    ]
}
\ No newline at end of file

D web/src/routes/+layout.svelte => web/src/routes/+layout.svelte +0 -8
@@ 1,8 0,0 @@
<script lang="ts">
	//import './layout.css';

	let { children } = $props();
</script>

<svelte:head><title>StarKingdoms</title></svelte:head>
{@render children()}

D web/src/routes/+page.svelte => web/src/routes/+page.svelte +0 -34
@@ 1,34 0,0 @@
<script lang="ts">
    import { browser } from "$app/environment";

    let username = $state('');
    let url = $state('ws://localhost:5151');

    let isPlaying = $state(false);

    async function launch() {
        isPlaying = true;
        let module = await import('$lib/bundle/starkingdoms-opt.js');
        await module.default();
        module.play(url);
    }
</script>

{#if !isPlaying}
    <h1 class="font-semibold text-2xl">StarKingdoms</h1>
    <label for="username">Username</label>
    <input id="username" type="text" bind:value={username} >
    <label for="url">URL</label>
    <input id="url" type="text" bind:value={url} >
    <button onclick={launch}>bonk</button>
{/if}

<style>
    :global(canvas) {
        position: absolute;
        top: 0;
        left: 0;
        width: 100vw !important;
        height: 100vh !important;
    }
</style>
\ No newline at end of file

D web/src/routes/layout.css => web/src/routes/layout.css +0 -1
@@ 1,1 0,0 @@
@import 'tailwindcss';

D web/static/assets => web/static/assets +0 -1
@@ 1,1 0,0 @@
../../crates/unified/assets
\ No newline at end of file

D web/static/robots.txt => web/static/robots.txt +0 -3
@@ 1,3 0,0 @@
# allow crawling everything by default
User-agent: *
Disallow:

D web/svelte.config.js => web/svelte.config.js +0 -17
@@ 1,17 0,0 @@
import adapter from '@sveltejs/adapter-auto';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	compilerOptions: {
		// Force runes mode for the project, except for libraries. Can be removed in svelte 6.
		runes: ({ filename }) => (filename.split(/[/\\]/).includes('node_modules') ? undefined : true)
	},
	kit: {
		// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
		// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
		// See https://svelte.dev/docs/kit/adapters for more information about adapters.
		adapter: adapter()
	}
};

export default config;

D web/tsconfig.json => web/tsconfig.json +0 -20
@@ 1,20 0,0 @@
{
	"extends": "./.svelte-kit/tsconfig.json",
	"compilerOptions": {
		"rewriteRelativeImportExtensions": true,
		"allowJs": true,
		"checkJs": true,
		"esModuleInterop": true,
		"forceConsistentCasingInFileNames": true,
		"resolveJsonModule": true,
		"skipLibCheck": true,
		"sourceMap": true,
		"strict": true,
		"moduleResolution": "bundler"
	}
	// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
	// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
	//
	// To make changes to top-level options such as include and exclude, we recommend extending
	// the generated config; see https://svelte.dev/docs/kit/configuration#typescript
}

D web/vite.config.ts => web/vite.config.ts +0 -5
@@ 1,5 0,0 @@
import tailwindcss from '@tailwindcss/vite';
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';

export default defineConfig({ plugins: [tailwindcss(), sveltekit()] });