Browse Source

feat: inline dioxus-native from blitz (#3675)

* Rename dioxus-blitz to dioxus-native

* Add CSS import support (#139)

* Remove data dependencie from NetProvider + global provider.

* Feat CSS import

* Move net handler code out of util

* Fixing test...

* Use the better suited OnceLock instead of LazyLock

* Removing static and move resource callback back out of the document.

Signed-off-by: koko <kokos.kekse@gmail.com>

* Make things work

Signed-off-by: koko <kokos.kekse@gmail.com>

* Fix the servo example

Signed-off-by: koko <kokos.kekse@gmail.com>

* Replace servo image with a more compact version

Signed-off-by: koko <kokos.kekse@gmail.com>

* revert: 8467b271

Signed-off-by: koko <kokos.kekse@gmail.com>

---------

Signed-off-by: koko <kokos.kekse@gmail.com>

* Create readme app

* WPT: reuse FontContext to avoid reloading system fonts

Takes runtime for css-flexbox from 12s -> 8s

* Move Devtools to traits crate

* Suppress unused variable warning

* Implement net for DioxusDocument

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Eliminate BlitzWindowEvent type

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Make net crate use document id instead of window id

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Rename and document net traits

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Split `dioxus-native` crate into `dioxus-native` and `blitz-shell` crates (#163)

* Rename waker module to event

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Create seperate DioxusNativeApplication

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Rename dioxus-native crate to blitz-shell

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Split blitz-shell out of dioxus-native crate

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Remove need for dioxus-native to depend directly on stylo

---------

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Unnest dioxus-native modules

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Split MutationWriter into it's own module

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Split HtmlDocument into it's own crate

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Rename dom field of Window to doc

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Support prefers-color-scheme (dark mode)

* Remove use of the `todo` macro in event handling and add a comment about it being a todo (#168)

Using the `todo` macro causes a panic when this event is encountered. Noop is preferable in this case as it does not crash the application. This is especially annoying on platforms where `Ime::Enabled` event is sent upon application start even when the user is using a keyboard layout that does not need an IME support. There was added a "TODO" comment that informs about this feature being missing. Most IDEs and code editors have support/plugins/extensions to work with this type of comments and this type of comment is already used widely across the codebase. As such, the information about this feature not being implemented is not lost.

* Upgrade to dioxus 0.6-rc.0

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Fix text input in dioxus-native

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Make dioxus-native depend dioxus-core and dioxus-html rather than dioxus

* Remove "full" feature from tokio

* Move Viewport to blitz_traits

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Make tokio optional in dioxus-native and blitz-shell

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Make SVG support optional

* Abstract renderer behind a trait

blitz-shell no longer depends on blitz-renderer-vello

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Split HTML launch functions out in `blitz` crate

* feat: Add mousedown and mouseup event (#172)

* feat: Add mousedown and mouseup event

* feat: Triggering :active pseudo-class

* fix: Triggering :active pseudo-class

* Rename RendererEvent to DomEvent

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Rename Document to BaseDocument. DocumentLike to Document

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Move event and document abstractions to blitz-traits

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Rename BlitzEvent to BlitzShellEvent

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Restyle when style attribute is mutated

* feat: Support text box mouse selection (#182)

* Rename raw_dom_data to data

Signed-off-by: Nico Burns <nico@nicoburns.com>

* Rename dioxus-native to native

* Add to workspace

* simplify launch module, integrate native

* Fix it up again

* Update cargo lock

* FIx: propagate accessibility feature fla

* implement asset resolver

* add native to feature match in cli

* Implement document and history for native

* use no-op eval

* clippy

* typos

* typo

* Convert logs to trace

* Bump blitz to alpha releases

* unset image data

* fix style integration with blitz

* fix a few lints

* wire up ids

* implement a few more events

* add more helpful todo note

* bump ci to allow edition 2024, use newer nightly

* make clippy happy

* also update matrix tests to rust 2024

* Add autofocus

Co-authored-by: otgerrogla 2356820+otgerrogla@users.noreply.github.com

* Wait for the suspense boundary above the router to resolve before sending the first streaming chunk (#3891)

* Change the suspense streaming context after suspense is resolved in the router

* Wait for the suspense context before streaming the first chunk in ssr

* forward more response parts

* warn

* extract the hydration format into a crate

* Fix hydration when no data is sent

* forward web and server features

* Fix suspense that starts on the client

* fix use_server_future on the client

* Add documentation for fullstack hooks and protocol

* downgrade rust edition

* fix clippy

* fix tests

* fix clippy

* Fix pure web compile

* undo changes to the fullstack router example

* fix formatting

* hoist a bunch of deps

---------

Signed-off-by: koko <kokos.kekse@gmail.com>
Signed-off-by: Nico Burns <nico@nicoburns.com>
Co-authored-by: Nico Burns <nico@nicoburns.com>
Co-authored-by: koko <72217393+kokoISnoTarget@users.noreply.github.com>
Co-authored-by: David Husička <25853767+DavidHusicka@users.noreply.github.com>
Co-authored-by: luoxiaozero <48741584+luoxiaozero@users.noreply.github.com>
Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
Jonathan Kelley 2 months ago
parent
commit
12c6938346
38 changed files with 6165 additions and 2096 deletions
  1. 13 13
      .github/workflows/main.yml
  2. 3191 1739
      Cargo.lock
  3. 17 0
      Cargo.toml
  4. 1 1
      example-projects/file-explorer/src/main.rs
  5. 379 0
      examples/assets/todomvc-native.css
  6. 1 1
      examples/assets/todomvc.css
  7. 269 0
      examples/todomvc-native.rs
  8. 24 0
      packages/asset-resolver/Cargo.toml
  9. 180 0
      packages/asset-resolver/src/lib.rs
  10. 4 4
      packages/cli/src/build/builder.rs
  11. 13 4
      packages/cli/src/build/prerender.rs
  12. 1 1
      packages/cli/src/dioxus_crate.rs
  13. 1 1
      packages/cli/src/platform.rs
  14. 5 5
      packages/cli/src/serve/mod.rs
  15. 7 7
      packages/cli/src/serve/output.rs
  16. 2 2
      packages/cli/src/serve/server.rs
  17. 1 0
      packages/core/src/nodes.rs
  18. 3 2
      packages/desktop/Cargo.toml
  19. 3 167
      packages/desktop/src/protocol.rs
  20. 2 0
      packages/dioxus/Cargo.toml
  21. 164 140
      packages/dioxus/src/launch.rs
  22. 1 1
      packages/hooks/Cargo.toml
  23. 1 1
      packages/html/Cargo.toml
  24. 1 0
      packages/isrg/Cargo.toml
  25. 1 1
      packages/isrg/src/config.rs
  26. 20 2
      packages/isrg/src/fs_cache.rs
  27. 59 0
      packages/native/Cargo.toml
  28. 80 0
      packages/native/src/assets.rs
  29. 70 0
      packages/native/src/contexts.rs
  30. 166 0
      packages/native/src/dioxus_application.rs
  31. 564 0
      packages/native/src/dioxus_document.rs
  32. 23 0
      packages/native/src/event.rs
  33. 220 0
      packages/native/src/event_handler.rs
  34. 96 0
      packages/native/src/lib.rs
  35. 575 0
      packages/native/src/mutation_writer.rs
  36. 3 0
      packages/playwright-tests/nested-suspense/src/ssg.rs
  37. 3 3
      packages/router/Cargo.toml
  38. 1 1
      packages/server-macro/src/lib.rs

+ 13 - 13
.github/workflows/main.yml

@@ -39,7 +39,7 @@ env:
   CARGO_TERM_COLOR: always
   CARGO_INCREMENTAL: 0 # todo(jon): cargo-cache wipes incremental artifacts, but we eventually want to cache them
   RUST_BACKTRACE: 1
-  rust_nightly: nightly-2024-10-20
+  rust_nightly: nightly-2025-04-07
 
 jobs:
   check-msrv:
@@ -48,7 +48,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
-      - uses: dtolnay/rust-toolchain@1.84.0
+      - uses: dtolnay/rust-toolchain@1.86.0
       - uses: Swatinem/rust-cache@v2
         with:
           cache-all-crates: "true"
@@ -73,7 +73,7 @@ jobs:
         with:
           packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev
           version: 1.0
-      - uses: dtolnay/rust-toolchain@1.84.0
+      - uses: dtolnay/rust-toolchain@1.86.0
         with:
           components: rustfmt, clippy
       - uses: Swatinem/rust-cache@v2
@@ -92,7 +92,7 @@ jobs:
         with:
           packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev
           version: 1.0
-      - uses: dtolnay/rust-toolchain@1.84.0
+      - uses: dtolnay/rust-toolchain@1.86.0
         with:
           components: rustfmt, clippy
       - uses: Swatinem/rust-cache@v2
@@ -107,7 +107,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
-      - uses: dtolnay/rust-toolchain@1.84.0
+      - uses: dtolnay/rust-toolchain@1.86.0
         with:
           components: rustfmt
       - uses: Swatinem/rust-cache@v2
@@ -152,7 +152,7 @@ jobs:
         with:
           packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev
           version: 1.0
-      - uses: dtolnay/rust-toolchain@1.84.0
+      - uses: dtolnay/rust-toolchain@1.86.0
       - uses: Swatinem/rust-cache@v2
         with:
           cache-all-crates: "true"
@@ -168,7 +168,7 @@ jobs:
         with:
           packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev
           version: 1.0
-      - uses: dtolnay/rust-toolchain@1.84.0
+      - uses: dtolnay/rust-toolchain@1.86.0
         with:
           components: rustfmt, clippy
       - uses: Swatinem/rust-cache@v2
@@ -237,7 +237,7 @@ jobs:
           - {
               target: aarch64-apple-darwin,
               os: macos-latest,
-              toolchain: "1.84.0",
+              toolchain: "1.86.0",
               cross: false,
               command: "test",
               args: "--all --tests",
@@ -245,7 +245,7 @@ jobs:
           - {
               target: x86_64-apple-darwin,
               os: macos-13,
-              toolchain: "1.84.0",
+              toolchain: "1.86.0",
               cross: false,
               command: "test",
               args: "--all --tests",
@@ -253,7 +253,7 @@ jobs:
           - {
               target: aarch64-apple-ios,
               os: macos-latest,
-              toolchain: "1.84.0",
+              toolchain: "1.86.0",
               cross: false,
               command: "build",
               args: "--package dioxus-mobile",
@@ -261,7 +261,7 @@ jobs:
           - {
               target: aarch64-linux-android,
               os: ubuntu-latest,
-              toolchain: "1.84.0",
+              toolchain: "1.86.0",
               cross: true,
               command: "build",
               args: "--package dioxus-mobile",
@@ -302,7 +302,7 @@ jobs:
     name: "cargo test | windows"
     steps:
       - uses: actions/checkout@v4
-      - uses: dtolnay/rust-toolchain@1.84.0
+      - uses: dtolnay/rust-toolchain@1.86.0
         with:
           components: rustfmt, clippy
       - uses: Swatinem/rust-cache@v2
@@ -335,7 +335,7 @@ jobs:
   #   runs-on: ubuntu-latest
   #   steps:
   #     - uses: actions/checkout@v4
-  #     - uses: dtolnay/rust-toolchain@1.84.0
+  #     - uses: dtolnay/rust-toolchain@1.86.0
   #     - uses: Swatinem/rust-cache@v2
   #       with:
   #         cache-all-crates: "true"

+ 3191 - 1739
Cargo.lock

@@ -2,6 +2,114 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "ab_glyph"
+version = "0.2.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec3672c180e71eeaaac3a541fbbc5f5ad4def8b747c595ad30d674e43049f7b0"
+dependencies = [
+ "ab_glyph_rasterizer",
+ "owned_ttf_parser",
+]
+
+[[package]]
+name = "ab_glyph_rasterizer"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
+
+[[package]]
+name = "accesskit"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3d3b8f9bae46a948369bc4a03e815d4ed6d616bd00de4051133a5019dc31c5a"
+
+[[package]]
+name = "accesskit_atspi_common"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c5dd55e6e94949498698daf4d48fb5659e824d7abec0d394089656ceaf99d4f"
+dependencies = [
+ "accesskit",
+ "accesskit_consumer",
+ "atspi-common",
+ "serde",
+ "thiserror 1.0.69",
+ "zvariant",
+]
+
+[[package]]
+name = "accesskit_consumer"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f47983a1084940ba9a39c077a8c63e55c619388be5476ac04c804cfbd1e63459"
+dependencies = [
+ "accesskit",
+ "hashbrown 0.15.2",
+ "immutable-chunkmap",
+]
+
+[[package]]
+name = "accesskit_macos"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7329821f3bd1101e03a7d2e03bd339e3ac0dc64c70b4c9f9ae1949e3ba8dece1"
+dependencies = [
+ "accesskit",
+ "accesskit_consumer",
+ "hashbrown 0.15.2",
+ "objc2 0.5.2",
+ "objc2-app-kit 0.2.2",
+ "objc2-foundation 0.2.2",
+]
+
+[[package]]
+name = "accesskit_unix"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcee751cc20d88678c33edaf9c07e8b693cd02819fe89053776f5313492273f5"
+dependencies = [
+ "accesskit",
+ "accesskit_atspi_common",
+ "async-channel 2.3.1",
+ "async-executor",
+ "async-task",
+ "atspi",
+ "futures-lite",
+ "futures-util",
+ "serde",
+ "zbus",
+]
+
+[[package]]
+name = "accesskit_windows"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24fcd5d23d70670992b823e735e859374d694a3d12bfd8dd32bd3bd8bedb5d81"
+dependencies = [
+ "accesskit",
+ "accesskit_consumer",
+ "hashbrown 0.15.2",
+ "paste",
+ "static_assertions",
+ "windows 0.58.0",
+ "windows-core 0.58.0",
+]
+
+[[package]]
+name = "accesskit_winit"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6a48dad5530b6deb9fc7a52cc6c3bf72cdd9eb8157ac9d32d69f2427a5e879"
+dependencies = [
+ "accesskit",
+ "accesskit_macos",
+ "accesskit_unix",
+ "accesskit_windows",
+ "raw-window-handle 0.6.2",
+ "winit",
+]
+
 [[package]]
 name = "addr2line"
 version = "0.24.2"
@@ -84,7 +192,7 @@ dependencies = [
  "once_cell",
  "serde",
  "version_check",
- "zerocopy",
+ "zerocopy 0.7.35",
 ]
 
 [[package]]
@@ -138,6 +246,33 @@ version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
 
+[[package]]
+name = "android-activity"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046"
+dependencies = [
+ "android-properties",
+ "bitflags 2.9.0",
+ "cc",
+ "cesu8",
+ "jni",
+ "jni-sys",
+ "libc",
+ "log",
+ "ndk",
+ "ndk-context",
+ "ndk-sys 0.6.0+11769913",
+ "num_enum",
+ "thiserror 1.0.69",
+]
+
+[[package]]
+name = "android-properties"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
+
 [[package]]
 name = "android-tzdata"
 version = "0.1.1"
@@ -223,19 +358,20 @@ dependencies = [
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.6"
+version = "3.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
+checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
 dependencies = [
  "anstyle",
+ "once_cell",
  "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.95"
+version = "1.0.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
+checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
 
 [[package]]
 name = "anymap2"
@@ -244,26 +380,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c"
 
 [[package]]
-name = "app-store-connect"
-version = "0.5.0"
+name = "app_units"
+version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33fb5489b9bfcfa3aec2f68cc79eafb999b5af9b9d9d70ca8dfe36acdd1b2b05"
+checksum = "467b60e4ee6761cd6fd4e03ea58acefc8eec0d1b1def995c1b3b783fa7be8a60"
 dependencies = [
- "anyhow",
- "base64 0.21.7",
- "clap",
- "dirs 5.0.1",
- "env_logger 0.10.2",
- "jsonwebtoken",
- "log",
- "pem",
- "rand 0.8.5",
- "reqwest 0.11.27",
- "rsa",
+ "num-traits",
  "serde",
- "serde_json",
- "thiserror 1.0.69",
- "x509-certificate",
 ]
 
 [[package]]
@@ -285,27 +408,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "329820aac7259ca0529d3cc21dd3b4c11651225dfce9e0ce25b121b23f923164"
 dependencies = [
  "anyhow",
- "app-store-connect",
  "apple-bundles",
  "apple-flat-package",
  "apple-xar",
- "aws-config",
- "aws-sdk-s3",
- "aws-smithy-http",
- "aws-smithy-types",
  "base64 0.21.7",
  "bcder",
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "bytes",
  "chrono",
  "clap",
  "cryptographic-message-syntax",
- "der 0.7.9",
+ "der",
  "dialoguer",
  "difference",
  "digest",
  "dirs 5.0.1",
- "elliptic-curve 0.13.8",
+ "elliptic-curve",
  "env_logger 0.10.2",
  "figment",
  "filetime",
@@ -320,10 +438,10 @@ dependencies = [
  "oid-registry",
  "once_cell",
  "p12",
- "p256 0.13.2",
+ "p256",
  "pem",
  "pkcs1",
- "pkcs8 0.10.2",
+ "pkcs8",
  "plist",
  "rand 0.8.5",
  "rasn",
@@ -335,15 +453,15 @@ dependencies = [
  "scroll",
  "security-framework 2.11.1",
  "security-framework-sys",
- "semver 1.0.23",
+ "semver 1.0.26",
  "serde",
  "serde_json",
  "serde_yaml",
  "sha2",
- "signature 2.2.0",
+ "signature",
  "simple-file-manifest",
  "spake2",
- "spki 0.7.3",
+ "spki",
  "subtle",
  "tempfile",
  "thiserror 1.0.69",
@@ -399,7 +517,7 @@ dependencies = [
  "serde-xml-rs",
  "sha1",
  "sha2",
- "signature 2.2.0",
+ "signature",
  "thiserror 1.0.69",
  "url",
  "x509-certificate",
@@ -436,7 +554,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -452,12 +570,24 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "arrayref"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
+
 [[package]]
 name = "arrayvec"
 version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
 
+[[package]]
+name = "as-raw-xcb-connection"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
+
 [[package]]
 name = "as-slice"
 version = "0.2.1"
@@ -476,6 +606,15 @@ dependencies = [
  "libloading 0.7.4",
 ]
 
+[[package]]
+name = "ash"
+version = "0.38.0+1.3.281"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f"
+dependencies = [
+ "libloading 0.8.6",
+]
+
 [[package]]
 name = "ashpd"
 version = "0.8.1"
@@ -546,16 +685,16 @@ dependencies = [
  "proc-macro2",
  "quote",
  "swc_macros_common",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "async-broadcast"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e"
+checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
 dependencies = [
- "event-listener 5.3.1",
+ "event-listener 5.4.0",
  "event-listener-strategy",
  "futures-core",
  "pin-project-lite",
@@ -586,9 +725,9 @@ dependencies = [
 
 [[package]]
 name = "async-compression"
-version = "0.4.18"
+version = "0.4.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522"
+checksum = "59a194f9d963d8099596278594b3107448656ba73831c9d8c783e613ce86da64"
 dependencies = [
  "brotli 7.0.0",
  "flate2",
@@ -614,6 +753,17 @@ dependencies = [
  "slab",
 ]
 
+[[package]]
+name = "async-fs"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a"
+dependencies = [
+ "async-lock",
+ "blocking",
+ "futures-lite",
+]
+
 [[package]]
 name = "async-global-executor"
 version = "2.4.1"
@@ -642,7 +792,7 @@ dependencies = [
  "futures-lite",
  "parking",
  "polling",
- "rustix",
+ "rustix 0.38.44",
  "slab",
  "tracing",
  "windows-sys 0.59.0",
@@ -654,7 +804,7 @@ version = "3.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
 dependencies = [
- "event-listener 5.3.1",
+ "event-listener 5.4.0",
  "event-listener-strategy",
  "pin-project-lite",
 ]
@@ -678,9 +828,9 @@ dependencies = [
  "async-task",
  "blocking",
  "cfg-if",
- "event-listener 5.3.1",
+ "event-listener 5.4.0",
  "futures-lite",
- "rustix",
+ "rustix 0.38.44",
  "tracing",
 ]
 
@@ -692,7 +842,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -707,7 +857,7 @@ dependencies = [
  "cfg-if",
  "futures-core",
  "futures-io",
- "rustix",
+ "rustix 0.38.44",
  "signal-hook-registry",
  "slab",
  "windows-sys 0.59.0",
@@ -715,9 +865,9 @@ dependencies = [
 
 [[package]]
 name = "async-std"
-version = "1.13.0"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615"
+checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24"
 dependencies = [
  "async-channel 1.9.0",
  "async-global-executor",
@@ -758,7 +908,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -769,13 +919,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
 
 [[package]]
 name = "async-trait"
-version = "0.1.83"
+version = "0.1.88"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
+checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -825,26 +975,86 @@ version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
 
+[[package]]
+name = "atomic_refcell"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "atspi"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be534b16650e35237bb1ed189ba2aab86ce65e88cc84c66f4935ba38575cecbf"
+dependencies = [
+ "atspi-common",
+ "atspi-connection",
+ "atspi-proxies",
+]
+
+[[package]]
+name = "atspi-common"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1909ed2dc01d0a17505d89311d192518507e8a056a48148e3598fef5e7bb6ba7"
+dependencies = [
+ "enumflags2",
+ "serde",
+ "static_assertions",
+ "zbus",
+ "zbus-lockstep",
+ "zbus-lockstep-macros",
+ "zbus_names",
+ "zvariant",
+]
+
+[[package]]
+name = "atspi-connection"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "430c5960624a4baaa511c9c0fcc2218e3b58f5dbcc47e6190cafee344b873333"
+dependencies = [
+ "atspi-common",
+ "atspi-proxies",
+ "futures-lite",
+ "zbus",
+]
+
+[[package]]
+name = "atspi-proxies"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e6c5de3e524cf967569722446bcd458d5032348554d9a17d7d72b041ab7496"
+dependencies = [
+ "atspi-common",
+ "serde",
+ "zbus",
+ "zvariant",
+]
+
 [[package]]
 name = "auth-git2"
-version = "0.5.5"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3810b5af212b013fe7302b12d86616c6c39a48e18f2e4b812a5a9e5710213791"
+checksum = "d55eead120c93036f531829cf9b85830a474e75ce71169680879d28078321ddc"
 dependencies = [
- "dirs 5.0.1",
+ "dirs 6.0.0",
  "git2",
  "terminal-prompt",
 ]
 
 [[package]]
 name = "auto_impl"
-version = "1.2.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42"
+checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -869,421 +1079,35 @@ dependencies = [
 
 [[package]]
 name = "avif-serialize"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62"
+checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e"
 dependencies = [
  "arrayvec",
 ]
 
-[[package]]
-name = "aws-config"
-version = "1.5.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b49afaa341e8dd8577e1a2200468f98956d6eda50bcf4a53246cc00174ba924"
-dependencies = [
- "aws-credential-types",
- "aws-runtime",
- "aws-sdk-sso",
- "aws-sdk-ssooidc",
- "aws-sdk-sts",
- "aws-smithy-async",
- "aws-smithy-http",
- "aws-smithy-json 0.60.7",
- "aws-smithy-runtime",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "aws-types",
- "bytes",
- "fastrand",
- "hex",
- "http 0.2.12",
- "ring",
- "time",
- "tokio",
- "tracing",
- "url",
- "zeroize",
-]
-
-[[package]]
-name = "aws-credential-types"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60e8f6b615cb5fc60a98132268508ad104310f0cfb25a1c22eee76efdf9154da"
-dependencies = [
- "aws-smithy-async",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "zeroize",
-]
-
 [[package]]
 name = "aws-lc-rs"
-version = "1.11.1"
+version = "1.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3"
+checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878"
 dependencies = [
  "aws-lc-sys",
- "paste",
  "untrusted 0.7.1",
  "zeroize",
 ]
 
 [[package]]
 name = "aws-lc-sys"
-version = "0.23.1"
+version = "0.28.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7"
+checksum = "b9f7720b74ed28ca77f90769a71fd8c637a0137f6fae4ae947e1050229cff57f"
 dependencies = [
  "bindgen",
  "cc",
  "cmake",
  "dunce",
  "fs_extra",
- "libc",
- "paste",
-]
-
-[[package]]
-name = "aws-runtime"
-version = "1.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5ac934720fbb46206292d2c75b57e67acfc56fe7dfd34fb9a02334af08409ea"
-dependencies = [
- "aws-credential-types",
- "aws-sigv4",
- "aws-smithy-async",
- "aws-smithy-eventstream",
- "aws-smithy-http",
- "aws-smithy-runtime",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "aws-types",
- "bytes",
- "fastrand",
- "http 0.2.12",
- "http-body 0.4.6",
- "once_cell",
- "percent-encoding",
- "pin-project-lite",
- "tracing",
- "uuid",
-]
-
-[[package]]
-name = "aws-sdk-s3"
-version = "1.65.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3ba2c5c0f2618937ce3d4a5ad574b86775576fa24006bcb3128c6e2cbf3c34e"
-dependencies = [
- "aws-credential-types",
- "aws-runtime",
- "aws-sigv4",
- "aws-smithy-async",
- "aws-smithy-checksums",
- "aws-smithy-eventstream",
- "aws-smithy-http",
- "aws-smithy-json 0.61.1",
- "aws-smithy-runtime",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "aws-smithy-xml",
- "aws-types",
- "bytes",
- "fastrand",
- "hex",
- "hmac",
- "http 0.2.12",
- "http-body 0.4.6",
- "lru 0.12.5",
- "once_cell",
- "percent-encoding",
- "regex-lite",
- "sha2",
- "tracing",
- "url",
-]
-
-[[package]]
-name = "aws-sdk-sso"
-version = "1.50.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05ca43a4ef210894f93096039ef1d6fa4ad3edfabb3be92b80908b9f2e4b4eab"
-dependencies = [
- "aws-credential-types",
- "aws-runtime",
- "aws-smithy-async",
- "aws-smithy-http",
- "aws-smithy-json 0.61.1",
- "aws-smithy-runtime",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "aws-types",
- "bytes",
- "http 0.2.12",
- "once_cell",
- "regex-lite",
- "tracing",
-]
-
-[[package]]
-name = "aws-sdk-ssooidc"
-version = "1.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abaf490c2e48eed0bb8e2da2fb08405647bd7f253996e0f93b981958ea0f73b0"
-dependencies = [
- "aws-credential-types",
- "aws-runtime",
- "aws-smithy-async",
- "aws-smithy-http",
- "aws-smithy-json 0.61.1",
- "aws-smithy-runtime",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "aws-types",
- "bytes",
- "http 0.2.12",
- "once_cell",
- "regex-lite",
- "tracing",
-]
-
-[[package]]
-name = "aws-sdk-sts"
-version = "1.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b68fde0d69c8bfdc1060ea7da21df3e39f6014da316783336deff0a9ec28f4bf"
-dependencies = [
- "aws-credential-types",
- "aws-runtime",
- "aws-smithy-async",
- "aws-smithy-http",
- "aws-smithy-json 0.61.1",
- "aws-smithy-query",
- "aws-smithy-runtime",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "aws-smithy-xml",
- "aws-types",
- "http 0.2.12",
- "once_cell",
- "regex-lite",
- "tracing",
-]
-
-[[package]]
-name = "aws-sigv4"
-version = "1.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d3820e0c08d0737872ff3c7c1f21ebbb6693d832312d6152bf18ef50a5471c2"
-dependencies = [
- "aws-credential-types",
- "aws-smithy-eventstream",
- "aws-smithy-http",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "bytes",
- "crypto-bigint 0.5.5",
- "form_urlencoded",
- "hex",
- "hmac",
- "http 0.2.12",
- "http 1.2.0",
- "once_cell",
- "p256 0.11.1",
- "percent-encoding",
- "ring",
- "sha2",
- "subtle",
- "time",
- "tracing",
- "zeroize",
-]
-
-[[package]]
-name = "aws-smithy-async"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c"
-dependencies = [
- "futures-util",
- "pin-project-lite",
- "tokio",
-]
-
-[[package]]
-name = "aws-smithy-checksums"
-version = "0.60.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba1a71073fca26775c8b5189175ea8863afb1c9ea2cceb02a5de5ad9dfbaa795"
-dependencies = [
- "aws-smithy-http",
- "aws-smithy-types",
- "bytes",
- "crc32c",
- "crc32fast",
- "hex",
- "http 0.2.12",
- "http-body 0.4.6",
- "md-5",
- "pin-project-lite",
- "sha1",
- "sha2",
- "tracing",
-]
-
-[[package]]
-name = "aws-smithy-eventstream"
-version = "0.60.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cef7d0a272725f87e51ba2bf89f8c21e4df61b9e49ae1ac367a6d69916ef7c90"
-dependencies = [
- "aws-smithy-types",
- "bytes",
- "crc32fast",
-]
-
-[[package]]
-name = "aws-smithy-http"
-version = "0.60.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c8bc3e8fdc6b8d07d976e301c02fe553f72a39b7a9fea820e023268467d7ab6"
-dependencies = [
- "aws-smithy-eventstream",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "bytes",
- "bytes-utils",
- "futures-core",
- "http 0.2.12",
- "http-body 0.4.6",
- "once_cell",
- "percent-encoding",
- "pin-project-lite",
- "pin-utils",
- "tracing",
-]
-
-[[package]]
-name = "aws-smithy-json"
-version = "0.60.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4683df9469ef09468dad3473d129960119a0d3593617542b7d52086c8486f2d6"
-dependencies = [
- "aws-smithy-types",
-]
-
-[[package]]
-name = "aws-smithy-json"
-version = "0.61.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee4e69cc50921eb913c6b662f8d909131bb3e6ad6cb6090d3a39b66fc5c52095"
-dependencies = [
- "aws-smithy-types",
-]
-
-[[package]]
-name = "aws-smithy-query"
-version = "0.60.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb"
-dependencies = [
- "aws-smithy-types",
- "urlencoding",
-]
-
-[[package]]
-name = "aws-smithy-runtime"
-version = "1.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f20685047ca9d6f17b994a07f629c813f08b5bce65523e47124879e60103d45"
-dependencies = [
- "aws-smithy-async",
- "aws-smithy-http",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "bytes",
- "fastrand",
- "h2 0.3.26",
- "http 0.2.12",
- "http-body 0.4.6",
- "http-body 1.0.1",
- "httparse",
- "hyper 0.14.31",
- "hyper-rustls 0.24.2",
- "once_cell",
- "pin-project-lite",
- "pin-utils",
- "rustls 0.21.12",
- "tokio",
- "tracing",
-]
-
-[[package]]
-name = "aws-smithy-runtime-api"
-version = "1.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd"
-dependencies = [
- "aws-smithy-async",
- "aws-smithy-types",
- "bytes",
- "http 0.2.12",
- "http 1.2.0",
- "pin-project-lite",
- "tokio",
- "tracing",
- "zeroize",
-]
-
-[[package]]
-name = "aws-smithy-types"
-version = "1.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fbd94a32b3a7d55d3806fe27d98d3ad393050439dd05eb53ece36ec5e3d3510"
-dependencies = [
- "base64-simd 0.8.0",
- "bytes",
- "bytes-utils",
- "futures-core",
- "http 0.2.12",
- "http 1.2.0",
- "http-body 0.4.6",
- "http-body 1.0.1",
- "http-body-util",
- "itoa 1.0.14",
- "num-integer",
- "pin-project-lite",
- "pin-utils",
- "ryu",
- "serde",
- "time",
- "tokio",
- "tokio-util",
-]
-
-[[package]]
-name = "aws-smithy-xml"
-version = "0.60.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab0b0166827aa700d3dc519f72f8b3a91c35d0b8d042dc5d643a91e6f80648fc"
-dependencies = [
- "xmlparser",
-]
-
-[[package]]
-name = "aws-types"
-version = "1.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5221b91b3e441e6675310829fd8984801b772cb1546ef6c0e54dec9f1ac13fef"
-dependencies = [
- "aws-credential-types",
- "aws-smithy-async",
- "aws-smithy-runtime-api",
- "aws-smithy-types",
- "rustc_version 0.4.1",
- "tracing",
 ]
 
 [[package]]
@@ -1299,8 +1123,8 @@ dependencies = [
  "futures-util",
  "http 0.2.12",
  "http-body 0.4.6",
- "hyper 0.14.31",
- "itoa 1.0.14",
+ "hyper 0.14.32",
+ "itoa 1.0.15",
  "matchit",
  "memchr",
  "mime",
@@ -1325,12 +1149,12 @@ dependencies = [
  "base64 0.22.1",
  "bytes",
  "futures-util",
- "http 1.2.0",
+ "http 1.3.1",
  "http-body 1.0.1",
  "http-body-util",
- "hyper 1.5.1",
+ "hyper 1.6.0",
  "hyper-util",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "matchit",
  "memchr",
  "mime",
@@ -1346,7 +1170,7 @@ dependencies = [
  "sync_wrapper 1.0.2",
  "tokio",
  "tokio-tungstenite 0.24.0",
- "tower 0.5.1",
+ "tower 0.5.2",
  "tower-layer",
  "tower-service",
  "tracing",
@@ -1378,7 +1202,7 @@ dependencies = [
  "async-trait",
  "bytes",
  "futures-util",
- "http 1.2.0",
+ "http 1.3.1",
  "http-body 1.0.1",
  "http-body-util",
  "mime",
@@ -1402,39 +1226,37 @@ dependencies = [
  "fastrand",
  "futures-util",
  "headers",
- "http 1.2.0",
+ "http 1.3.1",
  "http-body 1.0.1",
  "http-body-util",
  "mime",
  "multer",
  "pin-project-lite",
  "serde",
- "tower 0.5.1",
+ "tower 0.5.2",
  "tower-layer",
  "tower-service",
 ]
 
 [[package]]
 name = "axum-server"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56bac90848f6a9393ac03c63c640925c4b7c8ca21654de40d53f55964667c7d8"
+checksum = "495c05f60d6df0093e8fb6e74aa5846a0ad06abaf96d76166283720bf740f8ab"
 dependencies = [
  "arc-swap",
  "bytes",
- "futures-util",
- "http 1.2.0",
+ "fs-err 3.1.0",
+ "http 1.3.1",
  "http-body 1.0.1",
- "http-body-util",
- "hyper 1.5.1",
+ "hyper 1.6.0",
  "hyper-util",
  "pin-project-lite",
- "rustls 0.23.19",
+ "rustls 0.23.25",
  "rustls-pemfile 2.2.0",
  "rustls-pki-types",
  "tokio",
- "tokio-rustls 0.26.1",
- "tower 0.4.13",
+ "tokio-rustls 0.26.2",
  "tower-service",
 ]
 
@@ -1455,7 +1277,7 @@ dependencies = [
  "forwarded-header-value",
  "futures",
  "hmac",
- "http 1.2.0",
+ "http 1.3.1",
  "http-body 1.0.1",
  "rand 0.8.5",
  "serde",
@@ -1485,7 +1307,7 @@ dependencies = [
  "chrono",
  "dashmap 5.5.3",
  "futures",
- "http 1.2.0",
+ "http 1.3.1",
  "http-body 1.0.1",
  "serde",
  "tokio",
@@ -1504,7 +1326,7 @@ dependencies = [
  "cfg-if",
  "libc",
  "miniz_oxide",
- "object 0.36.5",
+ "object 0.36.7",
  "rustc-demangle",
  "windows-targets 0.52.6",
 ]
@@ -1515,12 +1337,6 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8"
 
-[[package]]
-name = "base16ct"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
-
 [[package]]
 name = "base16ct"
 version = "0.2.0"
@@ -1536,39 +1352,29 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
 [[package]]
 name = "base64"
 version = "0.22.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
-
-[[package]]
-name = "base64-simd"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5"
-dependencies = [
- "simd-abstraction",
-]
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
 
 [[package]]
 name = "base64-simd"
-version = "0.8.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195"
+checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5"
 dependencies = [
- "outref 0.5.1",
- "vsimd",
+ "simd-abstraction",
 ]
 
 [[package]]
 name = "base64ct"
-version = "1.6.0"
+version = "1.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3"
 
 [[package]]
 name = "bcder"
-version = "0.7.4"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c627747a6774aab38beb35990d88309481378558875a41da1a4b2e373c906ef0"
+checksum = "89ffdaa8c6398acd07176317eb6c1f9082869dd1cc3fee7c72c6354866b928cc"
 dependencies = [
  "bytes",
  "smallvec",
@@ -1600,7 +1406,7 @@ version = "0.69.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "cexpr",
  "clang-sys",
  "itertools 0.12.1",
@@ -1613,7 +1419,7 @@ dependencies = [
  "regex",
  "rustc-hash 1.1.0",
  "shlex",
- "syn 2.0.98",
+ "syn 2.0.100",
  "which 4.4.2",
 ]
 
@@ -1623,7 +1429,16 @@ version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
 dependencies = [
- "bit-vec",
+ "bit-vec 0.6.3",
+]
+
+[[package]]
+name = "bit-set"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
+dependencies = [
+ "bit-vec 0.8.0",
 ]
 
 [[package]]
@@ -1632,6 +1447,12 @@ version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
 
+[[package]]
+name = "bit-vec"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
+
 [[package]]
 name = "bit_field"
 version = "0.10.2"
@@ -1652,9 +1473,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitflags"
-version = "2.6.0"
+version = "2.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
 dependencies = [
  "serde",
 ]
@@ -1708,6 +1529,108 @@ dependencies = [
  "digest",
 ]
 
+[[package]]
+name = "blitz-dom"
+version = "0.1.0-alpha.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae8889dde80e2aaceec27455c63446ca841cb7217a4f5489691295da922792b"
+dependencies = [
+ "accesskit",
+ "app_units",
+ "atomic_refcell",
+ "blitz-traits",
+ "color",
+ "cursor-icon",
+ "euclid",
+ "html-escape",
+ "image",
+ "keyboard-types",
+ "markup5ever 0.15.0",
+ "parley",
+ "peniko",
+ "selectors 0.27.0",
+ "slab",
+ "smallvec",
+ "string_cache",
+ "stylo",
+ "stylo_config",
+ "stylo_dom",
+ "stylo_taffy",
+ "stylo_traits",
+ "taffy",
+ "tracing",
+ "url",
+ "usvg",
+]
+
+[[package]]
+name = "blitz-net"
+version = "0.1.0-alpha.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "efc80023b8f6758d7f61bda68440917b72cbe2fe6187cbe1b7837e73b2522dfe"
+dependencies = [
+ "blitz-traits",
+ "data-url 0.3.1",
+ "reqwest 0.12.15",
+ "thiserror 1.0.69",
+ "tokio",
+]
+
+[[package]]
+name = "blitz-renderer-vello"
+version = "0.1.0-alpha.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44fdafaf87eb502da99667fad2ae9757d01c8bd83772f6b7b6a78c48c3ab6ff5"
+dependencies = [
+ "blitz-dom",
+ "blitz-traits",
+ "color",
+ "euclid",
+ "futures-intrusive",
+ "image",
+ "parley",
+ "pollster 0.4.0",
+ "raw-window-handle 0.6.2",
+ "stylo",
+ "taffy",
+ "vello",
+ "vello_svg",
+ "wgpu 23.0.1",
+]
+
+[[package]]
+name = "blitz-shell"
+version = "0.1.0-alpha.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef0a6122f3619a746dddd21883edaae5f791d6e9f401dbdf7f7756caa4f69453"
+dependencies = [
+ "accesskit",
+ "accesskit_winit",
+ "android-activity",
+ "blitz-dom",
+ "blitz-traits",
+ "futures-util",
+ "keyboard-types",
+ "muda 0.11.5",
+ "tracing",
+ "winit",
+]
+
+[[package]]
+name = "blitz-traits"
+version = "0.1.0-alpha.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9972442314e8bf9dd65af7aee0634a2d575972587d404520c7c6986abbd523d3"
+dependencies = [
+ "bitflags 2.9.0",
+ "bytes",
+ "http 1.3.1",
+ "keyboard-types",
+ "raw-window-handle 0.6.2",
+ "smol_str",
+ "url",
+]
+
 [[package]]
 name = "block"
 version = "0.1.6"
@@ -1775,9 +1698,9 @@ dependencies = [
 
 [[package]]
 name = "borsh"
-version = "1.5.3"
+version = "1.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03"
+checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce"
 dependencies = [
  "borsh-derive",
  "cfg_aliases 0.2.1",
@@ -1785,15 +1708,15 @@ dependencies = [
 
 [[package]]
 name = "borsh-derive"
-version = "1.5.3"
+version = "1.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244"
+checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3"
 dependencies = [
  "once_cell",
- "proc-macro-crate 3.2.0",
+ "proc-macro-crate 3.3.0",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -1820,9 +1743,9 @@ dependencies = [
 
 [[package]]
 name = "brotli-decompressor"
-version = "4.0.1"
+version = "4.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362"
+checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37"
 dependencies = [
  "alloc-no-stdlib",
  "alloc-stdlib",
@@ -1837,7 +1760,7 @@ dependencies = [
  "ahash 0.8.11",
  "chrono",
  "either",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "itertools 0.13.0",
  "nom",
  "once_cell",
@@ -1846,11 +1769,28 @@ dependencies = [
  "thiserror 1.0.69",
 ]
 
+[[package]]
+name = "browserslist-rs"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74c973b79d9b6b89854493185ab760c6ef8e54bcfad10ad4e33991e46b374ac8"
+dependencies = [
+ "ahash 0.8.11",
+ "chrono",
+ "either",
+ "indexmap 2.9.0",
+ "itertools 0.13.0",
+ "nom",
+ "serde",
+ "serde_json",
+ "thiserror 1.0.69",
+]
+
 [[package]]
 name = "bstr"
-version = "1.11.0"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22"
+checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
 dependencies = [
  "memchr",
  "regex-automata 0.4.9",
@@ -1877,9 +1817,9 @@ dependencies = [
 
 [[package]]
 name = "bumpalo"
-version = "3.16.0"
+version = "3.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
 dependencies = [
  "allocator-api2",
 ]
@@ -1908,9 +1848,23 @@ dependencies = [
 
 [[package]]
 name = "bytemuck"
-version = "1.20.0"
+version = "1.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
+dependencies = [
+ "bytemuck_derive",
+]
+
+[[package]]
+name = "bytemuck_derive"
+version = "1.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a"
+checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+]
 
 [[package]]
 name = "byteorder"
@@ -1926,25 +1880,15 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
 
 [[package]]
 name = "bytes"
-version = "1.9.0"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
-
-[[package]]
-name = "bytes-utils"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35"
-dependencies = [
- "bytes",
- "either",
-]
+checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
 
 [[package]]
 name = "bytesize"
-version = "1.3.0"
+version = "1.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc"
+checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659"
 
 [[package]]
 name = "bzip2"
@@ -1958,12 +1902,11 @@ dependencies = [
 
 [[package]]
 name = "bzip2-sys"
-version = "0.1.11+1.0.8"
+version = "0.1.13+1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
+checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14"
 dependencies = [
  "cc",
- "libc",
  "pkg-config",
 ]
 
@@ -1973,7 +1916,7 @@ version = "0.18.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "cairo-sys-rs",
  "glib",
  "libc",
@@ -1992,6 +1935,32 @@ dependencies = [
  "system-deps",
 ]
 
+[[package]]
+name = "calloop"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec"
+dependencies = [
+ "bitflags 2.9.0",
+ "log",
+ "polling",
+ "rustix 0.38.44",
+ "slab",
+ "thiserror 1.0.69",
+]
+
+[[package]]
+name = "calloop-wayland-source"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20"
+dependencies = [
+ "calloop",
+ "rustix 0.38.44",
+ "wayland-backend",
+ "wayland-client",
+]
+
 [[package]]
 name = "camellia"
 version = "0.1.0"
@@ -2013,14 +1982,14 @@ dependencies = [
 
 [[package]]
 name = "cargo-config2"
-version = "0.1.29"
+version = "0.1.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1124054becb9262cc15c5e96e82f0d782f2aed3a3034d1f71a6385a6fa9e9595"
+checksum = "6dc3749a36e0423c991f1e7a3e4ab0c36a1f489658313db4b187d401d79cc461"
 dependencies = [
- "home",
  "serde",
  "serde_derive",
- "toml_edit 0.22.22",
+ "toml_edit 0.22.24",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -2035,14 +2004,14 @@ dependencies = [
  "clap",
  "console",
  "dialoguer",
- "env_logger 0.11.5",
- "fs-err",
+ "env_logger 0.11.8",
+ "fs-err 2.11.0",
  "git2",
  "gix-config",
  "heck 0.5.0",
  "home",
  "ignore",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "indicatif",
  "liquid",
  "liquid-core",
@@ -2056,7 +2025,7 @@ dependencies = [
  "remove_dir_all",
  "rhai",
  "sanitize-filename",
- "semver 1.0.23",
+ "semver 1.0.26",
  "serde",
  "tempfile",
  "thiserror 1.0.69",
@@ -2082,7 +2051,7 @@ checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037"
 dependencies = [
  "camino",
  "cargo-platform",
- "semver 1.0.23",
+ "semver 1.0.26",
  "serde",
  "serde_json",
  "thiserror 1.0.69",
@@ -2139,9 +2108,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.2.16"
+version = "1.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
+checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c"
 dependencies = [
  "jobserver",
  "libc",
@@ -2222,9 +2191,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
 
 [[package]]
 name = "chrono"
-version = "0.4.39"
+version = "0.4.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
+checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
 dependencies = [
  "android-tzdata",
  "iana-time-zone",
@@ -2232,7 +2201,7 @@ dependencies = [
  "num-traits",
  "serde",
  "wasm-bindgen",
- "windows-targets 0.52.6",
+ "windows-link",
 ]
 
 [[package]]
@@ -2285,9 +2254,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.23"
+version = "4.5.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
+checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -2295,9 +2264,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.23"
+version = "4.5.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
+checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9"
 dependencies = [
  "anstream",
  "anstyle",
@@ -2308,14 +2277,14 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.5.18"
+version = "4.5.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
+checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -2337,9 +2306,9 @@ dependencies = [
 
 [[package]]
 name = "cmake"
-version = "0.1.52"
+version = "0.1.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e"
+checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
 dependencies = [
  "cc",
 ]
@@ -2366,7 +2335,7 @@ version = "0.26.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "block",
  "cocoa-foundation 0.2.0",
  "core-foundation 0.10.0",
@@ -2396,7 +2365,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "block",
  "core-foundation 0.10.0",
  "core-graphics-types 0.2.0",
@@ -2420,6 +2389,23 @@ dependencies = [
  "unicode-width 0.1.14",
 ]
 
+[[package]]
+name = "codespan-reporting"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81"
+dependencies = [
+ "serde",
+ "termcolor",
+ "unicode-width 0.2.0",
+]
+
+[[package]]
+name = "color"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61c387f6cef110ee8eaf12fca5586d3d303c07c594f4a5f02c768b6470b70dbd"
+
 [[package]]
 name = "color_quant"
 version = "1.1.0"
@@ -2475,13 +2461,13 @@ dependencies = [
 
 [[package]]
 name = "compact_str"
-version = "0.8.0"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644"
+checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
 dependencies = [
  "castaway",
  "cfg-if",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "rustversion",
  "ryu",
  "static_assertions",
@@ -2498,15 +2484,15 @@ dependencies = [
 
 [[package]]
 name = "console"
-version = "0.15.8"
+version = "0.15.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
+checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
 dependencies = [
  "encode_unicode",
- "lazy_static",
  "libc",
- "unicode-width 0.1.14",
- "windows-sys 0.52.0",
+ "once_cell",
+ "unicode-width 0.2.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -2599,7 +2585,7 @@ version = "0.6.3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -2644,9 +2630,9 @@ dependencies = [
 
 [[package]]
 name = "const_panic"
-version = "0.2.10"
+version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "013b6c2c3a14d678f38cd23994b02da3a1a1b6a5d1eedddfe63a5a5f11b13a81"
+checksum = "2459fc9262a1aa204eb4b5764ad4f189caec88aea9634389c0a25f8be7f6265e"
 
 [[package]]
 name = "convert_case"
@@ -2732,7 +2718,7 @@ version = "0.24.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "core-foundation 0.10.0",
  "core-graphics-types 0.2.0",
  "foreign-types 0.5.0",
@@ -2756,11 +2742,20 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "core-foundation 0.10.0",
  "libc",
 ]
 
+[[package]]
+name = "core_maths"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30"
+dependencies = [
+ "libm",
+]
+
 [[package]]
 name = "cpio"
 version = "0.4.1"
@@ -2781,9 +2776,9 @@ dependencies = [
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.16"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
 dependencies = [
  "libc",
 ]
@@ -2824,15 +2819,6 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fd121741cf3eb82c08dd3023eb55bf2665e5f60ec20f89760cf836ae4562e6a0"
 
-[[package]]
-name = "crc32c"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47"
-dependencies = [
- "rustc_version 0.4.1",
-]
-
 [[package]]
 name = "crc32fast"
 version = "1.4.2"
@@ -2895,18 +2881,18 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.13"
+version = "0.5.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
+checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471"
 dependencies = [
  "crossbeam-utils",
 ]
 
 [[package]]
 name = "crossbeam-deque"
-version = "0.8.5"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
 dependencies = [
  "crossbeam-epoch",
  "crossbeam-utils",
@@ -2923,18 +2909,18 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-queue"
-version = "0.3.11"
+version = "0.3.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
+checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
 dependencies = [
  "crossbeam-utils",
 ]
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.20"
+version = "0.8.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
 
 [[package]]
 name = "crossterm"
@@ -2942,12 +2928,12 @@ version = "0.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "crossterm_winapi",
  "futures-core",
  "mio 1.0.3",
  "parking_lot",
- "rustix",
+ "rustix 0.38.44",
  "signal-hook",
  "signal-hook-mio",
  "winapi",
@@ -2964,21 +2950,9 @@ dependencies = [
 
 [[package]]
 name = "crunchy"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
-
-[[package]]
-name = "crypto-bigint"
-version = "0.4.9"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
-dependencies = [
- "generic-array 0.14.7",
- "rand_core 0.6.4",
- "subtle",
- "zeroize",
-]
+checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
 
 [[package]]
 name = "crypto-bigint"
@@ -3016,7 +2990,7 @@ dependencies = [
  "pem",
  "reqwest 0.11.27",
  "ring",
- "signature 2.2.0",
+ "signature",
  "x509-certificate",
 ]
 
@@ -3045,8 +3019,22 @@ checksum = "9be934d936a0fbed5bcdc01042b770de1398bf79d0e192f49fa7faea0e99281e"
 dependencies = [
  "cssparser-macros",
  "dtoa-short",
- "itoa 1.0.14",
- "phf 0.11.2",
+ "itoa 1.0.15",
+ "phf 0.11.3",
+ "smallvec",
+]
+
+[[package]]
+name = "cssparser"
+version = "0.35.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e901edd733a1472f944a45116df3f846f54d37e67e68640ac8bb69689aca2aa"
+dependencies = [
+ "cssparser-macros",
+ "dtoa-short",
+ "itoa 1.0.15",
+ "phf 0.11.3",
+ "serde",
  "smallvec",
 ]
 
@@ -3066,7 +3054,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
 dependencies = [
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3076,7 +3064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501"
 dependencies = [
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3090,14 +3078,20 @@ dependencies = [
 
 [[package]]
 name = "ctrlc"
-version = "3.4.5"
+version = "3.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3"
+checksum = "697b5419f348fd5ae2478e8018cb016c00a5881c7f46c717de98ffd135a5651c"
 dependencies = [
- "nix 0.29.0",
+ "nix",
  "windows-sys 0.59.0",
 ]
 
+[[package]]
+name = "cursor-icon"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
+
 [[package]]
 name = "curve25519-dalek"
 version = "4.1.3"
@@ -3123,7 +3117,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3137,9 +3131,9 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.133"
+version = "1.0.156"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05e1ec88093d2abd9cf1b09ffd979136b8e922bf31cad966a8fe0d73233112ef"
+checksum = "aa3a202fc4f3dd6d2ce5a2f87b04fb2becc00f5643ee9c4743ba10777efb314f"
 dependencies = [
  "cc",
  "cxxbridge-cmd",
@@ -3151,47 +3145,47 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.133"
+version = "1.0.156"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9afa390d956ee7ccb41aeed7ed7856ab3ffb4fc587e7216be7e0f83e949b4e6c"
+checksum = "644bdf46f34f6325783f76a8ad8e737ab995a302d7868b5236a1ba55008883e0"
 dependencies = [
  "cc",
- "codespan-reporting",
+ "codespan-reporting 0.12.0",
  "proc-macro2",
  "quote",
  "scratch",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.133"
+version = "1.0.156"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c23bfff654d6227cbc83de8e059d2f8678ede5fc3a6c5a35d5c379983cc61e6"
+checksum = "8e8cefbebcb74ed0b4a08b76139e6c29d8884a0bb94d02c6f35de821a14a6e39"
 dependencies = [
  "clap",
- "codespan-reporting",
+ "codespan-reporting 0.12.0",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.133"
+version = "1.0.156"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7c01b36e22051bc6928a78583f1621abaaf7621561c2ada1b00f7878fbe2caa"
+checksum = "604e3eff62e2f27289d618f621491a068330c3c9f8eb06555dabc292c123596e"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.133"
+version = "1.0.156"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6e14013136fac689345d17b9a6df55977251f11d333c0a571e8d963b55e1f95"
+checksum = "130c3a05501d9c15dedbf08f2ff9af60f8e78422e3dffac1f43e2d83c5b489a1"
 dependencies = [
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3200,16 +3194,16 @@ version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3e3d747f100290a1ca24b752186f61f6637e1deffe3bf6320de6fcb29510a307"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "libloading 0.8.6",
  "winapi",
 ]
 
 [[package]]
 name = "darling"
-version = "0.20.10"
+version = "0.20.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
+checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
 dependencies = [
  "darling_core",
  "darling_macro",
@@ -3217,27 +3211,27 @@ dependencies = [
 
 [[package]]
 name = "darling_core"
-version = "0.20.10"
+version = "0.20.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
+checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
 dependencies = [
  "fnv",
  "ident_case",
  "proc-macro2",
  "quote",
  "strsim",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "darling_macro"
-version = "0.20.10"
+version = "0.20.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
+checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
 dependencies = [
  "darling_core",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3269,9 +3263,9 @@ dependencies = [
 
 [[package]]
 name = "data-encoding"
-version = "2.6.0"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
+checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010"
 
 [[package]]
 name = "data-url"
@@ -3282,6 +3276,12 @@ dependencies = [
  "matches",
 ]
 
+[[package]]
+name = "data-url"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a"
+
 [[package]]
 name = "dbl"
 version = "0.3.2"
@@ -3301,16 +3301,6 @@ dependencies = [
  "uuid",
 ]
 
-[[package]]
-name = "der"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
-dependencies = [
- "const-oid",
- "zeroize",
-]
-
 [[package]]
 name = "der"
 version = "0.7.9"
@@ -3324,9 +3314,9 @@ dependencies = [
 
 [[package]]
 name = "deranged"
-version = "0.3.11"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
 dependencies = [
  "powerfmt",
  "serde",
@@ -3340,7 +3330,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3361,7 +3351,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3371,20 +3361,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
 dependencies = [
  "derive_builder_core",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "derive_more"
-version = "0.99.18"
+version = "0.99.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
+checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f"
 dependencies = [
  "convert_case 0.4.0",
  "proc-macro2",
  "quote",
  "rustc_version 0.4.1",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3404,7 +3394,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "unicode-xid",
 ]
 
@@ -3475,6 +3465,7 @@ dependencies = [
  "dioxus-liveview",
  "dioxus-logger",
  "dioxus-mobile",
+ "dioxus-native",
  "dioxus-router",
  "dioxus-signals",
  "dioxus-ssr",
@@ -3491,6 +3482,21 @@ dependencies = [
  "wasm-split",
 ]
 
+[[package]]
+name = "dioxus-asset-resolver"
+version = "0.6.3"
+dependencies = [
+ "dioxus-cli-config",
+ "http 1.3.1",
+ "infer",
+ "jni",
+ "ndk",
+ "ndk-context",
+ "ndk-sys 0.6.0+11769913",
+ "thiserror 1.0.69",
+ "urlencoding",
+]
+
 [[package]]
 name = "dioxus-autofmt"
 version = "0.6.3"
@@ -3501,7 +3507,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3513,7 +3519,7 @@ dependencies = [
  "pretty_assertions",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3556,7 +3562,7 @@ dependencies = [
  "dircpy",
  "dirs 5.0.1",
  "dunce",
- "env_logger 0.11.5",
+ "env_logger 0.11.8",
  "escargot",
  "flate2",
  "futures-channel",
@@ -3564,8 +3570,8 @@ dependencies = [
  "handlebars",
  "headers",
  "html_parser",
- "hyper 1.5.1",
- "hyper-rustls 0.27.3",
+ "hyper 1.6.0",
+ "hyper-rustls 0.27.5",
  "hyper-util",
  "ignore",
  "include_dir",
@@ -3577,7 +3583,7 @@ dependencies = [
  "manganis-core",
  "memoize",
  "notify",
- "object 0.36.5",
+ "object 0.36.7",
  "once_cell",
  "open",
  "path-absolutize",
@@ -3587,12 +3593,12 @@ dependencies = [
  "ratatui",
  "rayon",
  "regex",
- "reqwest 0.12.9",
- "rustls 0.23.19",
+ "reqwest 0.12.15",
+ "rustls 0.23.25",
  "serde",
  "serde_json",
  "strum 0.26.3",
- "syn 2.0.98",
+ "syn 2.0.100",
  "tar",
  "tauri-bundler",
  "tauri-utils",
@@ -3603,7 +3609,7 @@ dependencies = [
  "tokio-stream",
  "tokio-util",
  "toml",
- "toml_edit 0.22.22",
+ "toml_edit 0.22.24",
  "tower 0.4.13",
  "tower-http",
  "tracing",
@@ -3613,7 +3619,7 @@ dependencies = [
  "walkdir",
  "wasm-opt",
  "wasm-split-cli",
- "which 7.0.1",
+ "which 7.0.2",
 ]
 
 [[package]]
@@ -3628,7 +3634,7 @@ name = "dioxus-cli-opt"
 version = "0.6.3"
 dependencies = [
  "anyhow",
- "browserslist-rs",
+ "browserslist-rs 0.16.0",
  "codemap",
  "const-serialize",
  "grass",
@@ -3638,7 +3644,7 @@ dependencies = [
  "manganis",
  "manganis-core",
  "mozjpeg",
- "object 0.36.5",
+ "object 0.36.7",
  "png",
  "rayon",
  "serde",
@@ -3678,7 +3684,7 @@ version = "0.0.1"
 dependencies = [
  "dioxus",
  "flate2",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "tar",
 ]
 
@@ -3709,7 +3715,7 @@ dependencies = [
  "longest-increasing-subsequence",
  "pretty_assertions",
  "rand 0.8.5",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "rustc-hash 1.1.0",
  "rustversion",
  "serde",
@@ -3735,7 +3741,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 2.0.98",
+ "syn 2.0.100",
  "tokio",
  "trybuild",
 ]
@@ -3756,6 +3762,7 @@ dependencies = [
  "cocoa 0.25.0",
  "core-foundation 0.9.4",
  "dioxus",
+ "dioxus-asset-resolver",
  "dioxus-cli-config",
  "dioxus-core",
  "dioxus-devtools",
@@ -3773,10 +3780,10 @@ dependencies = [
  "generational-box",
  "global-hotkey",
  "http-range",
- "infer 0.11.0",
+ "infer",
  "jni",
  "lazy-js-bundle",
- "muda",
+ "muda 0.15.3",
  "ndk",
  "ndk-context",
  "ndk-sys 0.6.0+11769913",
@@ -3784,7 +3791,7 @@ dependencies = [
  "objc_id",
  "once_cell",
  "rand 0.8.5",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "rfd",
  "rustc-hash 1.1.0",
  "separator",
@@ -3870,14 +3877,14 @@ dependencies = [
  "openssl",
  "ouroboros",
  "rand 0.8.5",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "separator",
  "serde",
  "serde_json",
  "tokio",
  "wasm-split",
  "web-time",
- "wgpu",
+ "wgpu 0.19.4",
 ]
 
 [[package]]
@@ -3887,7 +3894,7 @@ dependencies = [
  "dioxus-autofmt",
  "dioxus-rsx-rosetta",
  "html_parser",
- "syn 2.0.98",
+ "syn 2.0.100",
  "wasm-bindgen",
 ]
 
@@ -3919,13 +3926,13 @@ dependencies = [
  "futures-channel",
  "futures-util",
  "generational-box",
- "http 1.2.0",
- "hyper 1.5.1",
- "hyper-rustls 0.27.3",
+ "http 1.3.1",
+ "hyper 1.6.0",
+ "hyper-rustls 0.27.5",
  "once_cell",
  "parking_lot",
  "pin-project",
- "rustls 0.23.19",
+ "rustls 0.23.25",
  "serde",
  "server_fn",
  "thiserror 1.0.69",
@@ -3983,7 +3990,7 @@ dependencies = [
  "futures-channel",
  "futures-util",
  "generational-box",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "rustversion",
  "slab",
  "tokio",
@@ -4028,7 +4035,7 @@ dependencies = [
  "convert_case 0.6.0",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "trybuild",
 ]
 
@@ -4055,11 +4062,12 @@ name = "dioxus-isrg"
 version = "0.6.3"
 dependencies = [
  "chrono",
- "http 1.2.0",
+ "http 1.3.1",
  "lru 0.12.5",
  "rustc-hash 1.1.0",
  "thiserror 1.0.69",
  "tracing",
+ "walkdir",
 ]
 
 [[package]]
@@ -4130,6 +4138,30 @@ dependencies = [
  "once_cell",
 ]
 
+[[package]]
+name = "dioxus-native"
+version = "0.6.3"
+dependencies = [
+ "blitz-dom",
+ "blitz-net",
+ "blitz-renderer-vello",
+ "blitz-shell",
+ "blitz-traits",
+ "dioxus-asset-resolver",
+ "dioxus-cli-config",
+ "dioxus-core",
+ "dioxus-devtools",
+ "dioxus-document",
+ "dioxus-history",
+ "dioxus-html",
+ "futures-util",
+ "keyboard-types",
+ "rustc-hash 1.1.0",
+ "tokio",
+ "tracing",
+ "winit",
+]
+
 [[package]]
 name = "dioxus-playwright-default-features-disabled-test"
 version = "0.1.0"
@@ -4227,7 +4259,7 @@ dependencies = [
  "quote",
  "sha2",
  "slab",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -4239,7 +4271,7 @@ dependencies = [
  "proc-macro2",
  "proc-macro2-diagnostics",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -4253,7 +4285,7 @@ dependencies = [
  "proc-macro2",
  "proc-macro2-diagnostics",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "tracing",
 ]
 
@@ -4270,7 +4302,7 @@ dependencies = [
  "pretty_assertions",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -4285,7 +4317,7 @@ dependencies = [
  "once_cell",
  "parking_lot",
  "rand 0.8.5",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "rustc-hash 1.1.0",
  "serde",
  "tokio",
@@ -4360,7 +4392,7 @@ dependencies = [
  "quote",
  "serde",
  "server_fn_macro",
- "syn 2.0.98",
+ "syn 2.0.100",
  "tower-http",
 ]
 
@@ -4385,22 +4417,12 @@ dependencies = [
 ]
 
 [[package]]
-name = "dirs"
-version = "6.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
-dependencies = [
- "dirs-sys 0.5.0",
-]
-
-[[package]]
-name = "dirs-next"
-version = "2.0.0"
+name = "dirs"
+version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
+checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
 dependencies = [
- "cfg-if",
- "dirs-sys-next",
+ "dirs-sys 0.5.0",
 ]
 
 [[package]]
@@ -4427,17 +4449,6 @@ dependencies = [
  "windows-sys 0.59.0",
 ]
 
-[[package]]
-name = "dirs-sys-next"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
-dependencies = [
- "libc",
- "redox_users 0.4.6",
- "winapi",
-]
-
 [[package]]
 name = "dispatch"
 version = "0.2.0"
@@ -4452,14 +4463,23 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "dissimilar"
-version = "1.0.9"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d"
+checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921"
+
+[[package]]
+name = "dlib"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
+dependencies = [
+ "libloading 0.8.6",
+]
 
 [[package]]
 name = "dlopen2"
@@ -4481,7 +4501,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -4490,12 +4510,27 @@ version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
 
+[[package]]
+name = "document-features"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d"
+dependencies = [
+ "litrs",
+]
+
 [[package]]
 name = "dotenvy"
 version = "0.15.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
 
+[[package]]
+name = "downcast-rs"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
+
 [[package]]
 name = "dpi"
 version = "0.1.1"
@@ -4511,18 +4546,18 @@ dependencies = [
  "digest",
  "num-bigint-dig",
  "num-traits",
- "pkcs8 0.10.2",
- "rfc6979 0.4.0",
+ "pkcs8",
+ "rfc6979",
  "sha2",
- "signature 2.2.0",
+ "signature",
  "zeroize",
 ]
 
 [[package]]
 name = "dtoa"
-version = "1.0.9"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653"
+checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04"
 
 [[package]]
 name = "dtoa-short"
@@ -4552,30 +4587,18 @@ dependencies = [
  "subtle",
 ]
 
-[[package]]
-name = "ecdsa"
-version = "0.14.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
-dependencies = [
- "der 0.6.1",
- "elliptic-curve 0.12.3",
- "rfc6979 0.3.1",
- "signature 1.6.4",
-]
-
 [[package]]
 name = "ecdsa"
 version = "0.16.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
 dependencies = [
- "der 0.7.9",
+ "der",
  "digest",
- "elliptic-curve 0.13.8",
- "rfc6979 0.4.0",
- "signature 2.2.0",
- "spki 0.7.3",
+ "elliptic-curve",
+ "rfc6979",
+ "signature",
+ "spki",
 ]
 
 [[package]]
@@ -4584,7 +4607,7 @@ version = "0.1.1"
 dependencies = [
  "chrono",
  "dioxus",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "serde",
 ]
 
@@ -4594,8 +4617,8 @@ version = "2.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
 dependencies = [
- "pkcs8 0.10.2",
- "signature 2.2.0",
+ "pkcs8",
+ "signature",
 ]
 
 [[package]]
@@ -4625,59 +4648,39 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.13.0"
+version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
 dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "elliptic-curve"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
-dependencies = [
- "base16ct 0.1.1",
- "crypto-bigint 0.4.9",
- "der 0.6.1",
- "digest",
- "ff 0.12.1",
- "generic-array 0.14.7",
- "group 0.12.1",
- "pkcs8 0.9.0",
- "rand_core 0.6.4",
- "sec1 0.3.0",
- "subtle",
- "zeroize",
-]
-
 [[package]]
 name = "elliptic-curve"
 version = "0.13.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
 dependencies = [
- "base16ct 0.2.0",
- "crypto-bigint 0.5.5",
+ "base16ct",
+ "crypto-bigint",
  "digest",
- "ff 0.13.0",
+ "ff",
  "generic-array 0.14.7",
- "group 0.13.0",
+ "group",
  "hkdf",
  "pem-rfc7468",
- "pkcs8 0.10.2",
+ "pkcs8",
  "rand_core 0.6.4",
- "sec1 0.7.3",
+ "sec1",
  "subtle",
  "zeroize",
 ]
 
 [[package]]
 name = "encode_unicode"
-version = "0.3.6"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
 
 [[package]]
 name = "encoding_rs"
@@ -4713,14 +4716,14 @@ checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c"
 dependencies = [
  "num-traits",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "enumflags2"
-version = "0.7.10"
+version = "0.7.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d"
+checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147"
 dependencies = [
  "enumflags2_derive",
  "serde",
@@ -4728,13 +4731,13 @@ dependencies = [
 
 [[package]]
 name = "enumflags2_derive"
-version = "0.7.10"
+version = "0.7.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8"
+checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -4755,14 +4758,14 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "env_filter"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
+checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
 dependencies = [
  "log",
  "regex",
@@ -4789,28 +4792,28 @@ dependencies = [
 
 [[package]]
 name = "env_logger"
-version = "0.11.5"
+version = "0.11.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
+checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
 dependencies = [
  "anstream",
  "anstyle",
  "env_filter",
- "humantime",
+ "jiff",
  "log",
 ]
 
 [[package]]
 name = "equivalent"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
 
 [[package]]
 name = "erased-serde"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d"
+checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7"
 dependencies = [
  "serde",
  "typeid",
@@ -4818,9 +4821,9 @@ dependencies = [
 
 [[package]]
 name = "errno"
-version = "0.3.10"
+version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
+checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
 dependencies = [
  "libc",
  "windows-sys 0.59.0",
@@ -4867,9 +4870,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
 
 [[package]]
 name = "event-listener"
-version = "5.3.1"
+version = "5.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
+checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae"
 dependencies = [
  "concurrent-queue",
  "parking",
@@ -4878,11 +4881,11 @@ dependencies = [
 
 [[package]]
 name = "event-listener-strategy"
-version = "0.5.3"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2"
+checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
 dependencies = [
- "event-listener 5.3.1",
+ "event-listener 5.4.0",
  "pin-project-lite",
 ]
 
@@ -4894,7 +4897,7 @@ checksum = "3a82608ee96ce76aeab659e9b8d3c2b787bffd223199af88c674923d861ada10"
 dependencies = [
  "execute-command-macro",
  "execute-command-tokens",
- "generic-array 1.1.1",
+ "generic-array 1.2.0",
 ]
 
 [[package]]
@@ -4914,7 +4917,7 @@ checksum = "ce8cd46a041ad005ab9c71263f9a0ff5b529eac0fe4cc9b4a20f4f0765d8cf4b"
 dependencies = [
  "execute-command-tokens",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -4973,19 +4976,9 @@ dependencies = [
 
 [[package]]
 name = "ff"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
-dependencies = [
- "rand_core 0.6.4",
- "subtle",
-]
-
-[[package]]
-name = "ff"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
+checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
 dependencies = [
  "rand_core 0.6.4",
  "subtle",
@@ -5055,14 +5048,20 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
 
 [[package]]
 name = "flate2"
-version = "1.0.35"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
+checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
 ]
 
+[[package]]
+name = "float-cmp"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
+
 [[package]]
 name = "flume"
 version = "0.11.1"
@@ -5082,9 +5081,73 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
 [[package]]
 name = "foldhash"
-version = "0.1.3"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
+[[package]]
+name = "font-types"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fa6a5e5a77b5f3f7f9e32879f484aa5b3632ddfbe568a16266c904a6f32cdaf"
+dependencies = [
+ "bytemuck",
+]
+
+[[package]]
+name = "fontconfig-cache-parser"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7f8afb20c8069fd676d27b214559a337cc619a605d25a87baa90b49a06f3b18"
+dependencies = [
+ "bytemuck",
+ "thiserror 1.0.69",
+]
+
+[[package]]
+name = "fontconfig-parser"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7"
+dependencies = [
+ "roxmltree",
+]
+
+[[package]]
+name = "fontdb"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3a6f9af55fb97ad673fb7a69533eb2f967648a06fa21f8c9bb2cd6d33975716"
+dependencies = [
+ "fontconfig-parser",
+ "log",
+ "memmap2",
+ "slotmap",
+ "tinyvec",
+ "ttf-parser 0.24.1",
+]
+
+[[package]]
+name = "fontique"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
+checksum = "6b5fcb214137f01bc842c4fd633236255c51f8a24c6d3923eb8361c6d0940737"
+dependencies = [
+ "bytemuck",
+ "fontconfig-cache-parser",
+ "hashbrown 0.15.2",
+ "icu_locid",
+ "memmap2",
+ "objc2-core-foundation",
+ "objc2-core-text",
+ "objc2-foundation 0.3.0",
+ "peniko",
+ "read-fonts",
+ "roxmltree",
+ "smallvec",
+ "windows 0.58.0",
+ "windows-core 0.58.0",
+]
 
 [[package]]
 name = "foreign-types"
@@ -5113,7 +5176,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -5155,7 +5218,7 @@ checksum = "8d7ccf961415e7aa17ef93dcb6c2441faaa8e768abe09e659b908089546f74c5"
 dependencies = [
  "proc-macro2",
  "swc_macros_common",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -5167,6 +5230,16 @@ dependencies = [
  "autocfg",
 ]
 
+[[package]]
+name = "fs-err"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f89bda4c2a21204059a977ed3bfe746677dfd137b83c339e702b0ac91d482aa"
+dependencies = [
+ "autocfg",
+ "tokio",
+]
+
 [[package]]
 name = "fs_at"
 version = "0.2.1"
@@ -5177,7 +5250,7 @@ dependencies = [
  "cfg-if",
  "cvt",
  "libc",
- "nix 0.29.0",
+ "nix",
  "windows-sys 0.52.0",
 ]
 
@@ -5210,7 +5283,7 @@ dependencies = [
  "dioxus-fullstack",
  "dioxus-web",
  "execute",
- "http 1.2.0",
+ "http 1.3.1",
  "serde",
  "sqlx",
  "tokio",
@@ -5232,7 +5305,7 @@ version = "0.1.0"
 dependencies = [
  "chrono",
  "dioxus",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "serde",
 ]
 
@@ -5241,7 +5314,7 @@ name = "fullstack-hello-world-example"
 version = "0.1.0"
 dependencies = [
  "dioxus",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "serde",
 ]
 
@@ -5344,9 +5417,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
 
 [[package]]
 name = "futures-lite"
-version = "2.5.0"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1"
+checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532"
 dependencies = [
  "fastrand",
  "futures-core",
@@ -5363,7 +5436,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -5527,13 +5600,23 @@ dependencies = [
 
 [[package]]
 name = "generic-array"
-version = "1.1.1"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cb8bc4c28d15ade99c7e90b219f30da4be5c88e586277e8cbe886beeb868ab2"
+checksum = "e8c8444bc9d71b935156cc0ccab7f622180808af7867b1daae6547d773591703"
 dependencies = [
  "typenum",
 ]
 
+[[package]]
+name = "gethostname"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
+dependencies = [
+ "libc",
+ "windows-targets 0.48.5",
+]
+
 [[package]]
 name = "getrandom"
 version = "0.1.16"
@@ -5558,6 +5641,20 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "getrandom"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "r-efi",
+ "wasi 0.14.2+wasi-0.2.4",
+ "wasm-bindgen",
+]
+
 [[package]]
 name = "ghash"
 version = "0.5.1"
@@ -5633,7 +5730,7 @@ version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "libc",
  "libgit2-sys",
  "log",
@@ -5651,9 +5748,9 @@ dependencies = [
  "bstr",
  "gix-date",
  "gix-utils",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "thiserror 1.0.69",
- "winnow 0.6.20",
+ "winnow 0.6.26",
 ]
 
 [[package]]
@@ -5674,20 +5771,20 @@ dependencies = [
  "smallvec",
  "thiserror 1.0.69",
  "unicode-bom",
- "winnow 0.6.20",
+ "winnow 0.6.26",
 ]
 
 [[package]]
 name = "gix-config-value"
-version = "0.14.10"
+version = "0.14.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49aaeef5d98390a3bcf9dbc6440b520b793d1bf3ed99317dc407b02be995b28e"
+checksum = "8dc2c844c4cf141884678cabef736fd91dd73068b9146e6f004ba1a0457944b6"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "bstr",
  "gix-path",
  "libc",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -5697,7 +5794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9eed6931f21491ee0aeb922751bd7ec97b4b2fe8fbfedcb678e2a2dce5f3b8c0"
 dependencies = [
  "bstr",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "thiserror 1.0.69",
  "time",
 ]
@@ -5734,7 +5831,7 @@ version = "0.16.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "74908b4bbc0a0a40852737e5d7889f676f081e340d5451a16e5b4c50d592f111"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "bstr",
  "gix-features",
  "gix-path",
@@ -5774,23 +5871,23 @@ dependencies = [
  "gix-hash",
  "gix-utils",
  "gix-validate",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "smallvec",
  "thiserror 1.0.69",
- "winnow 0.6.20",
+ "winnow 0.6.26",
 ]
 
 [[package]]
 name = "gix-path"
-version = "0.10.13"
+version = "0.10.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afc292ef1a51e340aeb0e720800338c805975724c1dfbd243185452efd8645b7"
+checksum = "f910668e2f6b2a55ff35a1f04df88a1a049f7b868507f4cbeeaa220eaba7be87"
 dependencies = [
  "bstr",
  "gix-trace",
  "home",
  "once_cell",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -5812,16 +5909,16 @@ dependencies = [
  "gix-validate",
  "memmap2",
  "thiserror 1.0.69",
- "winnow 0.6.20",
+ "winnow 0.6.26",
 ]
 
 [[package]]
 name = "gix-sec"
-version = "0.10.10"
+version = "0.10.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8b876ef997a955397809a2ec398d6a45b7a55b4918f2446344330f778d14fd6"
+checksum = "47aeb0f13de9ef2f3033f5ff218de30f44db827ac9f1286f9ef050aacddd5888"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "gix-path",
  "libc",
  "windows-sys 0.52.0",
@@ -5842,15 +5939,15 @@ dependencies = [
 
 [[package]]
 name = "gix-trace"
-version = "0.1.11"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04bdde120c29f1fc23a24d3e115aeeea3d60d8e65bab92cc5f9d90d9302eb952"
+checksum = "7c396a2036920c69695f760a65e7f2677267ccf483f25046977d87e4cb2665f7"
 
 [[package]]
 name = "gix-utils"
-version = "0.1.13"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba427e3e9599508ed98a6ddf8ed05493db114564e338e41f6a996d2e4790335f"
+checksum = "ff08f24e03ac8916c478c8419d7d3c33393da9bb41fa4c24455d5406aeefd35f"
 dependencies = [
  "fastrand",
  "unicode-normalization",
@@ -5883,7 +5980,7 @@ version = "0.18.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "futures-channel",
  "futures-core",
  "futures-executor",
@@ -5911,7 +6008,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -5926,9 +6023,9 @@ dependencies = [
 
 [[package]]
 name = "glob"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
 
 [[package]]
 name = "global-hotkey"
@@ -5936,7 +6033,7 @@ version = "0.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b436093d1598b05e3b7fddc097b2bad32763f53a1beb25ab6f9718c6a60acd09"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "cocoa 0.25.0",
  "crossbeam-channel",
  "keyboard-types",
@@ -5949,9 +6046,9 @@ dependencies = [
 
 [[package]]
 name = "globset"
-version = "0.4.15"
+version = "0.4.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19"
+checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"
 dependencies = [
  "aho-corasick",
  "bstr",
@@ -5980,7 +6077,7 @@ dependencies = [
  "futures-core",
  "futures-sink",
  "gloo-utils",
- "http 1.2.0",
+ "http 1.3.1",
  "js-sys",
  "pin-project",
  "serde",
@@ -6038,6 +6135,18 @@ dependencies = [
  "web-sys",
 ]
 
+[[package]]
+name = "glow"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d51fa363f025f5c111e03f13eda21162faeacb6911fe8caa0c0349f9cf0c4483"
+dependencies = [
+ "js-sys",
+ "slotmap",
+ "wasm-bindgen",
+ "web-sys",
+]
+
 [[package]]
 name = "glutin_wgl_sys"
 version = "0.5.0"
@@ -6047,6 +6156,15 @@ dependencies = [
  "gl_generator",
 ]
 
+[[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 = "gobject-sys"
 version = "0.18.0"
@@ -6075,7 +6193,7 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "gpu-alloc-types",
 ]
 
@@ -6085,7 +6203,7 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
 ]
 
 [[package]]
@@ -6101,24 +6219,56 @@ dependencies = [
  "windows 0.52.0",
 ]
 
+[[package]]
+name = "gpu-allocator"
+version = "0.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd"
+dependencies = [
+ "log",
+ "presser",
+ "thiserror 1.0.69",
+ "windows 0.58.0",
+]
+
 [[package]]
 name = "gpu-descriptor"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c"
 dependencies = [
- "bitflags 2.6.0",
- "gpu-descriptor-types",
+ "bitflags 2.9.0",
+ "gpu-descriptor-types 0.1.2",
  "hashbrown 0.14.5",
 ]
 
+[[package]]
+name = "gpu-descriptor"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcf29e94d6d243368b7a56caa16bc213e4f9f8ed38c4d9557069527b5d5281ca"
+dependencies = [
+ "bitflags 2.9.0",
+ "gpu-descriptor-types 0.2.0",
+ "hashbrown 0.15.2",
+]
+
 [[package]]
 name = "gpu-descriptor-types"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
+]
+
+[[package]]
+name = "gpu-descriptor-types"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91"
+dependencies = [
+ "bitflags 2.9.0",
 ]
 
 [[package]]
@@ -6139,23 +6289,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2d9e3df7f0222ce5184154973d247c591d9aadc28ce7a73c6cd31100c9facff6"
 dependencies = [
  "codemap",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "lasso",
  "once_cell",
- "phf 0.11.2",
+ "phf 0.11.3",
  "rand 0.8.5",
 ]
 
 [[package]]
-name = "group"
-version = "0.12.1"
+name = "grid"
+version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
-dependencies = [
- "ff 0.12.1",
- "rand_core 0.6.4",
- "subtle",
-]
+checksum = "fb6ae361963ea5fe52038156ea1729f3b4e4ccc0711c362ab2b2d2c0a259e7c3"
 
 [[package]]
 name = "group"
@@ -6163,7 +6308,7 @@ version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
 dependencies = [
- "ff 0.13.0",
+ "ff",
  "rand_core 0.6.4",
  "subtle",
 ]
@@ -6217,7 +6362,17 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
+]
+
+[[package]]
+name = "guillotiere"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782"
+dependencies = [
+ "euclid",
+ "svg_fmt",
 ]
 
 [[package]]
@@ -6232,7 +6387,7 @@ dependencies = [
  "futures-sink",
  "futures-util",
  "http 0.2.12",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "slab",
  "tokio",
  "tokio-util",
@@ -6241,17 +6396,17 @@ dependencies = [
 
 [[package]]
 name = "h2"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e"
+checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2"
 dependencies = [
  "atomic-waker",
  "bytes",
  "fnv",
  "futures-core",
  "futures-sink",
- "http 1.2.0",
- "indexmap 2.7.0",
+ "http 1.3.1",
+ "indexmap 2.9.0",
  "slab",
  "tokio",
  "tokio-util",
@@ -6260,9 +6415,9 @@ dependencies = [
 
 [[package]]
 name = "half"
-version = "2.4.1"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
+checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
 dependencies = [
  "cfg-if",
  "crunchy",
@@ -6270,17 +6425,18 @@ dependencies = [
 
 [[package]]
 name = "handlebars"
-version = "6.2.0"
+version = "6.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd4ccde012831f9a071a637b0d4e31df31c0f6c525784b35ae76a9ac6bc1e315"
+checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098"
 dependencies = [
+ "derive_builder",
  "log",
  "num-order",
  "pest",
  "pest_derive",
  "serde",
  "serde_json",
- "thiserror 1.0.69",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -6339,7 +6495,7 @@ version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "com",
  "libc",
  "libloading 0.8.6",
@@ -6370,7 +6526,7 @@ dependencies = [
  "base64 0.21.7",
  "bytes",
  "headers-core",
- "http 1.2.0",
+ "http 1.3.1",
  "httpdate",
  "mime",
  "sha1",
@@ -6382,7 +6538,7 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4"
 dependencies = [
- "http 1.2.0",
+ "http 1.3.1",
 ]
 
 [[package]]
@@ -6412,6 +6568,12 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
 
+[[package]]
+name = "hermit-abi"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e"
+
 [[package]]
 name = "hex"
 version = "0.4.3"
@@ -6444,27 +6606,36 @@ dependencies = [
 
 [[package]]
 name = "home"
-version = "0.5.9"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
+checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
 dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "hstr"
-version = "0.2.15"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63d6824358c0fd9a68bb23999ed2ef76c84f79408a26ef7ae53d5f370c94ad36"
+checksum = "a1a26def229ea95a8709dad32868d975d0dd40235bd2ce82920e4a8fe692b5e0"
 dependencies = [
  "hashbrown 0.14.5",
  "new_debug_unreachable",
  "once_cell",
- "phf 0.11.2",
+ "phf 0.11.3",
  "rustc-hash 1.1.0",
  "triomphe",
 ]
 
+[[package]]
+name = "html-escape"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476"
+dependencies = [
+ "utf8-width",
+]
+
 [[package]]
 name = "html5ever"
 version = "0.26.0"
@@ -6473,7 +6644,7 @@ checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7"
 dependencies = [
  "log",
  "mac",
- "markup5ever",
+ "markup5ever 0.11.0",
  "proc-macro2",
  "quote",
  "syn 1.0.109",
@@ -6513,18 +6684,18 @@ checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
 dependencies = [
  "bytes",
  "fnv",
- "itoa 1.0.14",
+ "itoa 1.0.15",
 ]
 
 [[package]]
 name = "http"
-version = "1.2.0"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea"
+checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
 dependencies = [
  "bytes",
  "fnv",
- "itoa 1.0.14",
+ "itoa 1.0.15",
 ]
 
 [[package]]
@@ -6545,18 +6716,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
 dependencies = [
  "bytes",
- "http 1.2.0",
+ "http 1.3.1",
 ]
 
 [[package]]
 name = "http-body-util"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
+checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
 dependencies = [
  "bytes",
- "futures-util",
- "http 1.2.0",
+ "futures-core",
+ "http 1.3.1",
  "http-body 1.0.1",
  "pin-project-lite",
 ]
@@ -6575,9 +6746,9 @@ checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c"
 
 [[package]]
 name = "httparse"
-version = "1.9.5"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
+checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
 
 [[package]]
 name = "httpdate"
@@ -6587,15 +6758,15 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
 
 [[package]]
 name = "humantime"
-version = "2.1.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
 
 [[package]]
 name = "hyper"
-version = "0.14.31"
+version = "0.14.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85"
+checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -6606,7 +6777,7 @@ dependencies = [
  "http-body 0.4.6",
  "httparse",
  "httpdate",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "pin-project-lite",
  "socket2",
  "tokio",
@@ -6617,19 +6788,19 @@ dependencies = [
 
 [[package]]
 name = "hyper"
-version = "1.5.1"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f"
+checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
 dependencies = [
  "bytes",
  "futures-channel",
  "futures-util",
- "h2 0.4.7",
- "http 1.2.0",
+ "h2 0.4.8",
+ "http 1.3.1",
  "http-body 1.0.1",
  "httparse",
  "httpdate",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "pin-project-lite",
  "smallvec",
  "tokio",
@@ -6644,32 +6815,30 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
 dependencies = [
  "futures-util",
  "http 0.2.12",
- "hyper 0.14.31",
- "log",
+ "hyper 0.14.32",
  "rustls 0.21.12",
- "rustls-native-certs 0.6.3",
  "tokio",
  "tokio-rustls 0.24.1",
 ]
 
 [[package]]
 name = "hyper-rustls"
-version = "0.27.3"
+version = "0.27.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333"
+checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
 dependencies = [
  "futures-util",
- "http 1.2.0",
- "hyper 1.5.1",
+ "http 1.3.1",
+ "hyper 1.6.0",
  "hyper-util",
  "log",
- "rustls 0.23.19",
+ "rustls 0.23.25",
  "rustls-native-certs 0.8.1",
  "rustls-pki-types",
  "tokio",
- "tokio-rustls 0.26.1",
+ "tokio-rustls 0.26.2",
  "tower-service",
- "webpki-roots 0.26.7",
+ "webpki-roots 0.26.8",
 ]
 
 [[package]]
@@ -6678,7 +6847,7 @@ version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
 dependencies = [
- "hyper 0.14.31",
+ "hyper 0.14.32",
  "pin-project-lite",
  "tokio",
  "tokio-io-timeout",
@@ -6692,7 +6861,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
 dependencies = [
  "bytes",
  "http-body-util",
- "hyper 1.5.1",
+ "hyper 1.6.0",
  "hyper-util",
  "native-tls",
  "tokio",
@@ -6702,16 +6871,17 @@ dependencies = [
 
 [[package]]
 name = "hyper-util"
-version = "0.1.10"
+version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
+checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2"
 dependencies = [
  "bytes",
  "futures-channel",
  "futures-util",
- "http 1.2.0",
+ "http 1.3.1",
  "http-body 1.0.1",
- "hyper 1.5.1",
+ "hyper 1.6.0",
+ "libc",
  "pin-project-lite",
  "socket2",
  "tokio",
@@ -6721,16 +6891,17 @@ dependencies = [
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.61"
+version = "0.1.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
+checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
  "iana-time-zone-haiku",
  "js-sys",
+ "log",
  "wasm-bindgen",
- "windows-core 0.52.0",
+ "windows-core 0.61.0",
 ]
 
 [[package]]
@@ -6783,9 +6954,9 @@ dependencies = [
 
 [[package]]
 name = "icu_locid_transform_data"
-version = "1.5.0"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
 
 [[package]]
 name = "icu_normalizer"
@@ -6807,9 +6978,9 @@ dependencies = [
 
 [[package]]
 name = "icu_normalizer_data"
-version = "1.5.0"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
 
 [[package]]
 name = "icu_properties"
@@ -6828,9 +6999,9 @@ dependencies = [
 
 [[package]]
 name = "icu_properties_data"
-version = "1.5.0"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2"
 
 [[package]]
 name = "icu_provider"
@@ -6857,9 +7028,31 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
+]
+
+[[package]]
+name = "icu_segmenter"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a717725612346ffc2d7b42c94b820db6908048f39434504cb130e8b46256b0de"
+dependencies = [
+ "core_maths",
+ "displaydoc",
+ "icu_collections",
+ "icu_locid",
+ "icu_provider",
+ "icu_segmenter_data",
+ "utf8_iter",
+ "zerovec",
 ]
 
+[[package]]
+name = "icu_segmenter_data"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1e52775179941363cc594e49ce99284d13d6948928d8e72c755f55e98caa1eb"
+
 [[package]]
 name = "id-arena"
 version = "2.2.1"
@@ -6929,9 +7122,9 @@ dependencies = [
 
 [[package]]
 name = "image"
-version = "0.25.5"
+version = "0.25.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b"
+checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a"
 dependencies = [
  "bytemuck",
  "byteorder-lite",
@@ -6952,9 +7145,9 @@ dependencies = [
 
 [[package]]
 name = "image-webp"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f"
+checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f"
 dependencies = [
  "byteorder-lite",
  "quick-error",
@@ -6962,9 +7155,9 @@ dependencies = [
 
 [[package]]
 name = "imagequant"
-version = "4.3.3"
+version = "4.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fecc99538c9061ee4d88476f6cd704c9f06575a34f0083affdaa1337a331aa7"
+checksum = "1cede25dbe6a6c3842989fa341cba6e2a4dc33ba12a33f553baeed257f965cb5"
 dependencies = [
  "arrayvec",
  "once_cell",
@@ -6973,12 +7166,27 @@ dependencies = [
  "thread_local",
 ]
 
+[[package]]
+name = "imagesize"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285"
+
 [[package]]
 name = "imgref"
 version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408"
 
+[[package]]
+name = "immutable-chunkmap"
+version = "2.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12f97096f508d54f8f8ab8957862eee2ccd628847b6217af1a335e1c44dee578"
+dependencies = [
+ "arrayvec",
+]
+
 [[package]]
 name = "include_dir"
 version = "0.7.4"
@@ -7011,9 +7219,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.7.0"
+version = "2.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
+checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
 dependencies = [
  "equivalent",
  "hashbrown 0.15.2",
@@ -7022,9 +7230,9 @@ dependencies = [
 
 [[package]]
 name = "indicatif"
-version = "0.17.9"
+version = "0.17.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281"
+checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235"
 dependencies = [
  "console",
  "number_prefix",
@@ -7035,18 +7243,9 @@ dependencies = [
 
 [[package]]
 name = "indoc"
-version = "2.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
-
-[[package]]
-name = "infer"
-version = "0.11.0"
+version = "2.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a6c16b11a665b26aeeb9b1d7f954cdeb034be38dd00adab4f2ae921a8fee804"
-dependencies = [
- "cfb",
-]
+checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
 
 [[package]]
 name = "infer"
@@ -7085,9 +7284,9 @@ dependencies = [
 
 [[package]]
 name = "inout"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
 dependencies = [
  "block-padding",
  "generic-array 0.14.7",
@@ -7095,16 +7294,15 @@ dependencies = [
 
 [[package]]
 name = "instability"
-version = "0.3.3"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b829f37dead9dc39df40c2d3376c179fdfd2ac771f53f55d3c30dc096a3c0c6e"
+checksum = "0bf9fed6d91cfb734e7476a06bde8300a1b94e217e1b523b6f0cd1a01998c71d"
 dependencies = [
  "darling",
  "indoc",
- "pretty_assertions",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -7134,20 +7332,23 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "inventory"
-version = "0.3.15"
+version = "0.3.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767"
+checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83"
+dependencies = [
+ "rustversion",
+]
 
 [[package]]
 name = "ipnet"
-version = "2.10.1"
+version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708"
+checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
 
 [[package]]
 name = "ipnetwork"
@@ -7160,9 +7361,9 @@ dependencies = [
 
 [[package]]
 name = "iri-string"
-version = "0.7.7"
+version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc0f0a572e8ffe56e2ff4f769f32ffe919282c3916799f8b68688b6030063bea"
+checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2"
 dependencies = [
  "memchr",
  "serde",
@@ -7186,18 +7387,18 @@ dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "is-terminal"
-version = "0.4.13"
+version = "0.4.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b"
+checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
 dependencies = [
- "hermit-abi 0.4.0",
+ "hermit-abi 0.5.0",
  "libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -7290,9 +7491,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
 
 [[package]]
 name = "itoa"
-version = "1.0.14"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
 
 [[package]]
 name = "javascriptcore-rs"
@@ -7317,6 +7518,30 @@ dependencies = [
  "system-deps",
 ]
 
+[[package]]
+name = "jiff"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f33145a5cbea837164362c7bd596106eb7c5198f97d1ba6f6ebb3223952e488"
+dependencies = [
+ "jiff-static",
+ "log",
+ "portable-atomic",
+ "portable-atomic-util",
+ "serde",
+]
+
+[[package]]
+name = "jiff-static"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43ce13c40ec6956157a3635d97a1ee2df323b263f09ea14165131289cb0f5c19"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+]
+
 [[package]]
 name = "jni"
 version = "0.21.1"
@@ -7341,10 +7566,11 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
 
 [[package]]
 name = "jobserver"
-version = "0.1.32"
+version = "0.1.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
+checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
 dependencies = [
+ "getrandom 0.3.2",
  "libc",
 ]
 
@@ -7386,21 +7612,6 @@ dependencies = [
  "serde_json",
 ]
 
-[[package]]
-name = "jsonwebtoken"
-version = "9.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f"
-dependencies = [
- "base64 0.21.7",
- "js-sys",
- "pem",
- "ring",
- "serde",
- "serde_json",
- "simple_asn1",
-]
-
 [[package]]
 name = "jwalk"
 version = "0.8.1"
@@ -7424,11 +7635,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b"
 dependencies = [
  "cfg-if",
- "ecdsa 0.16.9",
- "elliptic-curve 0.13.8",
+ "ecdsa",
+ "elliptic-curve",
  "once_cell",
  "sha2",
- "signature 2.2.0",
+ "signature",
 ]
 
 [[package]]
@@ -7446,7 +7657,7 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "serde",
  "unicode-segmentation",
 ]
@@ -7470,9 +7681,9 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
 
 [[package]]
 name = "konst"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "298ddf99f06a97c1ecd0e910932662b7842855046234b0d0376d35d93add087f"
+checksum = "4381b9b00c55f251f2ebe9473aef7c117e96828def1a7cb3bd3f0f903c6894e9"
 dependencies = [
  "const_panic",
  "konst_kernel",
@@ -7517,7 +7728,7 @@ dependencies = [
  "camino",
  "cfg-expr 0.17.2",
  "petgraph",
- "semver 1.0.23",
+ "semver 1.0.26",
  "serde",
  "serde_json",
 ]
@@ -7542,7 +7753,17 @@ dependencies = [
  "html5ever",
  "indexmap 1.9.3",
  "matches",
- "selectors",
+ "selectors 0.22.0",
+]
+
+[[package]]
+name = "kurbo"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f"
+dependencies = [
+ "arrayvec",
+ "smallvec",
 ]
 
 [[package]]
@@ -7620,15 +7841,15 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.168"
+version = "0.2.171"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
+checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
 
 [[package]]
 name = "libfuzzer-sys"
-version = "0.4.8"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b9569d2f74e257076d8c6bfa73fb505b46b851e51ddaecc825944aa3bed17fa"
+checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75"
 dependencies = [
  "arbitrary",
  "cc",
@@ -7680,9 +7901,9 @@ version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.5.11",
 ]
 
 [[package]]
@@ -7698,9 +7919,9 @@ dependencies = [
 
 [[package]]
 name = "libssh2-sys"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee"
+checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9"
 dependencies = [
  "cc",
  "libc",
@@ -7731,9 +7952,9 @@ dependencies = [
 
 [[package]]
 name = "libz-sys"
-version = "1.1.20"
+version = "1.1.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472"
+checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d"
 dependencies = [
  "cc",
  "libc",
@@ -7743,20 +7964,20 @@ dependencies = [
 
 [[package]]
 name = "lightningcss"
-version = "1.0.0-alpha.61"
+version = "1.0.0-alpha.65"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20c9e1f991b3861d25bf872ecca2eb6a73f7a9fe671da047cd1f9b49c65cbc40"
+checksum = "c84f971730745f4aaac013b6cf4328baf1548efc973c0d95cfd843a3c1ca07af"
 dependencies = [
  "ahash 0.8.11",
- "bitflags 2.6.0",
- "browserslist-rs",
+ "bitflags 2.9.0",
+ "browserslist-rs 0.17.0",
  "const-str",
  "cssparser 0.33.0",
  "cssparser-color",
  "dashmap 5.5.3",
  "data-encoding",
  "getrandom 0.2.15",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "itertools 0.10.5",
  "lazy_static",
  "lightningcss-derive",
@@ -7784,26 +8005,31 @@ dependencies = [
 
 [[package]]
 name = "link-cplusplus"
-version = "1.0.9"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9"
+checksum = "4a6f6da007f968f9def0d65a05b187e2960183de70c160204ecfccf0ee330212"
 dependencies = [
  "cc",
 ]
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.4.14"
+version = "0.4.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413"
 
 [[package]]
 name = "liquid"
-version = "0.26.9"
+version = "0.26.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cdcc72b82748f47c2933c172313f5a9aea5b2c4eb3fa4c66b4ea55bb60bb4b1"
+checksum = "2a494c3f9dad3cb7ed16f1c51812cbe4b29493d6c2e5cd1e2b87477263d9534d"
 dependencies = [
- "doc-comment",
  "liquid-core",
  "liquid-derive",
  "liquid-lib",
@@ -7812,15 +8038,14 @@ dependencies = [
 
 [[package]]
 name = "liquid-core"
-version = "0.26.9"
+version = "0.26.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2752e978ffc53670f3f2e8b3ef09f348d6f7b5474a3be3f8a5befe5382e4effb"
+checksum = "fc623edee8a618b4543e8e8505584f4847a4e51b805db1af6d9af0a3395d0d57"
 dependencies = [
  "anymap2",
- "itertools 0.13.0",
+ "itertools 0.14.0",
  "kstring",
  "liquid-derive",
- "num-traits",
  "pest",
  "pest_derive",
  "regex",
@@ -7830,24 +8055,23 @@ dependencies = [
 
 [[package]]
 name = "liquid-derive"
-version = "0.26.8"
+version = "0.26.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b51f1d220e3fa869e24cfd75915efe3164bd09bb11b3165db3f37f57bf673e3"
+checksum = "de66c928222984aea59fcaed8ba627f388aaac3c1f57dcb05cc25495ef8faefe"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "liquid-lib"
-version = "0.26.9"
+version = "0.26.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59b1a298d3d2287ee5b1e43840d885b8fdfc37d3f4e90d82aacfd04d021618da"
+checksum = "9befeedd61f5995bc128c571db65300aeb50d62e4f0542c88282dbcb5f72372a"
 dependencies = [
- "itertools 0.13.0",
+ "itertools 0.14.0",
  "liquid-core",
- "once_cell",
  "percent-encoding",
  "regex",
  "time",
@@ -7856,9 +8080,15 @@ dependencies = [
 
 [[package]]
 name = "litemap"
-version = "0.7.4"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
+
+[[package]]
+name = "litrs"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
+checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
 
 [[package]]
 name = "local-ip-address"
@@ -7890,9 +8120,9 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e"
 
 [[package]]
 name = "log"
-version = "0.4.22"
+version = "0.4.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
 dependencies = [
  "value-bag",
 ]
@@ -7958,23 +8188,23 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 
 [[package]]
 name = "mac_address"
-version = "1.1.7"
+version = "1.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8836fae9d0d4be2c8b4efcdd79e828a2faa058a90d005abf42f91cac5493a08e"
+checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303"
 dependencies = [
- "nix 0.28.0",
+ "nix",
  "winapi",
 ]
 
 [[package]]
 name = "macro-string"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dcd5686122470c31bc2e3db08d750b0298b53c7cfb712f343ae47e13502877e"
+checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -7986,6 +8216,17 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "malloc_size_of_derive"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f44db74bde26fdf427af23f1d146c211aed857c59e3be750cf2617f6b0b05c94"
+dependencies = [
+ "proc-macro2",
+ "syn 2.0.100",
+ "synstructure 0.13.1",
+]
+
 [[package]]
 name = "manganis"
 version = "0.6.3"
@@ -8017,7 +8258,7 @@ dependencies = [
  "manganis-core",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -8034,6 +8275,20 @@ dependencies = [
  "tendril",
 ]
 
+[[package]]
+name = "markup5ever"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03a7b81dfb91586d0677086d40a6d755070e0799b71bb897485bac408dfd5c69"
+dependencies = [
+ "log",
+ "phf 0.11.3",
+ "phf_codegen 0.11.3",
+ "string_cache",
+ "string_cache_codegen",
+ "tendril",
+]
+
 [[package]]
 name = "matchers"
 version = "0.1.0"
@@ -8134,7 +8389,22 @@ version = "0.27.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
+ "block",
+ "core-graphics-types 0.1.3",
+ "foreign-types 0.5.0",
+ "log",
+ "objc",
+ "paste",
+]
+
+[[package]]
+name = "metal"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21"
+dependencies = [
+ "bitflags 2.9.0",
  "block",
  "core-graphics-types 0.1.3",
  "foreign-types 0.5.0",
@@ -8197,9 +8467,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.8.0"
+version = "0.8.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
+checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
 dependencies = [
  "adler2",
  "simd-adler32",
@@ -8231,9 +8501,9 @@ dependencies = [
 
 [[package]]
 name = "mozjpeg"
-version = "0.10.11"
+version = "0.10.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55571bce4f12d80ceb4296526e7614f796df72daaaac85f265ab732fa47b7bc9"
+checksum = "b7891b80aaa86097d38d276eb98b3805d6280708c4e0a1e6f6aed9380c51fec9"
 dependencies = [
  "arrayvec",
  "bytemuck",
@@ -8244,9 +8514,9 @@ dependencies = [
 
 [[package]]
 name = "mozjpeg-sys"
-version = "2.2.1"
+version = "2.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27e31c0171e0b1158c0dfb7386dbdf999f4a9afaa83fd68de39c7929f4d5c16f"
+checksum = "7f0dc668bf9bf888c88e2fb1ab16a406d2c380f1d082b20d51dd540ab2aa70c1"
 dependencies = [
  "cc",
  "dunce",
@@ -8254,6 +8524,24 @@ dependencies = [
  "nasm-rs",
 ]
 
+[[package]]
+name = "muda"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c47e7625990fc1af2226ea4f34fb2412b03c12639fcb91868581eb3a6893453"
+dependencies = [
+ "cocoa 0.25.0",
+ "crossbeam-channel",
+ "gtk",
+ "keyboard-types",
+ "objc",
+ "once_cell",
+ "png",
+ "serde",
+ "thiserror 1.0.69",
+ "windows-sys 0.52.0",
+]
+
 [[package]]
 name = "muda"
 version = "0.15.3"
@@ -8283,7 +8571,7 @@ dependencies = [
  "bytes",
  "encoding_rs",
  "futures-util",
- "http 1.2.0",
+ "http 1.3.1",
  "httparse",
  "memchr",
  "mime",
@@ -8297,11 +8585,11 @@ version = "0.19.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "50e3524642f53d9af419ab5e8dd29d3ba155708267667c2f3f06c88c9e130843"
 dependencies = [
- "bit-set",
- "bitflags 2.6.0",
- "codespan-reporting",
+ "bit-set 0.5.3",
+ "bitflags 2.9.0",
+ "codespan-reporting 0.11.1",
  "hexf-parse",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "log",
  "num-traits",
  "rustc-hash 1.1.0",
@@ -8311,6 +8599,27 @@ dependencies = [
  "unicode-xid",
 ]
 
+[[package]]
+name = "naga"
+version = "23.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "364f94bc34f61332abebe8cad6f6cd82a5b65cff22c828d05d0968911462ca4f"
+dependencies = [
+ "arrayvec",
+ "bit-set 0.8.0",
+ "bitflags 2.9.0",
+ "cfg_aliases 0.1.1",
+ "codespan-reporting 0.11.1",
+ "hexf-parse",
+ "indexmap 2.9.0",
+ "log",
+ "rustc-hash 1.1.0",
+ "spirv",
+ "termcolor",
+ "thiserror 1.0.69",
+ "unicode-xid",
+]
+
 [[package]]
 name = "names"
 version = "0.14.0"
@@ -8331,9 +8640,9 @@ dependencies = [
 
 [[package]]
 name = "native-tls"
-version = "0.2.12"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
+checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
 dependencies = [
  "libc",
  "log",
@@ -8352,7 +8661,7 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "jni-sys",
  "log",
  "ndk-sys 0.6.0+11769913",
@@ -8387,9 +8696,9 @@ dependencies = [
 
 [[package]]
 name = "neli"
-version = "0.6.4"
+version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1100229e06604150b3becd61a4965d5c70f3be1759544ea7274166f4be41ef43"
+checksum = "93062a0dce6da2517ea35f301dfc88184ce18d3601ec786a727a87bf535deca9"
 dependencies = [
  "byteorder",
  "libc",
@@ -8399,9 +8708,9 @@ dependencies = [
 
 [[package]]
 name = "neli-proc-macros"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c168194d373b1e134786274020dae7fc5513d565ea2ebb9bc9ff17ffb69106d4"
+checksum = "0c8034b7fbb6f9455b2a96c19e6edf8dc9fc34c70449938d8ee3b4df363f61fe"
 dependencies = [
  "either",
  "proc-macro2",
@@ -8425,26 +8734,13 @@ version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
 
-[[package]]
-name = "nix"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
-dependencies = [
- "bitflags 2.6.0",
- "cfg-if",
- "cfg_aliases 0.1.1",
- "libc",
- "memoffset",
-]
-
 [[package]]
 name = "nix"
 version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "cfg-if",
  "cfg_aliases 0.2.1",
  "libc",
@@ -8503,7 +8799,7 @@ version = "6.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "crossbeam-channel",
  "filetime",
  "fsevent-sys",
@@ -8602,7 +8898,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -8686,10 +8982,10 @@ version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
 dependencies = [
- "proc-macro-crate 3.2.0",
+ "proc-macro-crate 3.3.0",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -8760,7 +9056,7 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "block2 0.5.1",
  "libc",
  "objc2 0.5.2",
@@ -8776,19 +9072,43 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5906f93257178e2f7ae069efb89fbd6ee94f0592740b5f8a1512ca498814d0fb"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "objc2 0.6.0",
  "objc2-core-foundation",
  "objc2-foundation 0.3.0",
 ]
 
+[[package]]
+name = "objc2-cloud-kit"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
+dependencies = [
+ "bitflags 2.9.0",
+ "block2 0.5.1",
+ "objc2 0.5.2",
+ "objc2-core-location",
+ "objc2-foundation 0.2.2",
+]
+
+[[package]]
+name = "objc2-contacts"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889"
+dependencies = [
+ "block2 0.5.1",
+ "objc2 0.5.2",
+ "objc2-foundation 0.2.2",
+]
+
 [[package]]
 name = "objc2-core-data"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "block2 0.5.1",
  "objc2 0.5.2",
  "objc2-foundation 0.2.2",
@@ -8800,20 +9120,52 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "objc2 0.6.0",
 ]
 
+[[package]]
+name = "objc2-core-graphics"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8dca602628b65356b6513290a21a6405b4d4027b8b250f0b98dddbb28b7de02"
+dependencies = [
+ "bitflags 2.9.0",
+ "objc2-core-foundation",
+]
+
 [[package]]
 name = "objc2-core-image"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
+checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
+dependencies = [
+ "block2 0.5.1",
+ "objc2 0.5.2",
+ "objc2-foundation 0.2.2",
+ "objc2-metal",
+]
+
+[[package]]
+name = "objc2-core-location"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781"
 dependencies = [
  "block2 0.5.1",
  "objc2 0.5.2",
+ "objc2-contacts",
  "objc2-foundation 0.2.2",
- "objc2-metal",
+]
+
+[[package]]
+name = "objc2-core-text"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fde15abfe00bf9f1eda220addbdfa6c62b0e5595e98208e8cdbc2ec0f6970a6"
+dependencies = [
+ "bitflags 2.9.0",
+ "objc2-core-foundation",
 ]
 
 [[package]]
@@ -8837,8 +9189,9 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "block2 0.5.1",
+ "dispatch",
  "libc",
  "objc2 0.5.2",
 ]
@@ -8849,18 +9202,31 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
+ "block2 0.6.0",
  "objc2 0.6.0",
  "objc2-core-foundation",
 ]
 
+[[package]]
+name = "objc2-link-presentation"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
+dependencies = [
+ "block2 0.5.1",
+ "objc2 0.5.2",
+ "objc2-app-kit 0.2.2",
+ "objc2-foundation 0.2.2",
+]
+
 [[package]]
 name = "objc2-metal"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "block2 0.5.1",
  "objc2 0.5.2",
  "objc2-foundation 0.2.2",
@@ -8872,32 +9238,87 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "block2 0.5.1",
  "objc2 0.5.2",
  "objc2-foundation 0.2.2",
  "objc2-metal",
 ]
 
+[[package]]
+name = "objc2-symbols"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc"
+dependencies = [
+ "objc2 0.5.2",
+ "objc2-foundation 0.2.2",
+]
+
+[[package]]
+name = "objc2-ui-kit"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
+dependencies = [
+ "bitflags 2.9.0",
+ "block2 0.5.1",
+ "objc2 0.5.2",
+ "objc2-cloud-kit",
+ "objc2-core-data",
+ "objc2-core-image",
+ "objc2-core-location",
+ "objc2-foundation 0.2.2",
+ "objc2-link-presentation",
+ "objc2-quartz-core",
+ "objc2-symbols",
+ "objc2-uniform-type-identifiers",
+ "objc2-user-notifications",
+]
+
 [[package]]
 name = "objc2-ui-kit"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "777a571be14a42a3990d4ebedaeb8b54cd17377ec21b92e8200ac03797b3bee1"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "objc2 0.6.0",
  "objc2-core-foundation",
  "objc2-foundation 0.3.0",
 ]
 
+[[package]]
+name = "objc2-uniform-type-identifiers"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
+dependencies = [
+ "block2 0.5.1",
+ "objc2 0.5.2",
+ "objc2-foundation 0.2.2",
+]
+
+[[package]]
+name = "objc2-user-notifications"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
+dependencies = [
+ "bitflags 2.9.0",
+ "block2 0.5.1",
+ "objc2 0.5.2",
+ "objc2-core-location",
+ "objc2-foundation 0.2.2",
+]
+
 [[package]]
 name = "objc2-web-kit"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b717127e4014b0f9f3e8bba3d3f2acec81f1bde01f656823036e823ed2c94dce"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "block2 0.6.0",
  "objc2 0.6.0",
  "objc2-app-kit 0.3.0",
@@ -8932,21 +9353,21 @@ dependencies = [
  "crc32fast",
  "flate2",
  "hashbrown 0.14.5",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "memchr",
  "ruzstd 0.5.0",
 ]
 
 [[package]]
 name = "object"
-version = "0.36.5"
+version = "0.36.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
 dependencies = [
  "flate2",
  "memchr",
  "ruzstd 0.7.3",
- "wasmparser 0.218.0",
+ "wasmparser 0.222.1",
 ]
 
 [[package]]
@@ -8982,15 +9403,15 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.20.2"
+version = "1.21.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
 
 [[package]]
 name = "oorandom"
-version = "11.1.4"
+version = "11.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
+checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
 
 [[package]]
 name = "opaque-debug"
@@ -9000,9 +9421,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
 
 [[package]]
 name = "open"
-version = "5.3.1"
+version = "5.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ecd52f0b8d15c40ce4820aa251ed5de032e5d91fab27f7db2f40d42a8bdf69c"
+checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95"
 dependencies = [
  "is-wsl",
  "libc",
@@ -9015,7 +9436,7 @@ version = "0.10.72"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "cfg-if",
  "foreign-types 0.3.2",
  "libc",
@@ -9032,20 +9453,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "openssl-probe"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
 
 [[package]]
 name = "openssl-src"
-version = "300.4.1+3.4.0"
+version = "300.4.2+3.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c"
+checksum = "168ce4e058f975fe43e89d9ccf78ca668601887ae736090aacc23ae353c298e2"
 dependencies = [
  "cc",
 ]
@@ -9069,6 +9490,15 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
 
+[[package]]
+name = "orbclient"
+version = "0.3.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43"
+dependencies = [
+ "libredox",
+]
+
 [[package]]
 name = "ordered-stream"
 version = "0.2.0"
@@ -9091,9 +9521,9 @@ dependencies = [
 
 [[package]]
 name = "ouroboros"
-version = "0.18.4"
+version = "0.18.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "944fa20996a25aded6b4795c6d63f10014a7a83f8be9828a11860b08c5fc4a67"
+checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59"
 dependencies = [
  "aliasable",
  "ouroboros_macro",
@@ -9102,16 +9532,15 @@ dependencies = [
 
 [[package]]
 name = "ouroboros_macro"
-version = "0.18.4"
+version = "0.18.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39b0deead1528fd0e5947a8546a9642a9777c25f6e1e26f34c97b204bbb465bd"
+checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0"
 dependencies = [
  "heck 0.4.1",
- "itertools 0.12.1",
  "proc-macro2",
  "proc-macro2-diagnostics",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -9120,23 +9549,26 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4"
 
-[[package]]
-name = "outref"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a"
-
 [[package]]
 name = "overload"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
 
+[[package]]
+name = "owned_ttf_parser"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4"
+dependencies = [
+ "ttf-parser 0.25.1",
+]
+
 [[package]]
 name = "owo-colors"
-version = "4.1.0"
+version = "4.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56"
+checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
 dependencies = [
  "supports-color 2.1.0",
  "supports-color 3.0.2",
@@ -9159,37 +9591,26 @@ dependencies = [
  "yasna",
 ]
 
-[[package]]
-name = "p256"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594"
-dependencies = [
- "ecdsa 0.14.8",
- "elliptic-curve 0.12.3",
- "sha2",
-]
-
 [[package]]
 name = "p256"
 version = "0.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
 dependencies = [
- "ecdsa 0.16.9",
- "elliptic-curve 0.13.8",
+ "ecdsa",
+ "elliptic-curve",
  "primeorder",
  "sha2",
 ]
 
 [[package]]
 name = "p384"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
+checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6"
 dependencies = [
- "ecdsa 0.16.9",
- "elliptic-curve 0.13.8",
+ "ecdsa",
+ "elliptic-curve",
  "primeorder",
  "sha2",
 ]
@@ -9200,9 +9621,9 @@ version = "0.13.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2"
 dependencies = [
- "base16ct 0.2.0",
- "ecdsa 0.16.9",
- "elliptic-curve 0.13.8",
+ "base16ct",
+ "ecdsa",
+ "elliptic-curve",
  "primeorder",
  "rand_core 0.6.4",
  "sha2",
@@ -9235,17 +9656,17 @@ dependencies = [
 
 [[package]]
 name = "parcel_selectors"
-version = "0.28.0"
+version = "0.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7645c578d3a5c4cdf667af1ad39765f5f751c4883d251e050d5e1204b5cad0a9"
+checksum = "dccbc6fb560df303a44e511618256029410efbc87779018f751ef12c488271fe"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "cssparser 0.33.0",
  "log",
- "phf 0.11.2",
- "phf_codegen 0.11.2",
+ "phf 0.11.3",
+ "phf_codegen 0.11.3",
  "precomputed-hash",
- "rustc-hash 2.1.0",
+ "rustc-hash 2.1.1",
  "smallvec",
  "static-self",
 ]
@@ -9256,8 +9677,8 @@ version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "485b74d7218068b2b7c0e3ff12fbc61ae11d57cb5d8224f525bd304c6be05bbb"
 dependencies = [
- "base64-simd 0.7.0",
- "data-url",
+ "base64-simd",
+ "data-url 0.1.1",
  "rkyv",
  "serde",
  "serde_json",
@@ -9288,11 +9709,24 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.5.11",
  "smallvec",
  "windows-targets 0.52.6",
 ]
 
+[[package]]
+name = "parley"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d1c2b33b240c246f06cfceac48dc6c96040cb177d2aa5348899982b298b5577"
+dependencies = [
+ "fontique",
+ "hashbrown 0.15.2",
+ "peniko",
+ "skrifa",
+ "swash",
+]
+
 [[package]]
 name = "password-hash"
 version = "0.5.0"
@@ -9360,14 +9794,14 @@ dependencies = [
  "proc-macro2",
  "proc-macro2-diagnostics",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "pem"
-version = "3.0.4"
+version = "3.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae"
+checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3"
 dependencies = [
  "base64 0.22.1",
  "serde",
@@ -9382,6 +9816,17 @@ dependencies = [
  "base64ct",
 ]
 
+[[package]]
+name = "peniko"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ec061f435b573ff602b2c5690f1a5bfcf461327194654cfbfce4412b95cf2a1"
+dependencies = [
+ "color",
+ "kurbo",
+ "smallvec",
+]
+
 [[package]]
 name = "percent-encoding"
 version = "2.3.1"
@@ -9390,20 +9835,20 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
 [[package]]
 name = "pest"
-version = "2.7.15"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc"
+checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6"
 dependencies = [
  "memchr",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
  "ucd-trie",
 ]
 
 [[package]]
 name = "pest_derive"
-version = "2.7.15"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e"
+checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5"
 dependencies = [
  "pest",
  "pest_generator",
@@ -9411,22 +9856,22 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.7.15"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b"
+checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841"
 dependencies = [
  "pest",
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "pest_meta"
-version = "2.7.15"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea"
+checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0"
 dependencies = [
  "once_cell",
  "pest",
@@ -9440,7 +9885,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
 dependencies = [
  "fixedbitset",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
 ]
 
 [[package]]
@@ -9474,9 +9919,9 @@ dependencies = [
  "digest",
  "dsa",
  "eax",
- "ecdsa 0.16.9",
+ "ecdsa",
  "ed25519-dalek",
- "elliptic-curve 0.13.8",
+ "elliptic-curve",
  "flate2",
  "generic-array 0.14.7",
  "hex",
@@ -9491,7 +9936,7 @@ dependencies = [
  "num-traits",
  "num_enum",
  "ocb3",
- "p256 0.13.2",
+ "p256",
  "p384",
  "p521",
  "rand 0.8.5",
@@ -9501,7 +9946,7 @@ dependencies = [
  "sha1-checked",
  "sha2",
  "sha3",
- "signature 2.2.0",
+ "signature",
  "smallvec",
  "thiserror 1.0.69",
  "twofish",
@@ -9532,12 +9977,12 @@ dependencies = [
 
 [[package]]
 name = "phf"
-version = "0.11.2"
+version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
+checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
 dependencies = [
- "phf_macros 0.11.2",
- "phf_shared 0.11.2",
+ "phf_macros 0.11.3",
+ "phf_shared 0.11.3",
 ]
 
 [[package]]
@@ -9562,12 +10007,12 @@ dependencies = [
 
 [[package]]
 name = "phf_codegen"
-version = "0.11.2"
+version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
+checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
 dependencies = [
- "phf_generator 0.11.2",
- "phf_shared 0.11.2",
+ "phf_generator 0.11.3",
+ "phf_shared 0.11.3",
 ]
 
 [[package]]
@@ -9592,11 +10037,11 @@ dependencies = [
 
 [[package]]
 name = "phf_generator"
-version = "0.11.2"
+version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
+checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
 dependencies = [
- "phf_shared 0.11.2",
+ "phf_shared 0.11.3",
  "rand 0.8.5",
 ]
 
@@ -9616,15 +10061,15 @@ dependencies = [
 
 [[package]]
 name = "phf_macros"
-version = "0.11.2"
+version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
+checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
 dependencies = [
- "phf_generator 0.11.2",
- "phf_shared 0.11.2",
+ "phf_generator 0.11.3",
+ "phf_shared 0.11.3",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -9633,7 +10078,7 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
 dependencies = [
- "siphasher",
+ "siphasher 0.3.11",
 ]
 
 [[package]]
@@ -9642,43 +10087,49 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
 dependencies = [
- "siphasher",
+ "siphasher 0.3.11",
 ]
 
 [[package]]
 name = "phf_shared"
-version = "0.11.2"
+version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
+checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
 dependencies = [
- "siphasher",
+ "siphasher 1.0.1",
 ]
 
+[[package]]
+name = "pico-args"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
+
 [[package]]
 name = "pin-project"
-version = "1.1.7"
+version = "1.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95"
+checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
 dependencies = [
  "pin-project-internal",
 ]
 
 [[package]]
 name = "pin-project-internal"
-version = "1.1.7"
+version = "1.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
+checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.15"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
 
 [[package]]
 name = "pin-utils"
@@ -9703,19 +10154,9 @@ version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
 dependencies = [
- "der 0.7.9",
- "pkcs8 0.10.2",
- "spki 0.7.3",
-]
-
-[[package]]
-name = "pkcs8"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
-dependencies = [
- "der 0.6.1",
- "spki 0.6.0",
+ "der",
+ "pkcs8",
+ "spki",
 ]
 
 [[package]]
@@ -9724,15 +10165,15 @@ version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
 dependencies = [
- "der 0.7.9",
- "spki 0.7.3",
+ "der",
+ "spki",
 ]
 
 [[package]]
 name = "pkg-config"
-version = "0.3.31"
+version = "0.3.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
 
 [[package]]
 name = "plain"
@@ -9742,13 +10183,13 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
 
 [[package]]
 name = "plist"
-version = "1.7.0"
+version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
+checksum = "eac26e981c03a6e53e0aee43c113e3202f5581d5360dae7bd2c70e800dd0451d"
 dependencies = [
  "base64 0.22.1",
- "indexmap 2.7.0",
- "quick-xml",
+ "indexmap 2.9.0",
+ "quick-xml 0.32.0",
  "serde",
  "time",
 ]
@@ -9783,9 +10224,9 @@ dependencies = [
 
 [[package]]
 name = "png"
-version = "0.17.15"
+version = "0.17.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b67582bd5b65bdff614270e2ea89a1cf15bef71245cc1e5f7ea126977144211d"
+checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
 dependencies = [
  "bitflags 1.3.2",
  "crc32fast",
@@ -9804,7 +10245,7 @@ dependencies = [
  "concurrent-queue",
  "hermit-abi 0.4.0",
  "pin-project-lite",
- "rustix",
+ "rustix 0.38.44",
  "tracing",
  "windows-sys 0.59.0",
 ]
@@ -9815,6 +10256,12 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2"
 
+[[package]]
+name = "pollster"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3"
+
 [[package]]
 name = "polyval"
 version = "0.6.2"
@@ -9829,9 +10276,18 @@ dependencies = [
 
 [[package]]
 name = "portable-atomic"
-version = "1.10.0"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
+
+[[package]]
+name = "portable-atomic-util"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"
+checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
+dependencies = [
+ "portable-atomic",
+]
 
 [[package]]
 name = "powerfmt"
@@ -9841,11 +10297,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.20"
+version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
 dependencies = [
- "zerocopy",
+ "zerocopy 0.8.24",
 ]
 
 [[package]]
@@ -9867,7 +10323,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32db37eb2b0ec0af154e9c1b33425902d8cd9481e35167c4e9ffb28fec3916bb"
 dependencies = [
  "proc-macro2",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -9882,12 +10338,12 @@ dependencies = [
 
 [[package]]
 name = "prettyplease"
-version = "0.2.25"
+version = "0.2.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
+checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6"
 dependencies = [
  "proc-macro2",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -9896,7 +10352,7 @@ version = "0.13.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
 dependencies = [
- "elliptic-curve 0.13.8",
+ "elliptic-curve",
 ]
 
 [[package]]
@@ -9920,11 +10376,11 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-crate"
-version = "3.2.0"
+version = "3.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
+checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
 dependencies = [
- "toml_edit 0.22.22",
+ "toml_edit 0.22.24",
 ]
 
 [[package]]
@@ -9959,9 +10415,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.92"
+version = "1.0.94"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
 dependencies = [
  "unicode-ident",
 ]
@@ -9974,7 +10430,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "version_check",
  "yansi",
 ]
@@ -10001,7 +10457,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"
 dependencies = [
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -10024,7 +10480,7 @@ dependencies = [
  "itertools 0.12.1",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -10038,9 +10494,9 @@ dependencies = [
 
 [[package]]
 name = "psm"
-version = "0.1.24"
+version = "0.1.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810"
+checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88"
 dependencies = [
  "cc",
 ]
@@ -10082,7 +10538,7 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -10100,6 +10556,16 @@ version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
 
+[[package]]
+name = "quick-xml"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
 [[package]]
 name = "quick-xml"
 version = "0.32.0"
@@ -10109,39 +10575,50 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "quick-xml"
+version = "0.37.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4ce8c88de324ff838700f36fb6ab86c96df0e3c4ab6ef3a9b2044465cce1369"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "quinn"
-version = "0.11.6"
+version = "0.11.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef"
+checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012"
 dependencies = [
  "bytes",
+ "cfg_aliases 0.2.1",
  "pin-project-lite",
  "quinn-proto",
  "quinn-udp",
- "rustc-hash 2.1.0",
- "rustls 0.23.19",
+ "rustc-hash 2.1.1",
+ "rustls 0.23.25",
  "socket2",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
  "tokio",
  "tracing",
+ "web-time",
 ]
 
 [[package]]
 name = "quinn-proto"
-version = "0.11.9"
+version = "0.11.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d"
+checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc"
 dependencies = [
  "bytes",
- "getrandom 0.2.15",
- "rand 0.8.5",
+ "getrandom 0.3.2",
+ "rand 0.9.0",
  "ring",
- "rustc-hash 2.1.0",
- "rustls 0.23.19",
+ "rustc-hash 2.1.1",
+ "rustls 0.23.25",
  "rustls-pki-types",
  "slab",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
  "tinyvec",
  "tracing",
  "web-time",
@@ -10149,9 +10626,9 @@ dependencies = [
 
 [[package]]
 name = "quinn-udp"
-version = "0.5.8"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527"
+checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5"
 dependencies = [
  "cfg_aliases 0.2.1",
  "libc",
@@ -10163,13 +10640,19 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.37"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
 dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "r-efi"
+version = "5.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
+
 [[package]]
 name = "radium"
 version = "0.7.0"
@@ -10207,6 +10690,17 @@ dependencies = [
  "rand_core 0.6.4",
 ]
 
+[[package]]
+name = "rand"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
+dependencies = [
+ "rand_chacha 0.9.0",
+ "rand_core 0.9.3",
+ "zerocopy 0.8.24",
+]
+
 [[package]]
 name = "rand_chacha"
 version = "0.2.2"
@@ -10227,6 +10721,16 @@ dependencies = [
  "rand_core 0.6.4",
 ]
 
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.9.3",
+]
+
 [[package]]
 name = "rand_core"
 version = "0.5.1"
@@ -10245,6 +10749,15 @@ dependencies = [
  "getrandom 0.2.15",
 ]
 
+[[package]]
+name = "rand_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+dependencies = [
+ "getrandom 0.3.2",
+]
+
 [[package]]
 name = "rand_hc"
 version = "0.2.0"
@@ -10265,9 +10778,9 @@ dependencies = [
 
 [[package]]
 name = "range-alloc"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab"
+checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde"
 
 [[package]]
 name = "rasn"
@@ -10313,7 +10826,7 @@ version = "0.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fdef7f9be5c0122f890d58bdf4d964349ba6a6161f705907526d891efabba57d"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "cassowary",
  "compact_str",
  "crossterm",
@@ -10419,13 +10932,32 @@ dependencies = [
  "cipher",
 ]
 
+[[package]]
+name = "read-fonts"
+version = "0.25.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f9e8a4f503e5c8750e4cd3b32a4e090035c46374b305a15c70bad833dca05f"
+dependencies = [
+ "bytemuck",
+ "font-types",
+]
+
 [[package]]
 name = "redox_syscall"
-version = "0.5.7"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
+checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
 ]
 
 [[package]]
@@ -10447,7 +10979,7 @@ checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
 dependencies = [
  "getrandom 0.2.15",
  "libredox",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -10482,12 +11014,6 @@ dependencies = [
  "regex-syntax 0.8.5",
 ]
 
-[[package]]
-name = "regex-lite"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
-
 [[package]]
 name = "regex-syntax"
 version = "0.6.29"
@@ -10549,7 +11075,7 @@ dependencies = [
  "h2 0.3.26",
  "http 0.2.12",
  "http-body 0.4.6",
- "hyper 0.14.31",
+ "hyper 0.14.32",
  "hyper-rustls 0.24.2",
  "ipnet",
  "js-sys",
@@ -10579,9 +11105,9 @@ dependencies = [
 
 [[package]]
 name = "reqwest"
-version = "0.12.9"
+version = "0.12.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f"
+checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
 dependencies = [
  "base64 0.22.1",
  "bytes",
@@ -10589,12 +11115,12 @@ dependencies = [
  "futures-channel",
  "futures-core",
  "futures-util",
- "h2 0.4.7",
- "http 1.2.0",
+ "h2 0.4.8",
+ "http 1.3.1",
  "http-body 1.0.1",
  "http-body-util",
- "hyper 1.5.1",
- "hyper-rustls 0.27.3",
+ "hyper 1.6.0",
+ "hyper-rustls 0.27.5",
  "hyper-tls",
  "hyper-util",
  "ipnet",
@@ -10607,7 +11133,7 @@ dependencies = [
  "percent-encoding",
  "pin-project-lite",
  "quinn",
- "rustls 0.23.19",
+ "rustls 0.23.25",
  "rustls-pemfile 2.2.0",
  "rustls-pki-types",
  "serde",
@@ -10617,27 +11143,17 @@ dependencies = [
  "system-configuration 0.6.1",
  "tokio",
  "tokio-native-tls",
- "tokio-rustls 0.26.1",
+ "tokio-rustls 0.26.2",
  "tokio-util",
+ "tower 0.5.2",
  "tower-service",
  "url",
  "wasm-bindgen",
  "wasm-bindgen-futures",
  "wasm-streams",
  "web-sys",
- "webpki-roots 0.26.7",
- "windows-registry 0.2.0",
-]
-
-[[package]]
-name = "rfc6979"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
-dependencies = [
- "crypto-bigint 0.4.9",
- "hmac",
- "zeroize",
+ "webpki-roots 0.26.8",
+ "windows-registry",
 ]
 
 [[package]]
@@ -10664,7 +11180,7 @@ dependencies = [
  "objc",
  "objc-foundation",
  "objc_id",
- "pollster",
+ "pollster 0.3.0",
  "raw-window-handle 0.6.2",
  "urlencoding",
  "wasm-bindgen",
@@ -10689,7 +11205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "61797318be89b1a268a018a92a7657096d83f3ecb31418b9e9c16dcbb043b702"
 dependencies = [
  "ahash 0.8.11",
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "instant",
  "num-traits",
  "once_cell",
@@ -10707,14 +11223,14 @@ checksum = "a5a11a05ee1ce44058fa3d5961d05194fdbe3ad6b40f904af764d81b86450e6b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "ring"
-version = "0.17.13"
+version = "0.17.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee"
+checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
 dependencies = [
  "cc",
  "cfg-if",
@@ -10762,13 +11278,19 @@ dependencies = [
  "syn 1.0.109",
 ]
 
+[[package]]
+name = "roxmltree"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
+
 [[package]]
 name = "rpm"
 version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1630639f4dbc1c71ad7b704cda2171584c80735c502efae94804d02763fc6f7d"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "bzip2",
  "chrono",
  "cpio",
@@ -10787,16 +11309,16 @@ dependencies = [
  "pgp",
  "sha1",
  "sha2",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
  "xz2",
  "zstd",
 ]
 
 [[package]]
 name = "rsa"
-version = "0.9.7"
+version = "0.9.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519"
+checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b"
 dependencies = [
  "const-oid",
  "digest",
@@ -10804,19 +11326,19 @@ dependencies = [
  "num-integer",
  "num-traits",
  "pkcs1",
- "pkcs8 0.10.2",
+ "pkcs8",
  "rand_core 0.6.4",
- "signature 2.2.0",
- "spki 0.7.3",
+ "signature",
+ "spki",
  "subtle",
  "zeroize",
 ]
 
 [[package]]
 name = "rust_decimal"
-version = "1.36.0"
+version = "1.37.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555"
+checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50"
 dependencies = [
  "arrayvec",
  "borsh",
@@ -10842,9 +11364,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
 [[package]]
 name = "rustc-hash"
-version = "2.1.0"
+version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
+checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
 
 [[package]]
 name = "rustc_version"
@@ -10861,7 +11383,7 @@ version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
 dependencies = [
- "semver 1.0.23",
+ "semver 1.0.26",
 ]
 
 [[package]]
@@ -10875,14 +11397,27 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.42"
+version = "0.38.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
+dependencies = [
+ "bitflags 2.9.0",
+ "errno",
+ "libc",
+ "linux-raw-sys 0.4.15",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "rustix"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
+checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "errno",
  "libc",
- "linux-raw-sys",
+ "linux-raw-sys 0.9.3",
  "windows-sys 0.59.0",
 ]
 
@@ -10914,16 +11449,16 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.23.19"
+version = "0.23.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1"
+checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c"
 dependencies = [
  "aws-lc-rs",
  "log",
  "once_cell",
  "ring",
  "rustls-pki-types",
- "rustls-webpki 0.102.8",
+ "rustls-webpki 0.103.1",
  "subtle",
  "zeroize",
 ]
@@ -10962,7 +11497,7 @@ dependencies = [
  "openssl-probe",
  "rustls-pki-types",
  "schannel",
- "security-framework 3.0.1",
+ "security-framework 3.2.0",
 ]
 
 [[package]]
@@ -10985,9 +11520,9 @@ dependencies = [
 
 [[package]]
 name = "rustls-pki-types"
-version = "1.10.0"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
+checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
 dependencies = [
  "web-time",
 ]
@@ -10996,17 +11531,28 @@ dependencies = [
 name = "rustls-webpki"
 version = "0.101.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
+checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
+dependencies = [
+ "ring",
+ "untrusted 0.9.0",
+]
+
+[[package]]
+name = "rustls-webpki"
+version = "0.102.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
 dependencies = [
  "ring",
+ "rustls-pki-types",
  "untrusted 0.9.0",
 ]
 
 [[package]]
 name = "rustls-webpki"
-version = "0.102.8"
+version = "0.103.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
+checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
 dependencies = [
  "aws-lc-rs",
  "ring",
@@ -11016,9 +11562,27 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.18"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
+
+[[package]]
+name = "rustybuzz"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
+checksum = "c85d1ccd519e61834798eb52c4e886e8c2d7d698dd3d6ce0b1b47eb8557f1181"
+dependencies = [
+ "bitflags 2.9.0",
+ "bytemuck",
+ "core_maths",
+ "log",
+ "smallvec",
+ "ttf-parser 0.24.1",
+ "unicode-bidi-mirroring",
+ "unicode-ccc",
+ "unicode-properties",
+ "unicode-script",
+]
 
 [[package]]
 name = "ruzstd"
@@ -11027,7 +11591,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d"
 dependencies = [
  "byteorder",
- "derive_more 0.99.18",
+ "derive_more 0.99.19",
  "twox-hash",
 ]
 
@@ -11042,15 +11606,15 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.18"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 
 [[package]]
 name = "ryu-js"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5"
+checksum = "dd29631678d6fb0903b69223673e122c32e9ae559d0960a38d574695ebc0ea15"
 
 [[package]]
 name = "same-file"
@@ -11094,9 +11658,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "scratch"
-version = "1.0.7"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152"
+checksum = "9f6280af86e5f559536da57a45ebc84948833b3bee313a7dd25232e09c878a52"
 
 [[package]]
 name = "scroll"
@@ -11109,13 +11673,13 @@ dependencies = [
 
 [[package]]
 name = "scroll_derive"
-version = "0.12.0"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932"
+checksum = "1783eabc414609e28a5ba76aee5ddd52199f7107a0b24c2e9746a1ecc34a683d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -11129,24 +11693,23 @@ dependencies = [
 ]
 
 [[package]]
-name = "seahash"
-version = "4.1.0"
+name = "sctk-adwaita"
+version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
+checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec"
+dependencies = [
+ "ab_glyph",
+ "log",
+ "memmap2",
+ "smithay-client-toolkit",
+ "tiny-skia",
+]
 
 [[package]]
-name = "sec1"
-version = "0.3.0"
+name = "seahash"
+version = "4.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
-dependencies = [
- "base16ct 0.1.1",
- "der 0.6.1",
- "generic-array 0.14.7",
- "pkcs8 0.9.0",
- "subtle",
- "zeroize",
-]
+checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
 
 [[package]]
 name = "sec1"
@@ -11154,10 +11717,10 @@ version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
 dependencies = [
- "base16ct 0.2.0",
- "der 0.7.9",
+ "base16ct",
+ "der",
  "generic-array 0.14.7",
- "pkcs8 0.10.2",
+ "pkcs8",
  "subtle",
  "zeroize",
 ]
@@ -11168,7 +11731,7 @@ version = "2.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "core-foundation 0.9.4",
  "core-foundation-sys",
  "libc",
@@ -11177,11 +11740,11 @@ dependencies = [
 
 [[package]]
 name = "security-framework"
-version = "3.0.1"
+version = "3.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8"
+checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "core-foundation 0.10.0",
  "core-foundation-sys",
  "libc",
@@ -11190,9 +11753,9 @@ dependencies = [
 
 [[package]]
 name = "security-framework-sys"
-version = "2.12.1"
+version = "2.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2"
+checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
 dependencies = [
  "core-foundation-sys",
  "libc",
@@ -11206,18 +11769,39 @@ checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe"
 dependencies = [
  "bitflags 1.3.2",
  "cssparser 0.27.2",
- "derive_more 0.99.18",
+ "derive_more 0.99.19",
  "fxhash",
  "log",
  "matches",
  "phf 0.8.0",
  "phf_codegen 0.8.0",
  "precomputed-hash",
- "servo_arc",
+ "servo_arc 0.1.1",
  "smallvec",
  "thin-slice",
 ]
 
+[[package]]
+name = "selectors"
+version = "0.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b75e048a93e14929e68e37b82e207db957cbb368375a80ed3ca28ac75080856"
+dependencies = [
+ "bitflags 2.9.0",
+ "cssparser 0.35.0",
+ "derive_more 0.99.19",
+ "fxhash",
+ "log",
+ "new_debug_unreachable",
+ "phf 0.11.3",
+ "phf_codegen 0.11.3",
+ "precomputed-hash",
+ "servo_arc 0.4.0",
+ "smallvec",
+ "to_shmem",
+ "to_shmem_derive",
+]
+
 [[package]]
 name = "semver"
 version = "0.9.0"
@@ -11229,9 +11813,9 @@ dependencies = [
 
 [[package]]
 name = "semver"
-version = "1.0.23"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
 dependencies = [
  "serde",
 ]
@@ -11259,18 +11843,18 @@ checksum = "f97841a747eef040fcd2e7b3b9a220a7205926e60488e673d9e4926d27772ce5"
 
 [[package]]
 name = "serde"
-version = "1.0.217"
+version = "1.0.219"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde-untagged"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2676ba99bd82f75cae5cbd2c8eda6fa0b8760f18978ea840e980dd5567b5c5b6"
+checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e"
 dependencies = [
  "erased-serde",
  "serde",
@@ -11302,22 +11886,22 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.217"
+version = "1.0.219"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.138"
+version = "1.0.140"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
+checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
 dependencies = [
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "memchr",
  "ryu",
  "serde",
@@ -11325,11 +11909,11 @@ dependencies = [
 
 [[package]]
 name = "serde_path_to_error"
-version = "0.1.16"
+version = "0.1.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
+checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a"
 dependencies = [
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "serde",
 ]
 
@@ -11346,13 +11930,13 @@ dependencies = [
 
 [[package]]
 name = "serde_repr"
-version = "0.1.19"
+version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
+checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -11371,22 +11955,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
 dependencies = [
  "form_urlencoded",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "ryu",
  "serde",
 ]
 
 [[package]]
 name = "serde_with"
-version = "3.11.0"
+version = "3.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817"
+checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa"
 dependencies = [
  "base64 0.22.1",
  "chrono",
  "hex",
  "indexmap 1.9.3",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "serde",
  "serde_derive",
  "serde_json",
@@ -11396,14 +11980,14 @@ dependencies = [
 
 [[package]]
 name = "serde_with_macros"
-version = "3.11.0"
+version = "3.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d"
+checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e"
 dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -11412,8 +11996,8 @@ version = "0.9.34+deprecated"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
 dependencies = [
- "indexmap 2.7.0",
- "itoa 1.0.14",
+ "indexmap 2.9.0",
+ "itoa 1.0.15",
  "ryu",
  "serde",
  "unsafe-libyaml",
@@ -11421,9 +12005,9 @@ dependencies = [
 
 [[package]]
 name = "server_fn"
-version = "0.7.3"
+version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0b9f0d2eecb2bf4f909661acc731009e3657574dec93a0ec9f114e250f74bc4"
+checksum = "8d05a9e3fd8d7404985418db38c6617cc793a1a27f398d4fbc9dfe8e41b804e6"
 dependencies = [
  "axum 0.7.9",
  "bytes",
@@ -11431,22 +12015,22 @@ dependencies = [
  "dashmap 6.1.0",
  "futures",
  "gloo-net",
- "http 1.2.0",
+ "http 1.3.1",
  "http-body-util",
- "hyper 1.5.1",
+ "hyper 1.6.0",
  "inventory",
  "js-sys",
  "once_cell",
  "pin-project-lite",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "send_wrapper",
  "serde",
  "serde_json",
  "serde_qs",
  "server_fn_macro_default",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
  "throw_error",
- "tower 0.5.1",
+ "tower 0.5.2",
  "tower-layer",
  "url",
  "wasm-bindgen",
@@ -11458,26 +12042,26 @@ dependencies = [
 
 [[package]]
 name = "server_fn_macro"
-version = "0.7.3"
+version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee7723bef57b4353cd9939e280d3b5b2ebe45b4a4630c9e9e97a6fa4b84e8b1c"
+checksum = "504b35e883267b3206317b46d02952ed7b8bf0e11b2e209e2eb453b609a5e052"
 dependencies = [
  "const_format",
  "convert_case 0.6.0",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "xxhash-rust",
 ]
 
 [[package]]
 name = "server_fn_macro_default"
-version = "0.7.3"
+version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87663ec10f17fbe8f6c53adc2d038df3304bfd17aaaab22f777810a9e6e05fff"
+checksum = "eb8b274f568c94226a8045668554aace8142a59b8bca5414ac5a79627c825568"
 dependencies = [
  "server_fn_macro",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -11490,6 +12074,16 @@ dependencies = [
  "stable_deref_trait",
 ]
 
+[[package]]
+name = "servo_arc"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae65c4249478a2647db249fb43e23cec56a2c8974a427e7bd8cb5a1d0964921a"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+]
+
 [[package]]
 name = "sha1"
 version = "0.10.6"
@@ -11590,16 +12184,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "signature"
-version = "1.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
-dependencies = [
- "digest",
- "rand_core 0.6.4",
-]
-
 [[package]]
 name = "signature"
 version = "2.2.0"
@@ -11616,7 +12200,7 @@ version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987"
 dependencies = [
- "outref 0.1.0",
+ "outref",
 ]
 
 [[package]]
@@ -11647,15 +12231,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5dd19be0257552dd56d1bb6946f89f193c6e5b9f13cc9327c4bc84a357507c74"
 
 [[package]]
-name = "simple_asn1"
-version = "0.6.2"
+name = "simplecss"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085"
+checksum = "7a9c6883ca9c3c7c90e888de77b7a5c849c779d25d74a1269b0218b14e8b136c"
 dependencies = [
- "num-bigint",
- "num-traits",
- "thiserror 1.0.69",
- "time",
+ "log",
 ]
 
 [[package]]
@@ -11664,6 +12245,22 @@ version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
 
+[[package]]
+name = "siphasher"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
+
+[[package]]
+name = "skrifa"
+version = "0.26.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cc1aa86c26dbb1b63875a7180aa0819709b33348eb5b1491e4321fae388179d"
+dependencies = [
+ "bytemuck",
+ "read-fonts",
+]
+
 [[package]]
 name = "slab"
 version = "0.4.9"
@@ -11690,7 +12287,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "33a1b4f13e2bbf2f5b29d09dfebc9de69229ffee245aed80e3b70f9b5fd28c06"
 dependencies = [
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -11712,11 +12309,17 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "smallbitvec"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d31d263dd118560e1a492922182ab6ca6dc1d03a3bf54e7699993f31a4150e3f"
+
 [[package]]
 name = "smallvec"
-version = "1.13.2"
+version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
 
 [[package]]
 name = "smartstring"
@@ -11729,6 +12332,40 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "smithay-client-toolkit"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016"
+dependencies = [
+ "bitflags 2.9.0",
+ "calloop",
+ "calloop-wayland-source",
+ "cursor-icon",
+ "libc",
+ "log",
+ "memmap2",
+ "rustix 0.38.44",
+ "thiserror 1.0.69",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-csd-frame",
+ "wayland-cursor",
+ "wayland-protocols",
+ "wayland-protocols-wlr",
+ "wayland-scanner",
+ "xkeysym",
+]
+
+[[package]]
+name = "smol_str"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "snafu"
 version = "0.7.5"
@@ -11754,9 +12391,9 @@ dependencies = [
 
 [[package]]
 name = "socket2"
-version = "0.5.8"
+version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
+checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
 dependencies = [
  "libc",
  "windows-sys 0.52.0",
@@ -11805,7 +12442,7 @@ version = "9.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "27c4ea7042fd1a155ad95335b5d505ab00d5124ea0332a06c8390d200bb1a76a"
 dependencies = [
- "base64-simd 0.7.0",
+ "base64-simd",
  "bitvec",
  "data-encoding",
  "debugid",
@@ -11845,17 +12482,7 @@ version = "0.3.0+sdk-1.3.268.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
 dependencies = [
- "bitflags 2.6.0",
-]
-
-[[package]]
-name = "spki"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
-dependencies = [
- "base64ct",
- "der 0.6.1",
+ "bitflags 2.9.0",
 ]
 
 [[package]]
@@ -11865,7 +12492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
 dependencies = [
  "base64ct",
- "der 0.7.9",
+ "der",
 ]
 
 [[package]]
@@ -11900,7 +12527,7 @@ dependencies = [
  "ahash 0.8.11",
  "atoi",
  "bigdecimal",
- "bit-vec",
+ "bit-vec 0.6.3",
  "byteorder",
  "bytes",
  "chrono",
@@ -11915,7 +12542,7 @@ dependencies = [
  "futures-util",
  "hashlink",
  "hex",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "ipnetwork",
  "log",
  "mac_address",
@@ -11990,7 +12617,7 @@ dependencies = [
  "atoi",
  "base64 0.21.7",
  "bigdecimal",
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "byteorder",
  "bytes",
  "chrono",
@@ -12006,7 +12633,7 @@ dependencies = [
  "hex",
  "hkdf",
  "hmac",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "log",
  "md-5",
  "memchr",
@@ -12037,8 +12664,8 @@ dependencies = [
  "atoi",
  "base64 0.21.7",
  "bigdecimal",
- "bit-vec",
- "bitflags 2.6.0",
+ "bit-vec 0.6.3",
+ "bitflags 2.9.0",
  "byteorder",
  "chrono",
  "crc 3.2.1",
@@ -12053,7 +12680,7 @@ dependencies = [
  "hmac",
  "home",
  "ipnetwork",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "log",
  "mac_address",
  "md-5",
@@ -12109,9 +12736,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
 [[package]]
 name = "stacker"
-version = "0.1.17"
+version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b"
+checksum = "601f9201feb9b09c00266478bf459952b9ef9a6b94edb2f21eba14ab681a60a9"
 dependencies = [
  "cc",
  "cfg-if",
@@ -12126,6 +12753,7 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f6635404b73efc136af3a7956e53c53d4f34b2f16c95a15c438929add0f69412"
 dependencies = [
+ "indexmap 2.9.0",
  "smallvec",
  "static-self-derive",
 ]
@@ -12147,28 +12775,36 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
+[[package]]
+name = "strict-num"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
+dependencies = [
+ "float-cmp",
+]
+
 [[package]]
 name = "string_cache"
-version = "0.8.7"
+version = "0.8.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
+checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
 dependencies = [
  "new_debug_unreachable",
- "once_cell",
  "parking_lot",
- "phf_shared 0.10.0",
+ "phf_shared 0.11.3",
  "precomputed-hash",
  "serde",
 ]
 
 [[package]]
 name = "string_cache_codegen"
-version = "0.5.2"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
+checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
 dependencies = [
- "phf_generator 0.10.0",
- "phf_shared 0.10.0",
+ "phf_generator 0.11.3",
+ "phf_shared 0.11.3",
  "proc-macro2",
  "quote",
 ]
@@ -12182,7 +12818,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "swc_macros_common",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -12240,7 +12876,161 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 2.0.98",
+ "syn 2.0.100",
+]
+
+[[package]]
+name = "stylo"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfacf8821bb157fbd6cebaa682f22bcebddc38e4165cdedba0061dae24b241c2"
+dependencies = [
+ "app_units",
+ "arrayvec",
+ "atomic_refcell",
+ "bitflags 2.9.0",
+ "byteorder",
+ "cssparser 0.35.0",
+ "derive_more 0.99.19",
+ "encoding_rs",
+ "euclid",
+ "fxhash",
+ "icu_segmenter",
+ "indexmap 2.9.0",
+ "itertools 0.10.5",
+ "itoa 1.0.15",
+ "lazy_static",
+ "log",
+ "malloc_size_of_derive",
+ "markup5ever 0.15.0",
+ "matches",
+ "mime",
+ "new_debug_unreachable",
+ "num-derive",
+ "num-integer",
+ "num-traits",
+ "num_cpus",
+ "parking_lot",
+ "precomputed-hash",
+ "rayon",
+ "rayon-core",
+ "selectors 0.27.0",
+ "serde",
+ "servo_arc 0.4.0",
+ "smallbitvec",
+ "smallvec",
+ "static_assertions",
+ "string_cache",
+ "stylo_atoms",
+ "stylo_config",
+ "stylo_derive",
+ "stylo_dom",
+ "stylo_malloc_size_of",
+ "stylo_static_prefs",
+ "stylo_traits",
+ "thin-vec",
+ "to_shmem",
+ "to_shmem_derive",
+ "uluru",
+ "unicode-bidi",
+ "url",
+ "void",
+ "walkdir",
+]
+
+[[package]]
+name = "stylo_atoms"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b943c983729930ee70141ab6515604bb33ff5de8d7626024072c38a27c8023bb"
+dependencies = [
+ "string_cache",
+ "string_cache_codegen",
+]
+
+[[package]]
+name = "stylo_config"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2e53afe5289d75063564e60aa59c591a2c496d3425f2bb2a3002251785e2058"
+
+[[package]]
+name = "stylo_derive"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e745b58d581ba8eb932825e684634eae9be848fd49c086b3f17ccb7d6c417594"
+dependencies = [
+ "darling",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+ "synstructure 0.13.1",
+]
+
+[[package]]
+name = "stylo_dom"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06606e83c4feb986ea601a2c7d625aa5c303ecfc9526494480f6e599b8d6956e"
+dependencies = [
+ "bitflags 2.9.0",
+ "stylo_malloc_size_of",
+]
+
+[[package]]
+name = "stylo_malloc_size_of"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93db6fdbcde7f037f7810873374d85a2b3d37686b046577943818167a6e52d3f"
+dependencies = [
+ "app_units",
+ "cssparser 0.35.0",
+ "euclid",
+ "selectors 0.27.0",
+ "servo_arc 0.4.0",
+ "smallbitvec",
+ "smallvec",
+ "string_cache",
+ "thin-vec",
+ "void",
+]
+
+[[package]]
+name = "stylo_static_prefs"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "decb57071c4b4d5690a9719fb04a07cf2fab0fa3df99a830ef735192a1a98e5d"
+
+[[package]]
+name = "stylo_taffy"
+version = "0.1.0-alpha.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6da84b2bae9d25a2156b7cf89acab90683ac4d25dcb3fe1817dc9e77a20ce2f"
+dependencies = [
+ "stylo",
+ "taffy",
+]
+
+[[package]]
+name = "stylo_traits"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f611ebeee90c0d255bf4d4fadc05f964ef019f8aaed307108fa859c826f2753"
+dependencies = [
+ "app_units",
+ "bitflags 2.9.0",
+ "cssparser 0.35.0",
+ "euclid",
+ "malloc_size_of_derive",
+ "selectors 0.27.0",
+ "serde",
+ "servo_arc 0.4.0",
+ "stylo_atoms",
+ "stylo_malloc_size_of",
+ "thin-vec",
+ "to_shmem",
+ "to_shmem_derive",
+ "url",
 ]
 
 [[package]]
@@ -12272,9 +13062,36 @@ dependencies = [
 name = "suspense-carousel"
 version = "0.6.3"
 dependencies = [
- "async-std",
- "dioxus",
- "serde",
+ "async-std",
+ "dioxus",
+ "serde",
+]
+
+[[package]]
+name = "svg_fmt"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce5d813d71d82c4cbc1742135004e4a79fd870214c155443451c139c9470a0aa"
+
+[[package]]
+name = "svgtypes"
+version = "0.15.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68c7541fff44b35860c1a7a47a7cadf3e4a304c457b58f9870d9706ece028afc"
+dependencies = [
+ "kurbo",
+ "siphasher 1.0.1",
+]
+
+[[package]]
+name = "swash"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fae9a562c7b46107d9c78cd78b75bbe1e991c16734c0aee8ff0ee711fb8b620a"
+dependencies = [
+ "skrifa",
+ "yazi",
+ "zeno",
 ]
 
 [[package]]
@@ -12310,7 +13127,7 @@ checksum = "c88a91910cd8430f88f8987019cf3a96d92a5d5dded3e0ba8203e0379e4a2f6f"
 dependencies = [
  "anyhow",
  "crc 2.1.0",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "is-macro",
  "once_cell",
  "parking_lot",
@@ -12362,7 +13179,7 @@ dependencies = [
  "once_cell",
  "rustc-hash 1.1.0",
  "serde",
- "siphasher",
+ "siphasher 0.3.11",
  "swc_allocator",
  "swc_atoms",
  "swc_eq_ignore_macros",
@@ -12380,7 +13197,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4aa30931f9b26af8edcb4cce605909d15dcfd7577220b22c50a2988f2a53c4c1"
 dependencies = [
  "anyhow",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "serde",
  "serde_json",
  "sourcemap",
@@ -12397,7 +13214,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "swc_macros_common",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -12406,10 +13223,10 @@ version = "5.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "82f448db2d1c52ffd2bd3788d89cafd8b5a75b97f0dc8aae00874dda2647f6b6"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "is-macro",
  "num-bigint",
- "phf 0.11.2",
+ "phf 0.11.3",
  "scoped-tls",
  "serde",
  "string_enum",
@@ -12448,7 +13265,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "swc_macros_common",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -12479,12 +13296,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "164291b068cca947462d87ede1baf276f69da137db1a0c66059a8aed81b785b2"
 dependencies = [
  "arrayvec",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "num-bigint",
  "num_cpus",
  "once_cell",
  "parking_lot",
- "phf 0.11.2",
+ "phf 0.11.3",
  "radix_fmt",
  "regex",
  "rustc-hash 1.1.0",
@@ -12518,7 +13335,7 @@ dependencies = [
  "new_debug_unreachable",
  "num-bigint",
  "num-traits",
- "phf 0.11.2",
+ "phf 0.11.3",
  "serde",
  "smallvec",
  "smartstring",
@@ -12537,10 +13354,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09fdc36d220bcd51f70b1d78bdd8c1e1a172b4e594c385bdd9614b84a7c0e112"
 dependencies = [
  "better_scoped_tls",
- "bitflags 2.6.0",
- "indexmap 2.7.0",
+ "bitflags 2.9.0",
+ "indexmap 2.9.0",
  "once_cell",
- "phf 0.11.2",
+ "phf 0.11.3",
  "rustc-hash 1.1.0",
  "serde",
  "smallvec",
@@ -12563,7 +13380,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "swc_macros_common",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -12573,7 +13390,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5e4232534b28fc57b745e8c709723544e5548af29abaa62281eab427099f611d"
 dependencies = [
  "dashmap 5.5.3",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "once_cell",
  "petgraph",
  "rustc-hash 1.1.0",
@@ -12596,7 +13413,7 @@ version = "7.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "15eb86aaa82d7ec4c1a6c3a8a824b1fdbbaace73c3ed81035a1fbbac49f8e0bd"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "rustc-hash 1.1.0",
  "swc_atoms",
  "swc_common",
@@ -12613,7 +13430,7 @@ version = "7.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1c9d22b4883dc6d6c21a8216bbf5aacedd7f104230b1557367ae126a2ec3a2b5"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "num_cpus",
  "once_cell",
  "rustc-hash 1.1.0",
@@ -12650,7 +13467,7 @@ checksum = "e96e15288bf385ab85eb83cff7f9e2d834348da58d0a31b33bdb572e66ee413e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -12659,7 +13476,7 @@ version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c22e0a0478b1b06610453a97c8371cafa742e371a79aff860ccfbabe1ab160a7"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "petgraph",
  "rustc-hash 1.1.0",
  "swc_common",
@@ -12686,7 +13503,7 @@ checksum = "a509f56fca05b39ba6c15f3e58636c3924c78347d63853632ed2ffcb6f5a0ac7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -12730,9 +13547,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.98"
+version = "2.0.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -12774,7 +13591,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -12821,7 +13638,7 @@ version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "core-foundation 0.9.4",
  "system-configuration-sys 0.6.0",
 ]
@@ -12859,13 +13676,25 @@ dependencies = [
  "version-compare",
 ]
 
+[[package]]
+name = "taffy"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56a844965df28147d726ecc321bf67f287a9bdec5a655f53d4e7e5cad20443dc"
+dependencies = [
+ "arrayvec",
+ "grid",
+ "serde",
+ "slotmap",
+]
+
 [[package]]
 name = "tao"
 version = "0.30.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "cocoa 0.26.0",
  "core-foundation 0.10.0",
  "core-graphics 0.24.0",
@@ -12907,7 +13736,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -12918,9 +13747,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
 
 [[package]]
 name = "tar"
-version = "0.4.43"
+version = "0.4.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6"
+checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a"
 dependencies = [
  "filetime",
  "libc",
@@ -12935,9 +13764,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
 
 [[package]]
 name = "target-triple"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078"
+checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790"
 
 [[package]]
 name = "tauri-bundler"
@@ -12962,7 +13791,7 @@ dependencies = [
  "plist",
  "regex",
  "rpm",
- "semver 1.0.23",
+ "semver 1.0.26",
  "serde",
  "serde_json",
  "sha1",
@@ -12973,15 +13802,15 @@ dependencies = [
  "tauri-macos-sign",
  "tauri-utils",
  "tempfile",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
  "time",
  "ureq",
  "url",
  "uuid",
  "walkdir",
- "windows-registry 0.4.0",
+ "windows-registry",
  "windows-sys 0.59.0",
- "zip 2.2.1",
+ "zip 2.6.1",
 ]
 
 [[package]]
@@ -12996,14 +13825,14 @@ dependencies = [
 
 [[package]]
 name = "tauri-macos-sign"
-version = "2.0.1"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be95e2d37d1e3605831da071234418c786684af48982509af1b7f50b31af4546"
+checksum = "e0b02c73cafad954f587af3845d8f275112ccf4b8a101fd1ce5753c873ee35e4"
 dependencies = [
  "anyhow",
  "apple-codesign",
  "chrono",
- "dirs-next",
+ "dirs 6.0.0",
  "log",
  "once-cell-regex",
  "os_pipe",
@@ -13026,20 +13855,20 @@ dependencies = [
  "dunce",
  "glob",
  "html5ever",
- "http 1.2.0",
- "infer 0.16.0",
+ "http 1.3.1",
+ "infer",
  "json-patch",
  "kuchikiki",
  "log",
  "memchr",
- "phf 0.11.2",
+ "phf 0.11.3",
  "regex",
- "semver 1.0.23",
+ "semver 1.0.26",
  "serde",
  "serde-untagged",
  "serde_json",
  "serde_with",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
  "toml",
  "url",
  "urlpattern",
@@ -13055,7 +13884,7 @@ checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
 dependencies = [
  "cfg-if",
  "fastrand",
- "rustix",
+ "rustix 0.38.44",
  "windows-sys 0.52.0",
 ]
 
@@ -13091,11 +13920,11 @@ dependencies = [
 
 [[package]]
 name = "terminal_size"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9"
+checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed"
 dependencies = [
- "rustix",
+ "rustix 1.0.5",
  "windows-sys 0.59.0",
 ]
 
@@ -13107,9 +13936,9 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
 
 [[package]]
 name = "thin-vec"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b"
+checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d"
 
 [[package]]
 name = "thiserror"
@@ -13122,11 +13951,11 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "2.0.6"
+version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47"
+checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
 dependencies = [
- "thiserror-impl 2.0.6",
+ "thiserror-impl 2.0.12",
 ]
 
 [[package]]
@@ -13137,18 +13966,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "2.0.6"
+version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312"
+checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -13193,12 +14022,12 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.37"
+version = "0.3.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
+checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
 dependencies = [
  "deranged",
- "itoa 1.0.14",
+ "itoa 1.0.15",
  "libc",
  "num-conv",
  "num_threads",
@@ -13210,15 +14039,15 @@ dependencies = [
 
 [[package]]
 name = "time-core"
-version = "0.1.2"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
 
 [[package]]
 name = "time-macros"
-version = "0.2.19"
+version = "0.2.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
+checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
 dependencies = [
  "num-conv",
  "time-core",
@@ -13233,6 +14062,31 @@ dependencies = [
  "crunchy",
 ]
 
+[[package]]
+name = "tiny-skia"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "bytemuck",
+ "cfg-if",
+ "log",
+ "tiny-skia-path",
+]
+
+[[package]]
+name = "tiny-skia-path"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93"
+dependencies = [
+ "arrayref",
+ "bytemuck",
+ "strict-num",
+]
+
 [[package]]
 name = "tinystr"
 version = "0.7.6"
@@ -13255,9 +14109,9 @@ dependencies = [
 
 [[package]]
 name = "tinyvec"
-version = "1.8.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
+checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
 dependencies = [
  "tinyvec_macros",
 ]
@@ -13268,11 +14122,38 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
+[[package]]
+name = "to_shmem"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb61262d1e7e4cc777e40cb2f101d5fa51f3eeac50c3a7355b2027b9274baa35"
+dependencies = [
+ "cssparser 0.35.0",
+ "servo_arc 0.4.0",
+ "smallbitvec",
+ "smallvec",
+ "string_cache",
+ "thin-vec",
+]
+
+[[package]]
+name = "to_shmem_derive"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ba1f5563024b63bb6acb4558452d9ba737518c1d11fcc1861febe98d1e31cf4"
+dependencies = [
+ "darling",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+ "synstructure 0.13.1",
+]
+
 [[package]]
 name = "tokio"
-version = "1.42.0"
+version = "1.44.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551"
+checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
 dependencies = [
  "backtrace",
  "bytes",
@@ -13299,13 +14180,13 @@ dependencies = [
 
 [[package]]
 name = "tokio-macros"
-version = "2.4.0"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
+checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -13330,11 +14211,11 @@ dependencies = [
 
 [[package]]
 name = "tokio-rustls"
-version = "0.26.1"
+version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
+checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
 dependencies = [
- "rustls 0.23.19",
+ "rustls 0.23.25",
  "tokio",
 ]
 
@@ -13359,7 +14240,7 @@ dependencies = [
  "futures-util",
  "log",
  "native-tls",
- "rustls 0.23.19",
+ "rustls 0.23.25",
  "tokio",
  "tokio-native-tls",
  "tungstenite 0.23.0",
@@ -13379,9 +14260,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-util"
-version = "0.7.13"
+version = "0.7.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
+checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034"
 dependencies = [
  "bytes",
  "futures-core",
@@ -13396,15 +14277,15 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.8.19"
+version = "0.8.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
+checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "serde",
  "serde_spanned",
  "toml_datetime",
- "toml_edit 0.22.22",
+ "toml_edit 0.22.24",
 ]
 
 [[package]]
@@ -13422,7 +14303,7 @@ version = "0.19.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "toml_datetime",
  "winnow 0.5.40",
 ]
@@ -13433,22 +14314,22 @@ version = "0.20.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "toml_datetime",
  "winnow 0.5.40",
 ]
 
 [[package]]
 name = "toml_edit"
-version = "0.22.22"
+version = "0.22.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
+checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
 dependencies = [
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "serde",
  "serde_spanned",
  "toml_datetime",
- "winnow 0.6.20",
+ "winnow 0.7.6",
 ]
 
 [[package]]
@@ -13465,7 +14346,7 @@ dependencies = [
  "h2 0.3.26",
  "http 0.2.12",
  "http-body 0.4.6",
- "hyper 0.14.31",
+ "hyper 0.14.32",
  "hyper-timeout",
  "percent-encoding",
  "pin-project",
@@ -13500,14 +14381,14 @@ dependencies = [
 
 [[package]]
 name = "tower"
-version = "0.5.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f"
+checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
 dependencies = [
  "futures-core",
  "futures-util",
  "pin-project-lite",
- "sync_wrapper 0.1.2",
+ "sync_wrapper 1.0.2",
  "tokio",
  "tower-layer",
  "tower-service",
@@ -13522,11 +14403,11 @@ checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
 dependencies = [
  "async-compression",
  "base64 0.21.7",
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "bytes",
  "futures-core",
  "futures-util",
- "http 1.2.0",
+ "http 1.3.1",
  "http-body 1.0.1",
  "http-body-util",
  "http-range-header",
@@ -13577,7 +14458,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -13666,21 +14547,22 @@ dependencies = [
 
 [[package]]
 name = "tray-icon"
-version = "0.19.2"
+version = "0.19.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d48a05076dd272615d03033bf04f480199f7d1b66a8ac64d75c625fc4a70c06b"
+checksum = "eadd75f5002e2513eaa19b2365f533090cc3e93abd38788452d9ea85cff7b48a"
 dependencies = [
- "core-graphics 0.24.0",
  "crossbeam-channel",
- "dirs 5.0.1",
+ "dirs 6.0.0",
  "libappindicator",
- "muda",
- "objc2 0.5.2",
- "objc2-app-kit 0.2.2",
- "objc2-foundation 0.2.2",
+ "muda 0.15.3",
+ "objc2 0.6.0",
+ "objc2-app-kit 0.3.0",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+ "objc2-foundation 0.3.0",
  "once_cell",
  "png",
- "thiserror 1.0.69",
+ "thiserror 2.0.12",
  "windows-sys 0.59.0",
 ]
 
@@ -13702,9 +14584,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
 
 [[package]]
 name = "trybuild"
-version = "1.0.101"
+version = "1.0.104"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dcd332a5496c026f1e14b7f3d2b7bd98e509660c04239c58b0ba38a12daded4"
+checksum = "6ae08be68c056db96f0e6c6dd820727cca756ced9e1f4cc7fdd20e2a55e23898"
 dependencies = [
  "dissimilar",
  "glob",
@@ -13716,6 +14598,21 @@ dependencies = [
  "toml",
 ]
 
+[[package]]
+name = "ttf-parser"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a"
+dependencies = [
+ "core_maths",
+]
+
+[[package]]
+name = "ttf-parser"
+version = "0.25.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
+
 [[package]]
 name = "tungstenite"
 version = "0.21.0"
@@ -13725,7 +14622,7 @@ dependencies = [
  "byteorder",
  "bytes",
  "data-encoding",
- "http 1.2.0",
+ "http 1.3.1",
  "httparse",
  "log",
  "rand 0.8.5",
@@ -13747,7 +14644,7 @@ dependencies = [
  "byteorder",
  "bytes",
  "data-encoding",
- "http 1.2.0",
+ "http 1.3.1",
  "httparse",
  "log",
  "native-tls",
@@ -13766,7 +14663,7 @@ dependencies = [
  "byteorder",
  "bytes",
  "data-encoding",
- "http 1.2.0",
+ "http 1.3.1",
  "httparse",
  "log",
  "rand 0.8.5",
@@ -13802,15 +14699,15 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
 
 [[package]]
 name = "typeid"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e"
+checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
 
 [[package]]
 name = "typenum"
-version = "1.17.0"
+version = "1.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
 
 [[package]]
 name = "typewit"
@@ -13844,6 +14741,15 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "uluru"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c8a2469e56e6e5095c82ccd3afb98dad95f7af7929aab6d8ba8d6e0f73657da"
+dependencies = [
+ "arrayvec",
+]
+
 [[package]]
 name = "uname"
 version = "0.1.1"
@@ -13905,15 +14811,21 @@ dependencies = [
 
 [[package]]
 name = "unicase"
-version = "2.8.0"
+version = "2.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
+checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.17"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
+
+[[package]]
+name = "unicode-bidi-mirroring"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
+checksum = "64af057ad7466495ca113126be61838d8af947f41d93a949980b2389a118082f"
 
 [[package]]
 name = "unicode-bom"
@@ -13921,6 +14833,12 @@ version = "2.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217"
 
+[[package]]
+name = "unicode-ccc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "260bc6647b3893a9a90668360803a15f96b85a5257b1c3a0c3daf6ae2496de42"
+
 [[package]]
 name = "unicode-id"
 version = "0.3.5"
@@ -13935,9 +14853,9 @@ checksum = "2f322b60f6b9736017344fa0635d64be2f458fbc04eef65f6be22976dd1ffd5b"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.14"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
 
 [[package]]
 name = "unicode-normalization"
@@ -13954,6 +14872,12 @@ version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
 
+[[package]]
+name = "unicode-script"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f"
+
 [[package]]
 name = "unicode-segmentation"
 version = "1.12.0"
@@ -13971,6 +14895,12 @@ dependencies = [
  "unicode-width 0.1.14",
 ]
 
+[[package]]
+name = "unicode-vo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94"
+
 [[package]]
 name = "unicode-width"
 version = "0.1.14"
@@ -14032,11 +14962,11 @@ dependencies = [
  "base64 0.22.1",
  "log",
  "once_cell",
- "rustls 0.23.19",
+ "rustls 0.23.25",
  "rustls-pki-types",
  "socks",
  "url",
- "webpki-roots 0.26.7",
+ "webpki-roots 0.26.8",
 ]
 
 [[package]]
@@ -14069,6 +14999,33 @@ dependencies = [
  "url",
 ]
 
+[[package]]
+name = "usvg"
+version = "0.44.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7447e703d7223b067607655e625e0dbca80822880248937da65966194c4864e6"
+dependencies = [
+ "base64 0.22.1",
+ "data-url 0.3.1",
+ "flate2",
+ "fontdb",
+ "imagesize",
+ "kurbo",
+ "log",
+ "pico-args",
+ "roxmltree",
+ "rustybuzz",
+ "simplecss",
+ "siphasher 1.0.1",
+ "strict-num",
+ "svgtypes",
+ "tiny-skia-path",
+ "unicode-bidi",
+ "unicode-script",
+ "unicode-vo",
+ "xmlwriter",
+]
+
 [[package]]
 name = "utf-8"
 version = "0.7.6"
@@ -14081,6 +15038,12 @@ version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
 
+[[package]]
+name = "utf8-width"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
+
 [[package]]
 name = "utf8_iter"
 version = "1.0.4"
@@ -14095,11 +15058,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 
 [[package]]
 name = "uuid"
-version = "1.11.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
+checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
 dependencies = [
- "getrandom 0.2.15",
+ "getrandom 0.3.2",
  "serde",
  "sha1_smol",
 ]
@@ -14117,15 +15080,15 @@ dependencies = [
 
 [[package]]
 name = "valuable"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
 
 [[package]]
 name = "value-bag"
-version = "1.10.0"
+version = "1.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2"
+checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5"
 
 [[package]]
 name = "vcpkg"
@@ -14133,6 +15096,62 @@ version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
 
+[[package]]
+name = "vello"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d5b0bafa35e0c2e4132104576d6bcec4bf7cd0044f1760e92ecae0d4d9bc0e7"
+dependencies = [
+ "bytemuck",
+ "futures-intrusive",
+ "log",
+ "peniko",
+ "png",
+ "skrifa",
+ "static_assertions",
+ "thiserror 2.0.12",
+ "vello_encoding",
+ "vello_shaders",
+ "wgpu 23.0.1",
+]
+
+[[package]]
+name = "vello_encoding"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbbdec68dea2b39ece9f82ab15ec4cf2c4f8600ce6926df0638290702d95b3f7"
+dependencies = [
+ "bytemuck",
+ "guillotiere",
+ "peniko",
+ "skrifa",
+ "smallvec",
+]
+
+[[package]]
+name = "vello_shaders"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e0179d74cf9131dfd7882323751d2544f3aefdfda9d16c39bbe2729799410d2"
+dependencies = [
+ "bytemuck",
+ "naga 23.1.0",
+ "thiserror 2.0.12",
+ "vello_encoding",
+]
+
+[[package]]
+name = "vello_svg"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a0fd265f55b496a8048a43c769bf15487f2be9f6642086b3468c64677cc8c87"
+dependencies = [
+ "image",
+ "thiserror 2.0.12",
+ "usvg",
+ "vello",
+]
+
 [[package]]
 name = "version-compare"
 version = "0.2.0"
@@ -14152,10 +15171,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "65dd7eed29412da847b0f78bcec0ac98588165988a8cfe41d4ea1d429f8ccfff"
 
 [[package]]
-name = "vsimd"
-version = "0.8.0"
+name = "void"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64"
+checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 
 [[package]]
 name = "walkdir"
@@ -14193,7 +15212,7 @@ dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -14224,7 +15243,7 @@ checksum = "59195a1db0e95b920366d949ba5e0d3fc0e70b67c09be15ce5abb790106b0571"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -14239,6 +15258,15 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasi"
+version = "0.14.2+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
 [[package]]
 name = "wasite"
 version = "0.1.0"
@@ -14267,7 +15295,7 @@ dependencies = [
  "log",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "wasm-bindgen-shared",
 ]
 
@@ -14302,7 +15330,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -14337,7 +15365,7 @@ checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -14425,7 +15453,7 @@ dependencies = [
  "getrandom 0.2.15",
  "js-sys",
  "once_cell",
- "reqwest 0.12.9",
+ "reqwest 0.12.15",
  "wasm-bindgen",
  "wasm-bindgen-futures",
  "web-sys",
@@ -14440,7 +15468,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "sha2",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -14472,20 +15500,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5309c1090e3e84dad0d382f42064e9933fdaedb87e468cc239f0eabea73ddcb6"
 dependencies = [
  "ahash 0.8.11",
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "hashbrown 0.14.5",
- "indexmap 2.7.0",
- "semver 1.0.23",
+ "indexmap 2.9.0",
+ "semver 1.0.26",
  "serde",
 ]
 
 [[package]]
 name = "wasmparser"
-version = "0.218.0"
+version = "0.222.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b09e46c7fceceaa72b2dd1a8a137ea7fd8f93dfaa69806010a709918e496c5dc"
+checksum = "fa210fd1788e6b37a1d1930f3389c48e1d6ebd1a013d34fa4b7f9e3e3bf03146"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
 ]
 
 [[package]]
@@ -14494,13 +15522,122 @@ version = "0.225.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "36e5456165f81e64cb9908a0fe9b9d852c2c74582aa3fe2be3c2da57f937d3ae"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
  "hashbrown 0.15.2",
- "indexmap 2.7.0",
- "semver 1.0.23",
+ "indexmap 2.9.0",
+ "semver 1.0.26",
  "serde",
 ]
 
+[[package]]
+name = "wayland-backend"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf"
+dependencies = [
+ "cc",
+ "downcast-rs",
+ "rustix 0.38.44",
+ "scoped-tls",
+ "smallvec",
+ "wayland-sys",
+]
+
+[[package]]
+name = "wayland-client"
+version = "0.31.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f"
+dependencies = [
+ "bitflags 2.9.0",
+ "rustix 0.38.44",
+ "wayland-backend",
+ "wayland-scanner",
+]
+
+[[package]]
+name = "wayland-csd-frame"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
+dependencies = [
+ "bitflags 2.9.0",
+ "cursor-icon",
+ "wayland-backend",
+]
+
+[[package]]
+name = "wayland-cursor"
+version = "0.31.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d"
+dependencies = [
+ "rustix 0.38.44",
+ "wayland-client",
+ "xcursor",
+]
+
+[[package]]
+name = "wayland-protocols"
+version = "0.32.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc"
+dependencies = [
+ "bitflags 2.9.0",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-scanner",
+]
+
+[[package]]
+name = "wayland-protocols-plasma"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ccaacc76703fefd6763022ac565b590fcade92202492381c95b2edfdf7d46b3"
+dependencies = [
+ "bitflags 2.9.0",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-protocols",
+ "wayland-scanner",
+]
+
+[[package]]
+name = "wayland-protocols-wlr"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "248a02e6f595aad796561fa82d25601bd2c8c3b145b1c7453fc8f94c1a58f8b2"
+dependencies = [
+ "bitflags 2.9.0",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-protocols",
+ "wayland-scanner",
+]
+
+[[package]]
+name = "wayland-scanner"
+version = "0.31.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484"
+dependencies = [
+ "proc-macro2",
+ "quick-xml 0.37.4",
+ "quote",
+]
+
+[[package]]
+name = "wayland-sys"
+version = "0.31.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615"
+dependencies = [
+ "dlib",
+ "log",
+ "once_cell",
+ "pkg-config",
+]
+
 [[package]]
 name = "web-sys"
 version = "0.3.77"
@@ -14590,9 +15727,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
 
 [[package]]
 name = "webpki-roots"
-version = "0.26.7"
+version = "0.26.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
+checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9"
 dependencies = [
  "rustls-pki-types",
 ]
@@ -14608,7 +15745,7 @@ dependencies = [
  "windows 0.60.0",
  "windows-core 0.60.1",
  "windows-implement 0.59.0",
- "windows-interface 0.59.0",
+ "windows-interface 0.59.1",
 ]
 
 [[package]]
@@ -14619,7 +15756,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -14628,7 +15765,7 @@ version = "0.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bfb27fccd3c27f68e9a6af1bcf48c2d82534b8675b83608a4d81446d095a17ac"
 dependencies = [
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
  "windows 0.60.0",
  "windows-core 0.60.1",
 ]
@@ -14641,16 +15778,41 @@ checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
 
 [[package]]
 name = "wgpu"
-version = "0.19.4"
+version = "0.19.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbd7311dbd2abcfebaabf1841a2824ed7c8be443a0f29166e5d3c6a53a762c01"
+dependencies = [
+ "arrayvec",
+ "cfg-if",
+ "cfg_aliases 0.1.1",
+ "js-sys",
+ "log",
+ "naga 0.19.2",
+ "parking_lot",
+ "profiling",
+ "raw-window-handle 0.6.2",
+ "smallvec",
+ "static_assertions",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+ "wgpu-core 0.19.4",
+ "wgpu-hal 0.19.5",
+ "wgpu-types 0.19.2",
+]
+
+[[package]]
+name = "wgpu"
+version = "23.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbd7311dbd2abcfebaabf1841a2824ed7c8be443a0f29166e5d3c6a53a762c01"
+checksum = "80f70000db37c469ea9d67defdc13024ddf9a5f1b89cb2941b812ad7cde1735a"
 dependencies = [
  "arrayvec",
- "cfg-if",
  "cfg_aliases 0.1.1",
+ "document-features",
  "js-sys",
  "log",
- "naga",
+ "naga 23.1.0",
  "parking_lot",
  "profiling",
  "raw-window-handle 0.6.2",
@@ -14659,9 +15821,9 @@ dependencies = [
  "wasm-bindgen",
  "wasm-bindgen-futures",
  "web-sys",
- "wgpu-core",
- "wgpu-hal",
- "wgpu-types",
+ "wgpu-core 23.0.1",
+ "wgpu-hal 23.0.1",
+ "wgpu-types 23.0.0",
 ]
 
 [[package]]
@@ -14671,13 +15833,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "28b94525fc99ba9e5c9a9e24764f2bc29bad0911a7446c12f446a8277369bf3a"
 dependencies = [
  "arrayvec",
- "bit-vec",
- "bitflags 2.6.0",
+ "bit-vec 0.6.3",
+ "bitflags 2.9.0",
  "cfg_aliases 0.1.1",
- "codespan-reporting",
- "indexmap 2.7.0",
+ "codespan-reporting 0.11.1",
+ "indexmap 2.9.0",
  "log",
- "naga",
+ "naga 0.19.2",
  "once_cell",
  "parking_lot",
  "profiling",
@@ -14686,8 +15848,33 @@ dependencies = [
  "smallvec",
  "thiserror 1.0.69",
  "web-sys",
- "wgpu-hal",
- "wgpu-types",
+ "wgpu-hal 0.19.5",
+ "wgpu-types 0.19.2",
+]
+
+[[package]]
+name = "wgpu-core"
+version = "23.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d63c3c478de8e7e01786479919c8769f62a22eec16788d8c2ac77ce2c132778a"
+dependencies = [
+ "arrayvec",
+ "bit-vec 0.8.0",
+ "bitflags 2.9.0",
+ "cfg_aliases 0.1.1",
+ "document-features",
+ "indexmap 2.9.0",
+ "log",
+ "naga 23.1.0",
+ "once_cell",
+ "parking_lot",
+ "profiling",
+ "raw-window-handle 0.6.2",
+ "rustc-hash 1.1.0",
+ "smallvec",
+ "thiserror 1.0.69",
+ "wgpu-hal 23.0.1",
+ "wgpu-types 23.0.0",
 ]
 
 [[package]]
@@ -14698,26 +15885,26 @@ checksum = "bfabcfc55fd86611a855816326b2d54c3b2fd7972c27ce414291562650552703"
 dependencies = [
  "android_system_properties",
  "arrayvec",
- "ash",
- "bit-set",
- "bitflags 2.6.0",
+ "ash 0.37.3+1.3.251",
+ "bit-set 0.5.3",
+ "bitflags 2.9.0",
  "block",
  "cfg_aliases 0.1.1",
  "core-graphics-types 0.1.3",
  "d3d12",
- "glow",
- "glutin_wgl_sys",
+ "glow 0.13.1",
+ "glutin_wgl_sys 0.5.0",
  "gpu-alloc",
- "gpu-allocator",
- "gpu-descriptor",
+ "gpu-allocator 0.25.0",
+ "gpu-descriptor 0.2.4",
  "hassle-rs",
  "js-sys",
  "khronos-egl",
  "libc",
  "libloading 0.8.6",
  "log",
- "metal",
- "naga",
+ "metal 0.27.0",
+ "naga 0.19.2",
  "ndk-sys 0.5.0+25.2.9519653",
  "objc",
  "once_cell",
@@ -14731,17 +15918,73 @@ dependencies = [
  "thiserror 1.0.69",
  "wasm-bindgen",
  "web-sys",
- "wgpu-types",
+ "wgpu-types 0.19.2",
  "winapi",
 ]
 
+[[package]]
+name = "wgpu-hal"
+version = "23.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89364b8a0b211adc7b16aeaf1bd5ad4a919c1154b44c9ce27838213ba05fd821"
+dependencies = [
+ "android_system_properties",
+ "arrayvec",
+ "ash 0.38.0+1.3.281",
+ "bit-set 0.8.0",
+ "bitflags 2.9.0",
+ "block",
+ "bytemuck",
+ "cfg_aliases 0.1.1",
+ "core-graphics-types 0.1.3",
+ "glow 0.14.2",
+ "glutin_wgl_sys 0.6.1",
+ "gpu-alloc",
+ "gpu-allocator 0.27.0",
+ "gpu-descriptor 0.3.1",
+ "js-sys",
+ "khronos-egl",
+ "libc",
+ "libloading 0.8.6",
+ "log",
+ "metal 0.29.0",
+ "naga 23.1.0",
+ "ndk-sys 0.5.0+25.2.9519653",
+ "objc",
+ "once_cell",
+ "parking_lot",
+ "profiling",
+ "range-alloc",
+ "raw-window-handle 0.6.2",
+ "renderdoc-sys",
+ "rustc-hash 1.1.0",
+ "smallvec",
+ "thiserror 1.0.69",
+ "wasm-bindgen",
+ "web-sys",
+ "wgpu-types 23.0.0",
+ "windows 0.58.0",
+ "windows-core 0.58.0",
+]
+
 [[package]]
 name = "wgpu-types"
 version = "0.19.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b671ff9fb03f78b46ff176494ee1ebe7d603393f42664be55b64dc8d53969805"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.9.0",
+ "js-sys",
+ "web-sys",
+]
+
+[[package]]
+name = "wgpu-types"
+version = "23.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "610f6ff27778148c31093f3b03abc4840f9636d58d597ca2f5977433acfe0068"
+dependencies = [
+ "bitflags 2.9.0",
  "js-sys",
  "web-sys",
 ]
@@ -14755,36 +15998,36 @@ dependencies = [
  "either",
  "home",
  "once_cell",
- "rustix",
+ "rustix 0.38.44",
 ]
 
 [[package]]
 name = "which"
-version = "7.0.1"
+version = "7.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb4a9e33648339dc1642b0e36e21b3385e6148e289226f657c809dee59df5028"
+checksum = "2774c861e1f072b3aadc02f8ba886c26ad6321567ecc294c935434cad06f1283"
 dependencies = [
  "either",
  "env_home",
- "rustix",
+ "rustix 0.38.44",
  "winsafe",
 ]
 
 [[package]]
 name = "whoami"
-version = "1.5.2"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d"
+checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7"
 dependencies = [
- "redox_syscall",
+ "redox_syscall 0.5.11",
  "wasite",
 ]
 
 [[package]]
 name = "widestring"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"
+checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
 
 [[package]]
 name = "wifi-scanner"
@@ -14932,12 +16175,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ca21a92a9cae9bf4ccae5cf8368dce0837100ddf6e6d57936749e85f152f6247"
 dependencies = [
  "windows-implement 0.59.0",
- "windows-interface 0.59.0",
+ "windows-interface 0.59.1",
  "windows-link",
- "windows-result 0.3.1",
+ "windows-result 0.3.2",
  "windows-strings 0.3.1",
 ]
 
+[[package]]
+name = "windows-core"
+version = "0.61.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
+dependencies = [
+ "windows-implement 0.60.0",
+ "windows-interface 0.59.1",
+ "windows-link",
+ "windows-result 0.3.2",
+ "windows-strings 0.4.0",
+]
+
 [[package]]
 name = "windows-future"
 version = "0.1.1"
@@ -14956,7 +16212,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -14967,7 +16223,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -14978,7 +16234,18 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -14989,7 +16256,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -15000,25 +16267,25 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "windows-interface"
-version = "0.59.0"
+version = "0.59.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "windows-link"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3"
+checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
 
 [[package]]
 name = "windows-numerics"
@@ -15030,24 +16297,13 @@ dependencies = [
  "windows-link",
 ]
 
-[[package]]
-name = "windows-registry"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
-dependencies = [
- "windows-result 0.2.0",
- "windows-strings 0.1.0",
- "windows-targets 0.52.6",
-]
-
 [[package]]
 name = "windows-registry"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
 dependencies = [
- "windows-result 0.3.1",
+ "windows-result 0.3.2",
  "windows-strings 0.3.1",
  "windows-targets 0.53.0",
 ]
@@ -15072,9 +16328,9 @@ dependencies = [
 
 [[package]]
 name = "windows-result"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189"
+checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
 dependencies = [
  "windows-link",
 ]
@@ -15098,6 +16354,15 @@ dependencies = [
  "windows-link",
 ]
 
+[[package]]
+name = "windows-strings"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
+dependencies = [
+ "windows-link",
+]
+
 [[package]]
 name = "windows-sys"
 version = "0.45.0"
@@ -15198,11 +16463,11 @@ dependencies = [
 
 [[package]]
 name = "windows-version"
-version = "0.1.1"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6998aa457c9ba8ff2fb9f13e9d2a930dabcea28f1d0ab94d687d8b3654844515"
+checksum = "e04a5c6627e310a23ad2358483286c7df260c964eb2d003d8efd6d0f4e79265c"
 dependencies = [
- "windows-targets 0.52.6",
+ "windows-link",
 ]
 
 [[package]]
@@ -15385,6 +16650,58 @@ version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
 
+[[package]]
+name = "winit"
+version = "0.30.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a809eacf18c8eca8b6635091543f02a5a06ddf3dad846398795460e6e0ae3cc0"
+dependencies = [
+ "ahash 0.8.11",
+ "android-activity",
+ "atomic-waker",
+ "bitflags 2.9.0",
+ "block2 0.5.1",
+ "bytemuck",
+ "calloop",
+ "cfg_aliases 0.2.1",
+ "concurrent-queue",
+ "core-foundation 0.9.4",
+ "core-graphics 0.23.2",
+ "cursor-icon",
+ "dpi",
+ "js-sys",
+ "libc",
+ "memmap2",
+ "ndk",
+ "objc2 0.5.2",
+ "objc2-app-kit 0.2.2",
+ "objc2-foundation 0.2.2",
+ "objc2-ui-kit 0.2.2",
+ "orbclient",
+ "percent-encoding",
+ "pin-project",
+ "raw-window-handle 0.6.2",
+ "redox_syscall 0.4.1",
+ "rustix 0.38.44",
+ "sctk-adwaita",
+ "smithay-client-toolkit",
+ "smol_str",
+ "tracing",
+ "unicode-segmentation",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-protocols",
+ "wayland-protocols-plasma",
+ "web-sys",
+ "web-time",
+ "windows-sys 0.52.0",
+ "x11-dl",
+ "x11rb",
+ "xkbcommon-dl",
+]
+
 [[package]]
 name = "winnow"
 version = "0.5.40"
@@ -15396,9 +16713,18 @@ dependencies = [
 
 [[package]]
 name = "winnow"
-version = "0.6.20"
+version = "0.6.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "winnow"
+version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
+checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10"
 dependencies = [
  "memchr",
 ]
@@ -15419,6 +16745,15 @@ version = "0.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
 
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.39.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
+dependencies = [
+ "bitflags 2.9.0",
+]
+
 [[package]]
 name = "write16"
 version = "1.0.0"
@@ -15433,9 +16768,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
 
 [[package]]
 name = "wry"
-version = "0.50.4"
+version = "0.50.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "804a7d1613bd699beccaa60f3b3c679acee21cebba1945a693f5eab95c08d1fa"
+checksum = "b19b78efae8b853c6c817e8752fc1dbf9cab8a8ffe9c30f399bd750ccf0f0730"
 dependencies = [
  "base64 0.22.1",
  "block2 0.6.0",
@@ -15446,7 +16781,7 @@ dependencies = [
  "gdkx11",
  "gtk",
  "html5ever",
- "http 1.2.0",
+ "http 1.3.1",
  "javascriptcore-rs",
  "jni",
  "kuchikiki",
@@ -15456,7 +16791,7 @@ dependencies = [
  "objc2-app-kit 0.3.0",
  "objc2-core-foundation",
  "objc2-foundation 0.3.0",
- "objc2-ui-kit",
+ "objc2-ui-kit 0.3.0",
  "objc2-web-kit",
  "once_cell",
  "percent-encoding",
@@ -15464,7 +16799,7 @@ dependencies = [
  "sha2",
  "soup3",
  "tao-macros",
- "thiserror 2.0.6",
+ "thiserror 2.0.12",
  "url",
  "webkit2gtk",
  "webkit2gtk-sys",
@@ -15505,6 +16840,27 @@ dependencies = [
  "pkg-config",
 ]
 
+[[package]]
+name = "x11rb"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
+dependencies = [
+ "as-raw-xcb-connection",
+ "gethostname",
+ "libc",
+ "libloading 0.8.6",
+ "once_cell",
+ "rustix 0.38.44",
+ "x11rb-protocol",
+]
+
+[[package]]
+name = "x11rb-protocol"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
+
 [[package]]
 name = "x25519-dalek"
 version = "2.0.1"
@@ -15547,27 +16903,32 @@ dependencies = [
  "bcder",
  "bytes",
  "chrono",
- "der 0.7.9",
+ "der",
  "hex",
  "pem",
  "ring",
- "signature 2.2.0",
- "spki 0.7.3",
+ "signature",
+ "spki",
  "thiserror 1.0.69",
  "zeroize",
 ]
 
 [[package]]
 name = "xattr"
-version = "1.3.1"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
+checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e"
 dependencies = [
  "libc",
- "linux-raw-sys",
- "rustix",
+ "rustix 1.0.5",
 ]
 
+[[package]]
+name = "xcursor"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61"
+
 [[package]]
 name = "xdg-home"
 version = "1.3.0"
@@ -15578,23 +16939,42 @@ dependencies = [
  "windows-sys 0.59.0",
 ]
 
+[[package]]
+name = "xkbcommon-dl"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5"
+dependencies = [
+ "bitflags 2.9.0",
+ "dlib",
+ "log",
+ "once_cell",
+ "xkeysym",
+]
+
+[[package]]
+name = "xkeysym"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
+
 [[package]]
 name = "xml-rs"
-version = "0.8.24"
+version = "0.8.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432"
+checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4"
 
 [[package]]
-name = "xmlparser"
-version = "0.13.6"
+name = "xmlwriter"
+version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
+checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
 
 [[package]]
 name = "xxhash-rust"
-version = "0.8.12"
+version = "0.8.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984"
+checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3"
 
 [[package]]
 name = "xz2"
@@ -15617,6 +16997,12 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd"
 
+[[package]]
+name = "yazi"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5"
+
 [[package]]
 name = "yoke"
 version = "0.7.5"
@@ -15637,7 +17023,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "synstructure 0.13.1",
 ]
 
@@ -15648,16 +17034,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725"
 dependencies = [
  "async-broadcast",
+ "async-executor",
+ "async-fs",
+ "async-io",
+ "async-lock",
  "async-process",
  "async-recursion",
+ "async-task",
  "async-trait",
+ "blocking",
  "enumflags2",
- "event-listener 5.3.1",
+ "event-listener 5.4.0",
  "futures-core",
  "futures-sink",
  "futures-util",
  "hex",
- "nix 0.29.0",
+ "nix",
  "ordered-stream",
  "rand 0.8.5",
  "serde",
@@ -15674,16 +17066,40 @@ dependencies = [
  "zvariant",
 ]
 
+[[package]]
+name = "zbus-lockstep"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ca2c5dceb099bddaade154055c926bb8ae507a18756ba1d8963fd7b51d8ed1d"
+dependencies = [
+ "zbus_xml",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus-lockstep-macros"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+ "zbus-lockstep",
+ "zbus_xml",
+ "zvariant",
+]
+
 [[package]]
 name = "zbus_macros"
 version = "4.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e"
 dependencies = [
- "proc-macro-crate 3.2.0",
+ "proc-macro-crate 3.3.0",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "zvariant_utils",
 ]
 
@@ -15698,14 +17114,41 @@ dependencies = [
  "zvariant",
 ]
 
+[[package]]
+name = "zbus_xml"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab3f374552b954f6abb4bd6ce979e6c9b38fb9d0cd7cc68a7d796e70c9f3a233"
+dependencies = [
+ "quick-xml 0.30.0",
+ "serde",
+ "static_assertions",
+ "zbus_names",
+ "zvariant",
+]
+
+[[package]]
+name = "zeno"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc0de2315dc13d00e5df3cd6b8d2124a6eaec6a2d4b6a1c5f37b7efad17fcc17"
+
 [[package]]
 name = "zerocopy"
 version = "0.7.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
 dependencies = [
- "byteorder",
- "zerocopy-derive",
+ "zerocopy-derive 0.7.35",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
+dependencies = [
+ "zerocopy-derive 0.8.24",
 ]
 
 [[package]]
@@ -15716,27 +17159,38 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "zerofrom"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
 dependencies = [
  "zerofrom-derive",
 ]
 
 [[package]]
 name = "zerofrom-derive"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "synstructure 0.13.1",
 ]
 
@@ -15757,7 +17211,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -15779,7 +17233,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -15796,18 +17250,16 @@ dependencies = [
 
 [[package]]
 name = "zip"
-version = "2.2.1"
+version = "2.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99d52293fc86ea7cf13971b3bb81eb21683636e7ae24c729cdaf1b7c4157a352"
+checksum = "1dcb24d0152526ae49b9b96c1dcf71850ca1e0b882e4e28ed898a93c41334744"
 dependencies = [
  "arbitrary",
  "crc32fast",
  "crossbeam-utils",
- "displaydoc",
  "flate2",
- "indexmap 2.7.0",
+ "indexmap 2.9.0",
  "memchr",
- "thiserror 2.0.6",
  "zopfli",
 ]
 
@@ -15838,27 +17290,27 @@ dependencies = [
 
 [[package]]
 name = "zstd"
-version = "0.13.2"
+version = "0.13.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
+checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
 dependencies = [
  "zstd-safe",
 ]
 
 [[package]]
 name = "zstd-safe"
-version = "7.2.1"
+version = "7.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
+checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
 dependencies = [
  "zstd-sys",
 ]
 
 [[package]]
 name = "zstd-sys"
-version = "2.0.13+zstd.1.5.6"
+version = "2.0.15+zstd.1.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa"
+checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
 dependencies = [
  "cc",
  "pkg-config",
@@ -15881,9 +17333,9 @@ dependencies = [
 
 [[package]]
 name = "zune-jpeg"
-version = "0.4.13"
+version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768"
+checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028"
 dependencies = [
  "zune-core",
 ]
@@ -15908,10 +17360,10 @@ version = "4.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449"
 dependencies = [
- "proc-macro-crate 3.2.0",
+ "proc-macro-crate 3.3.0",
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
  "zvariant_utils",
 ]
 
@@ -15923,5 +17375,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.98",
+ "syn 2.0.100",
 ]

+ 17 - 0
Cargo.toml

@@ -68,6 +68,15 @@ members = [
     "packages/dx-wire-format",
     "packages/logger",
     "packages/config-macros",
+    "packages/native",
+    "packages/asset-resolver",
+
+    # Playwright tests
+    "packages/playwright-tests/liveview",
+    "packages/playwright-tests/web",
+    "packages/playwright-tests/fullstack",
+    "packages/playwright-tests/suspense-carousel",
+    "packages/playwright-tests/nested-suspense",
 
     # manganis
     "packages/manganis/manganis",
@@ -150,6 +159,8 @@ dioxus-fullstack-protocol = { path = "packages/fullstack-protocol", version = "0
 dioxus_server_macro = { path = "packages/server-macro", version = "0.6.2", default-features = false }
 dioxus-dx-wire-format = { path = "packages/dx-wire-format", version = "0.6.2" }
 dioxus-logger = { path = "packages/logger", version = "0.6.2" }
+dioxus-native = { path = "packages/native", version = "0.6.2" }
+dioxus-asset-resolver = { path = "packages/asset-resolver", version = "0.6.2" }
 dioxus-config-macros = { path = "packages/config-macros", version = "0.6.3" }
 const-serialize = { path = "packages/const-serialize", version = "0.6.2" }
 const-serialize-macro = { path = "packages/const-serialize-macro", version = "0.6.2" }
@@ -253,6 +264,8 @@ rayon = "1.2.0"
 wasmparser = "0.225.0"
 itertools = "0.14.0"
 macro-string = "0.1.3"
+walkdir = "2.5.0"
+url = "2.3.1"
 
 # desktop
 wry = { version = "0.50.1", default-features = false }
@@ -270,6 +283,10 @@ objc = { version = "0.2.7", features = ["exception"] }
 objc_id = "0.1.1"
 tray-icon = "0.19"
 
+# native
+keyboard-types = "0.7"
+winit = { version = "0.30.2", features = ["rwh_06"] }
+
 # disable debug symbols in dev builds - shouldn't matter for downstream crates but makes our binaries (examples, cli, etc) build faster
 [profile.dev]
 debug = 0

+ 1 - 1
example-projects/file-explorer/src/main.rs

@@ -36,7 +36,7 @@ fn app() -> Element {
             main {
                 for (dir_id, path) in files.read().path_names.iter().enumerate() {
                     {
-                        let path_end = path.components().last().map(|p|p.as_os_str()).unwrap_or(path.as_os_str()).to_string_lossy();
+                        let path_end = path.components().next_back().map(|p|p.as_os_str()).unwrap_or(path.as_os_str()).to_string_lossy();
                         let path = path.display();
                         rsx! {
                             div { class: "folder", key: "{path}",

+ 379 - 0
examples/assets/todomvc-native.css

@@ -0,0 +1,379 @@
+html,
+body, pre {
+    margin: 0;
+    padding: 0;
+}
+
+button {
+    margin: 0;
+    padding: 0;
+    border: 0;
+    background: none;
+    font-size: 100%;
+    vertical-align: baseline;
+    font-family: inherit;
+    font-weight: inherit;
+    color: inherit;
+    -webkit-appearance: none;
+    appearance: none;
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+}
+
+body {
+    font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
+    line-height: 1.4em;
+    background: #f5f5f5;
+    color: #4d4d4d;
+    min-width: 230px;
+    max-width: 550px;
+    margin: 0 auto;
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+    font-weight: 300;
+}
+
+:focus {
+    outline: 0;
+}
+
+.hidden {
+    display: none;
+}
+
+.todoapp {
+    background: #fff;
+    margin: 130px 0 40px 0;
+    position: relative;
+    box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
+}
+
+.todoapp input::-webkit-input-placeholder {
+    font-style: italic;
+    font-weight: 300;
+    color: #e6e6e6;
+}
+
+.todoapp input::-moz-placeholder {
+    font-style: italic;
+    font-weight: 300;
+    color: #e6e6e6;
+}
+
+.todoapp input::input-placeholder {
+    font-style: italic;
+    font-weight: 300;
+    color: #e6e6e6;
+}
+
+.todoapp h1 {
+    position: absolute;
+    top: -155px;
+    width: 100%;
+    font-size: 100px;
+    font-weight: 100;
+    text-align: center;
+    color: rgba(175, 47, 47, 1.0);
+    -webkit-text-rendering: optimizeLegibility;
+    -moz-text-rendering: optimizeLegibility;
+    text-rendering: optimizeLegibility;
+}
+
+.new-todo,
+.edit {
+    position: relative;
+    margin: 0;
+    width: 100%;
+    font-size: 24px;
+    font-family: inherit;
+    font-weight: inherit;
+    line-height: 1.4em;
+    border: 0;
+    color: inherit;
+    padding: 6px;
+    border: 1px solid #999;
+    box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
+    box-sizing: border-box;
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+}
+
+.new-todo {
+    padding: 16px 16px 16px 60px;
+    border: none;
+    background: rgba(0, 0, 0, 0.003);
+    box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
+}
+
+.main {
+    position: relative;
+    z-index: 2;
+    border-top: 1px solid #e6e6e6;
+}
+
+.toggle-all {
+    text-align: center;
+    border: none;
+    /* Mobile Safari */
+    opacity: 0;
+    position: absolute;
+}
+
+.toggle-all+label {
+    width: 60px;
+    height: 34px;
+    font-size: 0;
+    position: absolute;
+    top: -52px;
+    left: -13px;
+    -webkit-transform: rotate(90deg);
+    transform: rotate(90deg);
+}
+
+.toggle-all+label:before {
+    content: '❯';
+    font-size: 22px;
+    color: #e6e6e6;
+    padding: 10px 27px 10px 27px;
+}
+
+.toggle-all:checked+label:before {
+    color: #737373;
+}
+
+.todo-list {
+    margin: 0;
+    padding: 0;
+    list-style: none;
+}
+
+.todo-list li {
+    position: relative;
+    font-size: 24px;
+    border-bottom: 1px solid #ededed;
+}
+
+.todo-list li:last-child {
+    border-bottom: none;
+}
+
+.todo-list li.editing {
+    border-bottom: none;
+    padding: 0;
+}
+
+.todo-list li.editing .edit {
+    display: block;
+    width: 506px;
+    padding: 12px 16px;
+    margin: 0 0 0 43px;
+}
+
+.todo-list li.editing .view {
+    display: none;
+}
+
+.todo-list li .toggle {
+    text-align: center;
+    width: 40px;
+    /* auto, since non-WebKit browsers doesn't support input styling */
+    height: auto;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    margin: auto 0;
+    border: none;
+    /* Mobile Safari */
+    -webkit-appearance: none;
+    appearance: none;
+}
+
+.todo-list li .toggle {
+    opacity: 0;
+}
+
+.todo-list li .toggle+label {
+    /*
+		Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
+		IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
+	*/
+    background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
+    background-repeat: no-repeat;
+    background-position: center left;
+}
+
+.todo-list li .toggle:checked+label {
+    background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
+}
+
+.todo-list li label {
+    word-break: break-all;
+    padding: 15px 15px 15px 60px;
+    display: block;
+    line-height: 1.2;
+    transition: color 0.4s;
+}
+
+.todo-list li.completed label {
+    color: #d9d9d9;
+    text-decoration: line-through;
+}
+
+.todo-list li .destroy {
+    display: none;
+    position: absolute;
+    top: 0;
+    right: 10px;
+    bottom: 0;
+    width: 40px;
+    height: 40px;
+    margin: auto 0;
+    font-size: 30px;
+    color: #cc9a9a;
+    margin-bottom: 11px;
+    transition: color 0.2s ease-out;
+}
+
+.todo-list li .destroy:hover {
+    color: #af5b5e;
+}
+
+.todo-list li .destroy:after {
+    content: '×';
+}
+
+.todo-list li:hover .destroy {
+    display: block;
+}
+
+.todo-list li .edit {
+    display: none;
+}
+
+.todo-list li.editing:last-child {
+    margin-bottom: -1px;
+}
+
+.footer {
+    color: #777;
+    padding: 10px 15px;
+    height: 20px;
+    text-align: center;
+    border-top: 1px solid #e6e6e6;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.footer:before {
+    content: '';
+    position: absolute;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    height: 50px;
+    overflow: hidden;
+    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6, 0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6, 0 17px 2px -6px rgba(0, 0, 0, 0.2);
+}
+
+.todo-count {
+    float: left;
+    text-align: left;
+    white-space-collapse: preserve;
+}
+
+.todo-count strong {
+    font-weight: 300;
+}
+
+.filters {
+    margin: 0;
+    padding: 0;
+    list-style: none;
+    position: absolute;
+    right: 0;
+    left: 0;
+}
+
+.filters li {
+    display: inline-block;
+}
+
+.filters li a {
+    display: inline-block;
+    color: inherit;
+    margin: 3px;
+    padding: 3px 7px;
+    text-decoration: none;
+    border: 1px solid transparent;
+    border-radius: 3px;
+}
+
+.filters li a:hover {
+    border-color: rgba(175, 47, 47, 0.1);
+}
+
+.filters li a.selected {
+    border-color: rgba(175, 47, 47, 0.2);
+}
+
+.clear-completed,
+html .clear-completed:active {
+    float: right;
+    position: relative;
+    line-height: 20px;
+    text-decoration: none;
+    cursor: pointer;
+    display: inline-block;
+}
+
+.clear-completed:hover {
+    text-decoration: underline;
+}
+
+.info {
+    margin: 65px auto 0;
+    color: #bfbfbf;
+    font-size: 10px;
+    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+    text-align: center;
+}
+
+.info p {
+    line-height: 1;
+}
+
+.info a {
+    color: inherit;
+    text-decoration: none;
+    font-weight: 400;
+}
+
+.info a:hover {
+    text-decoration: underline;
+}
+
+
+/*
+	Hack to remove background from Mobile Safari.
+	Can't use it globally since it destroys checkboxes in Firefox
+*/
+
+@media screen and (-webkit-min-device-pixel-ratio:0) {
+    .toggle-all,
+    .todo-list li .toggle {
+        background: none;
+    }
+    .todo-list li .toggle {
+        height: 40px;
+    }
+}
+
+@media (max-width: 430px) {
+    .footer {
+        height: 50px;
+    }
+    .filters {
+        bottom: 10px;
+    }
+}

+ 1 - 1
examples/assets/todomvc.css

@@ -370,4 +370,4 @@ html .clear-completed:active {
     .filters {
         bottom: 10px;
     }
-}
+}

+ 269 - 0
examples/todomvc-native.rs

@@ -0,0 +1,269 @@
+//! The typical TodoMVC app, implemented in Dioxus.
+
+use dioxus::prelude::*;
+use std::collections::HashMap;
+
+const STYLE: Asset = asset!("/examples/assets/todomvc-native.css");
+
+fn main() {
+    dioxus::launch(app);
+}
+
+#[derive(PartialEq, Eq, Clone, Copy)]
+enum FilterState {
+    All,
+    Active,
+    Completed,
+}
+
+#[derive(Debug, PartialEq, Eq)]
+struct TodoItem {
+    id: u32,
+    checked: bool,
+    contents: String,
+}
+
+fn app() -> Element {
+    // We store the todos in a HashMap in a Signal.
+    // Each key is the id of the todo, and the value is the todo itself.
+    let mut todos = use_signal(HashMap::<u32, TodoItem>::new);
+
+    let filter = use_signal(|| FilterState::All);
+
+    // We use a simple memoized signal to calculate the number of active todos.
+    // Whenever the todos change, the active_todo_count will be recalculated.
+    let active_todo_count =
+        use_memo(move || todos.read().values().filter(|item| !item.checked).count());
+
+    // We use a memoized signal to filter the todos based on the current filter state.
+    // Whenever the todos or filter change, the filtered_todos will be recalculated.
+    // Note that we're only storing the IDs of the todos, not the todos themselves.
+    let filtered_todos = use_memo(move || {
+        let mut filtered_todos = todos
+            .read()
+            .iter()
+            .filter(|(_, item)| match filter() {
+                FilterState::All => true,
+                FilterState::Active => !item.checked,
+                FilterState::Completed => item.checked,
+            })
+            .map(|f| *f.0)
+            .collect::<Vec<_>>();
+
+        filtered_todos.sort_unstable();
+
+        filtered_todos
+    });
+
+    // Toggle all the todos to the opposite of the current state.
+    // If all todos are checked, uncheck them all. If any are unchecked, check them all.
+    let toggle_all = move |_| {
+        let check = active_todo_count() != 0;
+        for (_, item) in todos.write().iter_mut() {
+            item.checked = check;
+        }
+    };
+
+    rsx! {
+        document::Link { rel: "stylesheet", href: STYLE }
+        body {
+            section { class: "todoapp",
+                TodoHeader { todos }
+                section { class: "main",
+                    if !todos.read().is_empty() {
+                        input {
+                            id: "toggle-all",
+                            class: "toggle-all",
+                            r#type: "checkbox",
+                            onchange: toggle_all,
+                            checked: active_todo_count() == 0
+                        }
+                        label { r#for: "toggle-all" }
+                    }
+
+                    // Render the todos using the filtered_todos signal
+                    // We pass the ID into the TodoEntry component so it can access the todo from the todos signal.
+                    // Since we store the todos in a signal too, we also need to send down the todo list
+                    ul { class: "todo-list",
+                        for id in filtered_todos() {
+                            TodoEntry { key: "{id}", id, todos }
+                        }
+                    }
+
+                    // We only show the footer if there are todos.
+                    if !todos.read().is_empty() {
+                        ListFooter { active_todo_count, todos, filter }
+                    }
+                }
+            }
+
+            // A simple info footer
+            footer { class: "info",
+                p { "Double-click to edit a todo" }
+                p {
+                    "Created by "
+                    a { href: "http://github.com/jkelleyrtp/", "jkelleyrtp" }
+                }
+                p {
+                    "Part of "
+                    a { href: "http://todomvc.com", "TodoMVC" }
+                }
+            }
+        }
+    }
+}
+
+#[component]
+fn TodoHeader(mut todos: Signal<HashMap<u32, TodoItem>>) -> Element {
+    let mut draft = use_signal(|| "".to_string());
+    let mut todo_id = use_signal(|| 0);
+
+    let onkeydown = move |evt: KeyboardEvent| {
+        if evt.key() == Key::Enter && !draft.read().is_empty() {
+            let id = todo_id();
+            let todo = TodoItem {
+                id,
+                checked: false,
+                contents: draft.to_string(),
+            };
+            todos.write().insert(id, todo);
+            todo_id += 1;
+            draft.set("".to_string());
+            evt.prevent_default();
+        }
+    };
+
+    rsx! {
+        header { class: "header",
+            h1 { "todos" }
+            input {
+                class: "new-todo",
+                r#type: "text",
+                placeholder: "What needs to be done?",
+                value: "{draft}",
+                autofocus: "true",
+                oninput: move |evt| draft.set(evt.value()),
+                onkeydown
+            }
+        }
+    }
+}
+
+/// A single todo entry
+/// This takes the ID of the todo and the todos signal as props
+/// We can use these together to memoize the todo contents and checked state
+#[component]
+fn TodoEntry(mut todos: Signal<HashMap<u32, TodoItem>>, id: u32) -> Element {
+    let mut is_editing = use_signal(|| false);
+
+    // To avoid re-rendering this component when the todo list changes, we isolate our reads to memos
+    // This way, the component will only re-render when the contents of the todo change, or when the editing state changes.
+    // This does involve taking a local clone of the todo contents, but it allows us to prevent this component from re-rendering
+    let checked = use_memo(move || todos.read().get(&id).unwrap().checked);
+    let contents = use_memo(move || todos.read().get(&id).unwrap().contents.clone());
+
+    rsx! {
+        li {
+            // Dioxus lets you use if statements in rsx to conditionally render attributes
+            // These will get merged into a single class attribute
+            class: if checked() { "completed" },
+            class: if is_editing() { "editing" },
+
+            // Some basic controls for the todo
+            div { class: "view",
+                input {
+                    class: "toggle",
+                    r#type: "checkbox",
+                    id: "cbg-{id}",
+                    checked: "{checked}",
+                    oninput: move |evt| todos.write().get_mut(&id).unwrap().checked = evt.checked()
+                }
+                label {
+                    r#for: "cbg-{id}",
+                    onclick: move |evt| {
+                        is_editing.set(true);
+                        evt.prevent_default()
+                    },
+                    "{contents}"
+                }
+                button {
+                    class: "destroy",
+                    onclick: move |evt| {
+                        todos.write().remove(&id);
+                        evt.prevent_default();
+                    },
+                }
+            }
+
+            // Only render the actual input if we're editing
+            if is_editing() {
+                input {
+                    class: "edit",
+                    r#type: "text",
+                    value: "{contents}",
+                    oninput: move |evt| todos.write().get_mut(&id).unwrap().contents = evt.value(),
+                    autofocus: "true",
+                    onfocusout: move |_| is_editing.set(false),
+                    onkeydown: move |evt| {
+                        if matches!(evt.key(), Key::Enter | Key::Escape | Key::Tab) {
+                            evt.prevent_default();
+                            is_editing.set(false);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+#[component]
+fn ListFooter(
+    mut todos: Signal<HashMap<u32, TodoItem>>,
+    active_todo_count: ReadOnlySignal<usize>,
+    mut filter: Signal<FilterState>,
+) -> Element {
+    // We use a memoized signal to calculate whether we should show the "Clear completed" button.
+    // This will recompute whenever the todos change, and if the value is true, the button will be shown.
+    let show_clear_completed = use_memo(move || todos.read().values().any(|todo| todo.checked));
+
+    rsx! {
+        footer { class: "footer",
+            span { class: "todo-count",
+                strong { "{active_todo_count} " }
+                span {
+                    match active_todo_count() {
+                        1 => "item",
+                        _ => "items",
+                    },
+                    " left"
+                }
+            }
+            ul { class: "filters",
+                for (state , state_text , url) in [
+                    (FilterState::All, "All", "#/"),
+                    (FilterState::Active, "Active", "#/active"),
+                    (FilterState::Completed, "Completed", "#/completed"),
+                ] {
+                    li {
+                        a {
+                            href: url,
+                            class: if filter() == state { "selected" },
+                            onclick: move |evt| {
+                                filter.set(state);
+                                evt.prevent_default();
+                            },
+                            {state_text}
+                        }
+                    }
+                }
+            }
+            if show_clear_completed() {
+                button {
+                    class: "clear-completed",
+                    onclick: move |_| todos.write().retain(|_, todo| !todo.checked),
+                    "Clear completed"
+                }
+            }
+        }
+    }
+}

+ 24 - 0
packages/asset-resolver/Cargo.toml

@@ -0,0 +1,24 @@
+[package]
+name = "dioxus-asset-resolver"
+edition = "2021"
+version.workspace = true
+authors = ["Jonathan Kelley", "Dioxus Labs"]
+description = "Cross-platform asset resolver for manganis and dioxus"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/DioxusLabs/dioxus/"
+homepage = "https://dioxuslabs.com"
+keywords = ["web", "desktop", "mobile", "gui", "wasm"]
+rust-version = "1.79.0"
+
+[dependencies]
+http = { workspace = true }
+urlencoding = { workspace = true }
+infer = { workspace = true }
+thiserror = { workspace = true }
+dioxus-cli-config = { workspace = true }
+
+[target.'cfg(target_os = "android")'.dependencies]
+jni = "0.21.1"
+ndk = { version = "0.9.0" }
+ndk-sys = { version = "0.6.0" }
+ndk-context = { version = "0.1.1" }

+ 180 - 0
packages/asset-resolver/src/lib.rs

@@ -0,0 +1,180 @@
+use http::{status::StatusCode, Response};
+use std::path::{Path, PathBuf};
+
+#[non_exhaustive]
+#[derive(Debug, thiserror::Error)]
+pub enum AssetServeError {
+    #[error("Failed to infer mime type for asset: {0}")]
+    InferringMimeType(std::io::Error),
+
+    #[error("Failed to serve asset: {0}")]
+    IoError(#[from] std::io::Error),
+
+    #[error("Failed to construct response: {0}")]
+    ResponseError(#[from] http::Error),
+}
+
+pub fn serve_asset_from_raw_path(path: &str) -> Result<Response<Vec<u8>>, AssetServeError> {
+    // If the user provided a custom asset handler, then call it and return the response if the request was handled.
+    // The path is the first part of the URI, so we need to trim the leading slash.
+    let mut uri_path = PathBuf::from(
+        urlencoding::decode(path)
+            .expect("expected URL to be UTF-8 encoded")
+            .as_ref(),
+    );
+
+    // Attempt to serve from the asset dir on android using its loader
+    #[cfg(target_os = "android")]
+    {
+        if let Some(asset) = to_java_load_asset(path) {
+            return Ok(Response::builder()
+                .header("Content-Type", get_mime_by_ext(&uri_path))
+                .header("Access-Control-Allow-Origin", "*")
+                .body(asset)?);
+        }
+    }
+
+    // If the asset doesn't exist, or starts with `/assets/`, then we'll try to serve out of the bundle
+    // This lets us handle both absolute and relative paths without being too "special"
+    // It just means that our macos bundle is a little "special" because we need to place an `assets`
+    // dir in the `Resources` dir.
+    //
+    // If there's no asset root, we use the cargo manifest dir as the root, or the current dir
+    if !uri_path.exists() || uri_path.starts_with("/assets/") {
+        let bundle_root = get_asset_root();
+        let relative_path = uri_path.strip_prefix("/").unwrap();
+        uri_path = bundle_root.join(relative_path);
+    }
+
+    // If the asset exists, then we can serve it!
+    if uri_path.exists() {
+        let mime_type =
+            get_mime_from_path(&uri_path).map_err(AssetServeError::InferringMimeType)?;
+        let body = std::fs::read(uri_path)?;
+        return Ok(Response::builder()
+            .header("Content-Type", mime_type)
+            .header("Access-Control-Allow-Origin", "*")
+            .body(body)?);
+    }
+
+    Ok(Response::builder()
+        .status(StatusCode::NOT_FOUND)
+        .body(String::from("Not Found").into_bytes())?)
+}
+
+/// Get the asset directory, following tauri/cargo-bundles directory discovery approach
+///
+/// Currently supports:
+/// - [x] macOS
+/// - [x] iOS
+/// - [x] Windows
+/// - [x] Linux (appimage)
+/// - [ ] Linux (rpm)
+/// - [ ] Linux (deb)
+/// - [ ] Android
+#[allow(unused)]
+fn get_asset_root() -> PathBuf {
+    let cur_exe = std::env::current_exe().unwrap();
+
+    #[cfg(target_os = "macos")]
+    {
+        return cur_exe
+            .parent()
+            .unwrap()
+            .parent()
+            .unwrap()
+            .join("Resources");
+    }
+
+    // For all others, the structure looks like this:
+    // app.(exe/appimage)
+    //   main.exe
+    //   assets/
+    cur_exe.parent().unwrap().to_path_buf()
+}
+
+/// Get the mime type from a path-like string
+fn get_mime_from_path(asset: &Path) -> std::io::Result<&'static str> {
+    if asset.extension().is_some_and(|ext| ext == "svg") {
+        return Ok("image/svg+xml");
+    }
+
+    match infer::get_from_path(asset)?.map(|f| f.mime_type()) {
+        Some(f) if f != "text/plain" => Ok(f),
+        _other => Ok(get_mime_by_ext(asset)),
+    }
+}
+
+/// Get the mime type from a URI using its extension
+fn get_mime_by_ext(trimmed: &Path) -> &'static str {
+    match trimmed.extension().and_then(|e| e.to_str()) {
+        // The common assets are all utf-8 encoded
+        Some("js") => "text/javascript; charset=utf-8",
+        Some("css") => "text/css; charset=utf-8",
+        Some("json") => "application/json; charset=utf-8",
+        Some("svg") => "image/svg+xml; charset=utf-8",
+        Some("html") => "text/html; charset=utf-8",
+
+        // the rest... idk? probably not
+        Some("mjs") => "text/javascript; charset=utf-8",
+        Some("bin") => "application/octet-stream",
+        Some("csv") => "text/csv",
+        Some("ico") => "image/vnd.microsoft.icon",
+        Some("jsonld") => "application/ld+json",
+        Some("rtf") => "application/rtf",
+        Some("mp4") => "video/mp4",
+        // Assume HTML when a TLD is found for eg. `dioxus:://dioxuslabs.app` | `dioxus://hello.com`
+        Some(_) => "text/html; charset=utf-8",
+        // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
+        // using octet stream according to this:
+        None => "application/octet-stream",
+    }
+}
+
+#[cfg(target_os = "android")]
+pub(crate) fn to_java_load_asset(filepath: &str) -> Option<Vec<u8>> {
+    let normalized = filepath
+        .trim_start_matches("/assets/")
+        .trim_start_matches('/');
+
+    // in debug mode, the asset might be under `/data/local/tmp/dx/` - attempt to read it from there if it exists
+    #[cfg(debug_assertions)]
+    {
+        let path = dioxus_cli_config::android_session_cache_dir().join(normalized);
+        if path.exists() {
+            return std::fs::read(path).ok();
+        }
+    }
+
+    use std::ptr::NonNull;
+
+    let ctx = ndk_context::android_context();
+    let vm = unsafe { jni::JavaVM::from_raw(ctx.vm().cast()) }.unwrap();
+    let mut env = vm.attach_current_thread().unwrap();
+
+    // Query the Asset Manager
+    let asset_manager_ptr = env
+        .call_method(
+            unsafe { jni::objects::JObject::from_raw(ctx.context().cast()) },
+            "getAssets",
+            "()Landroid/content/res/AssetManager;",
+            &[],
+        )
+        .expect("Failed to get asset manager")
+        .l()
+        .expect("Failed to get asset manager as object");
+
+    unsafe {
+        let asset_manager =
+            ndk_sys::AAssetManager_fromJava(env.get_native_interface(), *asset_manager_ptr);
+
+        let asset_manager = ndk::asset::AssetManager::from_ptr(
+            NonNull::new(asset_manager).expect("Invalid asset manager"),
+        );
+
+        let cstr = std::ffi::CString::new(normalized).unwrap();
+
+        let mut asset = asset_manager.open(&cstr)?;
+        Some(asset.buffer().unwrap().to_vec())
+    }
+}

+ 4 - 4
packages/cli/src/build/builder.rs

@@ -108,7 +108,7 @@ impl Builder {
                                 self.expected_crates = *crate_count;
                             }
                         }
-                        BuildStage::InstallingTooling {} => {}
+                        BuildStage::InstallingTooling => {}
                         BuildStage::Compiling {
                             current,
                             total,
@@ -127,12 +127,12 @@ impl Builder {
                                 self.compile_start = Some(Instant::now());
                             }
                         }
-                        BuildStage::Bundling {} => {
+                        BuildStage::Bundling => {
                             self.complete_compile();
                             self.bundling_progress = 0.0;
                             self.bundle_start = Some(Instant::now());
                         }
-                        BuildStage::OptimizingWasm {} => {}
+                        BuildStage::OptimizingWasm => {}
                         BuildStage::CopyingAssets { current, total, .. } => {
                             self.bundling_progress = *current as f64 / *total as f64;
                         }
@@ -153,7 +153,7 @@ impl Builder {
                             self.expected_crates = 1;
                             self.bundling_progress = 0.0;
                         }
-                        BuildStage::RunningBindgen {} => {}
+                        BuildStage::RunningBindgen => {}
                         _ => {}
                     }
                 }

+ 13 - 4
packages/cli/src/build/prerender.rs

@@ -21,19 +21,20 @@ pub(crate) async fn pre_render_static_routes(server_exe: &Path) -> anyhow::Resul
     let address = &address;
     let port = &port;
 
-    tracing::info!("Running SSG at http://{address}:{port}");
+    tracing::info!("Running SSG at http://{address}:{port} for {server_exe:?}");
 
     // Run the server executable
     let _child = Command::new(server_exe)
         .env(dioxus_cli_config::SERVER_PORT_ENV, port)
         .env(dioxus_cli_config::SERVER_IP_ENV, address)
-        .stdout(std::process::Stdio::piped())
-        .stderr(std::process::Stdio::piped())
+        .current_dir(server_exe.parent().unwrap())
+        .stdout(std::process::Stdio::null())
+        .stderr(std::process::Stdio::null())
         .kill_on_drop(true)
         .spawn()?;
 
-    let reqwest_client = reqwest::Client::new();
     // Borrow reqwest_client so we only move the reference into the futures
+    let reqwest_client = reqwest::Client::new();
     let reqwest_client = &reqwest_client;
 
     // Get the routes from the `/static_routes` endpoint
@@ -42,8 +43,13 @@ pub(crate) async fn pre_render_static_routes(server_exe: &Path) -> anyhow::Resul
     // The server may take a few seconds to start up. Try fetching the route up to 5 times with a one second delay
     const RETRY_ATTEMPTS: usize = 5;
     for i in 0..=RETRY_ATTEMPTS {
+        tracing::debug!(
+            "Attempting to get static routes from server. Attempt {i} of {RETRY_ATTEMPTS}"
+        );
+
         let request = reqwest_client
             .post(format!("http://{address}:{port}/api/static_routes"))
+            .body("{}".to_string())
             .send()
             .await;
         match request {
@@ -75,12 +81,14 @@ pub(crate) async fn pre_render_static_routes(server_exe: &Path) -> anyhow::Resul
         .into_iter()
         .map(|route| async move {
             tracing::info!("Rendering {route} for SSG");
+
             // For each route, ping the server to force it to cache the response for ssg
             let request = reqwest_client
                 .get(format!("http://{address}:{port}{route}"))
                 .header("Accept", "text/html")
                 .send()
                 .await?;
+
             // If it takes longer than 30 seconds to resolve the route, log a warning
             let warning_task = tokio::spawn({
                 let route = route.clone();
@@ -89,6 +97,7 @@ pub(crate) async fn pre_render_static_routes(server_exe: &Path) -> anyhow::Resul
                     tracing::warn!("Route {route} has been rendering for 30 seconds");
                 }
             });
+
             // Wait for the streaming response to completely finish before continuing. We don't use the html it returns directly
             // because it may contain artifacts of intermediate streaming steps while the page is loading. The SSG app should write
             // the final clean HTML to the disk automatically after the request completes.

+ 1 - 1
packages/cli/src/dioxus_crate.rs

@@ -686,7 +686,7 @@ impl DioxusCrate {
                 .flatten()
                 .map(|dir| (dir.file_name(), dir.path()))
                 .sorted()
-                .last()
+                .next_back()
                 .map(|(_, path)| path.to_path_buf())
         });
 

+ 1 - 1
packages/cli/src/platform.rs

@@ -160,7 +160,7 @@ impl Platform {
     pub(crate) fn autodetect_from_cargo_feature(feature: &str) -> Option<Self> {
         match feature {
             "web" => Some(Platform::Web),
-            "desktop" => {
+            "desktop" | "native" => {
                 #[cfg(target_os = "macos")]
                 {
                     Some(Platform::MacOS)

+ 5 - 5
packages/cli/src/serve/mod.rs

@@ -23,11 +23,11 @@ pub(crate) use watcher::*;
 ///
 /// Platform specifics:
 /// -------------------
-/// - Web:         we need to attach a filesystem server to our devtools webserver to serve the project. We
-///                want to emulate GithubPages here since most folks are deploying there and expect things like
-///                basepath to match.
-/// - Desktop:     We spin up the dev server but without a filesystem server.
-/// - Mobile:      Basically the same as desktop.
+/// - Web: we need to attach a filesystem server to our devtools webserver to serve the project. We
+///   want to emulate GithubPages here since most folks are deploying there and expect things like
+///   basepath to match.
+/// - Desktop: We spin up the dev server but without a filesystem server.
+/// - Mobile: Basically the same as desktop.
 ///
 /// When fullstack is enabled, we'll also build for the `server` target and then hotreload the server.
 /// The "server" is special here since "fullstack" is functionally just an addition to the regular client

+ 7 - 7
packages/cli/src/serve/output.rs

@@ -521,7 +521,7 @@ impl Output {
         match &state.build_engine.stage {
             BuildStage::Initializing => lines.push("Initializing".yellow()),
             BuildStage::Starting { .. } => lines.push("Starting build".yellow()),
-            BuildStage::InstallingTooling {} => lines.push("Installing tooling".yellow()),
+            BuildStage::InstallingTooling => lines.push("Installing tooling".yellow()),
             BuildStage::Compiling {
                 current,
                 total,
@@ -532,13 +532,13 @@ impl Output {
                 lines.push(format!("{current}/{total} ").gray());
                 lines.push(krate.as_str().dark_gray())
             }
-            BuildStage::OptimizingWasm {} => lines.push("Optimizing wasm".yellow()),
-            BuildStage::SplittingBundle {} => lines.push("Splitting bundle".yellow()),
+            BuildStage::OptimizingWasm => lines.push("Optimizing wasm".yellow()),
+            BuildStage::SplittingBundle => lines.push("Splitting bundle".yellow()),
             BuildStage::CompressingAssets => lines.push("Compressing assets".yellow()),
-            BuildStage::PrerenderingRoutes {} => lines.push("Prerendering static routes".yellow()),
-            BuildStage::RunningBindgen {} => lines.push("Running wasm-bindgen".yellow()),
-            BuildStage::RunningGradle {} => lines.push("Running gradle assemble".yellow()),
-            BuildStage::Bundling {} => lines.push("Bundling app".yellow()),
+            BuildStage::PrerenderingRoutes => lines.push("Prerendering static routes".yellow()),
+            BuildStage::RunningBindgen => lines.push("Running wasm-bindgen".yellow()),
+            BuildStage::RunningGradle => lines.push("Running gradle assemble".yellow()),
+            BuildStage::Bundling => lines.push("Bundling app".yellow()),
             BuildStage::CopyingAssets {
                 current,
                 total,

+ 2 - 2
packages/cli/src/serve/server.rs

@@ -252,7 +252,7 @@ impl WebServer {
                     BuildStage::Failed => self.send_reload_failed().await,
                     BuildStage::Restarting => self.send_reload_start().await,
                     BuildStage::Initializing => {}
-                    BuildStage::InstallingTooling {} => {}
+                    BuildStage::InstallingTooling => {}
                     BuildStage::Compiling {
                         current,
                         total,
@@ -267,7 +267,7 @@ impl WebServer {
                             self.send_build_status().await;
                         }
                     }
-                    BuildStage::OptimizingWasm {} => {}
+                    BuildStage::OptimizingWasm => {}
                     BuildStage::Aborted => {}
                     BuildStage::CopyingAssets { .. } => {}
                     _ => {}

+ 1 - 0
packages/core/src/nodes.rs

@@ -378,6 +378,7 @@ pub struct Template {
 
 // Are identical static items merged in the current build. Rust doesn't have a cfg(merge_statics) attribute
 // so we have to check this manually
+#[allow(unpredictable_function_pointer_comparisons)]
 fn static_items_merged() -> bool {
     fn a() {}
     fn b() {}

+ 3 - 2
packages/desktop/Cargo.toml

@@ -20,6 +20,7 @@ dioxus-document = { workspace = true }
 dioxus-signals = { workspace = true, optional = true }
 dioxus-interpreter-js = { workspace = true, features = ["binary-protocol", "serialize"] }
 dioxus-cli-config = { workspace = true }
+dioxus-asset-resolver = { workspace = true }
 generational-box = { workspace = true }
 # hotreload only works on desktop platforms.... mobile is still wip
 dioxus-devtools = { workspace = true, optional = true }
@@ -44,13 +45,13 @@ tokio = { workspace = true, features = [
     "io-util",
 ], optional = true }
 webbrowser = "0.8.0"
-infer = "0.11.0"
+infer = { workspace = true }
 dunce = { workspace = true }
 slab = { workspace = true }
 rustc-hash = { workspace = true }
 dioxus-hooks = { workspace = true }
 futures-util = { workspace = true }
-urlencoding = "2.1.2"
+urlencoding = { workspace = true }
 async-trait = "0.1.68"
 tao = { workspace = true, features = ["rwh_05"] }
 once_cell = { workspace = true }

+ 3 - 167
packages/desktop/src/protocol.rs

@@ -2,10 +2,9 @@ use crate::document::NATIVE_EVAL_JS;
 use crate::{assets::*, webview::WebviewEdits};
 use dioxus_interpreter_js::unified_bindings::SLEDGEHAMMER_JS;
 use dioxus_interpreter_js::NATIVE_JS;
-use std::path::{Path, PathBuf};
 use wry::{
     http::{status::StatusCode, Request, Response},
-    RequestAsyncResponder, Result,
+    RequestAsyncResponder,
 };
 
 #[cfg(any(target_os = "android", target_os = "windows"))]
@@ -64,7 +63,7 @@ pub(super) fn desktop_handler(
         }
     }
 
-    match serve_asset(request) {
+    match dioxus_asset_resolver::serve_asset_from_raw_path(request.uri().path()) {
         Ok(res) => responder.respond(res),
         Err(_e) => responder.respond(
             Response::builder()
@@ -75,52 +74,6 @@ pub(super) fn desktop_handler(
     }
 }
 
-fn serve_asset(request: Request<Vec<u8>>) -> Result<Response<Vec<u8>>> {
-    // If the user provided a custom asset handler, then call it and return the response if the request was handled.
-    // The path is the first part of the URI, so we need to trim the leading slash.
-    let mut uri_path = PathBuf::from(
-        urlencoding::decode(request.uri().path())
-            .expect("expected URL to be UTF-8 encoded")
-            .as_ref(),
-    );
-
-    // Attempt to serve from the asset dir on android using its loader
-    #[cfg(target_os = "android")]
-    {
-        if let Some(asset) = to_java_load_asset(request.uri().path()) {
-            return Ok(Response::builder()
-                .header("Content-Type", get_mime_by_ext(&uri_path))
-                .header("Access-Control-Allow-Origin", "*")
-                .body(asset)?);
-        }
-    }
-
-    // If the asset doesn't exist, or starts with `/assets/`, then we'll try to serve out of the bundle
-    // This lets us handle both absolute and relative paths without being too "special"
-    // It just means that our macos bundle is a little "special" because we need to place an `assets`
-    // dir in the `Resources` dir.
-    //
-    // If there's no asset root, we use the cargo manifest dir as the root, or the current dir
-    if !uri_path.exists() || uri_path.starts_with("/assets/") {
-        let bundle_root = get_asset_root();
-        let relative_path = uri_path.strip_prefix("/").unwrap();
-        uri_path = bundle_root.join(relative_path);
-    }
-
-    // If the asset exists, then we can serve it!
-    if uri_path.exists() {
-        let mime_type = get_mime_from_path(&uri_path);
-        return Ok(Response::builder()
-            .header("Content-Type", mime_type?)
-            .header("Access-Control-Allow-Origin", "*")
-            .body(std::fs::read(uri_path)?)?);
-    }
-
-    Ok(Response::builder()
-        .status(StatusCode::NOT_FOUND)
-        .body(String::from("Not Found").into_bytes())?)
-}
-
 /// Build the index.html file we use for bootstrapping a new app
 ///
 /// We use wry/webview by building a special index.html that forms a bridge between the webview and your rust code
@@ -172,7 +125,7 @@ fn index_request(
 /// The arguments here:
 /// - root_name: the root element (by Id) that we stream edits into
 /// - headless: is this page being loaded but invisible? Important because not all windows are visible and the
-///             interpreter can't connect until the window is ready.
+///   interpreter can't connect until the window is ready.
 fn module_loader(root_id: &str, headless: bool) -> String {
     format!(
         r#"
@@ -203,120 +156,3 @@ fn module_loader(root_id: &str, headless: bool) -> String {
 "#
     )
 }
-
-/// Get the asset directory, following tauri/cargo-bundles directory discovery approach
-///
-/// Currently supports:
-/// - [x] macOS
-/// - [x] iOS
-/// - [x] Windows
-/// - [x] Linux (appimage)
-/// - [ ] Linux (rpm)
-/// - [ ] Linux (deb)
-/// - [ ] Android
-#[allow(unreachable_code)]
-fn get_asset_root() -> PathBuf {
-    let cur_exe = std::env::current_exe().unwrap();
-
-    #[cfg(target_os = "macos")]
-    {
-        return cur_exe
-            .parent()
-            .unwrap()
-            .parent()
-            .unwrap()
-            .join("Resources");
-    }
-
-    // For all others, the structure looks like this:
-    // app.(exe/appimage)
-    //   main.exe
-    //   assets/
-    cur_exe.parent().unwrap().to_path_buf()
-}
-
-/// Get the mime type from a path-like string
-fn get_mime_from_path(asset: &Path) -> Result<&'static str> {
-    if asset.extension().is_some_and(|ext| ext == "svg") {
-        return Ok("image/svg+xml");
-    }
-
-    match infer::get_from_path(asset)?.map(|f| f.mime_type()) {
-        Some(f) if f != "text/plain" => Ok(f),
-        _other => Ok(get_mime_by_ext(asset)),
-    }
-}
-
-/// Get the mime type from a URI using its extension
-fn get_mime_by_ext(trimmed: &Path) -> &'static str {
-    match trimmed.extension().and_then(|e| e.to_str()) {
-        // The common assets are all utf-8 encoded
-        Some("js") => "text/javascript; charset=utf-8",
-        Some("css") => "text/css; charset=utf-8",
-        Some("json") => "application/json; charset=utf-8",
-        Some("svg") => "image/svg+xml; charset=utf-8",
-        Some("html") => "text/html; charset=utf-8",
-
-        // the rest... idk? probably not
-        Some("mjs") => "text/javascript; charset=utf-8",
-        Some("bin") => "application/octet-stream",
-        Some("csv") => "text/csv",
-        Some("ico") => "image/vnd.microsoft.icon",
-        Some("jsonld") => "application/ld+json",
-        Some("rtf") => "application/rtf",
-        Some("mp4") => "video/mp4",
-        // Assume HTML when a TLD is found for eg. `dioxus:://dioxuslabs.app` | `dioxus://hello.com`
-        Some(_) => "text/html; charset=utf-8",
-        // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
-        // using octet stream according to this:
-        None => "application/octet-stream",
-    }
-}
-
-#[cfg(target_os = "android")]
-pub(crate) fn to_java_load_asset(filepath: &str) -> Option<Vec<u8>> {
-    let normalized = filepath
-        .trim_start_matches("/assets/")
-        .trim_start_matches('/');
-
-    // in debug mode, the asset might be under `/data/local/tmp/dx/` - attempt to read it from there if it exists
-    #[cfg(debug_assertions)]
-    {
-        let path = dioxus_cli_config::android_session_cache_dir().join(normalized);
-        if path.exists() {
-            return std::fs::read(path).ok();
-        }
-    }
-
-    use std::ptr::NonNull;
-
-    let ctx = ndk_context::android_context();
-    let vm = unsafe { jni::JavaVM::from_raw(ctx.vm().cast()) }.unwrap();
-    let mut env = vm.attach_current_thread().unwrap();
-
-    // Query the Asset Manager
-    let asset_manager_ptr = env
-        .call_method(
-            unsafe { jni::objects::JObject::from_raw(ctx.context().cast()) },
-            "getAssets",
-            "()Landroid/content/res/AssetManager;",
-            &[],
-        )
-        .expect("Failed to get asset manager")
-        .l()
-        .expect("Failed to get asset manager as object");
-
-    unsafe {
-        let asset_manager =
-            ndk_sys::AAssetManager_fromJava(env.get_native_interface(), *asset_manager_ptr);
-
-        let asset_manager = ndk::asset::AssetManager::from_ptr(
-            NonNull::new(asset_manager).expect("Invalid asset manager"),
-        );
-
-        let cstr = std::ffi::CString::new(normalized).unwrap();
-
-        let mut asset = asset_manager.open(&cstr)?;
-        Some(asset.buffer().unwrap().to_vec())
-    }
-}

+ 2 - 0
packages/dioxus/Cargo.toml

@@ -27,6 +27,7 @@ dioxus-desktop = { workspace = true, default-features = true, optional = true }
 dioxus-fullstack = { workspace = true, default-features = true, optional = true }
 dioxus-liveview = { workspace = true, optional = true }
 dioxus-ssr = { workspace = true, optional = true }
+dioxus-native = { workspace = true, optional = true }
 manganis = { workspace = true, features = ["dioxus"], optional = true }
 dioxus-logger = { workspace = true, optional = true }
 warnings = { workspace = true, optional = true }
@@ -66,6 +67,7 @@ web = ["dep:dioxus-web", "dioxus-fullstack?/web", "dioxus-config-macro/web", "de
 ssr = ["dep:dioxus-ssr", "dioxus-config-macro/ssr"]
 liveview = ["dep:dioxus-liveview", "dioxus-config-macro/liveview"]
 server = ["dioxus-fullstack?/axum", "dioxus-fullstack?/server", "ssr", "dioxus-liveview?/axum"]
+native = ["dep:dioxus-native"] # todo(jon): decompose the desktop crate such that "webview" is the default and native is opt-in
 
 # This feature just disables the no-renderer-enabled warning
 third-party-renderer = []

+ 164 - 140
packages/dioxus/src/launch.rs

@@ -6,10 +6,58 @@ use std::any::Any;
 
 use crate::prelude::*;
 
+/// Launch your Dioxus application with the given root component, context and config.
+/// The platform will be determined from cargo features.
+///
+/// For a builder API, see `LaunchBuilder` defined in the `dioxus` crate.
+///
+/// # Feature selection
+///
+/// - `web`: Enables the web platform.
+/// - `desktop`: Enables the desktop platform.
+/// - `mobile`: Enables the mobile (ios + android webview) platform.
+/// - `server`: Enables the server (axum + server-side-rendering) platform.
+/// - `liveview`: Enables the liveview (websocke) platform.
+/// - `native`: Enables the native (wgpu + winit renderer) platform.
+///
+/// Currently `native` is its own platform that is not compatible with desktop or mobile since it
+/// unifies both platforms into one. If "desktop" and "native" are enabled, then the native renderer
+/// will be used.
+///
+/// # Feature priority
+///
+/// If multiple renderers are enabled, the order of priority goes:
+///
+/// 1. liveview
+/// 2. server
+/// 3. native
+/// 4. desktop
+/// 5. mobile
+/// 6. web
+///
+/// However, we don't recommend enabling multiple renderers at the same time due to feature conflicts
+/// and bloating of the binary size.
+///
+/// # Example
+/// ```rust, no_run
+/// # use dioxus::prelude::*;
+///
+/// dioxus::launch(app);
+/// fn app() -> Element {
+///     rsx! {
+///         div { "Hello, world!" }
+///     }
+/// }
+/// ```
+pub fn launch(app: fn() -> Element) {
+    #[allow(deprecated)]
+    LaunchBuilder::new().launch(app)
+}
+
 /// A builder for a fullstack app.
 #[must_use]
 pub struct LaunchBuilder {
-    launch_fn: LaunchFn,
+    platform: KnownPlatform,
     contexts: Vec<ContextFn>,
     configs: Vec<Box<dyn Any>>,
 }
@@ -19,6 +67,16 @@ pub type LaunchFn = fn(fn() -> Element, Vec<ContextFn>, Vec<Box<dyn Any>>);
 /// A context function is a Send and Sync closure that returns a boxed trait object
 pub type ContextFn = Box<dyn Fn() -> Box<dyn Any> + Send + Sync + 'static>;
 
+enum KnownPlatform {
+    Web,
+    Desktop,
+    Mobile,
+    Server,
+    Liveview,
+    Native,
+    Other(LaunchFn),
+}
+
 #[allow(clippy::redundant_closure)] // clippy doesnt doesn't understand our coercion to fn
 impl LaunchBuilder {
     /// Create a new builder for your application. This will create a launch configuration for the current platform based on the features enabled on the `dioxus` crate.
@@ -38,9 +96,24 @@ impl LaunchBuilder {
         )
     )]
     pub fn new() -> LaunchBuilder {
+        let platform = if cfg!(feature = "liveview") {
+            KnownPlatform::Liveview
+        } else if cfg!(feature = "server") {
+            KnownPlatform::Server
+        } else if cfg!(feature = "native") {
+            KnownPlatform::Native
+        } else if cfg!(feature = "desktop") {
+            KnownPlatform::Desktop
+        } else if cfg!(feature = "mobile") {
+            KnownPlatform::Mobile
+        } else if cfg!(feature = "web") {
+            KnownPlatform::Web
+        } else {
+            panic!("No platform feature enabled. Please enable one of the following features: liveview, desktop, mobile, web, tui, fullstack to use the launch API.")
+        };
+
         LaunchBuilder {
-            // We can't use the `current_platform::launch` function directly because it may return ! or ()
-            launch_fn: |root, contexts, cfg| current_platform::launch(root, contexts, cfg),
+            platform,
             contexts: Vec::new(),
             configs: Vec::new(),
         }
@@ -51,7 +124,7 @@ impl LaunchBuilder {
     #[cfg_attr(docsrs, doc(cfg(feature = "web")))]
     pub fn web() -> LaunchBuilder {
         LaunchBuilder {
-            launch_fn: web_launch,
+            platform: KnownPlatform::Web,
             contexts: Vec::new(),
             configs: Vec::new(),
         }
@@ -62,7 +135,7 @@ impl LaunchBuilder {
     #[cfg_attr(docsrs, doc(cfg(feature = "desktop")))]
     pub fn desktop() -> LaunchBuilder {
         LaunchBuilder {
-            launch_fn: |root, contexts, cfg| dioxus_desktop::launch::launch(root, contexts, cfg),
+            platform: KnownPlatform::Desktop,
             contexts: Vec::new(),
             configs: Vec::new(),
         }
@@ -73,9 +146,7 @@ impl LaunchBuilder {
     #[cfg_attr(docsrs, doc(cfg(all(feature = "fullstack", feature = "server"))))]
     pub fn server() -> LaunchBuilder {
         LaunchBuilder {
-            launch_fn: |root, contexts, cfg| {
-                dioxus_fullstack::server::launch::launch(root, contexts, cfg)
-            },
+            platform: KnownPlatform::Server,
             contexts: Vec::new(),
             configs: Vec::new(),
         }
@@ -86,7 +157,7 @@ impl LaunchBuilder {
     #[cfg_attr(docsrs, doc(cfg(feature = "mobile")))]
     pub fn mobile() -> LaunchBuilder {
         LaunchBuilder {
-            launch_fn: |root, contexts, cfg| dioxus_mobile::launch_cfg(root, contexts, cfg),
+            platform: KnownPlatform::Mobile,
             contexts: Vec::new(),
             configs: Vec::new(),
         }
@@ -121,14 +192,12 @@ impl LaunchBuilder {
     /// ```
     pub fn custom(launch_fn: LaunchFn) -> LaunchBuilder {
         LaunchBuilder {
-            launch_fn,
+            platform: KnownPlatform::Other(launch_fn),
             contexts: vec![],
             configs: Vec::new(),
         }
     }
-}
 
-impl LaunchBuilder {
     /// Inject state into the root component's context that is created on the thread that the app is launched on.
     ///
     /// # Example
@@ -186,9 +255,7 @@ impl LaunchBuilder {
             .push(Box::new(move || Box::new(state.clone())));
         self
     }
-}
 
-impl LaunchBuilder {
     /// Provide a platform-specific config to the builder.
     ///
     /// # Example
@@ -211,13 +278,28 @@ impl LaunchBuilder {
         self
     }
 
-    fn launch_inner(self, app: fn() -> Element) {
+    /// Launch your application.
+    ///
+    #[allow(clippy::diverging_sub_expression)]
+    pub fn launch(self, app: fn() -> Element) {
+        let Self {
+            platform,
+            contexts,
+            configs,
+        } = self;
+
+        // Make sure to turn on the logger if the user specified the logger feaature
         #[cfg(feature = "logger")]
         dioxus_logger::initialize_default();
 
-        #[cfg(all(feature = "fullstack", any(feature = "desktop", feature = "mobile")))]
+        // Set any flags if we're running under fullstack
+        #[cfg(feature = "fullstack")]
         {
             use dioxus_fullstack::prelude::server_fn::client::{get_server_url, set_server_url};
+
+            // Make sure to set the server_fn endpoint if the user specified the fullstack feature
+            // We only set this on native targets
+            #[cfg(any(feature = "desktop", feature = "mobile", feature = "native"))]
             if get_server_url().is_empty() {
                 let serverurl = format!(
                     "http://{}:{}",
@@ -226,143 +308,85 @@ impl LaunchBuilder {
                     std::env::var("DIOXUS_DEVSERVER_PORT").unwrap_or_else(|_| "8080".to_string())
                 )
                 .leak();
+
                 set_server_url(serverurl);
             }
+
+            // If there is a base path set, call server functions from that base path
+            #[cfg(feature = "web")]
+            if let Some(base_path) = dioxus_cli_config::base_path() {
+                let base_path = base_path.trim_matches('/');
+                set_server_url(format!("{}/{}", get_server_url(), base_path).leak());
+            }
         }
 
-        let cfg = self.configs;
-        (self.launch_fn)(app, self.contexts, cfg);
-    }
+        // If native is specified, we override the webview launcher
+        #[cfg(feature = "native")]
+        if matches!(platform, KnownPlatform::Native) {
+            return dioxus_native::launch_cfg(app, contexts, configs);
+        }
 
-    /// Launch your application.
-    pub fn launch(self, app: fn() -> Element) {
-        self.launch_inner(app);
-    }
-}
+        #[cfg(feature = "mobile")]
+        if matches!(platform, KnownPlatform::Mobile) {
+            return dioxus_mobile::launch_bindings::launch(app, contexts, configs);
+        }
 
-/// Re-export the platform we expect the user wants
-///
-/// If multiple platforms are enabled, we use this priority (from highest to lowest):
-/// - `fullstack`
-/// - `desktop`
-/// - `mobile`
-/// - `web`
-/// - `liveview`
-mod current_platform {
-    #[cfg(all(feature = "fullstack", feature = "server"))]
-    pub use dioxus_fullstack::server::launch::*;
-
-    #[cfg(all(
-        feature = "desktop",
-        not(all(feature = "fullstack", feature = "server"))
-    ))]
-    pub use dioxus_desktop::launch::*;
-
-    #[cfg(all(
-        feature = "mobile",
-        not(feature = "desktop"),
-        not(all(feature = "fullstack", feature = "server"))
-    ))]
-    pub use dioxus_mobile::launch_bindings::*;
-
-    #[cfg(all(
-        feature = "web",
-        not(all(feature = "fullstack", feature = "server")),
-        not(all(feature = "server")),
-        not(feature = "desktop"),
-        not(feature = "mobile"),
-    ))]
-    pub fn launch(
-        root: fn() -> dioxus_core::Element,
-        contexts: Vec<super::ContextFn>,
-        platform_config: Vec<Box<dyn std::any::Any>>,
-    ) {
-        super::web_launch(root, contexts, platform_config);
-    }
+        #[cfg(feature = "desktop")]
+        if matches!(platform, KnownPlatform::Desktop) {
+            return dioxus_desktop::launch::launch(app, contexts, configs);
+        }
 
-    #[cfg(all(
-        feature = "liveview",
-        not(all(feature = "fullstack", feature = "server")),
-        not(all(feature = "server")),
-        not(feature = "desktop"),
-        not(feature = "mobile"),
-        not(feature = "web"),
-    ))]
-    pub use dioxus_liveview::launch::*;
-
-    #[cfg(not(any(
-        feature = "liveview",
-        all(feature = "fullstack", feature = "server"),
-        all(feature = "server"),
-        feature = "desktop",
-        feature = "mobile",
-        feature = "web",
-    )))]
-    pub fn launch(
-        root: fn() -> dioxus_core::Element,
-        contexts: Vec<super::ContextFn>,
-        platform_config: Vec<Box<dyn std::any::Any>>,
-    ) {
-        #[cfg(feature = "third-party-renderer")]
-        panic!("No first party renderer feature enabled. It looks like you are trying to use a third party renderer. You will need to use the launch function from the third party renderer crate.");
+        #[cfg(feature = "server")]
+        if matches!(platform, KnownPlatform::Server) {
+            return dioxus_fullstack::server::launch::launch(app, contexts, configs);
+        }
 
-        panic!("No platform feature enabled. Please enable one of the following features: liveview, desktop, mobile, web, tui, fullstack to use the launch API.")
-    }
-}
+        #[cfg(feature = "web")]
+        if matches!(platform, KnownPlatform::Web) {
+            // If the server feature is enabled, launch the client with hydration enabled
+            #[cfg(feature = "fullstack")]
+            {
+                let platform_config = configs
+                    .into_iter()
+                    .find_map(|cfg| cfg.downcast::<dioxus_web::Config>().ok())
+                    .unwrap_or_default()
+                    .hydrate(true);
 
-pub fn launch(app: fn() -> Element) {
-    #[allow(deprecated)]
-    LaunchBuilder::new().launch(app)
-}
+                let mut vdom = dioxus_core::VirtualDom::new(app);
+                for context in contexts {
+                    vdom.insert_any_root_context(context());
+                }
 
-#[cfg(feature = "web")]
-fn web_launch(
-    root: fn() -> dioxus_core::Element,
-    contexts: Vec<super::ContextFn>,
-    platform_config: Vec<Box<dyn std::any::Any>>,
-) {
-    // If the server feature is enabled, launch the client with hydration enabled
-    #[cfg(feature = "fullstack")]
-    {
-        let platform_config = platform_config
-            .into_iter()
-            .find_map(|cfg| cfg.downcast::<dioxus_web::Config>().ok())
-            .unwrap_or_default()
-            .hydrate(true);
-
-        // If there is a base path set, call server functions from that base path
-        if let Some(base_path) = dioxus_cli_config::web_base_path() {
-            let base_path = base_path.trim_matches('/');
-            crate::prelude::server_fn::client::set_server_url(
-                format!(
-                    "{}/{}",
-                    crate::prelude::server_fn::client::get_server_url(),
-                    base_path
-                )
-                .leak(),
-            );
-        }
+                #[cfg(feature = "document")]
+                {
+                    use dioxus_fullstack::document;
+                    let document = std::rc::Rc::new(document::web::FullstackWebDocument)
+                        as std::rc::Rc<dyn crate::prelude::document::Document>;
+                    vdom.provide_root_context(document);
+                }
 
-        let factory = move || {
-            let mut vdom = dioxus_core::VirtualDom::new(root);
-            for context in contexts {
-                vdom.insert_any_root_context(context());
+                return dioxus_web::launch::launch_virtual_dom(vdom, platform_config);
             }
 
-            #[cfg(feature = "document")]
-            {
-                #[cfg(feature = "fullstack")]
-                use dioxus_fullstack::document;
-                let document = std::rc::Rc::new(document::web::FullstackWebDocument)
-                    as std::rc::Rc<dyn crate::prelude::document::Document>;
-                vdom.provide_root_context(document);
-            }
-            vdom
-        };
+            #[cfg(not(any(feature = "fullstack")))]
+            return dioxus_web::launch::launch(app, contexts, configs);
+        }
 
-        dioxus_web::launch::launch_virtual_dom(factory(), platform_config)
-    }
+        #[cfg(feature = "liveview")]
+        if matches!(platform, KnownPlatform::Liveview) {
+            return dioxus_liveview::launch::launch(app, contexts, configs);
+        }
+
+        // If the platform is not one of the above, then we assume it's a custom platform
+        if let KnownPlatform::Other(launch_fn) = platform {
+            return launch_fn(app, contexts, configs);
+        }
 
-    #[cfg(not(any(feature = "fullstack")))]
-    dioxus_web::launch::launch(root, contexts, platform_config);
+        // If we're here, then we have no platform feature enabled and third-party-renderer is enabled
+        if cfg!(feature = "third-party-renderer") {
+            panic!("No first party renderer feature enabled. It looks like you are trying to use a third party renderer. You will need to use the launch function from the third party renderer crate.");
+        }
+
+        panic!("No platform feature enabled. Please enable one of the following features: liveview, desktop, mobile, web, tui, fullstack to use the launch API.")
+    }
 }

+ 1 - 1
packages/hooks/Cargo.toml

@@ -21,7 +21,7 @@ tracing = { workspace = true }
 slab = { workspace = true }
 futures-util = { workspace = true}
 generational-box.workspace = true
-rustversion = "1.0.17"
+rustversion = { workspace = true }
 warnings = { workspace = true }
 
 [dev-dependencies]

+ 1 - 1
packages/html/Cargo.toml

@@ -28,7 +28,7 @@ tokio = { workspace = true, features = ["fs", "io-util"], optional = true }
 futures-channel = { workspace = true }
 serde_json = { version = "1", optional = true }
 tracing.workspace = true
-rustversion = "1.0.17"
+rustversion = { workspace = true }
 
 [build-dependencies]
 lazy-js-bundle = { workspace = true }

+ 1 - 0
packages/isrg/Cargo.toml

@@ -16,3 +16,4 @@ thiserror = { workspace = true }
 rustc-hash = { workspace = true }
 lru  = { workspace = true }
 tracing = { workspace = true }
+walkdir = { workspace = true }

+ 1 - 1
packages/isrg/src/config.rs

@@ -37,7 +37,7 @@ impl IncrementalRendererConfig {
             static_dir: PathBuf::from("./static"),
             memory_cache_limit: 10000,
             invalidate_after: None,
-            clear_cache: true,
+            clear_cache: false,
             pre_render: false,
             #[cfg(not(target_arch = "wasm32"))]
             map_path: None,

+ 20 - 2
packages/isrg/src/fs_cache.rs

@@ -55,8 +55,26 @@ impl FileSystemCache {
     }
 
     pub fn clear(&mut self) {
-        // clear the static directory
-        let _ = std::fs::remove_dir_all(&self.static_dir);
+        // clear the static directory of index.html files contained within folders
+        for entry in std::fs::read_dir(&self.static_dir)
+            .into_iter()
+            .flatten()
+            .flatten()
+        {
+            if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) {
+                for entry in walkdir::WalkDir::new(entry.path()).into_iter().flatten() {
+                    if entry.file_type().is_file() {
+                        if let Some(fnmae) = entry.file_name().to_str() {
+                            if fnmae.ends_with(".html") {
+                                if let Err(err) = std::fs::remove_file(entry.path()) {
+                                    tracing::error!("Failed to remove file: {}", err);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
 
     pub fn invalidate(&mut self, route: &str) {

+ 59 - 0
packages/native/Cargo.toml

@@ -0,0 +1,59 @@
+[package]
+name = "dioxus-native"
+version = { workspace = true }
+authors = ["Jonathan Kelley", "Nico Burns"]
+edition = "2021"
+description = "Native renderer for Dioxus based on blitz"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/DioxusLabs/dioxus/"
+homepage = "https://dioxuslabs.com/learn/0.6/getting_started"
+keywords = ["dom", "ui", "gui", "react"]
+
+
+[features]
+default = ["accessibility", "hot-reload", "menu", "tracing", "net", "svg"]
+svg = ["blitz-dom/svg", "blitz-renderer-vello/svg"]
+net = ["dep:tokio", "dep:blitz-net"]
+accessibility = ["blitz-shell/accessibility", "blitz-dom/accessibility"]
+menu = ["blitz-shell/menu"]
+tracing = ["dep:tracing", "blitz-shell/tracing", "blitz-dom/tracing"]
+hot-reload = ["dep:dioxus-cli-config", "dep:dioxus-devtools"]
+autofocus = []
+
+[dependencies]
+# Blitz dependencies
+blitz-renderer-vello = { version = "0.1.0-alpha.1", default-features = false }
+blitz-dom = { version = "0.1.0-alpha.1", default-features = false }
+blitz-net = { version = "0.1.0-alpha.1", optional = true }
+blitz-traits = { version = "0.1.0-alpha.1" }
+blitz-shell = { version = "0.1.0-alpha.1", default-features = false }
+# blitz-renderer-vello = { git = "https://github.com/dioxuslabs/blitz", rev="c1a7ecf06d1760a268e0046dc0e43f6c796ddc3c", default-features = false }
+# blitz-dom = { git = "https://github.com/dioxuslabs/blitz", rev="c1a7ecf06d1760a268e0046dc0e43f6c796ddc3c", default-features = false }
+# blitz-net = { git = "https://github.com/dioxuslabs/blitz", rev="c1a7ecf06d1760a268e0046dc0e43f6c796ddc3c", optional = true }
+# blitz-traits = { git = "https://github.com/dioxuslabs/blitz", rev="c1a7ecf06d1760a268e0046dc0e43f6c796ddc3c" }
+# blitz-shell = { git = "https://github.com/dioxuslabs/blitz", rev="c1a7ecf06d1760a268e0046dc0e43f6c796ddc3c", default-features = false }
+
+# DioxusLabs dependencies
+dioxus-core = { workspace = true }
+dioxus-html = { workspace = true }
+dioxus-asset-resolver = { workspace = true }
+dioxus-cli-config = { workspace = true, optional = true }
+dioxus-devtools = { workspace = true, optional = true }
+dioxus-history = { workspace = true }
+dioxus-document = { workspace = true }
+
+# Windowing & Input
+winit = { workspace = true }
+keyboard-types = { workspace = true }
+
+# IO & Networking
+tokio = { workspace = true, features = ["rt-multi-thread"], optional = true }
+
+# Other dependencies
+tracing = { workspace = true, optional = true }
+rustc-hash = { workspace = true }
+futures-util = { workspace = true }
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"]

+ 80 - 0
packages/native/src/assets.rs

@@ -0,0 +1,80 @@
+use blitz_shell::BlitzShellNetCallback;
+use std::sync::Arc;
+
+use blitz_dom::{
+    net::{CssHandler, ImageHandler, Resource},
+    util::ImageType,
+    BaseDocument,
+};
+use blitz_shell::BlitzShellEvent;
+use blitz_traits::net::{NetCallback, NetProvider};
+use winit::event_loop::EventLoopProxy;
+
+use crate::NodeId;
+
+pub struct DioxusNativeNetProvider {
+    callback: Arc<dyn NetCallback<Data = Resource> + 'static>,
+    inner_net_provider: Arc<dyn NetProvider<Data = Resource> + 'static>,
+}
+impl DioxusNativeNetProvider {
+    pub fn shared(proxy: EventLoopProxy<BlitzShellEvent>) -> Arc<dyn NetProvider<Data = Resource>> {
+        Arc::new(Self::new(proxy)) as Arc<dyn NetProvider<Data = Resource>>
+    }
+
+    pub fn new(proxy: EventLoopProxy<BlitzShellEvent>) -> Self {
+        let net_callback = BlitzShellNetCallback::shared(proxy);
+        let net_provider = blitz_net::Provider::shared(net_callback.clone());
+        Self {
+            callback: net_callback,
+            inner_net_provider: net_provider,
+        }
+    }
+}
+
+impl NetProvider for DioxusNativeNetProvider {
+    type Data = Resource;
+
+    fn fetch(
+        &self,
+        doc_id: usize,
+        request: blitz_traits::net::Request,
+        handler: blitz_traits::net::BoxedHandler<Self::Data>,
+    ) {
+        if request.url.scheme() == "dioxus" {
+            match dioxus_asset_resolver::serve_asset_from_raw_path(request.url.path()) {
+                Ok(res) => {
+                    tracing::trace!("fetching asset  from file system success {request:#?}");
+                    handler.bytes(doc_id, res.into_body().into(), self.callback.clone())
+                }
+                Err(_) => {
+                    tracing::warn!("fetching asset  from file system error {request:#?}");
+                }
+            }
+        } else {
+            self.inner_net_provider.fetch(doc_id, request, handler);
+        }
+    }
+}
+
+pub fn fetch_linked_stylesheet(doc: &BaseDocument, node_id: NodeId, queued_url: String) {
+    let url = doc.resolve_url(&queued_url);
+    doc.net_provider.fetch(
+        doc.id(),
+        blitz_traits::net::Request::get(url.clone()),
+        Box::new(CssHandler {
+            node: node_id,
+            source_url: url,
+            guard: doc.guard.clone(),
+            provider: doc.net_provider.clone(),
+        }),
+    );
+}
+
+pub fn fetch_image(doc: &BaseDocument, node_id: usize, queued_image: String) {
+    let src = doc.resolve_url(&queued_image);
+    doc.net_provider.fetch(
+        doc.id(),
+        blitz_traits::net::Request::get(src),
+        Box::new(ImageHandler::new(node_id, ImageType::Image)),
+    );
+}

+ 70 - 0
packages/native/src/contexts.rs

@@ -0,0 +1,70 @@
+use blitz_shell::BlitzShellEvent;
+use dioxus_document::{Document, NoOpDocument};
+use winit::{event_loop::EventLoopProxy, window::WindowId};
+
+use crate::DioxusNativeEvent;
+
+pub struct DioxusNativeDocument {
+    pub(crate) proxy: EventLoopProxy<BlitzShellEvent>,
+    pub(crate) window: WindowId,
+}
+
+impl DioxusNativeDocument {
+    pub(crate) fn new(proxy: EventLoopProxy<BlitzShellEvent>, window: WindowId) -> Self {
+        Self { proxy, window }
+    }
+}
+
+impl Document for DioxusNativeDocument {
+    fn eval(&self, _js: String) -> dioxus_document::Eval {
+        NoOpDocument.eval(_js)
+    }
+
+    fn create_head_element(
+        &self,
+        name: &str,
+        attributes: &[(&str, String)],
+        contents: Option<String>,
+    ) {
+        let window = self.window;
+        _ = self.proxy.send_event(BlitzShellEvent::embedder_event(
+            DioxusNativeEvent::CreateHeadElement {
+                name: name.to_string(),
+                attributes: attributes
+                    .iter()
+                    .map(|(name, value)| (name.to_string(), value.clone()))
+                    .collect(),
+                contents,
+                window,
+            },
+        ));
+    }
+
+    fn set_title(&self, title: String) {
+        self.create_head_element("title", &[], Some(title));
+    }
+
+    fn create_meta(&self, props: dioxus_document::MetaProps) {
+        let attributes = props.attributes();
+        self.create_head_element("meta", &attributes, None);
+    }
+
+    fn create_script(&self, props: dioxus_document::ScriptProps) {
+        let attributes = props.attributes();
+        self.create_head_element("script", &attributes, props.script_contents().ok());
+    }
+
+    fn create_style(&self, props: dioxus_document::StyleProps) {
+        let attributes = props.attributes();
+        self.create_head_element("style", &attributes, props.style_contents().ok());
+    }
+
+    fn create_link(&self, props: dioxus_document::LinkProps) {
+        let attributes = props.attributes();
+        self.create_head_element("link", &attributes, None);
+    }
+
+    fn create_head_component(&self) -> bool {
+        true
+    }
+}

+ 166 - 0
packages/native/src/dioxus_application.rs

@@ -0,0 +1,166 @@
+use blitz_renderer_vello::BlitzVelloRenderer;
+use blitz_shell::BlitzApplication;
+use dioxus_core::{ScopeId, VirtualDom};
+use dioxus_history::{History, MemoryHistory};
+use std::{collections::HashSet, rc::Rc};
+use winit::application::ApplicationHandler;
+use winit::event::{StartCause, WindowEvent};
+use winit::event_loop::{ActiveEventLoop, EventLoopProxy};
+use winit::window::WindowId;
+
+use crate::{
+    assets::DioxusNativeNetProvider, contexts::DioxusNativeDocument,
+    mutation_writer::MutationWriter, BlitzShellEvent, DioxusDocument, DioxusNativeEvent,
+    WindowConfig,
+};
+
+pub struct DioxusNativeApplication {
+    pending_vdom: Option<VirtualDom>,
+    inner: BlitzApplication<DioxusDocument, BlitzVelloRenderer>,
+    proxy: EventLoopProxy<BlitzShellEvent>,
+}
+
+impl DioxusNativeApplication {
+    pub fn new(proxy: EventLoopProxy<BlitzShellEvent>, vdom: VirtualDom) -> Self {
+        Self {
+            pending_vdom: Some(vdom),
+            inner: BlitzApplication::new(proxy.clone()),
+            proxy,
+        }
+    }
+
+    pub fn add_window(&mut self, window_config: WindowConfig<DioxusDocument, BlitzVelloRenderer>) {
+        self.inner.add_window(window_config);
+    }
+
+    fn handle_blitz_shell_event(
+        &mut self,
+        event_loop: &ActiveEventLoop,
+        event: &DioxusNativeEvent,
+    ) {
+        match event {
+            #[cfg(all(
+                feature = "hot-reload",
+                debug_assertions,
+                not(target_os = "android"),
+                not(target_os = "ios")
+            ))]
+            DioxusNativeEvent::DevserverEvent(event) => match event {
+                dioxus_devtools::DevserverMsg::HotReload(hotreload_message) => {
+                    for window in self.inner.windows.values_mut() {
+                        dioxus_devtools::apply_changes(&window.doc.vdom, hotreload_message);
+                        window.poll();
+                    }
+                }
+                dioxus_devtools::DevserverMsg::Shutdown => event_loop.exit(),
+                dioxus_devtools::DevserverMsg::FullReloadStart => {}
+                dioxus_devtools::DevserverMsg::FullReloadFailed => {}
+                dioxus_devtools::DevserverMsg::FullReloadCommand => {}
+            },
+
+            DioxusNativeEvent::CreateHeadElement {
+                name,
+                attributes,
+                contents,
+                window,
+            } => {
+                if let Some(window) = self.inner.windows.get_mut(window) {
+                    window.doc.create_head_element(name, attributes, contents);
+                    window.poll();
+                }
+            }
+
+            // Suppress unused variable warning
+            #[cfg(not(all(
+                feature = "hot-reload",
+                debug_assertions,
+                not(target_os = "android"),
+                not(target_os = "ios")
+            )))]
+            _ => {
+                let _ = event_loop;
+                let _ = event;
+            }
+        }
+    }
+}
+
+impl ApplicationHandler<BlitzShellEvent> for DioxusNativeApplication {
+    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
+        tracing::debug!("Injecting document provider into all windows");
+        let vdom = self.pending_vdom.take().unwrap();
+
+        #[cfg(feature = "net")]
+        let net_provider = {
+            let proxy = self.proxy.clone();
+            let net_provider = DioxusNativeNetProvider::shared(proxy);
+            Some(net_provider)
+        };
+
+        #[cfg(not(feature = "net"))]
+        let net_provider = None;
+
+        // Create document + window from the baked virtualdom
+        let doc = DioxusDocument::new(vdom, net_provider);
+        let window = WindowConfig::new(doc);
+
+        // little hack since View::init is not public - fix this once alpha-2 is out
+        let old_windows = self.inner.windows.keys().copied().collect::<HashSet<_>>();
+        self.add_window(window);
+        self.inner.resumed(event_loop);
+        let new_windows = self.inner.windows.keys().cloned().collect::<HashSet<_>>();
+
+        // todo(jon): we should actually mess with the pending windows instead of passing along the contexts
+        for window_id in new_windows.difference(&old_windows) {
+            let window = self.inner.windows.get_mut(window_id).unwrap();
+            window.doc.vdom.in_runtime(|| {
+                let shared: Rc<dyn dioxus_document::Document> =
+                    Rc::new(DioxusNativeDocument::new(self.proxy.clone(), *window_id));
+                ScopeId::ROOT.provide_context(shared);
+            });
+
+            // Add history
+            let history_provider: Rc<dyn History> = Rc::new(MemoryHistory::default());
+            window
+                .doc
+                .vdom
+                .in_runtime(|| ScopeId::ROOT.provide_context(history_provider));
+
+            // Queue rebuild
+            let mut writer = MutationWriter::new(&mut window.doc.inner, &mut window.doc.vdom_state);
+            window.doc.vdom.rebuild(&mut writer);
+            drop(writer);
+
+            // And then request redraw
+            window.request_redraw();
+        }
+    }
+
+    fn suspended(&mut self, event_loop: &ActiveEventLoop) {
+        self.inner.suspended(event_loop);
+    }
+
+    fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
+        self.inner.new_events(event_loop, cause);
+    }
+
+    fn window_event(
+        &mut self,
+        event_loop: &ActiveEventLoop,
+        window_id: WindowId,
+        event: WindowEvent,
+    ) {
+        self.inner.window_event(event_loop, window_id, event);
+    }
+
+    fn user_event(&mut self, event_loop: &ActiveEventLoop, event: BlitzShellEvent) {
+        match event {
+            BlitzShellEvent::Embedder(event) => {
+                if let Some(event) = event.downcast_ref::<DioxusNativeEvent>() {
+                    self.handle_blitz_shell_event(event_loop, event);
+                }
+            }
+            event => self.inner.user_event(event_loop, event),
+        }
+    }
+}

+ 564 - 0
packages/native/src/dioxus_document.rs

@@ -0,0 +1,564 @@
+//! Integration between Dioxus and Blitz
+
+use std::{any::Any, collections::HashMap, rc::Rc, sync::Arc};
+
+use blitz_dom::{
+    local_name, namespace_url,
+    net::Resource,
+    node::{Attribute, NodeSpecificData},
+    ns, Atom, BaseDocument, ElementNodeData, Node, NodeData, QualName, DEFAULT_CSS,
+};
+
+use blitz_traits::{net::NetProvider, ColorScheme, Document, DomEvent, DomEventData, Viewport};
+use dioxus_core::{ElementId, Event, VirtualDom};
+use dioxus_html::{set_event_converter, FormValue, PlatformEventData};
+use futures_util::{pin_mut, FutureExt};
+
+use super::event_handler::{BlitzKeyboardData, NativeClickData, NativeConverter, NativeFormData};
+use crate::mutation_writer::{DioxusState, MutationWriter};
+use crate::NodeId;
+
+pub(crate) fn qual_name(local_name: &str, namespace: Option<&str>) -> QualName {
+    QualName {
+        prefix: None,
+        ns: namespace.map(Atom::from).unwrap_or(ns!(html)),
+        local: Atom::from(local_name),
+    }
+}
+
+pub struct DioxusDocument {
+    pub(crate) vdom: VirtualDom,
+    pub(crate) vdom_state: DioxusState,
+    pub(crate) inner: BaseDocument,
+
+    #[allow(unused)]
+    pub(crate) html_element_id: NodeId,
+    #[allow(unused)]
+    pub(crate) head_element_id: NodeId,
+    #[allow(unused)]
+    pub(crate) body_element_id: NodeId,
+    #[allow(unused)]
+    pub(crate) main_element_id: NodeId,
+}
+
+// Implement DocumentLike and required traits for DioxusDocument
+
+impl AsRef<BaseDocument> for DioxusDocument {
+    fn as_ref(&self) -> &BaseDocument {
+        &self.inner
+    }
+}
+impl AsMut<BaseDocument> for DioxusDocument {
+    fn as_mut(&mut self) -> &mut BaseDocument {
+        &mut self.inner
+    }
+}
+impl From<DioxusDocument> for BaseDocument {
+    fn from(doc: DioxusDocument) -> BaseDocument {
+        doc.inner
+    }
+}
+impl Document for DioxusDocument {
+    type Doc = BaseDocument;
+
+    fn poll(&mut self, mut cx: std::task::Context) -> bool {
+        {
+            let fut = self.vdom.wait_for_work();
+            pin_mut!(fut);
+
+            match fut.poll_unpin(&mut cx) {
+                std::task::Poll::Ready(_) => {}
+                std::task::Poll::Pending => return false,
+            }
+        }
+
+        let mut writer = MutationWriter::new(&mut self.inner, &mut self.vdom_state);
+        self.vdom.render_immediate(&mut writer);
+
+        true
+    }
+
+    fn id(&self) -> usize {
+        self.inner.id()
+    }
+
+    fn handle_event(&mut self, event: &mut DomEvent) {
+        let chain = self.inner.node_chain(event.target);
+
+        set_event_converter(Box::new(NativeConverter {}));
+
+        let renderer_event = event.clone();
+
+        let mut prevent_default = false;
+        let mut stop_propagation = false;
+
+        match &event.data {
+            DomEventData::MouseMove(data)
+            | DomEventData::MouseDown(data)
+            | DomEventData::MouseUp(data) => {
+                let click_event_data = wrap_event_data(NativeClickData(data.clone()));
+
+                for node_id in chain.clone().into_iter() {
+                    let node = &self.inner.tree()[node_id];
+                    let dioxus_id = node.element_data().and_then(DioxusDocument::dioxus_id);
+
+                    if let Some(id) = dioxus_id {
+                        let click_event = Event::new(click_event_data.clone(), true);
+                        self.vdom
+                            .runtime()
+                            .handle_event(event.name(), click_event.clone(), id);
+                        prevent_default |= !click_event.default_action_enabled();
+                        stop_propagation |= !click_event.propagates();
+                    }
+
+                    if !event.bubbles || stop_propagation {
+                        break;
+                    }
+                }
+            }
+
+            DomEventData::Click(data) => {
+                let click_event_data = wrap_event_data(NativeClickData(data.clone()));
+
+                for node_id in chain.clone().into_iter() {
+                    let node = &self.inner.tree()[node_id];
+                    let dioxus_id = node.element_data().and_then(DioxusDocument::dioxus_id);
+                    let mut trigger_label = false;
+
+                    if let Some(id) = dioxus_id {
+                        // Trigger click event
+                        let click_event = Event::new(click_event_data.clone(), true);
+                        self.vdom
+                            .runtime()
+                            .handle_event("click", click_event.clone(), id);
+                        prevent_default |= !click_event.default_action_enabled();
+                        stop_propagation |= !click_event.propagates();
+
+                        if !prevent_default {
+                            let mut default_event =
+                                DomEvent::new(node_id, renderer_event.data.clone());
+                            self.inner.as_mut().handle_event(&mut default_event);
+                            prevent_default = true;
+
+                            let element = self.inner.tree()[node_id].element_data().unwrap();
+                            trigger_label = element.name.local == *"label";
+
+                            //TODO Check for other inputs which trigger input event on click here, eg radio
+                            let triggers_input_event = element.name.local == local_name!("input")
+                                && element.attr(local_name!("type")) == Some("checkbox");
+                            if triggers_input_event {
+                                let form_data =
+                                    wrap_event_data(self.input_event_form_data(&chain, element));
+                                let input_event = Event::new(form_data, true);
+                                self.vdom.runtime().handle_event("input", input_event, id);
+                            }
+                        }
+                    }
+
+                    //Clicking labels triggers click, and possibly input event, of bound input
+                    if trigger_label {
+                        if let Some((dioxus_id, node_id)) = self.label_bound_input_element(node_id)
+                        {
+                            let click_event = Event::new(click_event_data.clone(), true);
+                            self.vdom.runtime().handle_event(
+                                "click",
+                                click_event.clone(),
+                                dioxus_id,
+                            );
+
+                            // Handle default DOM event
+                            if click_event.default_action_enabled() {
+                                let DomEventData::Click(event) = &renderer_event.data else {
+                                    unreachable!();
+                                };
+                                let input_click_data = self
+                                    .inner
+                                    .get_node(node_id)
+                                    .unwrap()
+                                    .synthetic_click_event(event.mods);
+                                let mut default_event = DomEvent::new(node_id, input_click_data);
+                                self.inner.as_mut().handle_event(&mut default_event);
+                                prevent_default = true;
+
+                                // TODO: Generated click events should bubble separately
+                                // prevent_default |= !click_event.default_action_enabled();
+
+                                //TODO Check for other inputs which trigger input event on click here, eg radio
+                                let element_data = self
+                                    .inner
+                                    .get_node(node_id)
+                                    .unwrap()
+                                    .element_data()
+                                    .unwrap();
+                                let triggers_input_event =
+                                    element_data.attr(local_name!("type")) == Some("checkbox");
+                                let form_data = wrap_event_data(
+                                    self.input_event_form_data(&chain, element_data),
+                                );
+                                if triggers_input_event {
+                                    let input_event = Event::new(form_data, true);
+                                    self.vdom.runtime().handle_event(
+                                        "input",
+                                        input_event,
+                                        dioxus_id,
+                                    );
+                                }
+                            }
+                        }
+                    }
+
+                    if !event.bubbles || stop_propagation {
+                        break;
+                    }
+                }
+            }
+
+            DomEventData::KeyPress(kevent) => {
+                let key_event_data = wrap_event_data(BlitzKeyboardData(kevent.clone()));
+
+                for node_id in chain.clone().into_iter() {
+                    let node = &self.inner.tree()[node_id];
+                    let dioxus_id = node.element_data().and_then(DioxusDocument::dioxus_id);
+                    println!("{} {:?}", node_id, dioxus_id);
+
+                    if let Some(id) = dioxus_id {
+                        if kevent.state.is_pressed() {
+                            // Handle keydown event
+                            let event = Event::new(key_event_data.clone(), true);
+                            self.vdom
+                                .runtime()
+                                .handle_event("keydown", event.clone(), id);
+                            prevent_default |= !event.default_action_enabled();
+                            stop_propagation |= !event.propagates();
+
+                            if !prevent_default && kevent.text.is_some() {
+                                // Handle keypress event
+                                let event = Event::new(key_event_data.clone(), true);
+                                self.vdom
+                                    .runtime()
+                                    .handle_event("keypress", event.clone(), id);
+                                prevent_default |= !event.default_action_enabled();
+                                stop_propagation |= !event.propagates();
+
+                                if !prevent_default {
+                                    // Handle default DOM event
+                                    let mut default_event =
+                                        DomEvent::new(node_id, renderer_event.data.clone());
+                                    self.inner.as_mut().handle_event(&mut default_event);
+                                    prevent_default = true;
+
+                                    // Handle input event
+                                    let element =
+                                        self.inner.tree()[node_id].element_data().unwrap();
+                                    let triggers_input_event = &element.name.local == "input"
+                                        && matches!(
+                                            element.attr(local_name!("type")),
+                                            None | Some("text" | "password" | "email" | "search")
+                                        );
+                                    if triggers_input_event {
+                                        let form_data = wrap_event_data(dbg!(
+                                            self.input_event_form_data(&chain, element)
+                                        ));
+                                        let input_event = Event::new(form_data, true);
+                                        self.vdom.runtime().handle_event("input", input_event, id);
+                                    }
+                                }
+                            }
+                        } else {
+                            // Handle keyup event
+                            let event = Event::new(key_event_data.clone(), true);
+                            self.vdom.runtime().handle_event("keyup", event.clone(), id);
+                            prevent_default |= !event.default_action_enabled();
+                            stop_propagation |= !event.propagates();
+                        }
+                    }
+
+                    if !event.bubbles || stop_propagation {
+                        break;
+                    }
+                }
+            }
+
+            DomEventData::Hover => {}
+
+            // TODO: Implement IME and Hover events handling
+            DomEventData::Ime(_) => {}
+        }
+
+        if !event.cancelable || !prevent_default {
+            self.inner.as_mut().handle_event(event);
+        }
+    }
+}
+
+fn wrap_event_data<T: Any>(value: T) -> Rc<dyn Any> {
+    Rc::new(PlatformEventData::new(Box::new(value)))
+}
+
+impl DioxusDocument {
+    /// Generate the FormData from an input event
+    /// Currently only cares about input checkboxes
+    pub fn input_event_form_data(
+        &self,
+        parent_chain: &[usize],
+        element_node_data: &ElementNodeData,
+    ) -> NativeFormData {
+        let parent_form = parent_chain.iter().find_map(|id| {
+            let node = self.inner.get_node(*id)?;
+            let element_data = node.element_data()?;
+            if element_data.name.local == local_name!("form") {
+                Some(node)
+            } else {
+                None
+            }
+        });
+        let values = if let Some(parent_form) = parent_form {
+            let mut values = HashMap::<String, FormValue>::new();
+            for form_input in self.input_descendents(parent_form).into_iter() {
+                // Match html behaviour here. To be included in values:
+                // - input must have a name
+                // - if its an input, we only include it if checked
+                // - if value is not specified, it defaults to 'on'
+                if let Some(name) = form_input.attr(local_name!("name")) {
+                    if form_input.attr(local_name!("type")) == Some("checkbox")
+                        && form_input
+                            .element_data()
+                            .and_then(|data| data.checkbox_input_checked())
+                            .unwrap_or(false)
+                    {
+                        let value = form_input
+                            .attr(local_name!("value"))
+                            .unwrap_or("on")
+                            .to_string();
+                        values.insert(name.to_string(), FormValue(vec![value]));
+                    }
+                }
+            }
+            values
+        } else {
+            Default::default()
+        };
+        let value = match &element_node_data.node_specific_data {
+            NodeSpecificData::CheckboxInput(checked) => checked.to_string(),
+            NodeSpecificData::TextInput(input_data) => input_data.editor.text().to_string(),
+            _ => element_node_data
+                .attr(local_name!("value"))
+                .unwrap_or_default()
+                .to_string(),
+        };
+
+        NativeFormData { value, values }
+    }
+
+    /// Collect all the inputs which are descendents of a given node
+    fn input_descendents(&self, node: &Node) -> Vec<&Node> {
+        node.children
+            .iter()
+            .flat_map(|id| {
+                let mut res = Vec::<&Node>::new();
+                let Some(n) = self.inner.get_node(*id) else {
+                    return res;
+                };
+                let Some(element_data) = n.element_data() else {
+                    return res;
+                };
+                if element_data.name.local == local_name!("input") {
+                    res.push(n);
+                }
+                res.extend(self.input_descendents(n).iter());
+                res
+            })
+            .collect()
+    }
+
+    pub fn new(
+        vdom: VirtualDom,
+        net_provider: Option<Arc<dyn NetProvider<Data = Resource>>>,
+    ) -> Self {
+        let viewport = Viewport::new(0, 0, 1.0, ColorScheme::Light);
+        let mut doc = BaseDocument::new(viewport);
+
+        // Set net provider
+        if let Some(net_provider) = net_provider {
+            doc.set_net_provider(net_provider);
+        }
+
+        // Create a virtual "html" element to act as the root element, as we won't necessarily
+        // have a single root otherwise, while the rest of blitz requires that we do
+        let html_element_id = doc.create_node(NodeData::Element(ElementNodeData::new(
+            qual_name("html", None),
+            Vec::new(),
+        )));
+        let root_node_id = doc.root_node().id;
+        let html_element = doc.get_node_mut(html_element_id).unwrap();
+        html_element.parent = Some(root_node_id);
+        let root_node = doc.get_node_mut(root_node_id).unwrap();
+        root_node.children.push(html_element_id);
+
+        // Create the body element
+        let body_element_id = doc.create_node(NodeData::Element(ElementNodeData::new(
+            qual_name("body", None),
+            Vec::new(),
+        )));
+        let html_element = doc.get_node_mut(html_element_id).unwrap();
+        html_element.children.push(body_element_id);
+        let body_element = doc.get_node_mut(body_element_id).unwrap();
+        body_element.parent = Some(html_element_id);
+
+        // Create another virtual element to hold the root <div id="main"></div> under the html element
+        let main_element_id = doc.create_node(NodeData::Element(ElementNodeData::new(
+            qual_name("div", Some("id")),
+            vec![blitz_dom::node::Attribute {
+                name: qual_name("id", None),
+                value: "main".to_string(),
+            }],
+        )));
+        let body_element = doc.get_node_mut(body_element_id).unwrap();
+        body_element.children.push(main_element_id);
+        let main_element = doc.get_node_mut(main_element_id).unwrap();
+        main_element.parent = Some(body_element_id);
+
+        // Create the head element
+        let head_element_id = doc.create_node(NodeData::Element(ElementNodeData::new(
+            qual_name("head", None),
+            Vec::new(),
+        )));
+        let head_element = doc.get_node_mut(head_element_id).unwrap();
+        head_element.parent = Some(html_element_id);
+        let html_element = doc.get_node_mut(html_element_id).unwrap();
+        html_element.children.push(head_element_id);
+
+        // Include default and user-specified stylesheets
+        doc.add_user_agent_stylesheet(DEFAULT_CSS);
+
+        let state = DioxusState::create(&mut doc, main_element_id);
+        let mut doc = Self {
+            vdom,
+            vdom_state: state,
+            inner: doc,
+            html_element_id,
+            head_element_id,
+            body_element_id,
+            main_element_id,
+        };
+
+        doc.inner.set_base_url("dioxus://index.html");
+
+        // doc.initial_build();
+
+        // doc.inner.print_tree();
+
+        doc
+    }
+
+    pub fn initial_build(&mut self) {
+        // let mut writer = MutationWriter::new(&mut self.inner, &mut self.vdom_state);
+
+        // self.vdom.rebuild(&mut writer);
+        // dbg!(self.vdom.rebuild_to_vec());
+        // std::process::exit(0);
+        // dbg!(writer.state);
+    }
+
+    pub fn label_bound_input_element(&self, label_node_id: NodeId) -> Option<(ElementId, NodeId)> {
+        let bound_input_elements = self.inner.label_bound_input_elements(label_node_id);
+
+        // Filter down bound elements to those which have dioxus id
+        bound_input_elements.into_iter().find_map(|n| {
+            let target_element_data = n.element_data()?;
+            let node_id = n.id;
+            let dioxus_id = DioxusDocument::dioxus_id(target_element_data)?;
+            Some((dioxus_id, node_id))
+        })
+    }
+
+    fn dioxus_id(element_node_data: &ElementNodeData) -> Option<ElementId> {
+        Some(ElementId(
+            element_node_data
+                .attrs
+                .iter()
+                .find(|attr| *attr.name.local == *"data-dioxus-id")?
+                .value
+                .parse::<usize>()
+                .ok()?,
+        ))
+    }
+
+    pub fn create_head_element(
+        &mut self,
+        name: &str,
+        attributes: &[(String, String)],
+        contents: &Option<String>,
+    ) {
+        let mut stylesheet = None;
+        let mut title = None;
+        if name == "link" {
+            let is_stylesheet = attributes
+                .iter()
+                .any(|(name, value)| name == "rel" && value == "stylesheet");
+            if is_stylesheet {
+                stylesheet = attributes
+                    .iter()
+                    .find(|(name, _value)| name == "href")
+                    .map(|(_name, value)| value.clone());
+            }
+        }
+
+        if name == "title" {
+            title = attributes
+                .iter()
+                .find(|(name, _value)| name == "text")
+                .and_then(|(_name, _value)| contents.clone());
+        }
+
+        let attributes = attributes
+            .iter()
+            .map(|(name, value)| Attribute {
+                name: qual_name(name, None),
+                value: value.clone(),
+            })
+            .collect();
+
+        let new_element = self
+            .inner
+            .create_node(NodeData::Element(ElementNodeData::new(
+                qual_name(name, None),
+                attributes,
+            )));
+
+        if let Some(contents) = contents {
+            let text_node = self.inner.create_text_node(contents);
+            self.inner
+                .get_node_mut(new_element)
+                .unwrap()
+                .children
+                .push(text_node);
+        }
+
+        self.inner
+            .get_node_mut(self.head_element_id)
+            .unwrap()
+            .children
+            .push(new_element);
+
+        if let Some(url) = stylesheet {
+            crate::assets::fetch_linked_stylesheet(&self.inner, new_element, url);
+        }
+
+        if let Some(_title) = title {
+            println!("todo: set title");
+        }
+    }
+
+    // pub fn apply_mutations(&mut self) {
+    //     // Apply the mutations to the actual dom
+    //     let mut writer = MutationWriter {
+    //         doc: &mut self.inner,
+    //         state: &mut self.vdom_state,
+    //     };
+    //     self.vdom.render_immediate(&mut writer);
+
+    //     println!("APPLY MUTATIONS");
+    //     self.inner.print_tree();
+    // }
+}

+ 23 - 0
packages/native/src/event.rs

@@ -0,0 +1,23 @@
+use winit::window::WindowId;
+
+/// Dioxus-native specific event type
+pub enum DioxusNativeEvent {
+    /// A hotreload event, basically telling us to update our templates.
+    #[cfg(all(
+        feature = "hot-reload",
+        debug_assertions,
+        not(target_os = "android"),
+        not(target_os = "ios")
+    ))]
+    DevserverEvent(dioxus_devtools::DevserverMsg),
+
+    /// Create a new head element from the Link and Title elements
+    ///
+    /// todo(jon): these should probabkly be synchronous somehow
+    CreateHeadElement {
+        window: WindowId,
+        name: String,
+        attributes: Vec<(String, String)>,
+        contents: Option<String>,
+    },
+}

+ 220 - 0
packages/native/src/event_handler.rs

@@ -0,0 +1,220 @@
+use blitz_traits::{BlitzKeyEvent, BlitzMouseButtonEvent, MouseEventButton};
+use dioxus_html::{
+    geometry::{ClientPoint, ElementPoint, PagePoint, ScreenPoint},
+    input_data::{MouseButton, MouseButtonSet},
+    point_interaction::{
+        InteractionElementOffset, InteractionLocation, ModifiersInteraction, PointerInteraction,
+    },
+    AnimationData, ClipboardData, CompositionData, DragData, FocusData, FormData, FormValue,
+    HasFileData, HasFormData, HasMouseData, HtmlEventConverter, ImageData, KeyboardData, MediaData,
+    MountedData, MouseData, PlatformEventData, PointerData, ResizeData, ScrollData, SelectionData,
+    ToggleData, TouchData, TransitionData, VisibleData, WheelData,
+};
+use dioxus_html::{HasFocusData, HasKeyboardData};
+use keyboard_types::{Code, Key, Location, Modifiers};
+use std::any::Any;
+use std::collections::HashMap;
+
+pub struct NativeConverter {}
+
+impl HtmlEventConverter for NativeConverter {
+    fn convert_form_data(&self, event: &PlatformEventData) -> FormData {
+        event.downcast::<NativeFormData>().unwrap().clone().into()
+    }
+
+    fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData {
+        event.downcast::<NativeClickData>().unwrap().clone().into()
+    }
+
+    fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData {
+        event
+            .downcast::<BlitzKeyboardData>()
+            .unwrap()
+            .clone()
+            .into()
+    }
+
+    fn convert_focus_data(&self, _event: &PlatformEventData) -> FocusData {
+        NativeFocusData {}.into()
+    }
+
+    fn convert_animation_data(&self, _event: &PlatformEventData) -> AnimationData {
+        todo!("todo: convert_animation_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_clipboard_data(&self, _event: &PlatformEventData) -> ClipboardData {
+        todo!("todo: convert_clipboard_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_composition_data(&self, _event: &PlatformEventData) -> CompositionData {
+        todo!("todo: convert_composition_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_drag_data(&self, _event: &PlatformEventData) -> DragData {
+        todo!("todo: convert_drag_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_image_data(&self, _event: &PlatformEventData) -> ImageData {
+        todo!("todo: convert_image_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_media_data(&self, _event: &PlatformEventData) -> MediaData {
+        todo!("todo: convert_media_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_mounted_data(&self, _event: &PlatformEventData) -> MountedData {
+        todo!("todo: convert_mounted_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_pointer_data(&self, _event: &PlatformEventData) -> PointerData {
+        todo!("todo: convert_pointer_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_scroll_data(&self, _event: &PlatformEventData) -> ScrollData {
+        todo!("todo: convert_scroll_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_selection_data(&self, _event: &PlatformEventData) -> SelectionData {
+        todo!("todo: convert_selection_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_toggle_data(&self, _event: &PlatformEventData) -> ToggleData {
+        todo!("todo: convert_toggle_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_touch_data(&self, _event: &PlatformEventData) -> TouchData {
+        todo!("todo: convert_touch_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_transition_data(&self, _event: &PlatformEventData) -> TransitionData {
+        todo!("todo: convert_transition_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_wheel_data(&self, _event: &PlatformEventData) -> WheelData {
+        todo!("todo: convert_wheel_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_resize_data(&self, _event: &PlatformEventData) -> ResizeData {
+        todo!("todo: convert_resize_data in dioxus-native. requires support in blitz")
+    }
+
+    fn convert_visible_data(&self, _event: &PlatformEventData) -> VisibleData {
+        todo!("todo: convert_visible_data in dioxus-native. requires support in blitz")
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct NativeFormData {
+    pub value: String,
+    pub values: HashMap<String, FormValue>,
+}
+
+impl HasFormData for NativeFormData {
+    fn as_any(&self) -> &dyn std::any::Any {
+        self as &dyn std::any::Any
+    }
+
+    fn value(&self) -> String {
+        self.value.clone()
+    }
+
+    fn values(&self) -> HashMap<String, FormValue> {
+        self.values.clone()
+    }
+}
+
+impl HasFileData for NativeFormData {}
+
+#[derive(Clone, Debug)]
+pub(crate) struct BlitzKeyboardData(pub(crate) BlitzKeyEvent);
+
+impl ModifiersInteraction for BlitzKeyboardData {
+    fn modifiers(&self) -> Modifiers {
+        self.0.modifiers
+    }
+}
+
+impl HasKeyboardData for BlitzKeyboardData {
+    fn key(&self) -> Key {
+        self.0.key.clone()
+    }
+
+    fn code(&self) -> Code {
+        self.0.code
+    }
+
+    fn location(&self) -> Location {
+        self.0.location
+    }
+
+    fn is_auto_repeating(&self) -> bool {
+        self.0.is_auto_repeating
+    }
+
+    fn is_composing(&self) -> bool {
+        self.0.is_composing
+    }
+
+    fn as_any(&self) -> &dyn std::any::Any {
+        self as &dyn Any
+    }
+}
+
+#[derive(Clone)]
+pub struct NativeClickData(pub(crate) BlitzMouseButtonEvent);
+
+impl InteractionLocation for NativeClickData {
+    fn client_coordinates(&self) -> ClientPoint {
+        ClientPoint::new(self.0.x as _, self.0.y as _)
+    }
+
+    // these require blitz to pass them along, or a dom rect
+    fn screen_coordinates(&self) -> ScreenPoint {
+        unimplemented!()
+    }
+
+    fn page_coordinates(&self) -> PagePoint {
+        unimplemented!()
+    }
+}
+
+impl InteractionElementOffset for NativeClickData {
+    fn element_coordinates(&self) -> ElementPoint {
+        todo!()
+    }
+}
+
+impl ModifiersInteraction for NativeClickData {
+    fn modifiers(&self) -> Modifiers {
+        self.0.mods
+    }
+}
+
+impl PointerInteraction for NativeClickData {
+    fn trigger_button(&self) -> Option<MouseButton> {
+        Some(match self.0.button {
+            MouseEventButton::Main => MouseButton::Primary,
+            MouseEventButton::Auxiliary => MouseButton::Auxiliary,
+            MouseEventButton::Secondary => MouseButton::Secondary,
+            MouseEventButton::Fourth => MouseButton::Fourth,
+            MouseEventButton::Fifth => MouseButton::Fifth,
+        })
+    }
+
+    fn held_buttons(&self) -> MouseButtonSet {
+        dioxus_html::input_data::decode_mouse_button_set(self.0.buttons.bits() as u16)
+    }
+}
+impl HasMouseData for NativeClickData {
+    fn as_any(&self) -> &dyn std::any::Any {
+        self as &dyn std::any::Any
+    }
+}
+
+#[derive(Clone)]
+pub struct NativeFocusData {}
+impl HasFocusData for NativeFocusData {
+    fn as_any(&self) -> &dyn std::any::Any {
+        self as &dyn std::any::Any
+    }
+}

+ 96 - 0
packages/native/src/lib.rs

@@ -0,0 +1,96 @@
+#![cfg_attr(docsrs, feature(doc_cfg))]
+
+//! A native renderer for Dioxus.
+//!
+//! ## Feature flags
+//!  - `default`: Enables the features listed below.
+//!  - `accessibility`: Enables [`accesskit`] accessibility support.
+//!  - `hot-reload`: Enables hot-reloading of Dioxus RSX.
+//!  - `menu`: Enables the [`muda`] menubar.
+//!  - `tracing`: Enables tracing support.
+
+mod assets;
+mod contexts;
+mod dioxus_application;
+mod dioxus_document;
+mod event;
+mod event_handler;
+mod mutation_writer;
+
+pub use dioxus_application::DioxusNativeApplication;
+pub use dioxus_document::DioxusDocument;
+pub use event::DioxusNativeEvent;
+
+use blitz_shell::{create_default_event_loop, BlitzShellEvent, Config, WindowConfig};
+use dioxus_core::{ComponentFunction, Element, VirtualDom};
+use std::any::Any;
+
+type NodeId = usize;
+
+/// Launch an interactive HTML/CSS renderer driven by the Dioxus virtualdom
+pub fn launch(app: fn() -> Element) {
+    launch_cfg(app, vec![], vec![])
+}
+
+pub fn launch_cfg(
+    app: fn() -> Element,
+    contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
+    cfg: Vec<Box<dyn Any>>,
+) {
+    launch_cfg_with_props(app, (), contexts, cfg)
+}
+
+// todo: props shouldn't have the clone bound - should try and match dioxus-desktop behavior
+pub fn launch_cfg_with_props<P: Clone + 'static, M: 'static>(
+    app: impl ComponentFunction<P, M>,
+    props: P,
+    contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
+    _cfg: Vec<Box<dyn Any>>,
+) {
+    let _cfg = _cfg
+        .into_iter()
+        .find_map(|cfg| cfg.downcast::<Config>().ok())
+        .unwrap_or_default();
+    let event_loop = create_default_event_loop::<BlitzShellEvent>();
+
+    // Turn on the runtime and enter it
+    let rt = tokio::runtime::Builder::new_multi_thread()
+        .enable_all()
+        .build()
+        .unwrap();
+    let _guard = rt.enter();
+
+    // Setup hot-reloading if enabled.
+    #[cfg(all(
+        feature = "hot-reload",
+        debug_assertions,
+        not(target_os = "android"),
+        not(target_os = "ios")
+    ))]
+    {
+        use crate::event::DioxusNativeEvent;
+        if let Some(endpoint) = dioxus_cli_config::devserver_ws_endpoint() {
+            let proxy = event_loop.create_proxy();
+            dioxus_devtools::connect(endpoint, move |event| {
+                let dxn_event = DioxusNativeEvent::DevserverEvent(event);
+                let _ = proxy.send_event(BlitzShellEvent::embedder_event(dxn_event));
+            })
+        }
+    }
+
+    // Spin up the virtualdom
+    // We're going to need to hit it with a special waker
+    // Note that we are delaying the initialization of window-specific contexts (net provider, document, etc)
+    let mut vdom = VirtualDom::new_with_props(app, props);
+
+    // Add contexts
+    for context in contexts {
+        vdom.insert_any_root_context(context());
+    }
+
+    // Create application
+    let mut application = DioxusNativeApplication::new(event_loop.create_proxy(), vdom);
+
+    // Run event loop
+    event_loop.run_app(&mut application).unwrap();
+}

+ 575 - 0
packages/native/src/mutation_writer.rs

@@ -0,0 +1,575 @@
+use crate::{dioxus_document::qual_name, NodeId};
+use blitz_dom::{
+    local_name, namespace_url,
+    node::{Attribute, NodeSpecificData},
+    ns, BaseDocument, ElementNodeData, NodeData, QualName, RestyleHint,
+};
+use dioxus_core::{
+    AttributeValue, ElementId, Template, TemplateAttribute, TemplateNode, WriteMutations,
+};
+use rustc_hash::FxHashMap;
+use std::collections::HashSet;
+
+/// The state of the Dioxus integration with the RealDom
+#[derive(Debug)]
+pub struct DioxusState {
+    /// Store of templates keyed by unique name
+    templates: FxHashMap<Template, Vec<NodeId>>,
+    /// Stack machine state for applying dioxus mutations
+    stack: Vec<NodeId>,
+    /// Mapping from vdom ElementId -> rdom NodeId
+    node_id_mapping: Vec<Option<NodeId>>,
+}
+
+/// A writer for mutations that can be used with the RealDom.
+pub struct MutationWriter<'a> {
+    /// The realdom associated with this writer
+    pub doc: &'a mut BaseDocument,
+
+    /// The state associated with this writer
+    pub state: &'a mut DioxusState,
+
+    pub style_nodes: HashSet<usize>,
+
+    /// The (latest) node which has been mounted in and had autofocus=true, if any
+    #[cfg(feature = "autofocus")]
+    pub node_to_autofocus: Option<usize>,
+}
+
+impl<'a> MutationWriter<'a> {
+    pub fn new(doc: &'a mut BaseDocument, state: &'a mut DioxusState) -> Self {
+        MutationWriter {
+            doc,
+            state,
+            style_nodes: HashSet::new(),
+
+            #[cfg(feature = "autofocus")]
+            node_to_autofocus: None,
+        }
+    }
+
+    fn is_style_node(&self, node_id: NodeId) -> bool {
+        self.doc
+            .get_node(node_id)
+            .unwrap()
+            .data
+            .is_element_with_tag_name(&local_name!("style"))
+    }
+
+    fn maybe_push_style_node(&mut self, node_id: impl Into<Option<NodeId>>) {
+        if let Some(node_id) = node_id.into() {
+            if self.is_style_node(node_id) {
+                self.style_nodes.insert(node_id);
+            }
+        }
+    }
+
+    #[track_caller]
+    fn maybe_push_parent_style_node(&mut self, node_id: NodeId) {
+        let parent_id = self.doc.get_node(node_id).unwrap().parent;
+        self.maybe_push_style_node(parent_id);
+    }
+}
+
+impl Drop for MutationWriter<'_> {
+    fn drop(&mut self) {
+        // Add/Update inline stylesheets (<style> elements)
+        for &id in &self.style_nodes {
+            self.doc.upsert_stylesheet_for_node(id);
+        }
+
+        #[cfg(feature = "autofocus")]
+        if let Some(node_id) = self.node_to_autofocus {
+            if self.doc.get_node(node_id).is_some() {
+                self.doc.set_focus_to(node_id);
+            }
+        }
+    }
+}
+
+impl DioxusState {
+    /// Initialize the DioxusState in the RealDom
+    pub fn create(_doc: &mut BaseDocument, mount_node: NodeId) -> Self {
+        Self {
+            templates: FxHashMap::default(),
+            stack: vec![mount_node],
+            node_id_mapping: vec![Some(mount_node)],
+        }
+    }
+
+    /// Convert an ElementId to a NodeId
+    pub fn element_to_node_id(&self, element_id: ElementId) -> NodeId {
+        self.try_element_to_node_id(element_id).unwrap()
+    }
+
+    /// Attempt to convert an ElementId to a NodeId. This will return None if the ElementId is not in the RealDom.
+    pub fn try_element_to_node_id(&self, element_id: ElementId) -> Option<NodeId> {
+        self.node_id_mapping.get(element_id.0).copied().flatten()
+    }
+}
+
+impl MutationWriter<'_> {
+    /// Update an ElementId -> NodeId mapping
+    fn set_id_mapping(&mut self, node_id: NodeId, element_id: ElementId) {
+        let element_id: usize = element_id.0;
+
+        // Ensure node_id_mapping is large enough to contain element_id
+        if self.state.node_id_mapping.len() <= element_id {
+            self.state.node_id_mapping.resize(element_id + 1, None);
+        }
+
+        // Set the new mapping
+        self.state.node_id_mapping[element_id] = Some(node_id);
+    }
+
+    /// Find a child in the document by child index path
+    fn load_child(&self, path: &[u8]) -> NodeId {
+        let mut current = self
+            .doc
+            .get_node(*self.state.stack.last().unwrap())
+            .unwrap();
+        for i in path {
+            let new_id = current.children[*i as usize];
+            current = self.doc.get_node(new_id).unwrap();
+        }
+        current.id
+    }
+
+    fn create_template_node(&mut self, node: &TemplateNode) -> NodeId {
+        match node {
+            TemplateNode::Element {
+                tag,
+                namespace,
+                attrs,
+                children,
+            } => {
+                let name = qual_name(tag, *namespace);
+                let attrs = attrs
+                    .iter()
+                    .filter_map(|attr| match attr {
+                        TemplateAttribute::Static {
+                            name,
+                            value,
+                            namespace,
+                        } => Some(Attribute {
+                            name: qual_name(name, *namespace),
+                            value: value.to_string(),
+                        }),
+                        TemplateAttribute::Dynamic { .. } => None,
+                    })
+                    .collect();
+
+                let mut data = ElementNodeData::new(name, attrs);
+                data.flush_style_attribute(self.doc.guard());
+
+                let child_ids: Vec<NodeId> = children
+                    .iter()
+                    .map(|child| self.create_template_node(child))
+                    .collect();
+
+                let id = self.doc.create_node(NodeData::Element(data));
+                let node = self.doc.get_node(id).unwrap();
+
+                // Initialise style data
+                *node.stylo_element_data.borrow_mut() = Some(Default::default());
+
+                if let Some(src_attr) = node.attr(local_name!("src")) {
+                    crate::assets::fetch_image(self.doc, id, src_attr.to_string());
+                }
+
+                let rel_attr = node.attr(local_name!("rel"));
+                let href_attr = node.attr(local_name!("href"));
+                if let (Some("stylesheet"), Some(href)) = (rel_attr, href_attr) {
+                    crate::assets::fetch_linked_stylesheet(self.doc, id, href.to_string());
+                }
+
+                // If the node has an "id" attribute, store it in the ID map.
+                if let Some(id_attr) = node.attr(local_name!("id")) {
+                    self.doc.nodes_to_id.insert(id_attr.to_string(), id);
+                }
+
+                for &child_id in &child_ids {
+                    self.doc.get_node_mut(child_id).unwrap().parent = Some(id);
+                }
+                self.doc.get_node_mut(id).unwrap().children = child_ids;
+
+                id
+            }
+            TemplateNode::Text { text } => self.doc.create_text_node(text),
+            TemplateNode::Dynamic { .. } => self.doc.create_node(NodeData::Comment),
+        }
+    }
+}
+
+impl WriteMutations for MutationWriter<'_> {
+    fn append_children(&mut self, id: ElementId, m: usize) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("append_children id:{} m:{}", id.0, m);
+
+        let children = self.state.stack.split_off(self.state.stack.len() - m);
+        let parent = self.state.element_to_node_id(id);
+        for child in children {
+            self.doc.get_node_mut(parent).unwrap().children.push(child);
+            self.doc.get_node_mut(child).unwrap().parent = Some(parent);
+        }
+
+        self.maybe_push_style_node(parent);
+    }
+
+    fn assign_node_id(&mut self, path: &'static [u8], id: ElementId) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("assign_node_id path:{:?} id:{}", path, id.0);
+
+        // If there is an existing node already mapped to that ID and
+        // it has no parent, then drop it
+        if let Some(node_id) = self.state.try_element_to_node_id(id) {
+            if let Some(node) = self.doc.get_node(node_id) {
+                if node.parent.is_none() {
+                    self.doc.remove_and_drop_node(node_id);
+                }
+            }
+        }
+
+        let node_id = self.load_child(path);
+        self.set_id_mapping(node_id, id);
+    }
+
+    fn create_placeholder(&mut self, id: ElementId) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("create_placeholder id:{}", id.0);
+
+        let node_id = self.doc.create_node(NodeData::Comment);
+        self.set_id_mapping(node_id, id);
+        self.state.stack.push(node_id);
+    }
+
+    fn create_text_node(&mut self, value: &str, id: ElementId) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("create_text_node id:{} text:{}", id.0, value);
+
+        let node_id = self.doc.create_text_node(value);
+        self.set_id_mapping(node_id, id);
+        self.state.stack.push(node_id);
+    }
+
+    #[allow(clippy::map_entry)]
+    fn load_template(&mut self, template: Template, index: usize, id: ElementId) {
+        if !self.state.templates.contains_key(&template) {
+            let template_root_ids: Vec<NodeId> = template
+                .roots
+                .iter()
+                .map(|root| self.create_template_node(root))
+                .collect();
+
+            self.state.templates.insert(template, template_root_ids);
+        }
+
+        let template_entry = &self.state.templates[&template];
+
+        let template_node_id = template_entry[index];
+        let clone_id = self.doc.deep_clone_node(template_node_id);
+
+        #[cfg(feature = "autofocus")]
+        autofocus_node_recursive(self.doc, &mut self.node_to_autofocus, clone_id);
+
+        self.set_id_mapping(clone_id, id);
+        self.state.stack.push(clone_id);
+    }
+
+    fn replace_node_with(&mut self, id: ElementId, m: usize) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("replace_node_with id:{} m:{}", id.0, m);
+
+        let new_nodes = self.state.stack.split_off(self.state.stack.len() - m);
+        let anchor_node_id = self.state.element_to_node_id(id);
+        self.maybe_push_parent_style_node(anchor_node_id);
+        self.doc.insert_before(anchor_node_id, &new_nodes);
+        self.doc.remove_node(anchor_node_id);
+    }
+
+    fn replace_placeholder_with_nodes(&mut self, path: &'static [u8], m: usize) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("replace_placeholder_with_nodes path:{:?} m:{}", path, m);
+
+        let new_nodes = self.state.stack.split_off(self.state.stack.len() - m);
+        let anchor_node_id = self.load_child(path);
+        self.maybe_push_parent_style_node(anchor_node_id);
+        self.doc.insert_before(anchor_node_id, &new_nodes);
+        self.doc.remove_node(anchor_node_id);
+    }
+
+    fn insert_nodes_after(&mut self, id: ElementId, m: usize) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("insert_nodes_after id:{} m:{}", id.0, m);
+
+        let new_nodes = self.state.stack.split_off(self.state.stack.len() - m);
+        let anchor_node_id = self.state.element_to_node_id(id);
+        let next_sibling_id = self
+            .doc
+            .get_node(anchor_node_id)
+            .unwrap()
+            .forward(1)
+            .map(|node| node.id);
+
+        match next_sibling_id {
+            Some(anchor_node_id) => {
+                self.doc.insert_before(anchor_node_id, &new_nodes);
+            }
+            None => self.doc.append(anchor_node_id, &new_nodes),
+        }
+
+        self.maybe_push_parent_style_node(anchor_node_id);
+    }
+
+    fn insert_nodes_before(&mut self, id: ElementId, m: usize) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("insert_nodes_before id:{} m:{}", id.0, m);
+
+        let new_nodes = self.state.stack.split_off(self.state.stack.len() - m);
+        let anchor_node_id = self.state.element_to_node_id(id);
+        self.doc.insert_before(anchor_node_id, &new_nodes);
+
+        self.maybe_push_parent_style_node(anchor_node_id);
+    }
+
+    fn set_attribute(
+        &mut self,
+        name: &'static str,
+        ns: Option<&'static str>,
+        value: &AttributeValue,
+        id: ElementId,
+    ) {
+        let node_id = self.state.element_to_node_id(id);
+
+        #[cfg(feature = "tracing")]
+        tracing::info!(
+            "set_attribute node_id:{} ns: {:?} name:{}, value:{:?}",
+            node_id,
+            ns,
+            name,
+            value
+        );
+
+        self.doc.snapshot_node(node_id);
+
+        let mut queued_image = None;
+        let mut queued_stylesheet = None;
+
+        {
+            let node = &mut self.doc.nodes[node_id];
+
+            let stylo_element_data = &mut *node.stylo_element_data.borrow_mut();
+            if let Some(data) = stylo_element_data {
+                data.hint |= RestyleHint::restyle_subtree();
+            }
+
+            if let NodeData::Element(ref mut element) = node.data {
+                if element.name.local == local_name!("input") && name == "checked" {
+                    set_input_checked_state(element, value);
+                }
+                // FIXME: support other non-text attributes
+                else if let AttributeValue::Text(val) = value {
+                    if name == "value" {
+                        // Update text input value
+                        if let Some(input_data) = element.text_input_data_mut() {
+                            input_data.set_text(
+                                &mut self.doc.font_ctx,
+                                &mut self.doc.layout_ctx,
+                                val,
+                            );
+                        }
+                    }
+
+                    // FIXME check namespace
+                    let existing_attr = element
+                        .attrs
+                        .iter_mut()
+                        .find(|attr| attr.name.local == *name);
+
+                    if let Some(existing_attr) = existing_attr {
+                        existing_attr.value.clear();
+                        existing_attr.value.push_str(val);
+                    } else {
+                        // we have overloaded the style namespace to accumulate style attributes without a `style` block
+                        if ns == Some("style") {
+                            // todo: need to accumulate style attributes into a single style
+                            //
+                            // element.
+                        } else {
+                            element.attrs.push(Attribute {
+                                name: qual_name(name, ns),
+                                value: val.to_string(),
+                            });
+                        }
+                    }
+
+                    if name == "style" {
+                        element.flush_style_attribute(&self.doc.guard);
+                    }
+
+                    if name == "src" && !val.is_empty() {
+                        element.node_specific_data = NodeSpecificData::None;
+                        queued_image = Some(val.to_string());
+                    }
+
+                    if element.name.local == local_name!("link")
+                        && name == "href"
+                        && !val.is_empty()
+                    {
+                        queued_stylesheet = Some(val.to_string());
+                    }
+                }
+
+                if let AttributeValue::None = value {
+                    // Update text input value
+                    if name == "value" {
+                        if let Some(input_data) = element.text_input_data_mut() {
+                            input_data.set_text(
+                                &mut self.doc.font_ctx,
+                                &mut self.doc.layout_ctx,
+                                "",
+                            );
+                        }
+                    }
+
+                    // FIXME: check namespace
+                    element.attrs.retain(|attr| attr.name.local != *name);
+                }
+            }
+        }
+
+        if let Some(queued_image) = queued_image {
+            crate::assets::fetch_image(self.doc, node_id, queued_image);
+        }
+
+        if let Some(queued_stylesheet) = queued_stylesheet {
+            crate::assets::fetch_linked_stylesheet(self.doc, node_id, queued_stylesheet);
+        }
+    }
+
+    fn set_node_text(&mut self, value: &str, id: ElementId) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("set_node_text id:{} value:{}", id.0, value);
+
+        let node_id = self.state.element_to_node_id(id);
+        let node = self.doc.get_node_mut(node_id).unwrap();
+
+        let text = match node.data {
+            NodeData::Text(ref mut text) => text,
+            // todo: otherwise this is basically element.textContent which is a bit different - need to parse as html
+            _ => return,
+        };
+
+        let changed = text.content != value;
+        if changed {
+            text.content.clear();
+            text.content.push_str(value);
+            let parent = node.parent;
+            self.maybe_push_style_node(parent);
+        }
+    }
+
+    fn create_event_listener(&mut self, _name: &'static str, _id: ElementId) {
+        // we're going to actually set the listener here as a placeholder - in JS this would also be a placeholder
+        // we might actually just want to attach the attribute to the root element (delegation)
+        self.set_attribute(
+            _name,
+            None,
+            &AttributeValue::Text("<rust func>".into()),
+            _id,
+        );
+
+        // also set the data-dioxus-id attribute so we can find the element later
+        self.set_attribute(
+            "data-dioxus-id",
+            None,
+            &AttributeValue::Text(_id.0.to_string()),
+            _id,
+        );
+
+        // let node_id = self.state.element_to_node_id(id);
+        // let mut node = self.rdom.get_mut(node_id).unwrap();
+        // node.add_event_listener(name);
+    }
+
+    fn remove_event_listener(&mut self, _name: &'static str, _id: ElementId) {
+        // let node_id = self.state.element_to_node_id(id);
+        // let mut node = self.rdom.get_mut(node_id).unwrap();
+        // node.remove_event_listener(name);
+    }
+
+    fn remove_node(&mut self, id: ElementId) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("remove_node id:{}", id.0);
+
+        let node_id = self.state.element_to_node_id(id);
+        self.doc.remove_node(node_id);
+    }
+
+    fn push_root(&mut self, id: ElementId) {
+        #[cfg(feature = "tracing")]
+        tracing::info!("push_root id:{}", id.0,);
+
+        let node_id = self.state.element_to_node_id(id);
+        self.state.stack.push(node_id);
+    }
+}
+
+/// Set 'checked' state on an input based on given attributevalue
+fn set_input_checked_state(element: &mut ElementNodeData, value: &AttributeValue) {
+    let checked: bool;
+    match value {
+        AttributeValue::Bool(checked_bool) => {
+            checked = *checked_bool;
+        }
+        AttributeValue::Text(val) => {
+            if let Ok(checked_bool) = val.parse() {
+                checked = checked_bool;
+            } else {
+                return;
+            };
+        }
+        _ => {
+            return;
+        }
+    };
+    match element.node_specific_data {
+        NodeSpecificData::CheckboxInput(ref mut checked_mut) => *checked_mut = checked,
+        // If we have just constructed the element, set the node attribute,
+        // and NodeSpecificData will be created from that later
+        // this simulates the checked attribute being set in html,
+        // and the element's checked property being set from that
+        NodeSpecificData::None => element.attrs.push(Attribute {
+            name: QualName {
+                prefix: None,
+                ns: ns!(html),
+                local: local_name!("checked"),
+            },
+            value: checked.to_string(),
+        }),
+        _ => {}
+    }
+}
+
+#[cfg(feature = "autofocus")]
+fn autofocus_node_recursive(
+    doc: &BaseDocument,
+    node_to_autofocus: &mut Option<usize>,
+    node_id: usize,
+) {
+    if let Some(node) = doc.get_node(node_id) {
+        if node.is_focussable() {
+            if let NodeData::Element(ref element) = node.data {
+                if let Some(value) = element.attr(local_name!("autofocus")) {
+                    if value == "true" {
+                        *node_to_autofocus = Some(node_id);
+                    }
+                }
+            }
+        }
+
+        for child_node_id in &node.children {
+            autofocus_node_recursive(doc, node_to_autofocus, *child_node_id);
+        }
+    }
+}

+ 3 - 0
packages/playwright-tests/nested-suspense/src/ssg.rs

@@ -3,6 +3,8 @@ use dioxus::prelude::*;
 use nested_suspense::app;
 
 fn main() {
+    dioxus::logger::init(dioxus::logger::tracing::Level::TRACE).expect("logger failed to init");
+
     dioxus::LaunchBuilder::new()
         .with_cfg(server_only! {
             ServeConfig::builder()
@@ -15,6 +17,7 @@ fn main() {
                                 .unwrap()
                                 .join("public")
                         )
+                        .clear_cache(false)
                 )
                 .enable_out_of_order_streaming()
         })

+ 3 - 3
packages/router/Cargo.toml

@@ -15,10 +15,10 @@ dioxus-history = { workspace = true }
 dioxus-router-macro = { workspace = true }
 dioxus-fullstack-hooks = { workspace = true, optional = true }
 tracing = { workspace = true }
-urlencoding = "2.1.3"
-url = "2.3.1"
+urlencoding = { workspace = true }
+url = { workspace = true }
 dioxus-cli-config = { workspace = true }
-rustversion = "1.0.17"
+rustversion = { workspace = true }
 
 [features]
 default = []

+ 1 - 1
packages/server-macro/src/lib.rs

@@ -37,7 +37,7 @@ use syn::{
 ///
 /// You can any combination of the following named arguments:
 /// - `name`: sets the identifier for the server function’s type, which is a struct created
-///    to hold the arguments (defaults to the function identifier in PascalCase)
+///   to hold the arguments (defaults to the function identifier in PascalCase)
 /// - `prefix`: a prefix at which the server function handler will be mounted (defaults to `/api`)
 /// - `endpoint`: specifies the exact path at which the server function handler will be mounted,
 ///   relative to the prefix (defaults to the function name followed by unique hash)