diff --git a/.gitignore b/.gitignore index e63f8ae..06b8884 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ *.sqlite .env *.db-journal +node_modules/ +.cargo/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d928734 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,52 @@ +repos: + - repo: https://github.com/compilerla/conventional-pre-commit + rev: v4.4.0 + hooks: + - id: conventional-pre-commit + stages: [commit-msg] + args: + - feat + - fix + - chore + - test + - doc + - refactor + - perf + - ci + - style + - revert + + - repo: local + hooks: + - id: cargo-fmt + name: cargo fmt + language: system + entry: cargo fmt --all -- --check + pass_filenames: false + always_run: true + priority: 0 + + - id: cargo-machete + name: cargo machete + language: system + entry: cargo machete + pass_filenames: false + always_run: true + priority: 0 + + - id: cargo-clippy + name: cargo clippy + language: system + entry: cargo clippy --all-targets -- -W clippy::all -W clippy::pedantic -D warnings + pass_filenames: false + always_run: true + priority: 1 + + - id: sem-diff + name: sem diff (semantic changes) + language: system + entry: bash -c 'sem diff --staged --file-exts .rs || true' + pass_filenames: false + always_run: true + verbose: true + priority: 2 diff --git a/Cargo.lock b/Cargo.lock index 1cc24a9..4d27b72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,33 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "agcli" version = "0.7.0" @@ -33,6 +60,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.102" @@ -51,6 +93,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0f477b951e452a0b6b4a10b53ccd569042d1d01729b519e02074a9c0958a063" +[[package]] +name = "askama_escape" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df27b8d5ddb458c5fb1bbc1ce172d4a38c614a97d550b0ac89003897fb01de4" + [[package]] name = "async-stream" version = "0.3.6" @@ -70,7 +118,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -81,9 +129,85 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", +] + +[[package]] +name = "async-tungstenite" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee88b4c88ac8c9ea446ad43498955750a4bbe64c4392f21ccfe5d952865e318f" +dependencies = [ + "atomic-waker", + "futures-core", + "futures-io", + "futures-task", + "futures-util", + "log", + "pin-project-lite", + "tungstenite 0.27.0", +] + +[[package]] +name = "async-utility" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34a3b57207a7a1007832416c3e4862378c8451b4e8e093e436f48c2d3d2c151" +dependencies = [ + "futures-util", + "gloo-timers", + "tokio", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-wsocket" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c92385c7c8b3eb2de1b78aeca225212e4c9a69a78b802832759b108681a5069" +dependencies = [ + "async-utility", + "futures", + "futures-util", + "js-sys", + "tokio", + "tokio-rustls", + "tokio-socks", + "tokio-tungstenite 0.26.2", + "url", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "atk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" +dependencies = [ + "atk-sys", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", ] +[[package]] +name = "atomic-destructor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef49f5882e4b6afaac09ad239a4f8c70a24b8f2b0897edb1f706008efd109cf4" + [[package]] name = "atomic-waker" version = "1.1.2" @@ -118,6 +242,103 @@ dependencies = [ "fs_extra", ] +[[package]] +name = "axum" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +dependencies = [ + "axum-core", + "axum-macros", + "base64 0.22.1", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "multer", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sha1", + "sync_wrapper", + "tokio", + "tokio-tungstenite 0.28.0", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-extra" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9963ff19f40c6102c76756ef0a46004c0d58957d87259fc9208ff8441c12ab96" +dependencies = [ + "axum", + "axum-core", + "bytes", + "futures-util", + "headers", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "serde_core", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "base16" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" + [[package]] name = "base58ck" version = "0.1.0" @@ -140,6 +361,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + [[package]] name = "bdk-agcli" version = "0.1.0" @@ -310,11 +537,53 @@ dependencies = [ "serde", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +dependencies = [ + "serde_core", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] [[package]] name = "bumpalo" @@ -322,11 +591,45 @@ version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "serde", +] + +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.11.0", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror 1.0.69", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] [[package]] name = "carpet-agent" @@ -344,6 +647,30 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "carpet-ui" +version = "0.1.0" +dependencies = [ + "axum", + "bdk-lib", + "dioxus", + "nostr-lib", + "phoenixd-lib", + "serde", + "serde_json", + "tokio", + "tracing", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.2.56" @@ -362,6 +689,27 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -375,963 +723,3343 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] -name = "cmake" -version = "0.1.57" +name = "chacha20" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ - "cc", + "cfg-if", + "cipher", + "cpufeatures", ] [[package]] -name = "combine" -version = "4.6.7" +name = "chacha20poly1305" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" dependencies = [ - "bytes", - "memchr", + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", ] [[package]] -name = "convert_case" -version = "0.10.0" +name = "charset" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +checksum = "f1f927b07c74ba84c7e5fe4db2baeb3e996ab2688992e39ac68ce3220a677c7e" dependencies = [ - "unicode-segmentation", + "base64 0.22.1", + "encoding_rs", ] [[package]] -name = "core-foundation" -version = "0.9.4" +name = "chrono" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ - "core-foundation-sys", - "libc", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link 0.2.1", ] [[package]] -name = "core-foundation" -version = "0.10.1" +name = "ciborium" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ - "core-foundation-sys", - "libc", + "ciborium-io", + "ciborium-ll", + "serde", ] [[package]] -name = "core-foundation-sys" -version = "0.8.7" +name = "ciborium-io" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] -name = "deluxe" -version = "0.5.0" +name = "ciborium-ll" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed332aaf752b459088acf3dd4eca323e3ef4b83c70a84ca48fb0ec5305f1488" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ - "deluxe-core", - "deluxe-macros", - "once_cell", - "proc-macro2", - "syn", + "ciborium-io", + "half", ] [[package]] -name = "deluxe-core" -version = "0.5.0" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddada51c8576df9d6a8450c351ff63042b092c9458b8ac7d20f89cbd0ffd313" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "arrayvec", - "proc-macro2", - "quote", - "strsim", - "syn", + "crypto-common", + "inout", + "zeroize", ] [[package]] -name = "deluxe-macros" -version = "0.5.0" +name = "cmake" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87546d9c837f0b7557e47b8bd6eae52c3c223141b76aa233c345c9ab41d9117" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" dependencies = [ - "deluxe-core", - "heck 0.4.1", - "if_chain", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", + "cc", ] [[package]] -name = "dirs" -version = "6.0.0" +name = "cocoa" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +checksum = "ad36507aeb7e16159dfe68db81ccc27571c3ccd4b76fb2fb72fc59e7a4b1b64c" dependencies = [ - "dirs-sys", + "bitflags 2.11.0", + "block", + "cocoa-foundation", + "core-foundation 0.10.1", + "core-graphics 0.24.0", + "foreign-types 0.5.0", + "libc", + "objc", ] [[package]] -name = "dirs-sys" -version = "0.5.0" +name = "cocoa-foundation" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +checksum = "81411967c50ee9a1fc11365f8c585f863a22a9697c89239c452292c40ba79b0d" dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.61.2", + "bitflags 2.11.0", + "block", + "core-foundation 0.10.1", + "core-graphics-types", + "objc", ] [[package]] -name = "displaydoc" -version = "0.2.5" +name = "combine" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ - "proc-macro2", - "quote", - "syn", + "bytes", + "memchr", ] [[package]] -name = "dunce" -version = "1.0.5" +name = "const-serialize" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +checksum = "ad7154afa56de2f290e3c82c2c6dc4f5b282b6870903f56ef3509aba95866edc" +dependencies = [ + "const-serialize-macro 0.7.2", +] [[package]] -name = "dyn-clone" -version = "1.0.20" +name = "const-serialize" +version = "0.8.0-alpha.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +checksum = "9e42cd5aabba86f128b3763da1fec1491c0f728ce99245062cd49b6f9e6d235b" +dependencies = [ + "const-serialize 0.7.2", + "const-serialize-macro 0.8.0-alpha.0", + "serde", +] [[package]] -name = "encoding_rs" -version = "0.8.35" +name = "const-serialize-macro" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "4f160aad86b4343e8d4e261fee9965c3005b2fd6bc117d172ab65948779e4acf" dependencies = [ - "cfg-if", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "equivalent" -version = "1.0.2" +name = "const-serialize-macro" +version = "0.8.0-alpha.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "42571ed01eb46d2e1adcf99c8ca576f081e46f2623d13500eba70d1d99a4c439" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] -name = "errno" -version = "0.3.14" +name = "const-str" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +checksum = "b0664d2867b4a32697dfe655557f5c3b187e9b605b38612a748e5ec99811d160" + +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" dependencies = [ - "libc", - "windows-sys 0.61.2", + "const_format_proc_macros", ] [[package]] -name = "esplora-client" -version = "0.12.3" +name = "const_format_proc_macros" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f19e3ea99dbfbef0c1ec26d83e69de0c579f6aa6aaac4f44597805fcc27e97af" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" dependencies = [ - "bitcoin", - "hex-conservative", - "log", - "minreq", - "reqwest 0.12.28", - "serde", - "serde_json", - "tokio", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] -name = "eventsource-stream" -version = "0.2.3" +name = "content_disposition" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab" +checksum = "ebc14a88e1463ddd193906285abe5c360c7e8564e05ccc5d501755f7fbc9ca9c" dependencies = [ - "futures-core", - "nom", - "pin-project-lite", + "charset", ] [[package]] -name = "fastrand" -version = "2.3.0" +name = "convert_case" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] -name = "find-msvc-tools" -version = "0.1.9" +name = "convert_case" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] [[package]] -name = "fnv" -version = "1.0.7" +name = "convert_case" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] [[package]] -name = "foldhash" -version = "0.1.5" +name = "cookie" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] [[package]] -name = "foreign-types" -version = "0.3.2" +name = "cookie_store" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" dependencies = [ - "foreign-types-shared", + "cookie", + "document-features", + "idna", + "log", + "publicsuffix", + "serde", + "serde_derive", + "serde_json", + "time", + "url", ] [[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "core-foundation" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] [[package]] -name = "form_urlencoded" -version = "1.2.2" +name = "core-foundation" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ - "percent-encoding", + "core-foundation-sys", + "libc", ] [[package]] -name = "fs_extra" -version = "1.3.0" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "futures" -version = "0.3.32" +name = "core-graphics" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", + "bitflags 2.11.0", + "core-foundation 0.10.1", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", ] [[package]] -name = "futures-channel" -version = "0.3.32" +name = "core-graphics" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "futures-core", - "futures-sink", + "bitflags 2.11.0", + "core-foundation 0.10.1", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", ] [[package]] -name = "futures-core" -version = "0.3.32" +name = "core-graphics-types" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", + "libc", +] [[package]] -name = "futures-executor" -version = "0.3.32" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ - "futures-core", - "futures-task", - "futures-util", + "libc", ] [[package]] -name = "futures-io" -version = "0.3.32" +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] [[package]] -name = "futures-macro" -version = "0.3.32" +name = "crossbeam-channel" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "proc-macro2", - "quote", - "syn", + "crossbeam-utils", ] [[package]] -name = "futures-sink" -version = "0.3.32" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "futures-task" -version = "0.3.32" +name = "crunchy" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] -name = "futures-timer" -version = "3.0.3" +name = "crypto-common" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] [[package]] -name = "futures-util" -version = "0.3.32" +name = "cssparser" +version = "0.29.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "slab", + "cssparser-macros", + "dtoa-short", + "itoa", + "matches", + "phf 0.10.1", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", ] [[package]] -name = "getrandom" -version = "0.2.17" +name = "cssparser-macros" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", + "quote", + "syn 2.0.117", ] [[package]] -name = "getrandom" -version = "0.3.4" +name = "darling" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi 5.3.0", - "wasip2", - "wasm-bindgen", + "darling_core", + "darling_macro", ] [[package]] -name = "getrandom" -version = "0.4.2" +name = "darling_core" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ - "cfg-if", - "libc", - "r-efi 6.0.0", - "wasip2", - "wasip3", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "glob" -version = "0.3.3" +name = "darling_macro" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.117", +] [[package]] -name = "h2" -version = "0.4.13" +name = "dashmap" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] -name = "hashbrown" -version = "0.14.5" +name = "data-encoding" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" + +[[package]] +name = "dcosl-core" +version = "0.1.0" dependencies = [ - "ahash", - "serde", + "nostr", + "serde_json", + "thiserror 2.0.18", ] [[package]] -name = "hashbrown" -version = "0.15.5" +name = "deluxe" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "8ed332aaf752b459088acf3dd4eca323e3ef4b83c70a84ca48fb0ec5305f1488" dependencies = [ - "foldhash", + "deluxe-core", + "deluxe-macros", + "once_cell", + "proc-macro2", + "syn 2.0.117", ] [[package]] -name = "hashbrown" -version = "0.16.1" +name = "deluxe-core" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "eddada51c8576df9d6a8450c351ff63042b092c9458b8ac7d20f89cbd0ffd313" +dependencies = [ + "arrayvec", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] [[package]] -name = "heck" -version = "0.4.1" +name = "deluxe-macros" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "f87546d9c837f0b7557e47b8bd6eae52c3c223141b76aa233c345c9ab41d9117" +dependencies = [ + "deluxe-core", + "heck 0.4.1", + "if_chain", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] -name = "heck" -version = "0.5.0" +name = "deranged" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] [[package]] -name = "hex-conservative" -version = "0.2.2" +name = "derive_more" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ - "arrayvec", + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", ] [[package]] -name = "hex_lit" -version = "0.1.1" +name = "derive_more" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] [[package]] -name = "http" -version = "1.4.0" +name = "derive_more-impl" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "bytes", - "itoa", + "convert_case 0.10.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", + "unicode-xid", ] [[package]] -name = "http-body" -version = "1.0.1" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "bytes", - "http", + "block-buffer", + "crypto-common", + "subtle", ] [[package]] -name = "http-body-util" -version = "0.1.3" +name = "dioxus" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "92b583b48ac77158495e6678fe3a2b5954fc8866fc04cb9695dd146e88bc329d" dependencies = [ - "bytes", - "futures-core", + "dioxus-asset-resolver", + "dioxus-cli-config", + "dioxus-config-macro", + "dioxus-config-macros", + "dioxus-core", + "dioxus-core-macro", + "dioxus-desktop", + "dioxus-devtools", + "dioxus-document", + "dioxus-fullstack", + "dioxus-fullstack-macro", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-liveview", + "dioxus-logger", + "dioxus-router", + "dioxus-server", + "dioxus-signals", + "dioxus-ssr", + "dioxus-stores", + "dioxus-web", + "manganis", + "subsecond", + "warnings", +] + +[[package]] +name = "dioxus-asset-resolver" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0161af1d3cfc8ff31503ff1b7ee0068c97771fc38d0cc6566e23483142ddf4f" +dependencies = [ + "dioxus-cli-config", "http", - "http-body", - "pin-project-lite", + "infer", + "jni", + "js-sys", + "ndk", + "ndk-context", + "ndk-sys", + "percent-encoding", + "thiserror 2.0.18", + "tokio", + "wasm-bindgen-futures", + "web-sys", ] [[package]] -name = "httparse" -version = "1.10.1" +name = "dioxus-cli-config" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +checksum = "ccd67ab405e1915a47df9769cd5408545d1b559d5c01ce7a0f442caef520d1f3" +dependencies = [ + "wasm-bindgen", +] [[package]] -name = "hyper" -version = "1.8.1" +name = "dioxus-config-macro" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "f040ec7c41aa5428283f56bb0670afba9631bfe3ffd885f4814807f12c8c9d91" dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "h2", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "pin-utils", - "smallvec", - "tokio", - "want", + "proc-macro2", + "quote", ] [[package]] -name = "hyper-rustls" -version = "0.27.7" +name = "dioxus-config-macros" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "10c41b47b55a433b61f7c12327c85ba650572bacbcc42c342ba2e87a57975264" + +[[package]] +name = "dioxus-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b389b0e3cc01c7da292ad9b884b088835fdd1671d45fbd2f737506152b22eef0" dependencies = [ - "http", - "hyper", - "hyper-util", - "rustls 0.23.37", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", + "anyhow", + "const_format", + "dioxus-core-types", + "futures-channel", + "futures-util", + "generational-box", + "longest-increasing-subsequence", + "rustc-hash 2.1.1", + "rustversion", + "serde", + "slab", + "slotmap", + "subsecond", + "tracing", ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "dioxus-core-macro" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "6a82d65f0024fc86f01911a16156d280eea583be5a82a3bed85e7e8e4194302d" dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", + "convert_case 0.8.0", + "dioxus-rsx", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "hyper-util" -version = "0.1.20" +name = "dioxus-core-types" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +checksum = "bfc4b8cdc440a55c17355542fc2089d97949bba674255d84cac77805e1db8c9f" + +[[package]] +name = "dioxus-desktop" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e6ec66749d1556636c5b4f661495565c155a7f78a46d4d007d7478c6bdc288c" dependencies = [ + "async-trait", "base64 0.22.1", "bytes", + "cocoa", + "core-foundation 0.10.1", + "dioxus-asset-resolver", + "dioxus-cli-config", + "dioxus-core", + "dioxus-devtools", + "dioxus-document", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-interpreter-js", + "dioxus-signals", + "dunce", "futures-channel", "futures-util", - "http", - "http-body", - "hyper", - "ipnet", + "generational-box", + "global-hotkey", + "infer", + "jni", + "lazy-js-bundle", "libc", + "muda", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "objc_id", "percent-encoding", - "pin-project-lite", - "socket2", - "system-configuration", + "rand 0.9.2", + "rfd", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "signal-hook", + "slab", + "subtle", + "tao", + "thiserror 2.0.18", "tokio", - "tower-service", "tracing", - "windows-registry", + "tray-icon", + "tungstenite 0.27.0", + "webbrowser", + "wry", ] [[package]] -name = "icu_collections" -version = "2.1.1" +name = "dioxus-devtools" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "dcf89488bad8fb0f18b9086ee2db01f95f709801c10c68be42691a36378a0f2d" dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", + "dioxus-cli-config", + "dioxus-core", + "dioxus-devtools-types", + "dioxus-signals", + "futures-channel", + "futures-util", + "serde", + "serde_json", + "subsecond", + "thiserror 2.0.18", + "tracing", + "tungstenite 0.27.0", ] [[package]] -name = "icu_locale_core" +name = "dioxus-devtools-types" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e7381d9d7d0a0f66b9d5082d584853c3d53be21d34007073daca98ddf26fc4d" +dependencies = [ + "dioxus-core", + "serde", + "subsecond-types", +] + +[[package]] +name = "dioxus-document" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba0aeeff26d9d06441f59fd8d7f4f76098ba30ca9728e047c94486161185ceb" +dependencies = [ + "dioxus-core", + "dioxus-core-macro", + "dioxus-core-types", + "dioxus-html", + "futures-channel", + "futures-util", + "generational-box", + "lazy-js-bundle", + "serde", + "serde_json", + "tracing", +] + +[[package]] +name = "dioxus-fullstack" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7db1f8b70338072ec408b48d09c96559cf071f87847465d8161294197504c498" +dependencies = [ + "anyhow", + "async-stream", + "async-tungstenite", + "axum", + "axum-core", + "axum-extra", + "base64 0.22.1", + "bytes", + "ciborium", + "const-str", + "const_format", + "content_disposition", + "derive_more 2.1.1", + "dioxus-asset-resolver", + "dioxus-cli-config", + "dioxus-core", + "dioxus-fullstack-core", + "dioxus-fullstack-macro", + "dioxus-hooks", + "dioxus-html", + "dioxus-signals", + "form_urlencoded", + "futures", + "futures-channel", + "futures-util", + "gloo-net", + "headers", + "http", + "http-body", + "http-body-util", + "inventory", + "js-sys", + "mime", + "pin-project", + "reqwest 0.12.28", + "rustversion", + "send_wrapper", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tokio-tungstenite 0.27.0", + "tokio-util", + "tower", + "tower-http", + "tower-layer", + "tracing", + "tungstenite 0.27.0", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", + "xxhash-rust", +] + +[[package]] +name = "dioxus-fullstack-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda8b152e85121243741b9d5f2a3d8cb3c47a7b2299e902f98b6a7719915b0a2" +dependencies = [ + "anyhow", + "axum-core", + "base64 0.22.1", + "ciborium", + "dioxus-core", + "dioxus-document", + "dioxus-history", + "dioxus-hooks", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "http", + "inventory", + "parking_lot", + "serde", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tracing", +] + +[[package]] +name = "dioxus-fullstack-macro" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "255104d4a4f278f1a8482fa30536c91d22260c561c954b753e72987df8d65b2e" +dependencies = [ + "const_format", + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", + "xxhash-rust", +] + +[[package]] +name = "dioxus-history" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d00ba43bfe6e5ca226fef6128f240ca970bea73cac0462416188026360ccdcf" +dependencies = [ + "dioxus-core", + "tracing", +] + +[[package]] +name = "dioxus-hooks" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab2da4f038c33cb38caa37ffc3f5d6dfbc018f05da35b238210a533bb075823" +dependencies = [ + "dioxus-core", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "rustversion", + "slab", + "tracing", +] + +[[package]] +name = "dioxus-html" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded5fa6d2e677b7442a93f4228bf3c0ad2597a8bd3292cae50c869d015f3a99" +dependencies = [ + "async-trait", + "bytes", + "dioxus-core", + "dioxus-core-macro", + "dioxus-core-types", + "dioxus-hooks", + "dioxus-html-internal-macro", + "enumset", + "euclid", + "futures-channel", + "futures-util", + "generational-box", + "keyboard-types", + "lazy-js-bundle", + "rustversion", + "serde", + "serde_json", + "serde_repr", + "tracing", +] + +[[package]] +name = "dioxus-html-internal-macro" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45462ab85fe059a36841508d40545109fd0e25855012d22583a61908eb5cd02a" +dependencies = [ + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-interpreter-js" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a42a7f73ad32a5054bd8c1014f4ac78cca3b7f6889210ee2b57ea31b33b6d32f" +dependencies = [ + "dioxus-core", + "dioxus-core-types", + "dioxus-html", + "js-sys", + "lazy-js-bundle", + "rustc-hash 2.1.1", + "serde", + "sledgehammer_bindgen", + "sledgehammer_utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "dioxus-liveview" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f7a1cfe6f8e9f2e303607c8ae564d11932fd80714c8a8c97e3860d55538997" +dependencies = [ + "axum", + "dioxus-cli-config", + "dioxus-core", + "dioxus-devtools", + "dioxus-document", + "dioxus-history", + "dioxus-html", + "dioxus-interpreter-js", + "futures-channel", + "futures-util", + "generational-box", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "slab", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", +] + +[[package]] +name = "dioxus-logger" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1eeab114cb009d9e6b85ea10639a18cfc54bb342f3b837770b004c4daeb89c2" +dependencies = [ + "dioxus-cli-config", + "tracing", + "tracing-subscriber", + "tracing-wasm", +] + +[[package]] +name = "dioxus-router" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d5b31f9e27231389bf5a117b7074d22d8c58358b484a2558e56fbab20e64ca4" +dependencies = [ + "dioxus-cli-config", + "dioxus-core", + "dioxus-core-macro", + "dioxus-fullstack-core", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-router-macro", + "dioxus-signals", + "percent-encoding", + "rustversion", + "tracing", + "url", +] + +[[package]] +name = "dioxus-router-macro" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "838b9b441a95da62b39cae4defd240b5ebb0ec9f2daea1126099e00a838dc86f" +dependencies = [ + "base16", + "digest", + "proc-macro2", + "quote", + "sha2", + "slab", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-rsx" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53128858f0ccca9de54292a4d48409fda1df75fd5012c6243f664042f0225d68" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "rustversion", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-server" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adb2d4e0f0f3a157bda6af2d90f22bac40070e509a66e3ea58abf3b35f904c" +dependencies = [ + "anyhow", + "async-trait", + "axum", + "base64 0.22.1", + "bytes", + "chrono", + "ciborium", + "dashmap", + "dioxus-cli-config", + "dioxus-core", + "dioxus-core-macro", + "dioxus-devtools", + "dioxus-document", + "dioxus-fullstack-core", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-interpreter-js", + "dioxus-logger", + "dioxus-router", + "dioxus-signals", + "dioxus-ssr", + "enumset", + "futures", + "futures-channel", + "futures-util", + "generational-box", + "http", + "http-body-util", + "hyper", + "hyper-util", + "inventory", + "lru", + "parking_lot", + "pin-project", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "serde_qs", + "subsecond", + "thiserror 2.0.18", + "tokio", + "tokio-tungstenite 0.27.0", + "tokio-util", + "tower", + "tower-http", + "tracing", + "tracing-futures", + "url", + "walkdir", +] + +[[package]] +name = "dioxus-signals" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f48020bc23bc9766e7cce986c0fd6de9af0b8cbfd432652ec6b1094439c1ec6" +dependencies = [ + "dioxus-core", + "futures-channel", + "futures-util", + "generational-box", + "parking_lot", + "rustc-hash 2.1.1", + "tracing", + "warnings", +] + +[[package]] +name = "dioxus-ssr" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44cf9294a21fcd1098e02ad7a3ba61b99be8310ad3395fecf8210387c83f26b9" +dependencies = [ + "askama_escape", + "dioxus-core", + "dioxus-core-types", + "rustc-hash 2.1.1", +] + +[[package]] +name = "dioxus-stores" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77aaa9ac56d781bb506cf3c0d23bea96b768064b89fe50d3b4d4659cc6bd8058" +dependencies = [ + "dioxus-core", + "dioxus-signals", + "dioxus-stores-macro", + "generational-box", +] + +[[package]] +name = "dioxus-stores-macro" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b1a728622e7b63db45774f75e71504335dd4e6115b235bbcff272980499493a" +dependencies = [ + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-web" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b33fe739fed4e8143dac222a9153593f8e2451662ce8fc4c9d167a9d6ec0923" +dependencies = [ + "dioxus-cli-config", + "dioxus-core", + "dioxus-core-types", + "dioxus-devtools", + "dioxus-document", + "dioxus-history", + "dioxus-html", + "dioxus-interpreter-js", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "gloo-timers", + "js-sys", + "lazy-js-bundle", + "rustc-hash 2.1.1", + "send_wrapper", + "serde", + "serde-wasm-bindgen", + "serde_json", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.11.0", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dlopen2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "dtoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enumset" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b07a8dfbbbfc0064c0a6bdf9edcf966de6b1c33ce344bdeca3b41615452634" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "esplora-client" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f19e3ea99dbfbef0c1ec26d83e69de0c579f6aa6aaac4f44597805fcc27e97af" +dependencies = [ + "bitcoin", + "hex-conservative", + "log", + "minreq", + "reqwest 0.12.28", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "euclid" +version = "0.22.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df61bf483e837f88d5c2291dcf55c67be7e676b3a51acc48db3a7b163b91ed63" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "eventsource-stream" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab" +dependencies = [ + "futures-core", + "nom", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "gdk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkwayland-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69" +dependencies = [ + "gdk-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkx11-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d" +dependencies = [ + "gdk-sys", + "glib-sys", + "libc", + "system-deps", + "x11", +] + +[[package]] +name = "generational-box" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4ed190b9de8e734d47a70be59b1e7588b9e8e0d0036e332f4c014e8aed1bc5" +dependencies = [ + "parking_lot", + "tracing", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix", + "windows-link 0.2.1", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.11.0", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 2.0.2", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "global-hotkey" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9247516746aa8e53411a0db9b62b0e24efbcf6a76e0ba73e5a91b512ddabed7" +dependencies = [ + "crossbeam-channel", + "keyboard-types", + "objc2", + "objc2-app-kit", + "once_cell", + "thiserror 2.0.18", + "windows-sys 0.59.0", + "x11rb", + "xkeysym", +] + +[[package]] +name = "gloo-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror 1.0.69", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "h2" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "headers" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" +dependencies = [ + "base64 0.22.1", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "html5ever" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" +dependencies = [ + "log", + "mac", + "markup5ever", + "match_token", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls 0.23.37", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots 1.0.6", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-layer", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "if_chain" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd62e6b5e86ea8eeeb8db1de02880a6abc01a397b2ebb64b5d74ac255318f5cb" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +dependencies = [ + "cfb", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "inventory" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009ae045c87e7082cb72dab0ccd01ae075dd00141ddc108f43a0ea150a9e7227" +dependencies = [ + "rustversion", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "iri-string" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "javascriptcore-rs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.11.0", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "kuchikiki" +version = "0.8.8-speedreader" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" +dependencies = [ + "cssparser", + "html5ever", + "indexmap", + "selectors", +] + +[[package]] +name = "lazy-js-bundle" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7b88b715ab1496c6e6b8f5e927be961c4235196121b6ae59bcb51077a21dd36" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libappindicator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" +dependencies = [ + "gtk-sys", + "libloading 0.7.4", + "once_cell", +] + +[[package]] +name = "libc" +version = "0.2.182" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + +[[package]] +name = "libredox" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" +dependencies = [ + "libc", +] + +[[package]] +name = "libxdo" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00333b8756a3d28e78def82067a377de7fa61b24909000aeaa2b446a948d14db" +dependencies = [ + "libxdo-sys", +] + +[[package]] +name = "libxdo-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23b9e7e2b7831bbd8aac0bbeeeb7b68cbebc162b227e7052e8e55829a09212" +dependencies = [ + "libc", + "x11", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "longest-increasing-subsequence" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" + +[[package]] +name = "lru" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +dependencies = [ + "hashbrown 0.16.1", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "manganis" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cce7d688848bf9d034168513b9a2ffbfe5f61df2ff14ae15e6cfc866efdd344" +dependencies = [ + "const-serialize 0.7.2", + "const-serialize 0.8.0-alpha.0", + "manganis-core", + "manganis-macro", +] + +[[package]] +name = "manganis-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84ce917b978268fe8a7db49e216343ec7c8f471f7e686feb70940d67293f19d4" +dependencies = [ + "const-serialize 0.7.2", + "const-serialize 0.8.0-alpha.0", + "dioxus-cli-config", + "dioxus-core-types", + "serde", + "winnow 0.7.15", +] + +[[package]] +name = "manganis-macro" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad513e990f7c0bca86aa68659a7a3dc4c705572ed4c22fd6af32ccf261334cc2" +dependencies = [ + "dunce", + "macro-string", + "manganis-core", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "markup5ever" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" +dependencies = [ + "log", + "phf 0.11.3", + "phf_codegen 0.11.3", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memfd" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" +dependencies = [ + "rustix", +] + +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", ] [[package]] -name = "icu_normalizer" -version = "2.1.1" +name = "memoffset" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", + "autocfg", ] [[package]] -name = "icu_normalizer_data" -version = "2.1.1" +name = "mime" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] -name = "icu_properties" -version = "2.1.2" +name = "mime_guess" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", + "mime", + "unicase", ] [[package]] -name = "icu_properties_data" -version = "2.1.2" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] -name = "icu_provider" -version = "2.1.1" +name = "miniscript" +version = "12.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "487906208f38448e186e3deb02f2b8ef046a9078b0de00bdb28bf4fb9b76951c" dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", + "bech32", + "bitcoin", + "serde", ] [[package]] -name = "id-arena" -version = "2.3.0" +name = "miniz_oxide" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] [[package]] -name = "idna" -version = "1.1.0" +name = "minreq" +version = "2.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +checksum = "05015102dad0f7d61691ca347e9d9d9006685a64aefb3d79eecf62665de2153d" dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", + "base64 0.22.1", + "rustls 0.21.12", + "rustls-webpki 0.101.7", + "serde", + "serde_json", + "webpki-roots 0.25.4", ] [[package]] -name = "idna_adapter" -version = "1.2.1" +name = "mio" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ - "icu_normalizer", - "icu_properties", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.61.2", ] [[package]] -name = "if_chain" -version = "1.0.3" +name = "muda" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd62e6b5e86ea8eeeb8db1de02880a6abc01a397b2ebb64b5d74ac255318f5cb" +checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "libxdo", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "once_cell", + "png", + "thiserror 2.0.18", + "windows-sys 0.60.2", +] [[package]] -name = "indexmap" -version = "2.13.0" +name = "multer" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" dependencies = [ - "equivalent", - "hashbrown 0.16.1", - "serde", - "serde_core", + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "memchr", + "mime", + "spin", + "version_check", ] [[package]] -name = "indoc" -version = "2.0.7" +name = "nanoid" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" dependencies = [ - "rustversion", + "rand 0.8.5", ] [[package]] -name = "ipnet" -version = "2.12.0" +name = "native-tls" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] [[package]] -name = "iri-string" -version = "0.7.10" +name = "ndk" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "memchr", - "serde", + "bitflags 2.11.0", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle 0.6.2", + "thiserror 1.0.69", ] [[package]] -name = "itoa" -version = "1.0.17" +name = "ndk-context" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] -name = "jni" -version = "0.21.1" +name = "ndk-sys" +version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ - "cesu8", - "cfg-if", - "combine", "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", ] [[package]] -name = "jni-sys" -version = "0.3.0" +name = "negentropy" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "f0efe882e02d206d8d279c20eb40e03baf7cb5136a1476dc084a324fbc3ec42d" [[package]] -name = "jobserver" -version = "0.1.34" +name = "new_debug_unreachable" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] -name = "js-sys" -version = "0.3.91" +name = "nodrop" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "once_cell", - "wasm-bindgen", + "memchr", + "minimal-lexical", ] [[package]] -name = "lazy_static" -version = "1.5.0" +name = "nostr" +version = "0.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "3aa5e3b6a278ed061835fe1ee293b71641e6bf8b401cfe4e1834bbf4ef0a34e1" +dependencies = [ + "aes", + "base64 0.22.1", + "bech32", + "bip39", + "bitcoin_hashes", + "cbc", + "chacha20", + "chacha20poly1305", + "getrandom 0.2.17", + "hex", + "instant", + "scrypt", + "secp256k1", + "serde", + "serde_json", + "unicode-normalization", + "url", +] [[package]] -name = "leb128fmt" -version = "0.1.0" +name = "nostr-database" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +checksum = "7462c9d8ae5ef6a28d66a192d399ad2530f1f2130b13186296dbb11bdef5b3d1" +dependencies = [ + "lru", + "nostr", + "tokio", +] [[package]] -name = "libc" -version = "0.2.182" +name = "nostr-gossip" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "ade30de16869618919c6b5efc8258f47b654a98b51541eb77f85e8ec5e3c83a6" +dependencies = [ + "nostr", +] [[package]] -name = "libredox" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" +name = "nostr-lib" +version = "0.1.0" dependencies = [ - "libc", + "dcosl-core", + "nostr-sdk", + "phoenixd-lib", + "serde", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tracing", ] [[package]] -name = "linux-raw-sys" -version = "0.12.1" +name = "nostr-relay-pool" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +checksum = "4b1073ccfbaea5549fb914a9d52c68dab2aecda61535e5143dd73e95445a804b" +dependencies = [ + "async-utility", + "async-wsocket", + "atomic-destructor", + "hex", + "lru", + "negentropy", + "nostr", + "nostr-database", + "tokio", + "tracing", +] [[package]] -name = "litemap" -version = "0.8.1" +name = "nostr-sdk" +version = "0.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "471732576710e779b64f04c55e3f8b5292f865fea228436daf19694f0bf70393" +dependencies = [ + "async-utility", + "nostr", + "nostr-database", + "nostr-gossip", + "nostr-relay-pool", + "tokio", + "tracing", +] [[package]] -name = "lock_api" -version = "0.4.14" +name = "nu-ansi-term" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "scopeguard", + "windows-sys 0.61.2", ] [[package]] -name = "log" -version = "0.4.29" +name = "num-conv" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] -name = "lru-slab" -version = "0.1.2" +name = "num-traits" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] [[package]] -name = "matchers" -version = "0.2.0" +name = "num_enum" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ - "regex-automata", + "num_enum_derive", + "rustversion", ] [[package]] -name = "memchr" -version = "2.8.0" +name = "num_enum_derive" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] -name = "mime" -version = "0.3.17" +name = "objc" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] [[package]] -name = "mime_guess" -version = "2.0.5" +name = "objc2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ - "mime", - "unicase", + "objc2-encode", + "objc2-exception-helper", ] [[package]] -name = "minimal-lexical" -version = "0.2.1" +name = "objc2-app-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] [[package]] -name = "miniscript" -version = "12.3.5" +name = "objc2-core-foundation" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487906208f38448e186e3deb02f2b8ef046a9078b0de00bdb28bf4fb9b76951c" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bech32", - "bitcoin", - "serde", + "bitflags 2.11.0", + "dispatch2", + "objc2", ] [[package]] -name = "minreq" -version = "2.14.1" +name = "objc2-core-graphics" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05015102dad0f7d61691ca347e9d9d9006685a64aefb3d79eecf62665de2153d" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "base64 0.22.1", - "rustls 0.21.12", - "rustls-webpki 0.101.7", - "serde", - "serde_json", - "webpki-roots", + "bitflags 2.11.0", + "objc2-core-foundation", ] [[package]] -name = "mio" -version = "1.1.1" +name = "objc2-encode" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", -] +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] -name = "nanoid" -version = "0.4.0" +name = "objc2-exception-helper" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" +checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" dependencies = [ - "rand 0.8.5", + "cc", ] [[package]] -name = "native-tls" -version = "0.2.18" +name = "objc2-foundation" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", + "bitflags 2.11.0", + "block2", + "objc2", + "objc2-core-foundation", ] [[package]] -name = "nom" -version = "7.1.3" +name = "objc2-ui-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "memchr", - "minimal-lexical", + "bitflags 2.11.0", + "objc2", + "objc2-core-foundation", + "objc2-foundation", ] [[package]] -name = "nu-ansi-term" -version = "0.50.3" +name = "objc2-web-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "windows-sys 0.61.2", + "bitflags 2.11.0", + "block2", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", ] [[package]] -name = "num-traits" -version = "0.2.19" +name = "objc_id" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" dependencies = [ - "autocfg", + "objc", ] [[package]] @@ -1340,15 +4068,21 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "openssl" version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags", + "bitflags 2.11.0", "cfg-if", - "foreign-types", + "foreign-types 0.3.2", "libc", "once_cell", "openssl-macros", @@ -1363,7 +4097,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1399,6 +4133,31 @@ dependencies = [ "num-traits", ] +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -1419,7 +4178,28 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", ] [[package]] @@ -1428,6 +4208,126 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_shared 0.8.0", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_macros", + "phf_shared 0.10.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared 0.11.3", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher 1.0.2", +] + [[package]] name = "phoenixd-agcli" version = "0.1.0" @@ -1466,7 +4366,7 @@ checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1487,6 +4387,36 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "potential_utf" version = "0.1.4" @@ -1496,6 +4426,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1506,32 +4442,106 @@ dependencies = [ ] [[package]] -name = "prettyplease" -version = "0.2.37" +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", - "syn", + "quote", + "syn 2.0.117", + "version_check", ] [[package]] -name = "proc-macro-crate" -version = "1.3.1" +name = "psl-types" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit", -] +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] -name = "proc-macro2" -version = "1.0.106" +name = "publicsuffix" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" dependencies = [ - "unicode-ident", + "idna", + "psl-types", ] [[package]] @@ -1545,7 +4555,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", + "rustc-hash 2.1.1", "rustls 0.23.37", "socket2", "thiserror 2.0.18", @@ -1566,7 +4576,7 @@ dependencies = [ "lru-slab", "rand 0.9.2", "ring", - "rustc-hash", + "rustc-hash 2.1.1", "rustls 0.23.37", "rustls-pki-types", "slab", @@ -1611,6 +4621,20 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + [[package]] name = "rand" version = "0.8.5" @@ -1632,6 +4656,16 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -1652,6 +4686,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + [[package]] name = "rand_core" version = "0.6.4" @@ -1670,13 +4713,43 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.11.0", ] [[package]] @@ -1707,7 +4780,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1735,8 +4808,11 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", + "cookie", + "cookie_store", "encoding_rs", "futures-core", + "futures-util", "h2", "http", "http-body", @@ -1748,9 +4824,12 @@ dependencies = [ "js-sys", "log", "mime", + "mime_guess", "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls 0.23.37", "rustls-pki-types", "serde", "serde_json", @@ -1758,13 +4837,17 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", + "tokio-rustls", + "tokio-util", "tower", "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams 0.4.2", "web-sys", + "webpki-roots 1.0.6", ] [[package]] @@ -1807,8 +4890,32 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.5.0", + "web-sys", +] + +[[package]] +name = "rfd" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20dafead71c16a34e1ff357ddefc8afc11e7d51d6d2b9fbd07eaa48e3e540220" +dependencies = [ + "block2", + "dispatch2", + "js-sys", + "libc", + "log", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "percent-encoding", + "pollster", + "raw-window-handle 0.6.2", + "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1850,13 +4957,13 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b6d9818c9cb13d00664b52fd3e47b0554bc2d5c59cfb90340dd9411b09553bc" dependencies = [ - "convert_case", + "convert_case 0.10.0", "deluxe", "indoc", "proc-macro2", "quote", "serde_json", - "syn", + "syn 2.0.117", ] [[package]] @@ -1873,19 +4980,34 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys", @@ -1912,6 +5034,7 @@ checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ "aws-lc-rs", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki 0.103.9", "subtle", @@ -2001,6 +5124,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -2041,7 +5173,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn", + "syn 2.0.117", ] [[package]] @@ -2050,6 +5182,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash", + "pbkdf2", + "salsa20", + "sha2", +] + [[package]] name = "sct" version = "0.7.1" @@ -2087,7 +5231,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", + "bitflags 2.11.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -2104,12 +5248,39 @@ dependencies = [ "libc", ] +[[package]] +name = "selectors" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more 0.99.20", + "fxhash", + "log", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + [[package]] name = "semver" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +dependencies = [ + "futures-core", +] + [[package]] name = "serde" version = "1.0.228" @@ -2120,6 +5291,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_core" version = "1.0.228" @@ -2137,7 +5319,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2148,7 +5330,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2164,6 +5346,48 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", +] + +[[package]] +name = "serde_qs" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3faaf9e727533a19351a43cc5a8de957372163c7d35cc48c90b75cdda13c352" +dependencies = [ + "percent-encoding", + "serde", + "thiserror 2.0.18", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2176,6 +5400,38 @@ dependencies = [ "serde", ] +[[package]] +name = "servo_arc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2191,43 +5447,167 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + [[package]] name = "signal-hook-registry" version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "siphasher" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "sledgehammer_bindgen" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e83e178d176459c92bc129cfd0958afac3ced925471b889b3a75546cfc4133" +dependencies = [ + "sledgehammer_bindgen_macro", + "wasm-bindgen", +] + +[[package]] +name = "sledgehammer_bindgen_macro" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb251b407f50028476a600541542b605bb864d35d9ee1de4f6cab45d88475e6d" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "sledgehammer_utils" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "debdd4b83524961983cea3c55383b3910fd2f24fd13a188f5b091d2d504a61ae" +dependencies = [ + "rustc-hash 1.1.0", +] + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "serde", + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "soup3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" +dependencies = [ + "futures-channel", + "gio", + "glib", + "libc", + "soup3-sys", +] + +[[package]] +name = "soup3-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" dependencies = [ - "errno", + "gio-sys", + "glib-sys", + "gobject-sys", "libc", + "system-deps", ] [[package]] -name = "slab" -version = "0.4.12" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] -name = "smallvec" -version = "1.15.1" +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] -name = "socket2" -version = "0.6.3" +name = "string_cache" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ - "libc", - "windows-sys 0.61.2", + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.11.3", + "precomputed-hash", + "serde", ] [[package]] -name = "stable_deref_trait" -version = "1.2.1" +name = "string_cache_codegen" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] [[package]] name = "strsim" @@ -2235,12 +5615,51 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subsecond" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8438668e545834d795d04c4335aafc332ce046106521a29f0a5c6501de34187c" +dependencies = [ + "js-sys", + "libc", + "libloading 0.8.9", + "memfd", + "memmap2", + "serde", + "subsecond-types", + "thiserror 2.0.18", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "subsecond-types" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e72f747606fc19fe81d6c59e491af93ed7dcbcb6aad9d1d18b05129914ec298" +dependencies = [ + "serde", +] + [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.117" @@ -2269,7 +5688,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2278,7 +5697,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags", + "bitflags 2.11.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -2293,6 +5712,75 @@ dependencies = [ "libc", ] +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "tao" +version = "0.34.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d52c379e63da659a483a958110bbde891695a0ecb53e48cc7786d5eda7bb" +dependencies = [ + "bitflags 2.11.0", + "block2", + "core-foundation 0.10.1", + "core-graphics 0.25.0", + "crossbeam-channel", + "dispatch2", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "jni", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "once_cell", + "parking_lot", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "tao-macros", + "unicode-segmentation", + "url", + "windows", + "windows-core 0.61.2", + "windows-version", + "x11-dl", +] + +[[package]] +name = "tao-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "tempfile" version = "3.26.0" @@ -2306,6 +5794,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -2332,7 +5831,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2343,7 +5842,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2355,6 +5854,37 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinystr" version = "0.8.2" @@ -2405,7 +5935,7 @@ checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2428,6 +5958,70 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-socks" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +dependencies = [ + "either", + "futures-util", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" +dependencies = [ + "futures-util", + "log", + "rustls 0.23.37", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tungstenite 0.26.2", + "webpki-roots 0.26.11", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.27.0", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.28.0", +] + [[package]] name = "tokio-util" version = "0.7.18" @@ -2436,16 +6030,33 @@ checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", + "futures-util", "pin-project-lite", "tokio", ] +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", +] + [[package]] name = "toml_datetime" -version = "0.6.11" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -2455,7 +6066,20 @@ checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.5.40", ] [[package]] @@ -2471,6 +6095,7 @@ dependencies = [ "tokio", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -2479,16 +6104,26 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags", + "bitflags 2.11.0", "bytes", + "futures-core", "futures-util", "http", "http-body", + "http-body-util", + "http-range-header", + "httpdate", "iri-string", + "mime", + "mime_guess", + "percent-encoding", "pin-project-lite", + "tokio", + "tokio-util", "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -2509,6 +6144,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2522,7 +6158,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2576,12 +6212,105 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "tracing-wasm" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" +dependencies = [ + "tracing", + "tracing-subscriber", + "wasm-bindgen", +] + +[[package]] +name = "tray-icon" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e85aa143ceb072062fc4d6356c1b520a51d636e7bc8e77ec94be3608e5e80c" +dependencies = [ + "crossbeam-channel", + "dirs", + "libappindicator", + "muda", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "once_cell", + "png", + "thiserror 2.0.18", + "windows-sys 0.60.2", +] + [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.2", + "rustls 0.23.37", + "rustls-pki-types", + "sha1", + "thiserror 2.0.18", + "utf-8", +] + +[[package]] +name = "tungstenite" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "native-tls", + "rand 0.9.2", + "rustls 0.23.37", + "sha1", + "thiserror 2.0.18", + "utf-8", +] + +[[package]] +name = "tungstenite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.2", + "sha1", + "thiserror 2.0.18", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + [[package]] name = "unicase" version = "2.9.0" @@ -2615,6 +6344,16 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -2631,13 +6370,30 @@ dependencies = [ "idna", "percent-encoding", "serde", + "serde_derive", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "valuable" @@ -2651,6 +6407,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + [[package]] name = "version_check" version = "0.9.5" @@ -2676,6 +6438,34 @@ dependencies = [ "try-lock", ] +[[package]] +name = "warnings" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f68998838dab65727c9b30465595c6f7c953313559371ca8bf31759b3680ad" +dependencies = [ + "pin-project", + "tracing", + "warnings-macro", +] + +[[package]] +name = "warnings-macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59195a1db0e95b920366d949ba5e0d3fc0e70b67c09be15ce5abb790106b0571" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -2746,7 +6536,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -2781,6 +6571,19 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wasm-streams" version = "0.5.0" @@ -2800,7 +6603,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags", + "bitflags 2.11.0", "hashbrown 0.15.5", "indexmap", "semver", @@ -2826,6 +6629,66 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webbrowser" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f00bb839c1cf1e3036066614cbdcd035ecf215206691ea646aa3c60a24f68f2" +dependencies = [ + "core-foundation 0.10.1", + "jni", + "log", + "ndk-context", + "objc2", + "objc2-foundation", + "url", + "web-sys", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "soup3-sys", + "system-deps", +] + [[package]] name = "webpki-root-certs" version = "1.0.6" @@ -2841,6 +6704,76 @@ version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.6", +] + +[[package]] +name = "webpki-roots" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webview2-com" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows", + "windows-core 0.61.2", + "windows-implement", + "windows-interface", +] + +[[package]] +name = "webview2-com-macros" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "webview2-com-sys" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" +dependencies = [ + "thiserror 2.0.18", + "windows", + "windows-core 0.61.2", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" @@ -2850,21 +6783,133 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + [[package]] name = "windows-registry" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -2873,7 +6918,16 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -2882,7 +6936,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -2903,6 +6957,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.60.2" @@ -2918,7 +6981,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -2958,7 +7021,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link", + "windows-link 0.2.1", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -2969,6 +7032,24 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -3116,6 +7197,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen" version = "0.51.0" @@ -3146,7 +7236,7 @@ dependencies = [ "heck 0.5.0", "indexmap", "prettyplease", - "syn", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -3162,7 +7252,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -3174,7 +7264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags", + "bitflags 2.11.0", "indexmap", "log", "serde", @@ -3210,6 +7300,99 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +[[package]] +name = "wry" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2" +dependencies = [ + "base64 0.22.1", + "block2", + "cookie", + "crossbeam-channel", + "dirs", + "dpi", + "dunce", + "gtk", + "html5ever", + "http", + "javascriptcore-rs", + "jni", + "kuchikiki", + "libc", + "ndk", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", + "once_cell", + "percent-encoding", + "raw-window-handle 0.6.2", + "sha2", + "soup3", + "tao-macros", + "thiserror 2.0.18", + "url", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows", + "windows-core 0.61.2", + "windows-version", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "gethostname", + "rustix", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + [[package]] name = "yoke" version = "0.8.1" @@ -3229,7 +7412,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", "synstructure", ] @@ -3250,7 +7433,7 @@ checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -3270,7 +7453,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", "synstructure", ] @@ -3310,7 +7493,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a303a9b..8feca9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,15 @@ [workspace] resolver = "2" members = ["crates/*"] +# Exclude carpet-ui from default workspace checks — it needs platform-specific features +default-members = [ + "crates/bdk-lib", + "crates/bdk-agcli", + "crates/phoenixd-lib", + "crates/phoenixd-agcli", + "crates/carpet-agent", + "crates/nostr-lib", +] [workspace.package] edition = "2024" diff --git a/crates/bdk-agcli/src/main.rs b/crates/bdk-agcli/src/main.rs index 3dfc0ab..0128316 100644 --- a/crates/bdk-agcli/src/main.rs +++ b/crates/bdk-agcli/src/main.rs @@ -19,6 +19,7 @@ fn parse_bool_flag(req: &CommandRequest<'_>, name: &str) -> Result CommandError { let code = match &e { BdkLibError::Wallet(_) => "WALLET_ERROR", @@ -56,189 +57,170 @@ fn resolve_config() -> WalletConfig { } fn init_command() -> Command { - Command::new("init", "Generate or import a wallet mnemonic and descriptors") - .usage("bdk-agcli init --generate | --import=") - .sync_handler(|req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let generate = parse_bool_flag(req, "generate")?; - let import = req.flag("import").map(String::from); + Command::new( + "init", + "Generate or import a wallet mnemonic and descriptors", + ) + .usage("bdk-agcli init --generate | --import=") + .sync_handler(|req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let generate = parse_bool_flag(req, "generate")?; + let import = req.flag("import").map(String::from); - if generate && import.is_some() { - return Err(CommandError::new( - "--generate and --import are mutually exclusive", - "INVALID_ARGS", - "Use either --generate or --import, not both", - )); - } + if generate && import.is_some() { + return Err(CommandError::new( + "--generate and --import are mutually exclusive", + "INVALID_ARGS", + "Use either --generate or --import, not both", + )); + } - if !generate && import.is_none() { - return Err(CommandError::new( - "Specify --generate or --import", - "MISSING_ARG", - "Use --generate to create a new wallet, or --import=", - ) - .next_actions(vec![NextAction::new( - "bdk-agcli init --generate", - "Generate new wallet", - )])); - } + if !generate && import.is_none() { + return Err(CommandError::new( + "Specify --generate or --import", + "MISSING_ARG", + "Use --generate to create a new wallet, or --import=", + ) + .next_actions(vec![NextAction::new( + "bdk-agcli init --generate", + "Generate new wallet", + )])); + } - let config = resolve_config(); + let config = resolve_config(); - let result = if generate { - bdk_lib::init_wallet(&config).map_err(err)? - } else { - let mnemonic = import.unwrap(); - bdk_lib::import_wallet(&config, &mnemonic).map_err(err)? - }; + let result = if generate { + bdk_lib::init_wallet(&config).map_err(err)? + } else { + let mnemonic = import.unwrap(); + bdk_lib::import_wallet(&config, &mnemonic).map_err(err)? + }; - Ok(CommandOutput::new(json!(result)).next_actions(vec![ - NextAction::new("bdk-agcli address", "Get a receive address"), - NextAction::new("bdk-agcli sync", "Sync wallet with Esplora"), - ])) - }) + Ok(CommandOutput::new(json!(result)).next_actions(vec![ + NextAction::new("bdk-agcli address", "Get a receive address"), + NextAction::new("bdk-agcli sync", "Sync wallet with Esplora"), + ])) + }) } fn address_command() -> Command { Command::new("address", "Get next unused receive address") .usage("bdk-agcli address") - .sync_handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let config = resolve_config(); - let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; - let addr = bdk_lib::next_address(&mut wallet, &mut db).map_err(err)?; + .sync_handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let config = resolve_config(); + let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; + let addr = bdk_lib::next_address(&mut wallet, &mut db).map_err(err)?; - Ok(CommandOutput::new(json!(addr)).next_actions(vec![ - NextAction::new( - format!("just fund-bdk {}", addr.address), - "Fund this address (regtest)", - ), - NextAction::new("bdk-agcli sync", "Sync wallet after funding"), - ])) - }, - ) + Ok(CommandOutput::new(json!(addr)).next_actions(vec![ + NextAction::new( + format!("just fund-bdk {}", addr.address), + "Fund this address (regtest)", + ), + NextAction::new("bdk-agcli sync", "Sync wallet after funding"), + ])) + }) } fn sync_command() -> Command { Command::new("sync", "Sync wallet with Esplora") .usage("bdk-agcli sync") - .handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - Box::pin(async move { - let config = resolve_config(); - let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; + .handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + Box::pin(async move { + let config = resolve_config(); + let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; - bdk_lib::sync_wallet(&mut wallet, &mut db, &config.esplora_url) - .await - .map_err(err)?; + bdk_lib::sync_wallet(&mut wallet, &mut db, &config.esplora_url) + .await + .map_err(err)?; - let balance = bdk_lib::get_balance(&wallet); - Ok(CommandOutput::new(json!({ - "synced": true, - "balance": balance, - })) - .next_actions(vec![ - NextAction::new("bdk-agcli balance", "View balance"), - NextAction::new("bdk-agcli list-tx", "List transactions"), - ])) - }) - }, - ) + let balance = bdk_lib::get_balance(&wallet); + Ok(CommandOutput::new(json!({ + "synced": true, + "balance": balance, + })) + .next_actions(vec![ + NextAction::new("bdk-agcli balance", "View balance"), + NextAction::new("bdk-agcli list-tx", "List transactions"), + ])) + }) + }) } fn balance_command() -> Command { Command::new("balance", "Show wallet balance") .usage("bdk-agcli balance") - .sync_handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let config = resolve_config(); - let (_db, wallet) = bdk_lib::load_wallet(&config).map_err(err)?; - let balance = bdk_lib::get_balance(&wallet); + .sync_handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let config = resolve_config(); + let (_db, wallet) = bdk_lib::load_wallet(&config).map_err(err)?; + let balance = bdk_lib::get_balance(&wallet); - Ok(CommandOutput::new(json!(balance)).next_actions(vec![ - NextAction::new("bdk-agcli sync", "Sync first if stale"), - NextAction::new( - "bdk-agcli send --to --amount ", - "Send BTC", - ), - ])) - }, - ) + Ok(CommandOutput::new(json!(balance)).next_actions(vec![ + NextAction::new("bdk-agcli sync", "Sync first if stale"), + NextAction::new("bdk-agcli send --to --amount ", "Send BTC"), + ])) + }) } fn send_command() -> Command { Command::new("send", "Send BTC to an address") .usage("bdk-agcli send --to
--amount ") - .handler( - |req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let to = req.flag("to").map(String::from); - let amount_str = req.flag("amount").map(String::from); + .handler(|req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let to = req.flag("to").map(String::from); + let amount_str = req.flag("amount").map(String::from); - Box::pin(async move { - let to = to.ok_or_else(|| { + Box::pin(async move { + let to = to.ok_or_else(|| { + CommandError::new("--to is required", "MISSING_ARG", "Provide --to=
") + })?; + let amount_sats: u64 = amount_str + .ok_or_else(|| { CommandError::new( - "--to is required", + "--amount is required", "MISSING_ARG", - "Provide --to=
", + "Provide --amount=", + ) + })? + .parse() + .map_err(|_| { + CommandError::new( + "--amount must be a number", + "INVALID_ARGS", + "Provide amount in satoshis", ) })?; - let amount_sats: u64 = amount_str - .ok_or_else(|| { - CommandError::new( - "--amount is required", - "MISSING_ARG", - "Provide --amount=", - ) - })? - .parse() - .map_err(|_| { - CommandError::new( - "--amount must be a number", - "INVALID_ARGS", - "Provide amount in satoshis", - ) - })?; - let config = resolve_config(); - let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; + let config = resolve_config(); + let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; - let result = bdk_lib::send( - &mut wallet, - &mut db, - &config.esplora_url, - &to, - amount_sats, - ) - .await - .map_err(err)?; + let result = + bdk_lib::send(&mut wallet, &mut db, &config.esplora_url, &to, amount_sats) + .await + .map_err(err)?; - Ok(CommandOutput::new(json!(result)).next_actions(vec![ - NextAction::new("bdk-agcli sync", "Sync to see updated balance"), - NextAction::new("bdk-agcli list-tx", "View transactions"), - ])) - }) - }, - ) + Ok(CommandOutput::new(json!(result)).next_actions(vec![ + NextAction::new("bdk-agcli sync", "Sync to see updated balance"), + NextAction::new("bdk-agcli list-tx", "View transactions"), + ])) + }) + }) } fn list_tx_command() -> Command { Command::new("list-tx", "List wallet transactions") .usage("bdk-agcli list-tx") - .sync_handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let config = resolve_config(); - let (_db, wallet) = bdk_lib::load_wallet(&config).map_err(err)?; - let txs = bdk_lib::list_transactions(&wallet); + .sync_handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let config = resolve_config(); + let (_db, wallet) = bdk_lib::load_wallet(&config).map_err(err)?; + let txs = bdk_lib::list_transactions(&wallet); - Ok(CommandOutput::new(json!({ - "count": txs.len(), - "transactions": txs, - })) - .next_actions(vec![ - NextAction::new("bdk-agcli sync", "Sync for latest"), - NextAction::new("bdk-agcli balance", "View balance"), - ])) - }, - ) + Ok(CommandOutput::new(json!({ + "count": txs.len(), + "transactions": txs, + })) + .next_actions(vec![ + NextAction::new("bdk-agcli sync", "Sync for latest"), + NextAction::new("bdk-agcli balance", "View balance"), + ])) + }) } #[tokio::main] diff --git a/crates/bdk-lib/src/config.rs b/crates/bdk-lib/src/config.rs index 31c2d16..9493773 100644 --- a/crates/bdk-lib/src/config.rs +++ b/crates/bdk-lib/src/config.rs @@ -16,7 +16,7 @@ impl WalletConfig { Network::Testnet => "testnet", Network::Signet => "signet", Network::Regtest => "regtest", - _ => "unknown", + Network::Testnet4 => "testnet4", }; Self { network, diff --git a/crates/bdk-lib/src/lib.rs b/crates/bdk-lib/src/lib.rs index 04dd36b..6fcaeb7 100644 --- a/crates/bdk-lib/src/lib.rs +++ b/crates/bdk-lib/src/lib.rs @@ -1,3 +1,7 @@ +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::must_use_candidate)] + pub mod config; pub mod error; pub mod wallet; diff --git a/crates/bdk-lib/src/wallet.rs b/crates/bdk-lib/src/wallet.rs index 4b83cad..3c9be2e 100644 --- a/crates/bdk-lib/src/wallet.rs +++ b/crates/bdk-lib/src/wallet.rs @@ -1,8 +1,8 @@ use std::fs; use std::str::FromStr; -use bdk_esplora::esplora_client; use bdk_esplora::EsploraAsyncExt; +use bdk_esplora::esplora_client; use bdk_wallet::bitcoin::bip32::Xpriv; use bdk_wallet::bitcoin::{Address, Amount, Network}; use bdk_wallet::file_store::Store; @@ -278,6 +278,7 @@ pub async fn send( .finish() .map_err(|e| BdkLibError::Transaction(e.to_string()))?; + #[allow(clippy::default_trait_access)] let finalized = wallet .sign(&mut psbt, Default::default()) .map_err(|e| BdkLibError::Transaction(e.to_string()))?; @@ -293,10 +294,7 @@ pub async fn send( .map_err(|e| BdkLibError::Transaction(e.to_string()))?; let txid = tx.compute_txid(); - let fee_sats = wallet - .calculate_fee(&tx) - .map(|f| f.to_sat()) - .unwrap_or(0); + let fee_sats = wallet.calculate_fee(&tx).map(Amount::to_sat).unwrap_or(0); let client = esplora_client::Builder::new(esplora_url) .build_async() @@ -327,7 +325,7 @@ pub fn list_transactions(wallet: &BdkWallet) -> Vec { let fee = wallet .calculate_fee(&tx.tx_node.tx) .ok() - .map(|f| f.to_sat()); + .map(Amount::to_sat); let (confirmed, height) = match &tx.chain_position { bdk_wallet::chain::ChainPosition::Confirmed { anchor, .. } => { (true, Some(anchor.block_id.height)) diff --git a/crates/bdk-lib/tests/e2e.rs b/crates/bdk-lib/tests/e2e.rs index ec171ba..578429f 100644 --- a/crates/bdk-lib/tests/e2e.rs +++ b/crates/bdk-lib/tests/e2e.rs @@ -6,16 +6,17 @@ use bdk_wallet::bitcoin::Network; use tempfile::TempDir; fn workspace_root() -> PathBuf { - std::env::var("WORKSPACE_ROOT") - .map(PathBuf::from) - .unwrap_or_else(|_| { + std::env::var("WORKSPACE_ROOT").map_or_else( + |_| { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .parent() .unwrap() .parent() .unwrap() .to_path_buf() - }) + }, + PathBuf::from, + ) } fn bitcoin_cli(args: &[&str]) -> String { @@ -70,18 +71,16 @@ async fn wait_for_sync( if balance.confirmed_sats > 0 { return; } - if start.elapsed().as_secs() > timeout_secs { - panic!( - "Timed out after {}s waiting for confirmed balance", - timeout_secs - ); - } + assert!( + start.elapsed().as_secs() <= timeout_secs, + "Timed out after {timeout_secs}s waiting for confirmed balance" + ); tokio::time::sleep(std::time::Duration::from_secs(2)).await; } } #[tokio::test] -#[ignore] +#[ignore = "requires Docker infrastructure (bitcoind + esplora)"] async fn test_full_wallet_lifecycle() { let tmp = TempDir::new().unwrap(); let config = make_config(&tmp); @@ -110,9 +109,15 @@ async fn test_full_wallet_lifecycle() { let addr2 = next_address(&mut wallet, &mut db).unwrap(); // Send 50M sats to second address - let send_result = send(&mut wallet, &mut db, &config.esplora_url, &addr2.address, 50_000_000) - .await - .unwrap(); + let send_result = send( + &mut wallet, + &mut db, + &config.esplora_url, + &addr2.address, + 50_000_000, + ) + .await + .unwrap(); assert!(!send_result.txid.is_empty()); assert!(send_result.fee_sats > 0); @@ -138,7 +143,7 @@ async fn test_full_wallet_lifecycle() { } #[tokio::test] -#[ignore] +#[ignore = "requires Docker infrastructure (bitcoind + esplora)"] async fn test_wallet_already_exists() { let tmp = TempDir::new().unwrap(); let config = make_config(&tmp); @@ -147,13 +152,12 @@ async fn test_wallet_already_exists() { let err = init_wallet(&config).unwrap_err(); assert!( matches!(err, BdkLibError::WalletAlreadyExists { .. }), - "expected WalletAlreadyExists, got: {:?}", - err + "expected WalletAlreadyExists, got: {err:?}", ); } #[tokio::test] -#[ignore] +#[ignore = "requires Docker infrastructure (bitcoind + esplora)"] async fn test_sync_empty_wallet() { let tmp = TempDir::new().unwrap(); let config = make_config(&tmp); diff --git a/crates/carpet-agent/Cargo.toml b/crates/carpet-agent/Cargo.toml index 5f10c86..60c05a1 100644 --- a/crates/carpet-agent/Cargo.toml +++ b/crates/carpet-agent/Cargo.toml @@ -18,3 +18,6 @@ serde_json = { workspace = true } anyhow = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } + +[package.metadata.cargo-machete] +ignored = ["rig-core", "tracing"] diff --git a/crates/carpet-agent/src/main.rs b/crates/carpet-agent/src/main.rs index 8815d37..f91fe3d 100644 --- a/crates/carpet-agent/src/main.rs +++ b/crates/carpet-agent/src/main.rs @@ -35,8 +35,7 @@ async fn ensure_loaded(shared: &SharedWallet) -> Result<(), ToolError> { let mut guard = shared.lock().await; if guard.is_none() { let config = wallet_config(); - let (db, wallet) = - bdk_lib::load_wallet(&config).map_err(|e| ToolError(e.to_string()))?; + let (db, wallet) = bdk_lib::load_wallet(&config).map_err(|e| ToolError(e.to_string()))?; *guard = Some((db, wallet)); } Ok(()) @@ -112,7 +111,9 @@ impl Tool for GetAddressTool { async fn call(&self, _args: Self::Args) -> Result { ensure_loaded(&self.wallet).await?; let mut guard = self.wallet.lock().await; - let (db, wallet) = guard.as_mut().ok_or(ToolError("Wallet not loaded".into()))?; + let (db, wallet) = guard + .as_mut() + .ok_or(ToolError("Wallet not loaded".into()))?; let addr = bdk_lib::next_address(wallet, db).map_err(|e| ToolError(e.to_string()))?; serde_json::to_value(addr).map_err(|e| ToolError(e.to_string())) } @@ -140,7 +141,9 @@ impl Tool for SyncWalletTool { ensure_loaded(&self.wallet).await?; let config = wallet_config(); let mut guard = self.wallet.lock().await; - let (db, wallet) = guard.as_mut().ok_or(ToolError("Wallet not loaded".into()))?; + let (db, wallet) = guard + .as_mut() + .ok_or(ToolError("Wallet not loaded".into()))?; bdk_lib::sync_wallet(wallet, db, &config.esplora_url) .await .map_err(|e| ToolError(e.to_string()))?; @@ -171,7 +174,9 @@ impl Tool for GetBalanceTool { async fn call(&self, _args: Self::Args) -> Result { ensure_loaded(&self.wallet).await?; let guard = self.wallet.lock().await; - let (_, wallet) = guard.as_ref().ok_or(ToolError("Wallet not loaded".into()))?; + let (_, wallet) = guard + .as_ref() + .ok_or(ToolError("Wallet not loaded".into()))?; let balance = bdk_lib::get_balance(wallet); serde_json::to_value(balance).map_err(|e| ToolError(e.to_string())) } @@ -212,7 +217,9 @@ impl Tool for SendBitcoinTool { ensure_loaded(&self.wallet).await?; let config = wallet_config(); let mut guard = self.wallet.lock().await; - let (db, wallet) = guard.as_mut().ok_or(ToolError("Wallet not loaded".into()))?; + let (db, wallet) = guard + .as_mut() + .ok_or(ToolError("Wallet not loaded".into()))?; let result = bdk_lib::send(wallet, db, &config.esplora_url, &args.to, args.amount_sats) .await .map_err(|e| ToolError(e.to_string()))?; @@ -241,7 +248,9 @@ impl Tool for ListTransactionsTool { async fn call(&self, _args: Self::Args) -> Result { ensure_loaded(&self.wallet).await?; let guard = self.wallet.lock().await; - let (_, wallet) = guard.as_ref().ok_or(ToolError("Wallet not loaded".into()))?; + let (_, wallet) = guard + .as_ref() + .ok_or(ToolError("Wallet not loaded".into()))?; let txs = bdk_lib::list_transactions(wallet); serde_json::to_value(json!({"count": txs.len(), "transactions": txs})) .map_err(|e| ToolError(e.to_string())) @@ -425,8 +434,7 @@ async fn main() -> Result<()> { ) .init(); - let api_key = - std::env::var("ANTHROPIC_API_KEY").expect("ANTHROPIC_API_KEY must be set"); + let api_key = std::env::var("ANTHROPIC_API_KEY").expect("ANTHROPIC_API_KEY must be set"); let shared_wallet: SharedWallet = Arc::new(Mutex::new(None)); diff --git a/crates/carpet-ui/Cargo.toml b/crates/carpet-ui/Cargo.toml new file mode 100644 index 0000000..35776be --- /dev/null +++ b/crates/carpet-ui/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "carpet-ui" +version = "0.1.0" +edition.workspace = true + +[dependencies] +dioxus = { version = "0.7", features = ["router"] } +serde = { workspace = true } +serde_json = { workspace = true } +tracing = { workspace = true } + +# Backend crates — only needed on the server (they contain C deps that don't compile to wasm) +nostr-lib = { path = "../nostr-lib", optional = true } +bdk-lib = { path = "../bdk-lib", optional = true } +phoenixd-lib = { path = "../phoenixd-lib", optional = true } +axum = { version = "0.8", optional = true } +tokio = { version = "1", features = ["full"], optional = true } + +[features] +default = [] +web = ["dioxus/web"] +server = ["dioxus/server", "dep:axum", "dep:tokio", "dep:nostr-lib", "dep:bdk-lib", "dep:phoenixd-lib"] +desktop = ["dioxus/desktop"] + +[package.metadata.cargo-machete] +ignored = ["axum", "tokio", "nostr-lib", "bdk-lib", "phoenixd-lib", "serde", "serde_json"] diff --git a/crates/carpet-ui/Dioxus.toml b/crates/carpet-ui/Dioxus.toml new file mode 100644 index 0000000..b9c893c --- /dev/null +++ b/crates/carpet-ui/Dioxus.toml @@ -0,0 +1,16 @@ +[application] + +[web.app] +title = "Magic Carpet — Decentralized List Marketplace" + +[web.watcher] +reload_html = true +watch_path = ["src", "assets"] + +[web.resource] +style = [] +script = [] + +[web.resource.dev] +style = [] +script = [] diff --git a/crates/carpet-ui/assets/Phosphor.woff2 b/crates/carpet-ui/assets/Phosphor.woff2 new file mode 100644 index 0000000..76ff203 Binary files /dev/null and b/crates/carpet-ui/assets/Phosphor.woff2 differ diff --git a/crates/carpet-ui/assets/phosphor.css b/crates/carpet-ui/assets/phosphor.css new file mode 100644 index 0000000..0e5c790 --- /dev/null +++ b/crates/carpet-ui/assets/phosphor.css @@ -0,0 +1,4623 @@ +@font-face { + font-family: "Phosphor"; + src: url("./Phosphor.woff2") format("woff2"); + font-weight: normal; + font-style: normal; + font-display: block; +} + +.ph { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: "Phosphor" !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Enable Ligatures ================ */ + letter-spacing: 0; + -webkit-font-feature-settings: "liga"; + -moz-font-feature-settings: "liga=1"; + -moz-font-feature-settings: "liga"; + -ms-font-feature-settings: "liga" 1; + font-feature-settings: "liga"; + -webkit-font-variant-ligatures: discretionary-ligatures; + font-variant-ligatures: discretionary-ligatures; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.ph.ph-acorn:before { + content: "\eb9a"; +} +.ph.ph-address-book:before { + content: "\e6f8"; +} +.ph.ph-address-book-tabs:before { + content: "\ee4e"; +} +.ph.ph-air-traffic-control:before { + content: "\ecd8"; +} +.ph.ph-airplane:before { + content: "\e002"; +} +.ph.ph-airplane-in-flight:before { + content: "\e4fe"; +} +.ph.ph-airplane-landing:before { + content: "\e502"; +} +.ph.ph-airplane-takeoff:before { + content: "\e504"; +} +.ph.ph-airplane-taxiing:before { + content: "\e500"; +} +.ph.ph-airplane-tilt:before { + content: "\e5d6"; +} +.ph.ph-airplay:before { + content: "\e004"; +} +.ph.ph-alarm:before { + content: "\e006"; +} +.ph.ph-alien:before { + content: "\e8a6"; +} +.ph.ph-align-bottom:before { + content: "\e506"; +} +.ph.ph-align-bottom-simple:before { + content: "\eb0c"; +} +.ph.ph-align-center-horizontal:before { + content: "\e50a"; +} +.ph.ph-align-center-horizontal-simple:before { + content: "\eb0e"; +} +.ph.ph-align-center-vertical:before { + content: "\e50c"; +} +.ph.ph-align-center-vertical-simple:before { + content: "\eb10"; +} +.ph.ph-align-left:before { + content: "\e50e"; +} +.ph.ph-align-left-simple:before { + content: "\eaee"; +} +.ph.ph-align-right:before { + content: "\e510"; +} +.ph.ph-align-right-simple:before { + content: "\eb12"; +} +.ph.ph-align-top:before { + content: "\e512"; +} +.ph.ph-align-top-simple:before { + content: "\eb14"; +} +.ph.ph-amazon-logo:before { + content: "\e96c"; +} +.ph.ph-ambulance:before { + content: "\e572"; +} +.ph.ph-anchor:before { + content: "\e514"; +} +.ph.ph-anchor-simple:before { + content: "\e5d8"; +} +.ph.ph-android-logo:before { + content: "\e008"; +} +.ph.ph-angle:before { + content: "\e7bc"; +} +.ph.ph-angular-logo:before { + content: "\eb80"; +} +.ph.ph-aperture:before { + content: "\e00a"; +} +.ph.ph-app-store-logo:before { + content: "\e974"; +} +.ph.ph-app-window:before { + content: "\e5da"; +} +.ph.ph-apple-logo:before { + content: "\e516"; +} +.ph.ph-apple-podcasts-logo:before { + content: "\eb96"; +} +.ph.ph-approximate-equals:before { + content: "\edaa"; +} +.ph.ph-archive:before { + content: "\e00c"; +} +.ph.ph-armchair:before { + content: "\e012"; +} +.ph.ph-arrow-arc-left:before { + content: "\e014"; +} +.ph.ph-arrow-arc-right:before { + content: "\e016"; +} +.ph.ph-arrow-bend-double-up-left:before { + content: "\e03a"; +} +.ph.ph-arrow-bend-double-up-right:before { + content: "\e03c"; +} +.ph.ph-arrow-bend-down-left:before { + content: "\e018"; +} +.ph.ph-arrow-bend-down-right:before { + content: "\e01a"; +} +.ph.ph-arrow-bend-left-down:before { + content: "\e01c"; +} +.ph.ph-arrow-bend-left-up:before { + content: "\e01e"; +} +.ph.ph-arrow-bend-right-down:before { + content: "\e020"; +} +.ph.ph-arrow-bend-right-up:before { + content: "\e022"; +} +.ph.ph-arrow-bend-up-left:before { + content: "\e024"; +} +.ph.ph-arrow-bend-up-right:before { + content: "\e026"; +} +.ph.ph-arrow-circle-down:before { + content: "\e028"; +} +.ph.ph-arrow-circle-down-left:before { + content: "\e02a"; +} +.ph.ph-arrow-circle-down-right:before { + content: "\e02c"; +} +.ph.ph-arrow-circle-left:before { + content: "\e05a"; +} +.ph.ph-arrow-circle-right:before { + content: "\e02e"; +} +.ph.ph-arrow-circle-up:before { + content: "\e030"; +} +.ph.ph-arrow-circle-up-left:before { + content: "\e032"; +} +.ph.ph-arrow-circle-up-right:before { + content: "\e034"; +} +.ph.ph-arrow-clockwise:before { + content: "\e036"; +} +.ph.ph-arrow-counter-clockwise:before { + content: "\e038"; +} +.ph.ph-arrow-down:before { + content: "\e03e"; +} +.ph.ph-arrow-down-left:before { + content: "\e040"; +} +.ph.ph-arrow-down-right:before { + content: "\e042"; +} +.ph.ph-arrow-elbow-down-left:before { + content: "\e044"; +} +.ph.ph-arrow-elbow-down-right:before { + content: "\e046"; +} +.ph.ph-arrow-elbow-left:before { + content: "\e048"; +} +.ph.ph-arrow-elbow-left-down:before { + content: "\e04a"; +} +.ph.ph-arrow-elbow-left-up:before { + content: "\e04c"; +} +.ph.ph-arrow-elbow-right:before { + content: "\e04e"; +} +.ph.ph-arrow-elbow-right-down:before { + content: "\e050"; +} +.ph.ph-arrow-elbow-right-up:before { + content: "\e052"; +} +.ph.ph-arrow-elbow-up-left:before { + content: "\e054"; +} +.ph.ph-arrow-elbow-up-right:before { + content: "\e056"; +} +.ph.ph-arrow-fat-down:before { + content: "\e518"; +} +.ph.ph-arrow-fat-left:before { + content: "\e51a"; +} +.ph.ph-arrow-fat-line-down:before { + content: "\e51c"; +} +.ph.ph-arrow-fat-line-left:before { + content: "\e51e"; +} +.ph.ph-arrow-fat-line-right:before { + content: "\e520"; +} +.ph.ph-arrow-fat-line-up:before { + content: "\e522"; +} +.ph.ph-arrow-fat-lines-down:before { + content: "\e524"; +} +.ph.ph-arrow-fat-lines-left:before { + content: "\e526"; +} +.ph.ph-arrow-fat-lines-right:before { + content: "\e528"; +} +.ph.ph-arrow-fat-lines-up:before { + content: "\e52a"; +} +.ph.ph-arrow-fat-right:before { + content: "\e52c"; +} +.ph.ph-arrow-fat-up:before { + content: "\e52e"; +} +.ph.ph-arrow-left:before { + content: "\e058"; +} +.ph.ph-arrow-line-down:before { + content: "\e05c"; +} +.ph.ph-arrow-line-down-left:before { + content: "\e05e"; +} +.ph.ph-arrow-line-down-right:before { + content: "\e060"; +} +.ph.ph-arrow-line-left:before { + content: "\e062"; +} +.ph.ph-arrow-line-right:before { + content: "\e064"; +} +.ph.ph-arrow-line-up:before { + content: "\e066"; +} +.ph.ph-arrow-line-up-left:before { + content: "\e068"; +} +.ph.ph-arrow-line-up-right:before { + content: "\e06a"; +} +.ph.ph-arrow-right:before { + content: "\e06c"; +} +.ph.ph-arrow-square-down:before { + content: "\e06e"; +} +.ph.ph-arrow-square-down-left:before { + content: "\e070"; +} +.ph.ph-arrow-square-down-right:before { + content: "\e072"; +} +.ph.ph-arrow-square-in:before { + content: "\e5dc"; +} +.ph.ph-arrow-square-left:before { + content: "\e074"; +} +.ph.ph-arrow-square-out:before { + content: "\e5de"; +} +.ph.ph-arrow-square-right:before { + content: "\e076"; +} +.ph.ph-arrow-square-up:before { + content: "\e078"; +} +.ph.ph-arrow-square-up-left:before { + content: "\e07a"; +} +.ph.ph-arrow-square-up-right:before { + content: "\e07c"; +} +.ph.ph-arrow-u-down-left:before { + content: "\e07e"; +} +.ph.ph-arrow-u-down-right:before { + content: "\e080"; +} +.ph.ph-arrow-u-left-down:before { + content: "\e082"; +} +.ph.ph-arrow-u-left-up:before { + content: "\e084"; +} +.ph.ph-arrow-u-right-down:before { + content: "\e086"; +} +.ph.ph-arrow-u-right-up:before { + content: "\e088"; +} +.ph.ph-arrow-u-up-left:before { + content: "\e08a"; +} +.ph.ph-arrow-u-up-right:before { + content: "\e08c"; +} +.ph.ph-arrow-up:before { + content: "\e08e"; +} +.ph.ph-arrow-up-left:before { + content: "\e090"; +} +.ph.ph-arrow-up-right:before { + content: "\e092"; +} +.ph.ph-arrows-clockwise:before { + content: "\e094"; +} +.ph.ph-arrows-counter-clockwise:before { + content: "\e096"; +} +.ph.ph-arrows-down-up:before { + content: "\e098"; +} +.ph.ph-arrows-horizontal:before { + content: "\eb06"; +} +.ph.ph-arrows-in:before { + content: "\e09a"; +} +.ph.ph-arrows-in-cardinal:before { + content: "\e09c"; +} +.ph.ph-arrows-in-line-horizontal:before { + content: "\e530"; +} +.ph.ph-arrows-in-line-vertical:before { + content: "\e532"; +} +.ph.ph-arrows-in-simple:before { + content: "\e09e"; +} +.ph.ph-arrows-left-right:before { + content: "\e0a0"; +} +.ph.ph-arrows-merge:before { + content: "\ed3e"; +} +.ph.ph-arrows-out:before { + content: "\e0a2"; +} +.ph.ph-arrows-out-cardinal:before { + content: "\e0a4"; +} +.ph.ph-arrows-out-line-horizontal:before { + content: "\e534"; +} +.ph.ph-arrows-out-line-vertical:before { + content: "\e536"; +} +.ph.ph-arrows-out-simple:before { + content: "\e0a6"; +} +.ph.ph-arrows-split:before { + content: "\ed3c"; +} +.ph.ph-arrows-vertical:before { + content: "\eb04"; +} +.ph.ph-article:before { + content: "\e0a8"; +} +.ph.ph-article-medium:before { + content: "\e5e0"; +} +.ph.ph-article-ny-times:before { + content: "\e5e2"; +} +.ph.ph-asclepius:before { + content: "\ee34"; +} +.ph.ph-caduceus:before { + content: "\ee34"; +} +.ph.ph-asterisk:before { + content: "\e0aa"; +} +.ph.ph-asterisk-simple:before { + content: "\e832"; +} +.ph.ph-at:before { + content: "\e0ac"; +} +.ph.ph-atom:before { + content: "\e5e4"; +} +.ph.ph-avocado:before { + content: "\ee04"; +} +.ph.ph-axe:before { + content: "\e9fc"; +} +.ph.ph-baby:before { + content: "\e774"; +} +.ph.ph-baby-carriage:before { + content: "\e818"; +} +.ph.ph-backpack:before { + content: "\e922"; +} +.ph.ph-backspace:before { + content: "\e0ae"; +} +.ph.ph-bag:before { + content: "\e0b0"; +} +.ph.ph-bag-simple:before { + content: "\e5e6"; +} +.ph.ph-balloon:before { + content: "\e76c"; +} +.ph.ph-bandaids:before { + content: "\e0b2"; +} +.ph.ph-bank:before { + content: "\e0b4"; +} +.ph.ph-barbell:before { + content: "\e0b6"; +} +.ph.ph-barcode:before { + content: "\e0b8"; +} +.ph.ph-barn:before { + content: "\ec72"; +} +.ph.ph-barricade:before { + content: "\e948"; +} +.ph.ph-baseball:before { + content: "\e71a"; +} +.ph.ph-baseball-cap:before { + content: "\ea28"; +} +.ph.ph-baseball-helmet:before { + content: "\ee4a"; +} +.ph.ph-basket:before { + content: "\e964"; +} +.ph.ph-basketball:before { + content: "\e724"; +} +.ph.ph-bathtub:before { + content: "\e81e"; +} +.ph.ph-battery-charging:before { + content: "\e0ba"; +} +.ph.ph-battery-charging-vertical:before { + content: "\e0bc"; +} +.ph.ph-battery-empty:before { + content: "\e0be"; +} +.ph.ph-battery-full:before { + content: "\e0c0"; +} +.ph.ph-battery-high:before { + content: "\e0c2"; +} +.ph.ph-battery-low:before { + content: "\e0c4"; +} +.ph.ph-battery-medium:before { + content: "\e0c6"; +} +.ph.ph-battery-plus:before { + content: "\e808"; +} +.ph.ph-battery-plus-vertical:before { + content: "\ec50"; +} +.ph.ph-battery-vertical-empty:before { + content: "\e7c6"; +} +.ph.ph-battery-vertical-full:before { + content: "\e7c4"; +} +.ph.ph-battery-vertical-high:before { + content: "\e7c2"; +} +.ph.ph-battery-vertical-low:before { + content: "\e7be"; +} +.ph.ph-battery-vertical-medium:before { + content: "\e7c0"; +} +.ph.ph-battery-warning:before { + content: "\e0c8"; +} +.ph.ph-battery-warning-vertical:before { + content: "\e0ca"; +} +.ph.ph-beach-ball:before { + content: "\ed24"; +} +.ph.ph-beanie:before { + content: "\ea2a"; +} +.ph.ph-bed:before { + content: "\e0cc"; +} +.ph.ph-beer-bottle:before { + content: "\e7b0"; +} +.ph.ph-beer-stein:before { + content: "\eb62"; +} +.ph.ph-behance-logo:before { + content: "\e7f4"; +} +.ph.ph-bell:before { + content: "\e0ce"; +} +.ph.ph-bell-ringing:before { + content: "\e5e8"; +} +.ph.ph-bell-simple:before { + content: "\e0d0"; +} +.ph.ph-bell-simple-ringing:before { + content: "\e5ea"; +} +.ph.ph-bell-simple-slash:before { + content: "\e0d2"; +} +.ph.ph-bell-simple-z:before { + content: "\e5ec"; +} +.ph.ph-bell-slash:before { + content: "\e0d4"; +} +.ph.ph-bell-z:before { + content: "\e5ee"; +} +.ph.ph-belt:before { + content: "\ea2c"; +} +.ph.ph-bezier-curve:before { + content: "\eb00"; +} +.ph.ph-bicycle:before { + content: "\e0d6"; +} +.ph.ph-binary:before { + content: "\ee60"; +} +.ph.ph-binoculars:before { + content: "\ea64"; +} +.ph.ph-biohazard:before { + content: "\e9e0"; +} +.ph.ph-bird:before { + content: "\e72c"; +} +.ph.ph-blueprint:before { + content: "\eda0"; +} +.ph.ph-bluetooth:before { + content: "\e0da"; +} +.ph.ph-bluetooth-connected:before { + content: "\e0dc"; +} +.ph.ph-bluetooth-slash:before { + content: "\e0de"; +} +.ph.ph-bluetooth-x:before { + content: "\e0e0"; +} +.ph.ph-boat:before { + content: "\e786"; +} +.ph.ph-bomb:before { + content: "\ee0a"; +} +.ph.ph-bone:before { + content: "\e7f2"; +} +.ph.ph-book:before { + content: "\e0e2"; +} +.ph.ph-book-bookmark:before { + content: "\e0e4"; +} +.ph.ph-book-open:before { + content: "\e0e6"; +} +.ph.ph-book-open-text:before { + content: "\e8f2"; +} +.ph.ph-book-open-user:before { + content: "\ede0"; +} +.ph.ph-bookmark:before { + content: "\e0e8"; +} +.ph.ph-bookmark-simple:before { + content: "\e0ea"; +} +.ph.ph-bookmarks:before { + content: "\e0ec"; +} +.ph.ph-bookmarks-simple:before { + content: "\e5f0"; +} +.ph.ph-books:before { + content: "\e758"; +} +.ph.ph-boot:before { + content: "\ecca"; +} +.ph.ph-boules:before { + content: "\e722"; +} +.ph.ph-bounding-box:before { + content: "\e6ce"; +} +.ph.ph-bowl-food:before { + content: "\eaa4"; +} +.ph.ph-bowl-steam:before { + content: "\e8e4"; +} +.ph.ph-bowling-ball:before { + content: "\ea34"; +} +.ph.ph-box-arrow-down:before { + content: "\e00e"; +} +.ph.ph-archive-box:before { + content: "\e00e"; +} +.ph.ph-box-arrow-up:before { + content: "\ee54"; +} +.ph.ph-boxing-glove:before { + content: "\ea36"; +} +.ph.ph-brackets-angle:before { + content: "\e862"; +} +.ph.ph-brackets-curly:before { + content: "\e860"; +} +.ph.ph-brackets-round:before { + content: "\e864"; +} +.ph.ph-brackets-square:before { + content: "\e85e"; +} +.ph.ph-brain:before { + content: "\e74e"; +} +.ph.ph-brandy:before { + content: "\e6b4"; +} +.ph.ph-bread:before { + content: "\e81c"; +} +.ph.ph-bridge:before { + content: "\ea68"; +} +.ph.ph-briefcase:before { + content: "\e0ee"; +} +.ph.ph-briefcase-metal:before { + content: "\e5f2"; +} +.ph.ph-broadcast:before { + content: "\e0f2"; +} +.ph.ph-broom:before { + content: "\ec54"; +} +.ph.ph-browser:before { + content: "\e0f4"; +} +.ph.ph-browsers:before { + content: "\e0f6"; +} +.ph.ph-bug:before { + content: "\e5f4"; +} +.ph.ph-bug-beetle:before { + content: "\e5f6"; +} +.ph.ph-bug-droid:before { + content: "\e5f8"; +} +.ph.ph-building:before { + content: "\e100"; +} +.ph.ph-building-apartment:before { + content: "\e0fe"; +} +.ph.ph-building-office:before { + content: "\e0ff"; +} +.ph.ph-buildings:before { + content: "\e102"; +} +.ph.ph-bulldozer:before { + content: "\ec6c"; +} +.ph.ph-bus:before { + content: "\e106"; +} +.ph.ph-butterfly:before { + content: "\ea6e"; +} +.ph.ph-cable-car:before { + content: "\e49c"; +} +.ph.ph-cactus:before { + content: "\e918"; +} +.ph.ph-cake:before { + content: "\e780"; +} +.ph.ph-calculator:before { + content: "\e538"; +} +.ph.ph-calendar:before { + content: "\e108"; +} +.ph.ph-calendar-blank:before { + content: "\e10a"; +} +.ph.ph-calendar-check:before { + content: "\e712"; +} +.ph.ph-calendar-dot:before { + content: "\e7b2"; +} +.ph.ph-calendar-dots:before { + content: "\e7b4"; +} +.ph.ph-calendar-heart:before { + content: "\e8b0"; +} +.ph.ph-calendar-minus:before { + content: "\ea14"; +} +.ph.ph-calendar-plus:before { + content: "\e714"; +} +.ph.ph-calendar-slash:before { + content: "\ea12"; +} +.ph.ph-calendar-star:before { + content: "\e8b2"; +} +.ph.ph-calendar-x:before { + content: "\e10c"; +} +.ph.ph-call-bell:before { + content: "\e7de"; +} +.ph.ph-camera:before { + content: "\e10e"; +} +.ph.ph-camera-plus:before { + content: "\ec58"; +} +.ph.ph-camera-rotate:before { + content: "\e7a4"; +} +.ph.ph-camera-slash:before { + content: "\e110"; +} +.ph.ph-campfire:before { + content: "\e9d8"; +} +.ph.ph-car:before { + content: "\e112"; +} +.ph.ph-car-battery:before { + content: "\ee30"; +} +.ph.ph-car-profile:before { + content: "\e8cc"; +} +.ph.ph-car-simple:before { + content: "\e114"; +} +.ph.ph-cardholder:before { + content: "\e5fa"; +} +.ph.ph-cards:before { + content: "\e0f8"; +} +.ph.ph-cards-three:before { + content: "\ee50"; +} +.ph.ph-caret-circle-double-down:before { + content: "\e116"; +} +.ph.ph-caret-circle-double-left:before { + content: "\e118"; +} +.ph.ph-caret-circle-double-right:before { + content: "\e11a"; +} +.ph.ph-caret-circle-double-up:before { + content: "\e11c"; +} +.ph.ph-caret-circle-down:before { + content: "\e11e"; +} +.ph.ph-caret-circle-left:before { + content: "\e120"; +} +.ph.ph-caret-circle-right:before { + content: "\e122"; +} +.ph.ph-caret-circle-up:before { + content: "\e124"; +} +.ph.ph-caret-circle-up-down:before { + content: "\e13e"; +} +.ph.ph-caret-double-down:before { + content: "\e126"; +} +.ph.ph-caret-double-left:before { + content: "\e128"; +} +.ph.ph-caret-double-right:before { + content: "\e12a"; +} +.ph.ph-caret-double-up:before { + content: "\e12c"; +} +.ph.ph-caret-down:before { + content: "\e136"; +} +.ph.ph-caret-left:before { + content: "\e138"; +} +.ph.ph-caret-line-down:before { + content: "\e134"; +} +.ph.ph-caret-line-left:before { + content: "\e132"; +} +.ph.ph-caret-line-right:before { + content: "\e130"; +} +.ph.ph-caret-line-up:before { + content: "\e12e"; +} +.ph.ph-caret-right:before { + content: "\e13a"; +} +.ph.ph-caret-up:before { + content: "\e13c"; +} +.ph.ph-caret-up-down:before { + content: "\e140"; +} +.ph.ph-carrot:before { + content: "\ed38"; +} +.ph.ph-cash-register:before { + content: "\ed80"; +} +.ph.ph-cassette-tape:before { + content: "\ed2e"; +} +.ph.ph-castle-turret:before { + content: "\e9d0"; +} +.ph.ph-cat:before { + content: "\e748"; +} +.ph.ph-cell-signal-full:before { + content: "\e142"; +} +.ph.ph-cell-signal-high:before { + content: "\e144"; +} +.ph.ph-cell-signal-low:before { + content: "\e146"; +} +.ph.ph-cell-signal-medium:before { + content: "\e148"; +} +.ph.ph-cell-signal-none:before { + content: "\e14a"; +} +.ph.ph-cell-signal-slash:before { + content: "\e14c"; +} +.ph.ph-cell-signal-x:before { + content: "\e14e"; +} +.ph.ph-cell-tower:before { + content: "\ebaa"; +} +.ph.ph-certificate:before { + content: "\e766"; +} +.ph.ph-chair:before { + content: "\e950"; +} +.ph.ph-chalkboard:before { + content: "\e5fc"; +} +.ph.ph-chalkboard-simple:before { + content: "\e5fe"; +} +.ph.ph-chalkboard-teacher:before { + content: "\e600"; +} +.ph.ph-champagne:before { + content: "\eaca"; +} +.ph.ph-charging-station:before { + content: "\e8d0"; +} +.ph.ph-chart-bar:before { + content: "\e150"; +} +.ph.ph-chart-bar-horizontal:before { + content: "\e152"; +} +.ph.ph-chart-donut:before { + content: "\eaa6"; +} +.ph.ph-chart-line:before { + content: "\e154"; +} +.ph.ph-chart-line-down:before { + content: "\e8b6"; +} +.ph.ph-chart-line-up:before { + content: "\e156"; +} +.ph.ph-chart-pie:before { + content: "\e158"; +} +.ph.ph-chart-pie-slice:before { + content: "\e15a"; +} +.ph.ph-chart-polar:before { + content: "\eaa8"; +} +.ph.ph-chart-scatter:before { + content: "\eaac"; +} +.ph.ph-chat:before { + content: "\e15c"; +} +.ph.ph-chat-centered:before { + content: "\e160"; +} +.ph.ph-chat-centered-dots:before { + content: "\e164"; +} +.ph.ph-chat-centered-slash:before { + content: "\e162"; +} +.ph.ph-chat-centered-text:before { + content: "\e166"; +} +.ph.ph-chat-circle:before { + content: "\e168"; +} +.ph.ph-chat-circle-dots:before { + content: "\e16c"; +} +.ph.ph-chat-circle-slash:before { + content: "\e16a"; +} +.ph.ph-chat-circle-text:before { + content: "\e16e"; +} +.ph.ph-chat-dots:before { + content: "\e170"; +} +.ph.ph-chat-slash:before { + content: "\e15e"; +} +.ph.ph-chat-teardrop:before { + content: "\e172"; +} +.ph.ph-chat-teardrop-dots:before { + content: "\e176"; +} +.ph.ph-chat-teardrop-slash:before { + content: "\e174"; +} +.ph.ph-chat-teardrop-text:before { + content: "\e178"; +} +.ph.ph-chat-text:before { + content: "\e17a"; +} +.ph.ph-chats:before { + content: "\e17c"; +} +.ph.ph-chats-circle:before { + content: "\e17e"; +} +.ph.ph-chats-teardrop:before { + content: "\e180"; +} +.ph.ph-check:before { + content: "\e182"; +} +.ph.ph-check-circle:before { + content: "\e184"; +} +.ph.ph-check-fat:before { + content: "\eba6"; +} +.ph.ph-check-square:before { + content: "\e186"; +} +.ph.ph-check-square-offset:before { + content: "\e188"; +} +.ph.ph-checkerboard:before { + content: "\e8c4"; +} +.ph.ph-checks:before { + content: "\e53a"; +} +.ph.ph-cheers:before { + content: "\ea4a"; +} +.ph.ph-cheese:before { + content: "\e9fe"; +} +.ph.ph-chef-hat:before { + content: "\ed8e"; +} +.ph.ph-cherries:before { + content: "\e830"; +} +.ph.ph-church:before { + content: "\ecea"; +} +.ph.ph-cigarette:before { + content: "\ed90"; +} +.ph.ph-cigarette-slash:before { + content: "\ed92"; +} +.ph.ph-circle:before { + content: "\e18a"; +} +.ph.ph-circle-dashed:before { + content: "\e602"; +} +.ph.ph-circle-half:before { + content: "\e18c"; +} +.ph.ph-circle-half-tilt:before { + content: "\e18e"; +} +.ph.ph-circle-notch:before { + content: "\eb44"; +} +.ph.ph-circles-four:before { + content: "\e190"; +} +.ph.ph-circles-three:before { + content: "\e192"; +} +.ph.ph-circles-three-plus:before { + content: "\e194"; +} +.ph.ph-circuitry:before { + content: "\e9c2"; +} +.ph.ph-city:before { + content: "\ea6a"; +} +.ph.ph-clipboard:before { + content: "\e196"; +} +.ph.ph-clipboard-text:before { + content: "\e198"; +} +.ph.ph-clock:before { + content: "\e19a"; +} +.ph.ph-clock-afternoon:before { + content: "\e19c"; +} +.ph.ph-clock-clockwise:before { + content: "\e19e"; +} +.ph.ph-clock-countdown:before { + content: "\ed2c"; +} +.ph.ph-clock-counter-clockwise:before { + content: "\e1a0"; +} +.ph.ph-clock-user:before { + content: "\edec"; +} +.ph.ph-closed-captioning:before { + content: "\e1a4"; +} +.ph.ph-cloud:before { + content: "\e1aa"; +} +.ph.ph-cloud-arrow-down:before { + content: "\e1ac"; +} +.ph.ph-cloud-arrow-up:before { + content: "\e1ae"; +} +.ph.ph-cloud-check:before { + content: "\e1b0"; +} +.ph.ph-cloud-fog:before { + content: "\e53c"; +} +.ph.ph-cloud-lightning:before { + content: "\e1b2"; +} +.ph.ph-cloud-moon:before { + content: "\e53e"; +} +.ph.ph-cloud-rain:before { + content: "\e1b4"; +} +.ph.ph-cloud-slash:before { + content: "\e1b6"; +} +.ph.ph-cloud-snow:before { + content: "\e1b8"; +} +.ph.ph-cloud-sun:before { + content: "\e540"; +} +.ph.ph-cloud-warning:before { + content: "\ea98"; +} +.ph.ph-cloud-x:before { + content: "\ea96"; +} +.ph.ph-clover:before { + content: "\edc8"; +} +.ph.ph-club:before { + content: "\e1ba"; +} +.ph.ph-coat-hanger:before { + content: "\e7fe"; +} +.ph.ph-coda-logo:before { + content: "\e7ce"; +} +.ph.ph-code:before { + content: "\e1bc"; +} +.ph.ph-code-block:before { + content: "\eafe"; +} +.ph.ph-code-simple:before { + content: "\e1be"; +} +.ph.ph-codepen-logo:before { + content: "\e978"; +} +.ph.ph-codesandbox-logo:before { + content: "\ea06"; +} +.ph.ph-coffee:before { + content: "\e1c2"; +} +.ph.ph-coffee-bean:before { + content: "\e1c0"; +} +.ph.ph-coin:before { + content: "\e60e"; +} +.ph.ph-coin-vertical:before { + content: "\eb48"; +} +.ph.ph-coins:before { + content: "\e78e"; +} +.ph.ph-columns:before { + content: "\e546"; +} +.ph.ph-columns-plus-left:before { + content: "\e544"; +} +.ph.ph-columns-plus-right:before { + content: "\e542"; +} +.ph.ph-command:before { + content: "\e1c4"; +} +.ph.ph-compass:before { + content: "\e1c8"; +} +.ph.ph-compass-rose:before { + content: "\e1c6"; +} +.ph.ph-compass-tool:before { + content: "\ea0e"; +} +.ph.ph-computer-tower:before { + content: "\e548"; +} +.ph.ph-confetti:before { + content: "\e81a"; +} +.ph.ph-contactless-payment:before { + content: "\ed42"; +} +.ph.ph-control:before { + content: "\eca6"; +} +.ph.ph-cookie:before { + content: "\e6ca"; +} +.ph.ph-cooking-pot:before { + content: "\e764"; +} +.ph.ph-copy:before { + content: "\e1ca"; +} +.ph.ph-copy-simple:before { + content: "\e1cc"; +} +.ph.ph-copyleft:before { + content: "\e86a"; +} +.ph.ph-copyright:before { + content: "\e54a"; +} +.ph.ph-corners-in:before { + content: "\e1ce"; +} +.ph.ph-corners-out:before { + content: "\e1d0"; +} +.ph.ph-couch:before { + content: "\e7f6"; +} +.ph.ph-court-basketball:before { + content: "\ee36"; +} +.ph.ph-cow:before { + content: "\eabe"; +} +.ph.ph-cowboy-hat:before { + content: "\ed12"; +} +.ph.ph-cpu:before { + content: "\e610"; +} +.ph.ph-crane:before { + content: "\ed48"; +} +.ph.ph-crane-tower:before { + content: "\ed49"; +} +.ph.ph-credit-card:before { + content: "\e1d2"; +} +.ph.ph-cricket:before { + content: "\ee12"; +} +.ph.ph-crop:before { + content: "\e1d4"; +} +.ph.ph-cross:before { + content: "\e8a0"; +} +.ph.ph-crosshair:before { + content: "\e1d6"; +} +.ph.ph-crosshair-simple:before { + content: "\e1d8"; +} +.ph.ph-crown:before { + content: "\e614"; +} +.ph.ph-crown-cross:before { + content: "\ee5e"; +} +.ph.ph-crown-simple:before { + content: "\e616"; +} +.ph.ph-cube:before { + content: "\e1da"; +} +.ph.ph-cube-focus:before { + content: "\ed0a"; +} +.ph.ph-cube-transparent:before { + content: "\ec7c"; +} +.ph.ph-currency-btc:before { + content: "\e618"; +} +.ph.ph-currency-circle-dollar:before { + content: "\e54c"; +} +.ph.ph-currency-cny:before { + content: "\e54e"; +} +.ph.ph-currency-dollar:before { + content: "\e550"; +} +.ph.ph-currency-dollar-simple:before { + content: "\e552"; +} +.ph.ph-currency-eth:before { + content: "\eada"; +} +.ph.ph-currency-eur:before { + content: "\e554"; +} +.ph.ph-currency-gbp:before { + content: "\e556"; +} +.ph.ph-currency-inr:before { + content: "\e558"; +} +.ph.ph-currency-jpy:before { + content: "\e55a"; +} +.ph.ph-currency-krw:before { + content: "\e55c"; +} +.ph.ph-currency-kzt:before { + content: "\ec4c"; +} +.ph.ph-currency-ngn:before { + content: "\eb52"; +} +.ph.ph-currency-rub:before { + content: "\e55e"; +} +.ph.ph-cursor:before { + content: "\e1dc"; +} +.ph.ph-cursor-click:before { + content: "\e7c8"; +} +.ph.ph-cursor-text:before { + content: "\e7d8"; +} +.ph.ph-cylinder:before { + content: "\e8fc"; +} +.ph.ph-database:before { + content: "\e1de"; +} +.ph.ph-desk:before { + content: "\ed16"; +} +.ph.ph-desktop:before { + content: "\e560"; +} +.ph.ph-desktop-tower:before { + content: "\e562"; +} +.ph.ph-detective:before { + content: "\e83e"; +} +.ph.ph-dev-to-logo:before { + content: "\ed0e"; +} +.ph.ph-device-mobile:before { + content: "\e1e0"; +} +.ph.ph-device-mobile-camera:before { + content: "\e1e2"; +} +.ph.ph-device-mobile-slash:before { + content: "\ee46"; +} +.ph.ph-device-mobile-speaker:before { + content: "\e1e4"; +} +.ph.ph-device-rotate:before { + content: "\edf2"; +} +.ph.ph-device-tablet:before { + content: "\e1e6"; +} +.ph.ph-device-tablet-camera:before { + content: "\e1e8"; +} +.ph.ph-device-tablet-speaker:before { + content: "\e1ea"; +} +.ph.ph-devices:before { + content: "\eba4"; +} +.ph.ph-diamond:before { + content: "\e1ec"; +} +.ph.ph-diamonds-four:before { + content: "\e8f4"; +} +.ph.ph-dice-five:before { + content: "\e1ee"; +} +.ph.ph-dice-four:before { + content: "\e1f0"; +} +.ph.ph-dice-one:before { + content: "\e1f2"; +} +.ph.ph-dice-six:before { + content: "\e1f4"; +} +.ph.ph-dice-three:before { + content: "\e1f6"; +} +.ph.ph-dice-two:before { + content: "\e1f8"; +} +.ph.ph-disc:before { + content: "\e564"; +} +.ph.ph-disco-ball:before { + content: "\ed98"; +} +.ph.ph-discord-logo:before { + content: "\e61a"; +} +.ph.ph-divide:before { + content: "\e1fa"; +} +.ph.ph-dna:before { + content: "\e924"; +} +.ph.ph-dog:before { + content: "\e74a"; +} +.ph.ph-door:before { + content: "\e61c"; +} +.ph.ph-door-open:before { + content: "\e7e6"; +} +.ph.ph-dot:before { + content: "\ecde"; +} +.ph.ph-dot-outline:before { + content: "\ece0"; +} +.ph.ph-dots-nine:before { + content: "\e1fc"; +} +.ph.ph-dots-six:before { + content: "\e794"; +} +.ph.ph-dots-six-vertical:before { + content: "\eae2"; +} +.ph.ph-dots-three:before { + content: "\e1fe"; +} +.ph.ph-dots-three-circle:before { + content: "\e200"; +} +.ph.ph-dots-three-circle-vertical:before { + content: "\e202"; +} +.ph.ph-dots-three-outline:before { + content: "\e204"; +} +.ph.ph-dots-three-outline-vertical:before { + content: "\e206"; +} +.ph.ph-dots-three-vertical:before { + content: "\e208"; +} +.ph.ph-download:before { + content: "\e20a"; +} +.ph.ph-download-simple:before { + content: "\e20c"; +} +.ph.ph-dress:before { + content: "\ea7e"; +} +.ph.ph-dresser:before { + content: "\e94e"; +} +.ph.ph-dribbble-logo:before { + content: "\e20e"; +} +.ph.ph-drone:before { + content: "\ed74"; +} +.ph.ph-drop:before { + content: "\e210"; +} +.ph.ph-drop-half:before { + content: "\e566"; +} +.ph.ph-drop-half-bottom:before { + content: "\eb40"; +} +.ph.ph-drop-simple:before { + content: "\ee32"; +} +.ph.ph-drop-slash:before { + content: "\e954"; +} +.ph.ph-dropbox-logo:before { + content: "\e7d0"; +} +.ph.ph-ear:before { + content: "\e70c"; +} +.ph.ph-ear-slash:before { + content: "\e70e"; +} +.ph.ph-egg:before { + content: "\e812"; +} +.ph.ph-egg-crack:before { + content: "\eb64"; +} +.ph.ph-eject:before { + content: "\e212"; +} +.ph.ph-eject-simple:before { + content: "\e6ae"; +} +.ph.ph-elevator:before { + content: "\ecc0"; +} +.ph.ph-empty:before { + content: "\edbc"; +} +.ph.ph-engine:before { + content: "\ea80"; +} +.ph.ph-envelope:before { + content: "\e214"; +} +.ph.ph-envelope-open:before { + content: "\e216"; +} +.ph.ph-envelope-simple:before { + content: "\e218"; +} +.ph.ph-envelope-simple-open:before { + content: "\e21a"; +} +.ph.ph-equalizer:before { + content: "\ebbc"; +} +.ph.ph-equals:before { + content: "\e21c"; +} +.ph.ph-eraser:before { + content: "\e21e"; +} +.ph.ph-escalator-down:before { + content: "\ecba"; +} +.ph.ph-escalator-up:before { + content: "\ecbc"; +} +.ph.ph-exam:before { + content: "\e742"; +} +.ph.ph-exclamation-mark:before { + content: "\ee44"; +} +.ph.ph-exclude:before { + content: "\e882"; +} +.ph.ph-exclude-square:before { + content: "\e880"; +} +.ph.ph-export:before { + content: "\eaf0"; +} +.ph.ph-eye:before { + content: "\e220"; +} +.ph.ph-eye-closed:before { + content: "\e222"; +} +.ph.ph-eye-slash:before { + content: "\e224"; +} +.ph.ph-eyedropper:before { + content: "\e568"; +} +.ph.ph-eyedropper-sample:before { + content: "\eac4"; +} +.ph.ph-eyeglasses:before { + content: "\e7ba"; +} +.ph.ph-eyes:before { + content: "\ee5c"; +} +.ph.ph-face-mask:before { + content: "\e56a"; +} +.ph.ph-facebook-logo:before { + content: "\e226"; +} +.ph.ph-factory:before { + content: "\e760"; +} +.ph.ph-faders:before { + content: "\e228"; +} +.ph.ph-faders-horizontal:before { + content: "\e22a"; +} +.ph.ph-fallout-shelter:before { + content: "\e9de"; +} +.ph.ph-fan:before { + content: "\e9f2"; +} +.ph.ph-farm:before { + content: "\ec70"; +} +.ph.ph-fast-forward:before { + content: "\e6a6"; +} +.ph.ph-fast-forward-circle:before { + content: "\e22c"; +} +.ph.ph-feather:before { + content: "\e9c0"; +} +.ph.ph-fediverse-logo:before { + content: "\ed66"; +} +.ph.ph-figma-logo:before { + content: "\e22e"; +} +.ph.ph-file:before { + content: "\e230"; +} +.ph.ph-file-archive:before { + content: "\eb2a"; +} +.ph.ph-file-arrow-down:before { + content: "\e232"; +} +.ph.ph-file-arrow-up:before { + content: "\e61e"; +} +.ph.ph-file-audio:before { + content: "\ea20"; +} +.ph.ph-file-c:before { + content: "\eb32"; +} +.ph.ph-file-c-sharp:before { + content: "\eb30"; +} +.ph.ph-file-cloud:before { + content: "\e95e"; +} +.ph.ph-file-code:before { + content: "\e914"; +} +.ph.ph-file-cpp:before { + content: "\eb2e"; +} +.ph.ph-file-css:before { + content: "\eb34"; +} +.ph.ph-file-csv:before { + content: "\eb1c"; +} +.ph.ph-file-dashed:before { + content: "\e704"; +} +.ph.ph-file-dotted:before { + content: "\e704"; +} +.ph.ph-file-doc:before { + content: "\eb1e"; +} +.ph.ph-file-html:before { + content: "\eb38"; +} +.ph.ph-file-image:before { + content: "\ea24"; +} +.ph.ph-file-ini:before { + content: "\eb33"; +} +.ph.ph-file-jpg:before { + content: "\eb1a"; +} +.ph.ph-file-js:before { + content: "\eb24"; +} +.ph.ph-file-jsx:before { + content: "\eb3a"; +} +.ph.ph-file-lock:before { + content: "\e95c"; +} +.ph.ph-file-magnifying-glass:before { + content: "\e238"; +} +.ph.ph-file-search:before { + content: "\e238"; +} +.ph.ph-file-md:before { + content: "\ed50"; +} +.ph.ph-file-minus:before { + content: "\e234"; +} +.ph.ph-file-pdf:before { + content: "\e702"; +} +.ph.ph-file-plus:before { + content: "\e236"; +} +.ph.ph-file-png:before { + content: "\eb18"; +} +.ph.ph-file-ppt:before { + content: "\eb20"; +} +.ph.ph-file-py:before { + content: "\eb2c"; +} +.ph.ph-file-rs:before { + content: "\eb28"; +} +.ph.ph-file-sql:before { + content: "\ed4e"; +} +.ph.ph-file-svg:before { + content: "\ed08"; +} +.ph.ph-file-text:before { + content: "\e23a"; +} +.ph.ph-file-ts:before { + content: "\eb26"; +} +.ph.ph-file-tsx:before { + content: "\eb3c"; +} +.ph.ph-file-txt:before { + content: "\eb35"; +} +.ph.ph-file-video:before { + content: "\ea22"; +} +.ph.ph-file-vue:before { + content: "\eb3e"; +} +.ph.ph-file-x:before { + content: "\e23c"; +} +.ph.ph-file-xls:before { + content: "\eb22"; +} +.ph.ph-file-zip:before { + content: "\e958"; +} +.ph.ph-files:before { + content: "\e710"; +} +.ph.ph-film-reel:before { + content: "\e8c0"; +} +.ph.ph-film-script:before { + content: "\eb50"; +} +.ph.ph-film-slate:before { + content: "\e8c2"; +} +.ph.ph-film-strip:before { + content: "\e792"; +} +.ph.ph-fingerprint:before { + content: "\e23e"; +} +.ph.ph-fingerprint-simple:before { + content: "\e240"; +} +.ph.ph-finn-the-human:before { + content: "\e56c"; +} +.ph.ph-fire:before { + content: "\e242"; +} +.ph.ph-fire-extinguisher:before { + content: "\e9e8"; +} +.ph.ph-fire-simple:before { + content: "\e620"; +} +.ph.ph-fire-truck:before { + content: "\e574"; +} +.ph.ph-first-aid:before { + content: "\e56e"; +} +.ph.ph-first-aid-kit:before { + content: "\e570"; +} +.ph.ph-fish:before { + content: "\e728"; +} +.ph.ph-fish-simple:before { + content: "\e72a"; +} +.ph.ph-flag:before { + content: "\e244"; +} +.ph.ph-flag-banner:before { + content: "\e622"; +} +.ph.ph-flag-banner-fold:before { + content: "\ecf2"; +} +.ph.ph-flag-checkered:before { + content: "\ea38"; +} +.ph.ph-flag-pennant:before { + content: "\ecf0"; +} +.ph.ph-flame:before { + content: "\e624"; +} +.ph.ph-flashlight:before { + content: "\e246"; +} +.ph.ph-flask:before { + content: "\e79e"; +} +.ph.ph-flip-horizontal:before { + content: "\ed6a"; +} +.ph.ph-flip-vertical:before { + content: "\ed6c"; +} +.ph.ph-floppy-disk:before { + content: "\e248"; +} +.ph.ph-floppy-disk-back:before { + content: "\eaf4"; +} +.ph.ph-flow-arrow:before { + content: "\e6ec"; +} +.ph.ph-flower:before { + content: "\e75e"; +} +.ph.ph-flower-lotus:before { + content: "\e6cc"; +} +.ph.ph-flower-tulip:before { + content: "\eacc"; +} +.ph.ph-flying-saucer:before { + content: "\eb4a"; +} +.ph.ph-folder:before { + content: "\e24a"; +} +.ph.ph-folder-notch:before { + content: "\e24a"; +} +.ph.ph-folder-dashed:before { + content: "\e8f8"; +} +.ph.ph-folder-dotted:before { + content: "\e8f8"; +} +.ph.ph-folder-lock:before { + content: "\ea3c"; +} +.ph.ph-folder-minus:before { + content: "\e254"; +} +.ph.ph-folder-notch-minus:before { + content: "\e254"; +} +.ph.ph-folder-open:before { + content: "\e256"; +} +.ph.ph-folder-notch-open:before { + content: "\e256"; +} +.ph.ph-folder-plus:before { + content: "\e258"; +} +.ph.ph-folder-notch-plus:before { + content: "\e258"; +} +.ph.ph-folder-simple:before { + content: "\e25a"; +} +.ph.ph-folder-simple-dashed:before { + content: "\ec2a"; +} +.ph.ph-folder-simple-dotted:before { + content: "\ec2a"; +} +.ph.ph-folder-simple-lock:before { + content: "\eb5e"; +} +.ph.ph-folder-simple-minus:before { + content: "\e25c"; +} +.ph.ph-folder-simple-plus:before { + content: "\e25e"; +} +.ph.ph-folder-simple-star:before { + content: "\ec2e"; +} +.ph.ph-folder-simple-user:before { + content: "\eb60"; +} +.ph.ph-folder-star:before { + content: "\ea86"; +} +.ph.ph-folder-user:before { + content: "\eb46"; +} +.ph.ph-folders:before { + content: "\e260"; +} +.ph.ph-football:before { + content: "\e718"; +} +.ph.ph-football-helmet:before { + content: "\ee4c"; +} +.ph.ph-footprints:before { + content: "\ea88"; +} +.ph.ph-fork-knife:before { + content: "\e262"; +} +.ph.ph-four-k:before { + content: "\ea5c"; +} +.ph.ph-frame-corners:before { + content: "\e626"; +} +.ph.ph-framer-logo:before { + content: "\e264"; +} +.ph.ph-function:before { + content: "\ebe4"; +} +.ph.ph-funnel:before { + content: "\e266"; +} +.ph.ph-funnel-simple:before { + content: "\e268"; +} +.ph.ph-funnel-simple-x:before { + content: "\e26a"; +} +.ph.ph-funnel-x:before { + content: "\e26c"; +} +.ph.ph-game-controller:before { + content: "\e26e"; +} +.ph.ph-garage:before { + content: "\ecd6"; +} +.ph.ph-gas-can:before { + content: "\e8ce"; +} +.ph.ph-gas-pump:before { + content: "\e768"; +} +.ph.ph-gauge:before { + content: "\e628"; +} +.ph.ph-gavel:before { + content: "\ea32"; +} +.ph.ph-gear:before { + content: "\e270"; +} +.ph.ph-gear-fine:before { + content: "\e87c"; +} +.ph.ph-gear-six:before { + content: "\e272"; +} +.ph.ph-gender-female:before { + content: "\e6e0"; +} +.ph.ph-gender-intersex:before { + content: "\e6e6"; +} +.ph.ph-gender-male:before { + content: "\e6e2"; +} +.ph.ph-gender-neuter:before { + content: "\e6ea"; +} +.ph.ph-gender-nonbinary:before { + content: "\e6e4"; +} +.ph.ph-gender-transgender:before { + content: "\e6e8"; +} +.ph.ph-ghost:before { + content: "\e62a"; +} +.ph.ph-gif:before { + content: "\e274"; +} +.ph.ph-gift:before { + content: "\e276"; +} +.ph.ph-git-branch:before { + content: "\e278"; +} +.ph.ph-git-commit:before { + content: "\e27a"; +} +.ph.ph-git-diff:before { + content: "\e27c"; +} +.ph.ph-git-fork:before { + content: "\e27e"; +} +.ph.ph-git-merge:before { + content: "\e280"; +} +.ph.ph-git-pull-request:before { + content: "\e282"; +} +.ph.ph-github-logo:before { + content: "\e576"; +} +.ph.ph-gitlab-logo:before { + content: "\e694"; +} +.ph.ph-gitlab-logo-simple:before { + content: "\e696"; +} +.ph.ph-globe:before { + content: "\e288"; +} +.ph.ph-globe-hemisphere-east:before { + content: "\e28a"; +} +.ph.ph-globe-hemisphere-west:before { + content: "\e28c"; +} +.ph.ph-globe-simple:before { + content: "\e28e"; +} +.ph.ph-globe-simple-x:before { + content: "\e284"; +} +.ph.ph-globe-stand:before { + content: "\e290"; +} +.ph.ph-globe-x:before { + content: "\e286"; +} +.ph.ph-goggles:before { + content: "\ecb4"; +} +.ph.ph-golf:before { + content: "\ea3e"; +} +.ph.ph-goodreads-logo:before { + content: "\ed10"; +} +.ph.ph-google-cardboard-logo:before { + content: "\e7b6"; +} +.ph.ph-google-chrome-logo:before { + content: "\e976"; +} +.ph.ph-google-drive-logo:before { + content: "\e8f6"; +} +.ph.ph-google-logo:before { + content: "\e292"; +} +.ph.ph-google-photos-logo:before { + content: "\eb92"; +} +.ph.ph-google-play-logo:before { + content: "\e294"; +} +.ph.ph-google-podcasts-logo:before { + content: "\eb94"; +} +.ph.ph-gps:before { + content: "\edd8"; +} +.ph.ph-gps-fix:before { + content: "\edd6"; +} +.ph.ph-gps-slash:before { + content: "\edd4"; +} +.ph.ph-gradient:before { + content: "\eb42"; +} +.ph.ph-graduation-cap:before { + content: "\e62c"; +} +.ph.ph-grains:before { + content: "\ec68"; +} +.ph.ph-grains-slash:before { + content: "\ec6a"; +} +.ph.ph-graph:before { + content: "\eb58"; +} +.ph.ph-graphics-card:before { + content: "\e612"; +} +.ph.ph-greater-than:before { + content: "\edc4"; +} +.ph.ph-greater-than-or-equal:before { + content: "\eda2"; +} +.ph.ph-grid-four:before { + content: "\e296"; +} +.ph.ph-grid-nine:before { + content: "\ec8c"; +} +.ph.ph-guitar:before { + content: "\ea8a"; +} +.ph.ph-hair-dryer:before { + content: "\ea66"; +} +.ph.ph-hamburger:before { + content: "\e790"; +} +.ph.ph-hammer:before { + content: "\e80e"; +} +.ph.ph-hand:before { + content: "\e298"; +} +.ph.ph-hand-arrow-down:before { + content: "\ea4e"; +} +.ph.ph-hand-arrow-up:before { + content: "\ee5a"; +} +.ph.ph-hand-coins:before { + content: "\ea8c"; +} +.ph.ph-hand-deposit:before { + content: "\ee82"; +} +.ph.ph-hand-eye:before { + content: "\ea4c"; +} +.ph.ph-hand-fist:before { + content: "\e57a"; +} +.ph.ph-hand-grabbing:before { + content: "\e57c"; +} +.ph.ph-hand-heart:before { + content: "\e810"; +} +.ph.ph-hand-palm:before { + content: "\e57e"; +} +.ph.ph-hand-peace:before { + content: "\e7cc"; +} +.ph.ph-hand-pointing:before { + content: "\e29a"; +} +.ph.ph-hand-soap:before { + content: "\e630"; +} +.ph.ph-hand-swipe-left:before { + content: "\ec94"; +} +.ph.ph-hand-swipe-right:before { + content: "\ec92"; +} +.ph.ph-hand-tap:before { + content: "\ec90"; +} +.ph.ph-hand-waving:before { + content: "\e580"; +} +.ph.ph-hand-withdraw:before { + content: "\ee80"; +} +.ph.ph-handbag:before { + content: "\e29c"; +} +.ph.ph-handbag-simple:before { + content: "\e62e"; +} +.ph.ph-hands-clapping:before { + content: "\e6a0"; +} +.ph.ph-hands-praying:before { + content: "\ecc8"; +} +.ph.ph-handshake:before { + content: "\e582"; +} +.ph.ph-hard-drive:before { + content: "\e29e"; +} +.ph.ph-hard-drives:before { + content: "\e2a0"; +} +.ph.ph-hard-hat:before { + content: "\ed46"; +} +.ph.ph-hash:before { + content: "\e2a2"; +} +.ph.ph-hash-straight:before { + content: "\e2a4"; +} +.ph.ph-head-circuit:before { + content: "\e7d4"; +} +.ph.ph-headlights:before { + content: "\e6fe"; +} +.ph.ph-headphones:before { + content: "\e2a6"; +} +.ph.ph-headset:before { + content: "\e584"; +} +.ph.ph-heart:before { + content: "\e2a8"; +} +.ph.ph-heart-break:before { + content: "\ebe8"; +} +.ph.ph-heart-half:before { + content: "\ec48"; +} +.ph.ph-heart-straight:before { + content: "\e2aa"; +} +.ph.ph-heart-straight-break:before { + content: "\eb98"; +} +.ph.ph-heartbeat:before { + content: "\e2ac"; +} +.ph.ph-hexagon:before { + content: "\e2ae"; +} +.ph.ph-high-definition:before { + content: "\ea8e"; +} +.ph.ph-high-heel:before { + content: "\e8e8"; +} +.ph.ph-highlighter:before { + content: "\ec76"; +} +.ph.ph-highlighter-circle:before { + content: "\e632"; +} +.ph.ph-hockey:before { + content: "\ec86"; +} +.ph.ph-hoodie:before { + content: "\ecd0"; +} +.ph.ph-horse:before { + content: "\e2b0"; +} +.ph.ph-hospital:before { + content: "\e844"; +} +.ph.ph-hourglass:before { + content: "\e2b2"; +} +.ph.ph-hourglass-high:before { + content: "\e2b4"; +} +.ph.ph-hourglass-low:before { + content: "\e2b6"; +} +.ph.ph-hourglass-medium:before { + content: "\e2b8"; +} +.ph.ph-hourglass-simple:before { + content: "\e2ba"; +} +.ph.ph-hourglass-simple-high:before { + content: "\e2bc"; +} +.ph.ph-hourglass-simple-low:before { + content: "\e2be"; +} +.ph.ph-hourglass-simple-medium:before { + content: "\e2c0"; +} +.ph.ph-house:before { + content: "\e2c2"; +} +.ph.ph-house-line:before { + content: "\e2c4"; +} +.ph.ph-house-simple:before { + content: "\e2c6"; +} +.ph.ph-hurricane:before { + content: "\e88e"; +} +.ph.ph-ice-cream:before { + content: "\e804"; +} +.ph.ph-identification-badge:before { + content: "\e6f6"; +} +.ph.ph-identification-card:before { + content: "\e2c8"; +} +.ph.ph-image:before { + content: "\e2ca"; +} +.ph.ph-image-broken:before { + content: "\e7a8"; +} +.ph.ph-image-square:before { + content: "\e2cc"; +} +.ph.ph-images:before { + content: "\e836"; +} +.ph.ph-images-square:before { + content: "\e834"; +} +.ph.ph-infinity:before { + content: "\e634"; +} +.ph.ph-lemniscate:before { + content: "\e634"; +} +.ph.ph-info:before { + content: "\e2ce"; +} +.ph.ph-instagram-logo:before { + content: "\e2d0"; +} +.ph.ph-intersect:before { + content: "\e2d2"; +} +.ph.ph-intersect-square:before { + content: "\e87a"; +} +.ph.ph-intersect-three:before { + content: "\ecc4"; +} +.ph.ph-intersection:before { + content: "\edba"; +} +.ph.ph-invoice:before { + content: "\ee42"; +} +.ph.ph-island:before { + content: "\ee06"; +} +.ph.ph-jar:before { + content: "\e7e0"; +} +.ph.ph-jar-label:before { + content: "\e7e1"; +} +.ph.ph-jeep:before { + content: "\e2d4"; +} +.ph.ph-joystick:before { + content: "\ea5e"; +} +.ph.ph-kanban:before { + content: "\eb54"; +} +.ph.ph-key:before { + content: "\e2d6"; +} +.ph.ph-key-return:before { + content: "\e782"; +} +.ph.ph-keyboard:before { + content: "\e2d8"; +} +.ph.ph-keyhole:before { + content: "\ea78"; +} +.ph.ph-knife:before { + content: "\e636"; +} +.ph.ph-ladder:before { + content: "\e9e4"; +} +.ph.ph-ladder-simple:before { + content: "\ec26"; +} +.ph.ph-lamp:before { + content: "\e638"; +} +.ph.ph-lamp-pendant:before { + content: "\ee2e"; +} +.ph.ph-laptop:before { + content: "\e586"; +} +.ph.ph-lasso:before { + content: "\edc6"; +} +.ph.ph-lastfm-logo:before { + content: "\e842"; +} +.ph.ph-layout:before { + content: "\e6d6"; +} +.ph.ph-leaf:before { + content: "\e2da"; +} +.ph.ph-lectern:before { + content: "\e95a"; +} +.ph.ph-lego:before { + content: "\e8c6"; +} +.ph.ph-lego-smiley:before { + content: "\e8c7"; +} +.ph.ph-less-than:before { + content: "\edac"; +} +.ph.ph-less-than-or-equal:before { + content: "\eda4"; +} +.ph.ph-letter-circle-h:before { + content: "\ebf8"; +} +.ph.ph-letter-circle-p:before { + content: "\ec08"; +} +.ph.ph-letter-circle-v:before { + content: "\ec14"; +} +.ph.ph-lifebuoy:before { + content: "\e63a"; +} +.ph.ph-lightbulb:before { + content: "\e2dc"; +} +.ph.ph-lightbulb-filament:before { + content: "\e63c"; +} +.ph.ph-lighthouse:before { + content: "\e9f6"; +} +.ph.ph-lightning:before { + content: "\e2de"; +} +.ph.ph-lightning-a:before { + content: "\ea84"; +} +.ph.ph-lightning-slash:before { + content: "\e2e0"; +} +.ph.ph-line-segment:before { + content: "\e6d2"; +} +.ph.ph-line-segments:before { + content: "\e6d4"; +} +.ph.ph-line-vertical:before { + content: "\ed70"; +} +.ph.ph-link:before { + content: "\e2e2"; +} +.ph.ph-link-break:before { + content: "\e2e4"; +} +.ph.ph-link-simple:before { + content: "\e2e6"; +} +.ph.ph-link-simple-break:before { + content: "\e2e8"; +} +.ph.ph-link-simple-horizontal:before { + content: "\e2ea"; +} +.ph.ph-link-simple-horizontal-break:before { + content: "\e2ec"; +} +.ph.ph-linkedin-logo:before { + content: "\e2ee"; +} +.ph.ph-linktree-logo:before { + content: "\edee"; +} +.ph.ph-linux-logo:before { + content: "\eb02"; +} +.ph.ph-list:before { + content: "\e2f0"; +} +.ph.ph-list-bullets:before { + content: "\e2f2"; +} +.ph.ph-list-checks:before { + content: "\eadc"; +} +.ph.ph-list-dashes:before { + content: "\e2f4"; +} +.ph.ph-list-heart:before { + content: "\ebde"; +} +.ph.ph-list-magnifying-glass:before { + content: "\ebe0"; +} +.ph.ph-list-numbers:before { + content: "\e2f6"; +} +.ph.ph-list-plus:before { + content: "\e2f8"; +} +.ph.ph-list-star:before { + content: "\ebdc"; +} +.ph.ph-lock:before { + content: "\e2fa"; +} +.ph.ph-lock-key:before { + content: "\e2fe"; +} +.ph.ph-lock-key-open:before { + content: "\e300"; +} +.ph.ph-lock-laminated:before { + content: "\e302"; +} +.ph.ph-lock-laminated-open:before { + content: "\e304"; +} +.ph.ph-lock-open:before { + content: "\e306"; +} +.ph.ph-lock-simple:before { + content: "\e308"; +} +.ph.ph-lock-simple-open:before { + content: "\e30a"; +} +.ph.ph-lockers:before { + content: "\ecb8"; +} +.ph.ph-log:before { + content: "\ed82"; +} +.ph.ph-magic-wand:before { + content: "\e6b6"; +} +.ph.ph-magnet:before { + content: "\e680"; +} +.ph.ph-magnet-straight:before { + content: "\e682"; +} +.ph.ph-magnifying-glass:before { + content: "\e30c"; +} +.ph.ph-magnifying-glass-minus:before { + content: "\e30e"; +} +.ph.ph-magnifying-glass-plus:before { + content: "\e310"; +} +.ph.ph-mailbox:before { + content: "\ec1e"; +} +.ph.ph-map-pin:before { + content: "\e316"; +} +.ph.ph-map-pin-area:before { + content: "\ee3a"; +} +.ph.ph-map-pin-line:before { + content: "\e318"; +} +.ph.ph-map-pin-plus:before { + content: "\e314"; +} +.ph.ph-map-pin-simple:before { + content: "\ee3e"; +} +.ph.ph-map-pin-simple-area:before { + content: "\ee3c"; +} +.ph.ph-map-pin-simple-line:before { + content: "\ee38"; +} +.ph.ph-map-trifold:before { + content: "\e31a"; +} +.ph.ph-markdown-logo:before { + content: "\e508"; +} +.ph.ph-marker-circle:before { + content: "\e640"; +} +.ph.ph-martini:before { + content: "\e31c"; +} +.ph.ph-mask-happy:before { + content: "\e9f4"; +} +.ph.ph-mask-sad:before { + content: "\eb9e"; +} +.ph.ph-mastodon-logo:before { + content: "\ed68"; +} +.ph.ph-math-operations:before { + content: "\e31e"; +} +.ph.ph-matrix-logo:before { + content: "\ed64"; +} +.ph.ph-medal:before { + content: "\e320"; +} +.ph.ph-medal-military:before { + content: "\ecfc"; +} +.ph.ph-medium-logo:before { + content: "\e322"; +} +.ph.ph-megaphone:before { + content: "\e324"; +} +.ph.ph-megaphone-simple:before { + content: "\e642"; +} +.ph.ph-member-of:before { + content: "\edc2"; +} +.ph.ph-memory:before { + content: "\e9c4"; +} +.ph.ph-messenger-logo:before { + content: "\e6d8"; +} +.ph.ph-meta-logo:before { + content: "\ed02"; +} +.ph.ph-meteor:before { + content: "\e9ba"; +} +.ph.ph-metronome:before { + content: "\ec8e"; +} +.ph.ph-microphone:before { + content: "\e326"; +} +.ph.ph-microphone-slash:before { + content: "\e328"; +} +.ph.ph-microphone-stage:before { + content: "\e75c"; +} +.ph.ph-microscope:before { + content: "\ec7a"; +} +.ph.ph-microsoft-excel-logo:before { + content: "\eb6c"; +} +.ph.ph-microsoft-outlook-logo:before { + content: "\eb70"; +} +.ph.ph-microsoft-powerpoint-logo:before { + content: "\eace"; +} +.ph.ph-microsoft-teams-logo:before { + content: "\eb66"; +} +.ph.ph-microsoft-word-logo:before { + content: "\eb6a"; +} +.ph.ph-minus:before { + content: "\e32a"; +} +.ph.ph-minus-circle:before { + content: "\e32c"; +} +.ph.ph-minus-square:before { + content: "\ed4c"; +} +.ph.ph-money:before { + content: "\e588"; +} +.ph.ph-money-wavy:before { + content: "\ee68"; +} +.ph.ph-monitor:before { + content: "\e32e"; +} +.ph.ph-monitor-arrow-up:before { + content: "\e58a"; +} +.ph.ph-monitor-play:before { + content: "\e58c"; +} +.ph.ph-moon:before { + content: "\e330"; +} +.ph.ph-moon-stars:before { + content: "\e58e"; +} +.ph.ph-moped:before { + content: "\e824"; +} +.ph.ph-moped-front:before { + content: "\e822"; +} +.ph.ph-mosque:before { + content: "\ecee"; +} +.ph.ph-motorcycle:before { + content: "\e80a"; +} +.ph.ph-mountains:before { + content: "\e7ae"; +} +.ph.ph-mouse:before { + content: "\e33a"; +} +.ph.ph-mouse-left-click:before { + content: "\e334"; +} +.ph.ph-mouse-middle-click:before { + content: "\e338"; +} +.ph.ph-mouse-right-click:before { + content: "\e336"; +} +.ph.ph-mouse-scroll:before { + content: "\e332"; +} +.ph.ph-mouse-simple:before { + content: "\e644"; +} +.ph.ph-music-note:before { + content: "\e33c"; +} +.ph.ph-music-note-simple:before { + content: "\e33e"; +} +.ph.ph-music-notes:before { + content: "\e340"; +} +.ph.ph-music-notes-minus:before { + content: "\ee0c"; +} +.ph.ph-music-notes-plus:before { + content: "\eb7c"; +} +.ph.ph-music-notes-simple:before { + content: "\e342"; +} +.ph.ph-navigation-arrow:before { + content: "\eade"; +} +.ph.ph-needle:before { + content: "\e82e"; +} +.ph.ph-network:before { + content: "\edde"; +} +.ph.ph-network-slash:before { + content: "\eddc"; +} +.ph.ph-network-x:before { + content: "\edda"; +} +.ph.ph-newspaper:before { + content: "\e344"; +} +.ph.ph-newspaper-clipping:before { + content: "\e346"; +} +.ph.ph-not-equals:before { + content: "\eda6"; +} +.ph.ph-not-member-of:before { + content: "\edae"; +} +.ph.ph-not-subset-of:before { + content: "\edb0"; +} +.ph.ph-not-superset-of:before { + content: "\edb2"; +} +.ph.ph-notches:before { + content: "\ed3a"; +} +.ph.ph-note:before { + content: "\e348"; +} +.ph.ph-note-blank:before { + content: "\e34a"; +} +.ph.ph-note-pencil:before { + content: "\e34c"; +} +.ph.ph-notebook:before { + content: "\e34e"; +} +.ph.ph-notepad:before { + content: "\e63e"; +} +.ph.ph-notification:before { + content: "\e6fa"; +} +.ph.ph-notion-logo:before { + content: "\e9a0"; +} +.ph.ph-nuclear-plant:before { + content: "\ed7c"; +} +.ph.ph-number-circle-eight:before { + content: "\e352"; +} +.ph.ph-number-circle-five:before { + content: "\e358"; +} +.ph.ph-number-circle-four:before { + content: "\e35e"; +} +.ph.ph-number-circle-nine:before { + content: "\e364"; +} +.ph.ph-number-circle-one:before { + content: "\e36a"; +} +.ph.ph-number-circle-seven:before { + content: "\e370"; +} +.ph.ph-number-circle-six:before { + content: "\e376"; +} +.ph.ph-number-circle-three:before { + content: "\e37c"; +} +.ph.ph-number-circle-two:before { + content: "\e382"; +} +.ph.ph-number-circle-zero:before { + content: "\e388"; +} +.ph.ph-number-eight:before { + content: "\e350"; +} +.ph.ph-number-five:before { + content: "\e356"; +} +.ph.ph-number-four:before { + content: "\e35c"; +} +.ph.ph-number-nine:before { + content: "\e362"; +} +.ph.ph-number-one:before { + content: "\e368"; +} +.ph.ph-number-seven:before { + content: "\e36e"; +} +.ph.ph-number-six:before { + content: "\e374"; +} +.ph.ph-number-square-eight:before { + content: "\e354"; +} +.ph.ph-number-square-five:before { + content: "\e35a"; +} +.ph.ph-number-square-four:before { + content: "\e360"; +} +.ph.ph-number-square-nine:before { + content: "\e366"; +} +.ph.ph-number-square-one:before { + content: "\e36c"; +} +.ph.ph-number-square-seven:before { + content: "\e372"; +} +.ph.ph-number-square-six:before { + content: "\e378"; +} +.ph.ph-number-square-three:before { + content: "\e37e"; +} +.ph.ph-number-square-two:before { + content: "\e384"; +} +.ph.ph-number-square-zero:before { + content: "\e38a"; +} +.ph.ph-number-three:before { + content: "\e37a"; +} +.ph.ph-number-two:before { + content: "\e380"; +} +.ph.ph-number-zero:before { + content: "\e386"; +} +.ph.ph-numpad:before { + content: "\e3c8"; +} +.ph.ph-nut:before { + content: "\e38c"; +} +.ph.ph-ny-times-logo:before { + content: "\e646"; +} +.ph.ph-octagon:before { + content: "\e38e"; +} +.ph.ph-office-chair:before { + content: "\ea46"; +} +.ph.ph-onigiri:before { + content: "\ee2c"; +} +.ph.ph-open-ai-logo:before { + content: "\e7d2"; +} +.ph.ph-option:before { + content: "\e8a8"; +} +.ph.ph-orange:before { + content: "\ee40"; +} +.ph.ph-orange-slice:before { + content: "\ed36"; +} +.ph.ph-oven:before { + content: "\ed8c"; +} +.ph.ph-package:before { + content: "\e390"; +} +.ph.ph-paint-brush:before { + content: "\e6f0"; +} +.ph.ph-paint-brush-broad:before { + content: "\e590"; +} +.ph.ph-paint-brush-household:before { + content: "\e6f2"; +} +.ph.ph-paint-bucket:before { + content: "\e392"; +} +.ph.ph-paint-roller:before { + content: "\e6f4"; +} +.ph.ph-palette:before { + content: "\e6c8"; +} +.ph.ph-panorama:before { + content: "\eaa2"; +} +.ph.ph-pants:before { + content: "\ec88"; +} +.ph.ph-paper-plane:before { + content: "\e394"; +} +.ph.ph-paper-plane-right:before { + content: "\e396"; +} +.ph.ph-paper-plane-tilt:before { + content: "\e398"; +} +.ph.ph-paperclip:before { + content: "\e39a"; +} +.ph.ph-paperclip-horizontal:before { + content: "\e592"; +} +.ph.ph-parachute:before { + content: "\ea7c"; +} +.ph.ph-paragraph:before { + content: "\e960"; +} +.ph.ph-parallelogram:before { + content: "\ecc6"; +} +.ph.ph-park:before { + content: "\ecb2"; +} +.ph.ph-password:before { + content: "\e752"; +} +.ph.ph-path:before { + content: "\e39c"; +} +.ph.ph-patreon-logo:before { + content: "\e98a"; +} +.ph.ph-pause:before { + content: "\e39e"; +} +.ph.ph-pause-circle:before { + content: "\e3a0"; +} +.ph.ph-paw-print:before { + content: "\e648"; +} +.ph.ph-paypal-logo:before { + content: "\e98c"; +} +.ph.ph-peace:before { + content: "\e3a2"; +} +.ph.ph-pen:before { + content: "\e3aa"; +} +.ph.ph-pen-nib:before { + content: "\e3ac"; +} +.ph.ph-pen-nib-straight:before { + content: "\e64a"; +} +.ph.ph-pencil:before { + content: "\e3ae"; +} +.ph.ph-pencil-circle:before { + content: "\e3b0"; +} +.ph.ph-pencil-line:before { + content: "\e3b2"; +} +.ph.ph-pencil-ruler:before { + content: "\e906"; +} +.ph.ph-pencil-simple:before { + content: "\e3b4"; +} +.ph.ph-pencil-simple-line:before { + content: "\ebc6"; +} +.ph.ph-pencil-simple-slash:before { + content: "\ecf6"; +} +.ph.ph-pencil-slash:before { + content: "\ecf8"; +} +.ph.ph-pentagon:before { + content: "\ec7e"; +} +.ph.ph-pentagram:before { + content: "\ec5c"; +} +.ph.ph-pepper:before { + content: "\e94a"; +} +.ph.ph-percent:before { + content: "\e3b6"; +} +.ph.ph-person:before { + content: "\e3a8"; +} +.ph.ph-person-arms-spread:before { + content: "\ecfe"; +} +.ph.ph-person-simple:before { + content: "\e72e"; +} +.ph.ph-person-simple-bike:before { + content: "\e734"; +} +.ph.ph-person-simple-circle:before { + content: "\ee58"; +} +.ph.ph-person-simple-hike:before { + content: "\ed54"; +} +.ph.ph-person-simple-run:before { + content: "\e730"; +} +.ph.ph-person-simple-ski:before { + content: "\e71c"; +} +.ph.ph-person-simple-snowboard:before { + content: "\e71e"; +} +.ph.ph-person-simple-swim:before { + content: "\e736"; +} +.ph.ph-person-simple-tai-chi:before { + content: "\ed5c"; +} +.ph.ph-person-simple-throw:before { + content: "\e732"; +} +.ph.ph-person-simple-walk:before { + content: "\e73a"; +} +.ph.ph-perspective:before { + content: "\ebe6"; +} +.ph.ph-phone:before { + content: "\e3b8"; +} +.ph.ph-phone-call:before { + content: "\e3ba"; +} +.ph.ph-phone-disconnect:before { + content: "\e3bc"; +} +.ph.ph-phone-incoming:before { + content: "\e3be"; +} +.ph.ph-phone-list:before { + content: "\e3cc"; +} +.ph.ph-phone-outgoing:before { + content: "\e3c0"; +} +.ph.ph-phone-pause:before { + content: "\e3ca"; +} +.ph.ph-phone-plus:before { + content: "\ec56"; +} +.ph.ph-phone-slash:before { + content: "\e3c2"; +} +.ph.ph-phone-transfer:before { + content: "\e3c6"; +} +.ph.ph-phone-x:before { + content: "\e3c4"; +} +.ph.ph-phosphor-logo:before { + content: "\e3ce"; +} +.ph.ph-pi:before { + content: "\ec80"; +} +.ph.ph-piano-keys:before { + content: "\e9c8"; +} +.ph.ph-picnic-table:before { + content: "\ee26"; +} +.ph.ph-picture-in-picture:before { + content: "\e64c"; +} +.ph.ph-piggy-bank:before { + content: "\ea04"; +} +.ph.ph-pill:before { + content: "\e700"; +} +.ph.ph-ping-pong:before { + content: "\ea42"; +} +.ph.ph-pint-glass:before { + content: "\edd0"; +} +.ph.ph-pinterest-logo:before { + content: "\e64e"; +} +.ph.ph-pinwheel:before { + content: "\eb9c"; +} +.ph.ph-pipe:before { + content: "\ed86"; +} +.ph.ph-pipe-wrench:before { + content: "\ed88"; +} +.ph.ph-pix-logo:before { + content: "\ecc2"; +} +.ph.ph-pizza:before { + content: "\e796"; +} +.ph.ph-placeholder:before { + content: "\e650"; +} +.ph.ph-planet:before { + content: "\e652"; +} +.ph.ph-plant:before { + content: "\ebae"; +} +.ph.ph-play:before { + content: "\e3d0"; +} +.ph.ph-play-circle:before { + content: "\e3d2"; +} +.ph.ph-play-pause:before { + content: "\e8be"; +} +.ph.ph-playlist:before { + content: "\e6aa"; +} +.ph.ph-plug:before { + content: "\e946"; +} +.ph.ph-plug-charging:before { + content: "\eb5c"; +} +.ph.ph-plugs:before { + content: "\eb56"; +} +.ph.ph-plugs-connected:before { + content: "\eb5a"; +} +.ph.ph-plus:before { + content: "\e3d4"; +} +.ph.ph-plus-circle:before { + content: "\e3d6"; +} +.ph.ph-plus-minus:before { + content: "\e3d8"; +} +.ph.ph-plus-square:before { + content: "\ed4a"; +} +.ph.ph-poker-chip:before { + content: "\e594"; +} +.ph.ph-police-car:before { + content: "\ec4a"; +} +.ph.ph-polygon:before { + content: "\e6d0"; +} +.ph.ph-popcorn:before { + content: "\eb4e"; +} +.ph.ph-popsicle:before { + content: "\ebbe"; +} +.ph.ph-potted-plant:before { + content: "\ec22"; +} +.ph.ph-power:before { + content: "\e3da"; +} +.ph.ph-prescription:before { + content: "\e7a2"; +} +.ph.ph-presentation:before { + content: "\e654"; +} +.ph.ph-presentation-chart:before { + content: "\e656"; +} +.ph.ph-printer:before { + content: "\e3dc"; +} +.ph.ph-prohibit:before { + content: "\e3de"; +} +.ph.ph-prohibit-inset:before { + content: "\e3e0"; +} +.ph.ph-projector-screen:before { + content: "\e658"; +} +.ph.ph-projector-screen-chart:before { + content: "\e65a"; +} +.ph.ph-pulse:before { + content: "\e000"; +} +.ph.ph-activity:before { + content: "\e000"; +} +.ph.ph-push-pin:before { + content: "\e3e2"; +} +.ph.ph-push-pin-simple:before { + content: "\e65c"; +} +.ph.ph-push-pin-simple-slash:before { + content: "\e65e"; +} +.ph.ph-push-pin-slash:before { + content: "\e3e4"; +} +.ph.ph-puzzle-piece:before { + content: "\e596"; +} +.ph.ph-qr-code:before { + content: "\e3e6"; +} +.ph.ph-question:before { + content: "\e3e8"; +} +.ph.ph-question-mark:before { + content: "\e3e9"; +} +.ph.ph-queue:before { + content: "\e6ac"; +} +.ph.ph-quotes:before { + content: "\e660"; +} +.ph.ph-rabbit:before { + content: "\eac2"; +} +.ph.ph-racquet:before { + content: "\ee02"; +} +.ph.ph-radical:before { + content: "\e3ea"; +} +.ph.ph-radio:before { + content: "\e77e"; +} +.ph.ph-radio-button:before { + content: "\eb08"; +} +.ph.ph-radioactive:before { + content: "\e9dc"; +} +.ph.ph-rainbow:before { + content: "\e598"; +} +.ph.ph-rainbow-cloud:before { + content: "\e59a"; +} +.ph.ph-ranking:before { + content: "\ed62"; +} +.ph.ph-read-cv-logo:before { + content: "\ed0c"; +} +.ph.ph-receipt:before { + content: "\e3ec"; +} +.ph.ph-receipt-x:before { + content: "\ed40"; +} +.ph.ph-record:before { + content: "\e3ee"; +} +.ph.ph-rectangle:before { + content: "\e3f0"; +} +.ph.ph-rectangle-dashed:before { + content: "\e3f2"; +} +.ph.ph-recycle:before { + content: "\e75a"; +} +.ph.ph-reddit-logo:before { + content: "\e59c"; +} +.ph.ph-repeat:before { + content: "\e3f6"; +} +.ph.ph-repeat-once:before { + content: "\e3f8"; +} +.ph.ph-replit-logo:before { + content: "\eb8a"; +} +.ph.ph-resize:before { + content: "\ed6e"; +} +.ph.ph-rewind:before { + content: "\e6a8"; +} +.ph.ph-rewind-circle:before { + content: "\e3fa"; +} +.ph.ph-road-horizon:before { + content: "\e838"; +} +.ph.ph-robot:before { + content: "\e762"; +} +.ph.ph-rocket:before { + content: "\e3fc"; +} +.ph.ph-rocket-launch:before { + content: "\e3fe"; +} +.ph.ph-rows:before { + content: "\e5a2"; +} +.ph.ph-rows-plus-bottom:before { + content: "\e59e"; +} +.ph.ph-rows-plus-top:before { + content: "\e5a0"; +} +.ph.ph-rss:before { + content: "\e400"; +} +.ph.ph-rss-simple:before { + content: "\e402"; +} +.ph.ph-rug:before { + content: "\ea1a"; +} +.ph.ph-ruler:before { + content: "\e6b8"; +} +.ph.ph-sailboat:before { + content: "\e78a"; +} +.ph.ph-scales:before { + content: "\e750"; +} +.ph.ph-scan:before { + content: "\ebb6"; +} +.ph.ph-scan-smiley:before { + content: "\ebb4"; +} +.ph.ph-scissors:before { + content: "\eae0"; +} +.ph.ph-scooter:before { + content: "\e820"; +} +.ph.ph-screencast:before { + content: "\e404"; +} +.ph.ph-screwdriver:before { + content: "\e86e"; +} +.ph.ph-scribble:before { + content: "\e806"; +} +.ph.ph-scribble-loop:before { + content: "\e662"; +} +.ph.ph-scroll:before { + content: "\eb7a"; +} +.ph.ph-seal:before { + content: "\e604"; +} +.ph.ph-circle-wavy:before { + content: "\e604"; +} +.ph.ph-seal-check:before { + content: "\e606"; +} +.ph.ph-circle-wavy-check:before { + content: "\e606"; +} +.ph.ph-seal-percent:before { + content: "\e60a"; +} +.ph.ph-seal-question:before { + content: "\e608"; +} +.ph.ph-circle-wavy-question:before { + content: "\e608"; +} +.ph.ph-seal-warning:before { + content: "\e60c"; +} +.ph.ph-circle-wavy-warning:before { + content: "\e60c"; +} +.ph.ph-seat:before { + content: "\eb8e"; +} +.ph.ph-seatbelt:before { + content: "\edfe"; +} +.ph.ph-security-camera:before { + content: "\eca4"; +} +.ph.ph-selection:before { + content: "\e69a"; +} +.ph.ph-selection-all:before { + content: "\e746"; +} +.ph.ph-selection-background:before { + content: "\eaf8"; +} +.ph.ph-selection-foreground:before { + content: "\eaf6"; +} +.ph.ph-selection-inverse:before { + content: "\e744"; +} +.ph.ph-selection-plus:before { + content: "\e69c"; +} +.ph.ph-selection-slash:before { + content: "\e69e"; +} +.ph.ph-shapes:before { + content: "\ec5e"; +} +.ph.ph-share:before { + content: "\e406"; +} +.ph.ph-share-fat:before { + content: "\ed52"; +} +.ph.ph-share-network:before { + content: "\e408"; +} +.ph.ph-shield:before { + content: "\e40a"; +} +.ph.ph-shield-check:before { + content: "\e40c"; +} +.ph.ph-shield-checkered:before { + content: "\e708"; +} +.ph.ph-shield-chevron:before { + content: "\e40e"; +} +.ph.ph-shield-plus:before { + content: "\e706"; +} +.ph.ph-shield-slash:before { + content: "\e410"; +} +.ph.ph-shield-star:before { + content: "\ec34"; +} +.ph.ph-shield-warning:before { + content: "\e412"; +} +.ph.ph-shipping-container:before { + content: "\e78c"; +} +.ph.ph-shirt-folded:before { + content: "\ea92"; +} +.ph.ph-shooting-star:before { + content: "\ecfa"; +} +.ph.ph-shopping-bag:before { + content: "\e416"; +} +.ph.ph-shopping-bag-open:before { + content: "\e418"; +} +.ph.ph-shopping-cart:before { + content: "\e41e"; +} +.ph.ph-shopping-cart-simple:before { + content: "\e420"; +} +.ph.ph-shovel:before { + content: "\e9e6"; +} +.ph.ph-shower:before { + content: "\e776"; +} +.ph.ph-shrimp:before { + content: "\eab4"; +} +.ph.ph-shuffle:before { + content: "\e422"; +} +.ph.ph-shuffle-angular:before { + content: "\e424"; +} +.ph.ph-shuffle-simple:before { + content: "\e426"; +} +.ph.ph-sidebar:before { + content: "\eab6"; +} +.ph.ph-sidebar-simple:before { + content: "\ec24"; +} +.ph.ph-sigma:before { + content: "\eab8"; +} +.ph.ph-sign-in:before { + content: "\e428"; +} +.ph.ph-sign-out:before { + content: "\e42a"; +} +.ph.ph-signature:before { + content: "\ebac"; +} +.ph.ph-signpost:before { + content: "\e89c"; +} +.ph.ph-sim-card:before { + content: "\e664"; +} +.ph.ph-siren:before { + content: "\e9b8"; +} +.ph.ph-sketch-logo:before { + content: "\e42c"; +} +.ph.ph-skip-back:before { + content: "\e5a4"; +} +.ph.ph-skip-back-circle:before { + content: "\e42e"; +} +.ph.ph-skip-forward:before { + content: "\e5a6"; +} +.ph.ph-skip-forward-circle:before { + content: "\e430"; +} +.ph.ph-skull:before { + content: "\e916"; +} +.ph.ph-skype-logo:before { + content: "\e8dc"; +} +.ph.ph-slack-logo:before { + content: "\e5a8"; +} +.ph.ph-sliders:before { + content: "\e432"; +} +.ph.ph-sliders-horizontal:before { + content: "\e434"; +} +.ph.ph-slideshow:before { + content: "\ed32"; +} +.ph.ph-smiley:before { + content: "\e436"; +} +.ph.ph-smiley-angry:before { + content: "\ec62"; +} +.ph.ph-smiley-blank:before { + content: "\e438"; +} +.ph.ph-smiley-meh:before { + content: "\e43a"; +} +.ph.ph-smiley-melting:before { + content: "\ee56"; +} +.ph.ph-smiley-nervous:before { + content: "\e43c"; +} +.ph.ph-smiley-sad:before { + content: "\e43e"; +} +.ph.ph-smiley-sticker:before { + content: "\e440"; +} +.ph.ph-smiley-wink:before { + content: "\e666"; +} +.ph.ph-smiley-x-eyes:before { + content: "\e442"; +} +.ph.ph-snapchat-logo:before { + content: "\e668"; +} +.ph.ph-sneaker:before { + content: "\e80c"; +} +.ph.ph-sneaker-move:before { + content: "\ed60"; +} +.ph.ph-snowflake:before { + content: "\e5aa"; +} +.ph.ph-soccer-ball:before { + content: "\e716"; +} +.ph.ph-sock:before { + content: "\ecce"; +} +.ph.ph-solar-panel:before { + content: "\ed7a"; +} +.ph.ph-solar-roof:before { + content: "\ed7b"; +} +.ph.ph-sort-ascending:before { + content: "\e444"; +} +.ph.ph-sort-descending:before { + content: "\e446"; +} +.ph.ph-soundcloud-logo:before { + content: "\e8de"; +} +.ph.ph-spade:before { + content: "\e448"; +} +.ph.ph-sparkle:before { + content: "\e6a2"; +} +.ph.ph-speaker-hifi:before { + content: "\ea08"; +} +.ph.ph-speaker-high:before { + content: "\e44a"; +} +.ph.ph-speaker-low:before { + content: "\e44c"; +} +.ph.ph-speaker-none:before { + content: "\e44e"; +} +.ph.ph-speaker-simple-high:before { + content: "\e450"; +} +.ph.ph-speaker-simple-low:before { + content: "\e452"; +} +.ph.ph-speaker-simple-none:before { + content: "\e454"; +} +.ph.ph-speaker-simple-slash:before { + content: "\e456"; +} +.ph.ph-speaker-simple-x:before { + content: "\e458"; +} +.ph.ph-speaker-slash:before { + content: "\e45a"; +} +.ph.ph-speaker-x:before { + content: "\e45c"; +} +.ph.ph-speedometer:before { + content: "\ee74"; +} +.ph.ph-sphere:before { + content: "\ee66"; +} +.ph.ph-spinner:before { + content: "\e66a"; +} +.ph.ph-spinner-ball:before { + content: "\ee28"; +} +.ph.ph-spinner-gap:before { + content: "\e66c"; +} +.ph.ph-spiral:before { + content: "\e9fa"; +} +.ph.ph-split-horizontal:before { + content: "\e872"; +} +.ph.ph-split-vertical:before { + content: "\e876"; +} +.ph.ph-spotify-logo:before { + content: "\e66e"; +} +.ph.ph-spray-bottle:before { + content: "\e7e4"; +} +.ph.ph-square:before { + content: "\e45e"; +} +.ph.ph-square-half:before { + content: "\e462"; +} +.ph.ph-square-half-bottom:before { + content: "\eb16"; +} +.ph.ph-square-logo:before { + content: "\e690"; +} +.ph.ph-square-split-horizontal:before { + content: "\e870"; +} +.ph.ph-square-split-vertical:before { + content: "\e874"; +} +.ph.ph-squares-four:before { + content: "\e464"; +} +.ph.ph-stack:before { + content: "\e466"; +} +.ph.ph-stack-minus:before { + content: "\edf4"; +} +.ph.ph-stack-overflow-logo:before { + content: "\eb78"; +} +.ph.ph-stack-plus:before { + content: "\edf6"; +} +.ph.ph-stack-simple:before { + content: "\e468"; +} +.ph.ph-stairs:before { + content: "\e8ec"; +} +.ph.ph-stamp:before { + content: "\ea48"; +} +.ph.ph-standard-definition:before { + content: "\ea90"; +} +.ph.ph-star:before { + content: "\e46a"; +} +.ph.ph-star-and-crescent:before { + content: "\ecf4"; +} +.ph.ph-star-four:before { + content: "\e6a4"; +} +.ph.ph-star-half:before { + content: "\e70a"; +} +.ph.ph-star-of-david:before { + content: "\e89e"; +} +.ph.ph-steam-logo:before { + content: "\ead4"; +} +.ph.ph-steering-wheel:before { + content: "\e9ac"; +} +.ph.ph-steps:before { + content: "\ecbe"; +} +.ph.ph-stethoscope:before { + content: "\e7ea"; +} +.ph.ph-sticker:before { + content: "\e5ac"; +} +.ph.ph-stool:before { + content: "\ea44"; +} +.ph.ph-stop:before { + content: "\e46c"; +} +.ph.ph-stop-circle:before { + content: "\e46e"; +} +.ph.ph-storefront:before { + content: "\e470"; +} +.ph.ph-strategy:before { + content: "\ea3a"; +} +.ph.ph-stripe-logo:before { + content: "\e698"; +} +.ph.ph-student:before { + content: "\e73e"; +} +.ph.ph-subset-of:before { + content: "\edc0"; +} +.ph.ph-subset-proper-of:before { + content: "\edb6"; +} +.ph.ph-subtitles:before { + content: "\e1a8"; +} +.ph.ph-subtitles-slash:before { + content: "\e1a6"; +} +.ph.ph-subtract:before { + content: "\ebd6"; +} +.ph.ph-subtract-square:before { + content: "\ebd4"; +} +.ph.ph-subway:before { + content: "\e498"; +} +.ph.ph-suitcase:before { + content: "\e5ae"; +} +.ph.ph-suitcase-rolling:before { + content: "\e9b0"; +} +.ph.ph-suitcase-simple:before { + content: "\e5b0"; +} +.ph.ph-sun:before { + content: "\e472"; +} +.ph.ph-sun-dim:before { + content: "\e474"; +} +.ph.ph-sun-horizon:before { + content: "\e5b6"; +} +.ph.ph-sunglasses:before { + content: "\e816"; +} +.ph.ph-superset-of:before { + content: "\edb8"; +} +.ph.ph-superset-proper-of:before { + content: "\edb4"; +} +.ph.ph-swap:before { + content: "\e83c"; +} +.ph.ph-swatches:before { + content: "\e5b8"; +} +.ph.ph-swimming-pool:before { + content: "\ecb6"; +} +.ph.ph-sword:before { + content: "\e5ba"; +} +.ph.ph-synagogue:before { + content: "\ecec"; +} +.ph.ph-syringe:before { + content: "\e968"; +} +.ph.ph-t-shirt:before { + content: "\e670"; +} +.ph.ph-table:before { + content: "\e476"; +} +.ph.ph-tabs:before { + content: "\e778"; +} +.ph.ph-tag:before { + content: "\e478"; +} +.ph.ph-tag-chevron:before { + content: "\e672"; +} +.ph.ph-tag-simple:before { + content: "\e47a"; +} +.ph.ph-target:before { + content: "\e47c"; +} +.ph.ph-taxi:before { + content: "\e902"; +} +.ph.ph-tea-bag:before { + content: "\e8e6"; +} +.ph.ph-telegram-logo:before { + content: "\e5bc"; +} +.ph.ph-television:before { + content: "\e754"; +} +.ph.ph-television-simple:before { + content: "\eae6"; +} +.ph.ph-tennis-ball:before { + content: "\e720"; +} +.ph.ph-tent:before { + content: "\e8ba"; +} +.ph.ph-terminal:before { + content: "\e47e"; +} +.ph.ph-terminal-window:before { + content: "\eae8"; +} +.ph.ph-test-tube:before { + content: "\e7a0"; +} +.ph.ph-text-a-underline:before { + content: "\ed34"; +} +.ph.ph-text-aa:before { + content: "\e6ee"; +} +.ph.ph-text-align-center:before { + content: "\e480"; +} +.ph.ph-text-align-justify:before { + content: "\e482"; +} +.ph.ph-text-align-left:before { + content: "\e484"; +} +.ph.ph-text-align-right:before { + content: "\e486"; +} +.ph.ph-text-b:before { + content: "\e5be"; +} +.ph.ph-text-bolder:before { + content: "\e5be"; +} +.ph.ph-text-columns:before { + content: "\ec96"; +} +.ph.ph-text-h:before { + content: "\e6ba"; +} +.ph.ph-text-h-five:before { + content: "\e6c4"; +} +.ph.ph-text-h-four:before { + content: "\e6c2"; +} +.ph.ph-text-h-one:before { + content: "\e6bc"; +} +.ph.ph-text-h-six:before { + content: "\e6c6"; +} +.ph.ph-text-h-three:before { + content: "\e6c0"; +} +.ph.ph-text-h-two:before { + content: "\e6be"; +} +.ph.ph-text-indent:before { + content: "\ea1e"; +} +.ph.ph-text-italic:before { + content: "\e5c0"; +} +.ph.ph-text-outdent:before { + content: "\ea1c"; +} +.ph.ph-text-strikethrough:before { + content: "\e5c2"; +} +.ph.ph-text-subscript:before { + content: "\ec98"; +} +.ph.ph-text-superscript:before { + content: "\ec9a"; +} +.ph.ph-text-t:before { + content: "\e48a"; +} +.ph.ph-text-t-slash:before { + content: "\e488"; +} +.ph.ph-text-underline:before { + content: "\e5c4"; +} +.ph.ph-textbox:before { + content: "\eb0a"; +} +.ph.ph-thermometer:before { + content: "\e5c6"; +} +.ph.ph-thermometer-cold:before { + content: "\e5c8"; +} +.ph.ph-thermometer-hot:before { + content: "\e5ca"; +} +.ph.ph-thermometer-simple:before { + content: "\e5cc"; +} +.ph.ph-threads-logo:before { + content: "\ed9e"; +} +.ph.ph-three-d:before { + content: "\ea5a"; +} +.ph.ph-thumbs-down:before { + content: "\e48c"; +} +.ph.ph-thumbs-up:before { + content: "\e48e"; +} +.ph.ph-ticket:before { + content: "\e490"; +} +.ph.ph-tidal-logo:before { + content: "\ed1c"; +} +.ph.ph-tiktok-logo:before { + content: "\eaf2"; +} +.ph.ph-tilde:before { + content: "\eda8"; +} +.ph.ph-timer:before { + content: "\e492"; +} +.ph.ph-tip-jar:before { + content: "\e7e2"; +} +.ph.ph-tipi:before { + content: "\ed30"; +} +.ph.ph-tire:before { + content: "\edd2"; +} +.ph.ph-toggle-left:before { + content: "\e674"; +} +.ph.ph-toggle-right:before { + content: "\e676"; +} +.ph.ph-toilet:before { + content: "\e79a"; +} +.ph.ph-toilet-paper:before { + content: "\e79c"; +} +.ph.ph-toolbox:before { + content: "\eca0"; +} +.ph.ph-tooth:before { + content: "\e9cc"; +} +.ph.ph-tornado:before { + content: "\e88c"; +} +.ph.ph-tote:before { + content: "\e494"; +} +.ph.ph-tote-simple:before { + content: "\e678"; +} +.ph.ph-towel:before { + content: "\ede6"; +} +.ph.ph-tractor:before { + content: "\ec6e"; +} +.ph.ph-trademark:before { + content: "\e9f0"; +} +.ph.ph-trademark-registered:before { + content: "\e3f4"; +} +.ph.ph-traffic-cone:before { + content: "\e9a8"; +} +.ph.ph-traffic-sign:before { + content: "\e67a"; +} +.ph.ph-traffic-signal:before { + content: "\e9aa"; +} +.ph.ph-train:before { + content: "\e496"; +} +.ph.ph-train-regional:before { + content: "\e49e"; +} +.ph.ph-train-simple:before { + content: "\e4a0"; +} +.ph.ph-tram:before { + content: "\e9ec"; +} +.ph.ph-translate:before { + content: "\e4a2"; +} +.ph.ph-trash:before { + content: "\e4a6"; +} +.ph.ph-trash-simple:before { + content: "\e4a8"; +} +.ph.ph-tray:before { + content: "\e4aa"; +} +.ph.ph-tray-arrow-down:before { + content: "\e010"; +} +.ph.ph-archive-tray:before { + content: "\e010"; +} +.ph.ph-tray-arrow-up:before { + content: "\ee52"; +} +.ph.ph-treasure-chest:before { + content: "\ede2"; +} +.ph.ph-tree:before { + content: "\e6da"; +} +.ph.ph-tree-evergreen:before { + content: "\e6dc"; +} +.ph.ph-tree-palm:before { + content: "\e91a"; +} +.ph.ph-tree-structure:before { + content: "\e67c"; +} +.ph.ph-tree-view:before { + content: "\ee48"; +} +.ph.ph-trend-down:before { + content: "\e4ac"; +} +.ph.ph-trend-up:before { + content: "\e4ae"; +} +.ph.ph-triangle:before { + content: "\e4b0"; +} +.ph.ph-triangle-dashed:before { + content: "\e4b2"; +} +.ph.ph-trolley:before { + content: "\e5b2"; +} +.ph.ph-trolley-suitcase:before { + content: "\e5b4"; +} +.ph.ph-trophy:before { + content: "\e67e"; +} +.ph.ph-truck:before { + content: "\e4b4"; +} +.ph.ph-truck-trailer:before { + content: "\e4b6"; +} +.ph.ph-tumblr-logo:before { + content: "\e8d4"; +} +.ph.ph-twitch-logo:before { + content: "\e5ce"; +} +.ph.ph-twitter-logo:before { + content: "\e4ba"; +} +.ph.ph-umbrella:before { + content: "\e684"; +} +.ph.ph-umbrella-simple:before { + content: "\e686"; +} +.ph.ph-union:before { + content: "\edbe"; +} +.ph.ph-unite:before { + content: "\e87e"; +} +.ph.ph-unite-square:before { + content: "\e878"; +} +.ph.ph-upload:before { + content: "\e4be"; +} +.ph.ph-upload-simple:before { + content: "\e4c0"; +} +.ph.ph-usb:before { + content: "\e956"; +} +.ph.ph-user:before { + content: "\e4c2"; +} +.ph.ph-user-check:before { + content: "\eafa"; +} +.ph.ph-user-circle:before { + content: "\e4c4"; +} +.ph.ph-user-circle-check:before { + content: "\ec38"; +} +.ph.ph-user-circle-dashed:before { + content: "\ec36"; +} +.ph.ph-user-circle-gear:before { + content: "\e4c6"; +} +.ph.ph-user-circle-minus:before { + content: "\e4c8"; +} +.ph.ph-user-circle-plus:before { + content: "\e4ca"; +} +.ph.ph-user-focus:before { + content: "\e6fc"; +} +.ph.ph-user-gear:before { + content: "\e4cc"; +} +.ph.ph-user-list:before { + content: "\e73c"; +} +.ph.ph-user-minus:before { + content: "\e4ce"; +} +.ph.ph-user-plus:before { + content: "\e4d0"; +} +.ph.ph-user-rectangle:before { + content: "\e4d2"; +} +.ph.ph-user-sound:before { + content: "\eca8"; +} +.ph.ph-user-square:before { + content: "\e4d4"; +} +.ph.ph-user-switch:before { + content: "\e756"; +} +.ph.ph-users:before { + content: "\e4d6"; +} +.ph.ph-users-four:before { + content: "\e68c"; +} +.ph.ph-users-three:before { + content: "\e68e"; +} +.ph.ph-van:before { + content: "\e826"; +} +.ph.ph-vault:before { + content: "\e76e"; +} +.ph.ph-vector-three:before { + content: "\ee62"; +} +.ph.ph-vector-two:before { + content: "\ee64"; +} +.ph.ph-vibrate:before { + content: "\e4d8"; +} +.ph.ph-video:before { + content: "\e740"; +} +.ph.ph-video-camera:before { + content: "\e4da"; +} +.ph.ph-video-camera-slash:before { + content: "\e4dc"; +} +.ph.ph-video-conference:before { + content: "\edce"; +} +.ph.ph-vignette:before { + content: "\eba2"; +} +.ph.ph-vinyl-record:before { + content: "\ecac"; +} +.ph.ph-virtual-reality:before { + content: "\e7b8"; +} +.ph.ph-virus:before { + content: "\e7d6"; +} +.ph.ph-visor:before { + content: "\ee2a"; +} +.ph.ph-voicemail:before { + content: "\e4de"; +} +.ph.ph-volleyball:before { + content: "\e726"; +} +.ph.ph-wall:before { + content: "\e688"; +} +.ph.ph-wallet:before { + content: "\e68a"; +} +.ph.ph-warehouse:before { + content: "\ecd4"; +} +.ph.ph-warning:before { + content: "\e4e0"; +} +.ph.ph-warning-circle:before { + content: "\e4e2"; +} +.ph.ph-warning-diamond:before { + content: "\e7fc"; +} +.ph.ph-warning-octagon:before { + content: "\e4e4"; +} +.ph.ph-washing-machine:before { + content: "\ede8"; +} +.ph.ph-watch:before { + content: "\e4e6"; +} +.ph.ph-wave-sawtooth:before { + content: "\ea9c"; +} +.ph.ph-wave-sine:before { + content: "\ea9a"; +} +.ph.ph-wave-square:before { + content: "\ea9e"; +} +.ph.ph-wave-triangle:before { + content: "\eaa0"; +} +.ph.ph-waveform:before { + content: "\e802"; +} +.ph.ph-waveform-slash:before { + content: "\e800"; +} +.ph.ph-waves:before { + content: "\e6de"; +} +.ph.ph-webcam:before { + content: "\e9b2"; +} +.ph.ph-webcam-slash:before { + content: "\ecdc"; +} +.ph.ph-webhooks-logo:before { + content: "\ecae"; +} +.ph.ph-wechat-logo:before { + content: "\e8d2"; +} +.ph.ph-whatsapp-logo:before { + content: "\e5d0"; +} +.ph.ph-wheelchair:before { + content: "\e4e8"; +} +.ph.ph-wheelchair-motion:before { + content: "\e89a"; +} +.ph.ph-wifi-high:before { + content: "\e4ea"; +} +.ph.ph-wifi-low:before { + content: "\e4ec"; +} +.ph.ph-wifi-medium:before { + content: "\e4ee"; +} +.ph.ph-wifi-none:before { + content: "\e4f0"; +} +.ph.ph-wifi-slash:before { + content: "\e4f2"; +} +.ph.ph-wifi-x:before { + content: "\e4f4"; +} +.ph.ph-wind:before { + content: "\e5d2"; +} +.ph.ph-windmill:before { + content: "\e9f8"; +} +.ph.ph-windows-logo:before { + content: "\e692"; +} +.ph.ph-wine:before { + content: "\e6b2"; +} +.ph.ph-wrench:before { + content: "\e5d4"; +} +.ph.ph-x:before { + content: "\e4f6"; +} +.ph.ph-x-circle:before { + content: "\e4f8"; +} +.ph.ph-x-logo:before { + content: "\e4bc"; +} +.ph.ph-x-square:before { + content: "\e4fa"; +} +.ph.ph-yarn:before { + content: "\ed9a"; +} +.ph.ph-yin-yang:before { + content: "\e92a"; +} +.ph.ph-youtube-logo:before { + content: "\e4fc"; +} diff --git a/crates/carpet-ui/assets/tailwind.css b/crates/carpet-ui/assets/tailwind.css new file mode 100644 index 0000000..8497e98 --- /dev/null +++ b/crates/carpet-ui/assets/tailwind.css @@ -0,0 +1,903 @@ +/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */ +@layer properties; +@layer theme, base, components, utilities; +@layer theme { + :root, :host { + --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", + "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", + "Courier New", monospace; + --color-orange-400: oklch(75% 0.183 55.934); + --color-orange-500: oklch(70.5% 0.213 47.604); + --color-amber-300: oklch(87.9% 0.169 91.605); + --color-amber-400: oklch(82.8% 0.189 84.429); + --color-emerald-400: oklch(76.5% 0.177 163.223); + --color-blue-400: oklch(70.7% 0.165 254.624); + --color-gray-100: oklch(96.7% 0.003 264.542); + --color-gray-200: oklch(92.8% 0.006 264.531); + --color-gray-300: oklch(87.2% 0.01 258.338); + --color-gray-400: oklch(70.7% 0.022 261.325); + --color-gray-500: oklch(55.1% 0.027 264.364); + --color-gray-600: oklch(44.6% 0.03 256.802); + --color-gray-700: oklch(37.3% 0.034 259.733); + --color-gray-800: oklch(27.8% 0.033 256.848); + --color-gray-900: oklch(21% 0.034 264.665); + --color-gray-950: oklch(13% 0.028 261.692); + --color-white: #fff; + --spacing: 0.25rem; + --container-xl: 36rem; + --container-2xl: 42rem; + --container-3xl: 48rem; + --container-4xl: 56rem; + --container-7xl: 80rem; + --text-xs: 0.75rem; + --text-xs--line-height: calc(1 / 0.75); + --text-sm: 0.875rem; + --text-sm--line-height: calc(1.25 / 0.875); + --text-lg: 1.125rem; + --text-lg--line-height: calc(1.75 / 1.125); + --text-xl: 1.25rem; + --text-xl--line-height: calc(1.75 / 1.25); + --text-2xl: 1.5rem; + --text-2xl--line-height: calc(2 / 1.5); + --text-3xl: 1.875rem; + --text-3xl--line-height: calc(2.25 / 1.875); + --text-4xl: 2.25rem; + --text-4xl--line-height: calc(2.5 / 2.25); + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + --radius-lg: 0.5rem; + --radius-xl: 0.75rem; + --blur-md: 12px; + --default-transition-duration: 150ms; + --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + --default-font-family: var(--font-sans); + --default-mono-font-family: var(--font-mono); + } +} +@layer base { + *, ::after, ::before, ::backdrop, ::file-selector-button { + box-sizing: border-box; + margin: 0; + padding: 0; + border: 0 solid; + } + html, :host { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + tab-size: 4; + font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); + font-feature-settings: var(--default-font-feature-settings, normal); + font-variation-settings: var(--default-font-variation-settings, normal); + -webkit-tap-highlight-color: transparent; + } + hr { + height: 0; + color: inherit; + border-top-width: 1px; + } + abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + } + h1, h2, h3, h4, h5, h6 { + font-size: inherit; + font-weight: inherit; + } + a { + color: inherit; + -webkit-text-decoration: inherit; + text-decoration: inherit; + } + b, strong { + font-weight: bolder; + } + code, kbd, samp, pre { + font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); + font-feature-settings: var(--default-mono-font-feature-settings, normal); + font-variation-settings: var(--default-mono-font-variation-settings, normal); + font-size: 1em; + } + small { + font-size: 80%; + } + sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; + } + sub { + bottom: -0.25em; + } + sup { + top: -0.5em; + } + table { + text-indent: 0; + border-color: inherit; + border-collapse: collapse; + } + :-moz-focusring { + outline: auto; + } + progress { + vertical-align: baseline; + } + summary { + display: list-item; + } + ol, ul, menu { + list-style: none; + } + img, svg, video, canvas, audio, iframe, embed, object { + display: block; + vertical-align: middle; + } + img, video { + max-width: 100%; + height: auto; + } + button, input, select, optgroup, textarea, ::file-selector-button { + font: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + letter-spacing: inherit; + color: inherit; + border-radius: 0; + background-color: transparent; + opacity: 1; + } + :where(select:is([multiple], [size])) optgroup { + font-weight: bolder; + } + :where(select:is([multiple], [size])) optgroup option { + padding-inline-start: 20px; + } + ::file-selector-button { + margin-inline-end: 4px; + } + ::placeholder { + opacity: 1; + } + @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) { + ::placeholder { + color: currentcolor; + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, currentcolor 50%, transparent); + } + } + } + textarea { + resize: vertical; + } + ::-webkit-search-decoration { + -webkit-appearance: none; + } + ::-webkit-date-and-time-value { + min-height: 1lh; + text-align: inherit; + } + ::-webkit-datetime-edit { + display: inline-flex; + } + ::-webkit-datetime-edit-fields-wrapper { + padding: 0; + } + ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field { + padding-block: 0; + } + ::-webkit-calendar-picker-indicator { + line-height: 1; + } + :-moz-ui-invalid { + box-shadow: none; + } + button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button { + appearance: button; + } + ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { + height: auto; + } + [hidden]:where(:not([hidden="until-found"])) { + display: none !important; + } +} +@layer utilities { + .visible { + visibility: visible; + } + .absolute { + position: absolute; + } + .fixed { + position: fixed; + } + .relative { + position: relative; + } + .static { + position: static; + } + .start { + inset-inline-start: var(--spacing); + } + .top-0 { + top: calc(var(--spacing) * 0); + } + .top-1\/2 { + top: calc(1 / 2 * 100%); + } + .right-0 { + right: calc(var(--spacing) * 0); + } + .left-0 { + left: calc(var(--spacing) * 0); + } + .left-3 { + left: calc(var(--spacing) * 3); + } + .z-50 { + z-index: 50; + } + .mx-auto { + margin-inline: auto; + } + .mt-2 { + margin-top: calc(var(--spacing) * 2); + } + .mr-1 { + margin-right: calc(var(--spacing) * 1); + } + .mb-1 { + margin-bottom: calc(var(--spacing) * 1); + } + .mb-2 { + margin-bottom: calc(var(--spacing) * 2); + } + .mb-3 { + margin-bottom: calc(var(--spacing) * 3); + } + .mb-4 { + margin-bottom: calc(var(--spacing) * 4); + } + .mb-6 { + margin-bottom: calc(var(--spacing) * 6); + } + .mb-8 { + margin-bottom: calc(var(--spacing) * 8); + } + .mb-10 { + margin-bottom: calc(var(--spacing) * 10); + } + .ml-2 { + margin-left: calc(var(--spacing) * 2); + } + .line-clamp-2 { + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + } + .block { + display: block; + } + .contents { + display: contents; + } + .flex { + display: flex; + } + .grid { + display: grid; + } + .inline-flex { + display: inline-flex; + } + .h-2 { + height: calc(var(--spacing) * 2); + } + .h-7 { + height: calc(var(--spacing) * 7); + } + .h-10 { + height: calc(var(--spacing) * 10); + } + .h-14 { + height: calc(var(--spacing) * 14); + } + .h-16 { + height: calc(var(--spacing) * 16); + } + .min-h-screen { + min-height: 100vh; + } + .w-2 { + width: calc(var(--spacing) * 2); + } + .w-7 { + width: calc(var(--spacing) * 7); + } + .w-10 { + width: calc(var(--spacing) * 10); + } + .w-16 { + width: calc(var(--spacing) * 16); + } + .w-full { + width: 100%; + } + .max-w-2xl { + max-width: var(--container-2xl); + } + .max-w-3xl { + max-width: var(--container-3xl); + } + .max-w-4xl { + max-width: var(--container-4xl); + } + .max-w-7xl { + max-width: var(--container-7xl); + } + .max-w-xl { + max-width: var(--container-xl); + } + .flex-1 { + flex: 1; + } + .-translate-y-1\/2 { + --tw-translate-y: calc(calc(1 / 2 * 100%) * -1); + translate: var(--tw-translate-x) var(--tw-translate-y); + } + .cursor-pointer { + cursor: pointer; + } + .grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + .flex-wrap { + flex-wrap: wrap; + } + .items-center { + align-items: center; + } + .items-start { + align-items: flex-start; + } + .justify-between { + justify-content: space-between; + } + .justify-center { + justify-content: center; + } + .gap-1 { + gap: calc(var(--spacing) * 1); + } + .gap-1\.5 { + gap: calc(var(--spacing) * 1.5); + } + .gap-2 { + gap: calc(var(--spacing) * 2); + } + .gap-3 { + gap: calc(var(--spacing) * 3); + } + .gap-4 { + gap: calc(var(--spacing) * 4); + } + .gap-6 { + gap: calc(var(--spacing) * 6); + } + .space-y-1 { + :where(& > :not(:last-child)) { + --tw-space-y-reverse: 0; + margin-block-start: calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse)); + margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse))); + } + } + .space-y-2 { + :where(& > :not(:last-child)) { + --tw-space-y-reverse: 0; + margin-block-start: calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse)); + margin-block-end: calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse))); + } + } + .gap-x-4 { + column-gap: calc(var(--spacing) * 4); + } + .gap-y-1 { + row-gap: calc(var(--spacing) * 1); + } + .rounded-full { + border-radius: calc(infinity * 1px); + } + .rounded-lg { + border-radius: var(--radius-lg); + } + .rounded-xl { + border-radius: var(--radius-xl); + } + .border { + border-style: var(--tw-border-style); + border-width: 1px; + } + .border-b { + border-bottom-style: var(--tw-border-style); + border-bottom-width: 1px; + } + .border-blue-400\/20 { + border-color: color-mix(in srgb, oklch(70.7% 0.165 254.624) 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-blue-400) 20%, transparent); + } + } + .border-emerald-400\/20 { + border-color: color-mix(in srgb, oklch(76.5% 0.177 163.223) 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-emerald-400) 20%, transparent); + } + } + .border-gray-400\/20 { + border-color: color-mix(in srgb, oklch(70.7% 0.022 261.325) 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-gray-400) 20%, transparent); + } + } + .border-gray-800 { + border-color: var(--color-gray-800); + } + .bg-amber-400 { + background-color: var(--color-amber-400); + } + .bg-blue-400\/10 { + background-color: color-mix(in srgb, oklch(70.7% 0.165 254.624) 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-blue-400) 10%, transparent); + } + } + .bg-emerald-400 { + background-color: var(--color-emerald-400); + } + .bg-emerald-400\/10 { + background-color: color-mix(in srgb, oklch(76.5% 0.177 163.223) 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-emerald-400) 10%, transparent); + } + } + .bg-gray-400\/10 { + background-color: color-mix(in srgb, oklch(70.7% 0.022 261.325) 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-gray-400) 10%, transparent); + } + } + .bg-gray-800 { + background-color: var(--color-gray-800); + } + .bg-gray-900 { + background-color: var(--color-gray-900); + } + .bg-gray-900\/50 { + background-color: color-mix(in srgb, oklch(21% 0.034 264.665) 50%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-gray-900) 50%, transparent); + } + } + .bg-gray-900\/80 { + background-color: color-mix(in srgb, oklch(21% 0.034 264.665) 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-gray-900) 80%, transparent); + } + } + .bg-gray-950 { + background-color: var(--color-gray-950); + } + .bg-orange-500 { + background-color: var(--color-orange-500); + } + .p-4 { + padding: calc(var(--spacing) * 4); + } + .p-5 { + padding: calc(var(--spacing) * 5); + } + .p-6 { + padding: calc(var(--spacing) * 6); + } + .px-2 { + padding-inline: calc(var(--spacing) * 2); + } + .px-2\.5 { + padding-inline: calc(var(--spacing) * 2.5); + } + .px-3 { + padding-inline: calc(var(--spacing) * 3); + } + .px-4 { + padding-inline: calc(var(--spacing) * 4); + } + .px-6 { + padding-inline: calc(var(--spacing) * 6); + } + .py-0\.5 { + padding-block: calc(var(--spacing) * 0.5); + } + .py-1 { + padding-block: calc(var(--spacing) * 1); + } + .py-1\.5 { + padding-block: calc(var(--spacing) * 1.5); + } + .py-2 { + padding-block: calc(var(--spacing) * 2); + } + .py-2\.5 { + padding-block: calc(var(--spacing) * 2.5); + } + .py-3 { + padding-block: calc(var(--spacing) * 3); + } + .py-8 { + padding-block: calc(var(--spacing) * 8); + } + .py-20 { + padding-block: calc(var(--spacing) * 20); + } + .pt-14 { + padding-top: calc(var(--spacing) * 14); + } + .pr-4 { + padding-right: calc(var(--spacing) * 4); + } + .pl-10 { + padding-left: calc(var(--spacing) * 10); + } + .text-center { + text-align: center; + } + .font-mono { + font-family: var(--font-mono); + } + .text-2xl { + font-size: var(--text-2xl); + line-height: var(--tw-leading, var(--text-2xl--line-height)); + } + .text-3xl { + font-size: var(--text-3xl); + line-height: var(--tw-leading, var(--text-3xl--line-height)); + } + .text-4xl { + font-size: var(--text-4xl); + line-height: var(--tw-leading, var(--text-4xl--line-height)); + } + .text-lg { + font-size: var(--text-lg); + line-height: var(--tw-leading, var(--text-lg--line-height)); + } + .text-sm { + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + } + .text-xl { + font-size: var(--text-xl); + line-height: var(--tw-leading, var(--text-xl--line-height)); + } + .text-xs { + font-size: var(--text-xs); + line-height: var(--tw-leading, var(--text-xs--line-height)); + } + .font-bold { + --tw-font-weight: var(--font-weight-bold); + font-weight: var(--font-weight-bold); + } + .font-medium { + --tw-font-weight: var(--font-weight-medium); + font-weight: var(--font-weight-medium); + } + .font-semibold { + --tw-font-weight: var(--font-weight-semibold); + font-weight: var(--font-weight-semibold); + } + .break-all { + word-break: break-all; + } + .text-amber-400 { + color: var(--color-amber-400); + } + .text-amber-400\/70 { + color: color-mix(in srgb, oklch(82.8% 0.189 84.429) 70%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-amber-400) 70%, transparent); + } + } + .text-blue-400 { + color: var(--color-blue-400); + } + .text-emerald-400 { + color: var(--color-emerald-400); + } + .text-gray-100 { + color: var(--color-gray-100); + } + .text-gray-200 { + color: var(--color-gray-200); + } + .text-gray-300 { + color: var(--color-gray-300); + } + .text-gray-400 { + color: var(--color-gray-400); + } + .text-gray-500 { + color: var(--color-gray-500); + } + .text-gray-600 { + color: var(--color-gray-600); + } + .text-gray-950 { + color: var(--color-gray-950); + } + .text-orange-500 { + color: var(--color-orange-500); + } + .text-white { + color: var(--color-white); + } + .placeholder-gray-500 { + &::placeholder { + color: var(--color-gray-500); + } + } + .filter { + filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); + } + .backdrop-blur-md { + --tw-backdrop-blur: blur(var(--blur-md)); + -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); + backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); + } + .transition-colors { + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + .group-hover\:text-orange-400 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + color: var(--color-orange-400); + } + } + } + .hover\:border-gray-700 { + &:hover { + @media (hover: hover) { + border-color: var(--color-gray-700); + } + } + } + .hover\:bg-amber-300 { + &:hover { + @media (hover: hover) { + background-color: var(--color-amber-300); + } + } + } + .hover\:bg-gray-700 { + &:hover { + @media (hover: hover) { + background-color: var(--color-gray-700); + } + } + } + .hover\:bg-gray-800 { + &:hover { + @media (hover: hover) { + background-color: var(--color-gray-800); + } + } + } + .hover\:bg-gray-900\/80 { + &:hover { + @media (hover: hover) { + background-color: color-mix(in srgb, oklch(21% 0.034 264.665) 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-gray-900) 80%, transparent); + } + } + } + } + .hover\:text-gray-200 { + &:hover { + @media (hover: hover) { + color: var(--color-gray-200); + } + } + } + .hover\:text-gray-400 { + &:hover { + @media (hover: hover) { + color: var(--color-gray-400); + } + } + } + .hover\:text-orange-400 { + &:hover { + @media (hover: hover) { + color: var(--color-orange-400); + } + } + } + .focus\:border-gray-700 { + &:focus { + border-color: var(--color-gray-700); + } + } + .focus\:outline-none { + &:focus { + --tw-outline-style: none; + outline-style: none; + } + } + .md\:grid-cols-2 { + @media (width >= 48rem) { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + } + .lg\:grid-cols-3 { + @media (width >= 64rem) { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + } +} +@property --tw-translate-x { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-translate-y { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-translate-z { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-space-y-reverse { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-border-style { + syntax: "*"; + inherits: false; + initial-value: solid; +} +@property --tw-font-weight { + syntax: "*"; + inherits: false; +} +@property --tw-blur { + syntax: "*"; + inherits: false; +} +@property --tw-brightness { + syntax: "*"; + inherits: false; +} +@property --tw-contrast { + syntax: "*"; + inherits: false; +} +@property --tw-grayscale { + syntax: "*"; + inherits: false; +} +@property --tw-hue-rotate { + syntax: "*"; + inherits: false; +} +@property --tw-invert { + syntax: "*"; + inherits: false; +} +@property --tw-opacity { + syntax: "*"; + inherits: false; +} +@property --tw-saturate { + syntax: "*"; + inherits: false; +} +@property --tw-sepia { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow-color { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow-alpha { + syntax: ""; + inherits: false; + initial-value: 100%; +} +@property --tw-drop-shadow-size { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-blur { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-brightness { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-contrast { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-grayscale { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-hue-rotate { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-invert { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-opacity { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-saturate { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-sepia { + syntax: "*"; + inherits: false; +} +@layer properties { + @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { + *, ::before, ::after, ::backdrop { + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-translate-z: 0; + --tw-space-y-reverse: 0; + --tw-border-style: solid; + --tw-font-weight: initial; + --tw-blur: initial; + --tw-brightness: initial; + --tw-contrast: initial; + --tw-grayscale: initial; + --tw-hue-rotate: initial; + --tw-invert: initial; + --tw-opacity: initial; + --tw-saturate: initial; + --tw-sepia: initial; + --tw-drop-shadow: initial; + --tw-drop-shadow-color: initial; + --tw-drop-shadow-alpha: 100%; + --tw-drop-shadow-size: initial; + --tw-backdrop-blur: initial; + --tw-backdrop-brightness: initial; + --tw-backdrop-contrast: initial; + --tw-backdrop-grayscale: initial; + --tw-backdrop-hue-rotate: initial; + --tw-backdrop-invert: initial; + --tw-backdrop-opacity: initial; + --tw-backdrop-saturate: initial; + --tw-backdrop-sepia: initial; + } + } +} diff --git a/crates/carpet-ui/input.css b/crates/carpet-ui/input.css new file mode 100644 index 0000000..1cbfd34 --- /dev/null +++ b/crates/carpet-ui/input.css @@ -0,0 +1,2 @@ +@import "tailwindcss"; +@source "./src/**/*.rs"; diff --git a/crates/carpet-ui/src/app.rs b/crates/carpet-ui/src/app.rs new file mode 100644 index 0000000..621b30f --- /dev/null +++ b/crates/carpet-ui/src/app.rs @@ -0,0 +1,20 @@ +use dioxus::prelude::*; + +use crate::mock_data; +use crate::routes::Route; +use crate::state::marketplace::MarketplaceState; +static TAILWIND: Asset = asset!("/assets/tailwind.css"); +static PHOSPHOR: Asset = asset!("/assets/phosphor.css"); + +pub fn App() -> Element { + use_context_provider(|| Signal::new(mock_data::nostr_state())); + use_context_provider(|| Signal::new(mock_data::wallet_state())); + use_context_provider(|| Signal::new(MarketplaceState::default())); + use_context_provider(|| Signal::new(mock_data::mock_lists())); + + rsx! { + document::Stylesheet { href: TAILWIND } + document::Stylesheet { href: PHOSPHOR } + Router:: {} + } +} diff --git a/crates/carpet-ui/src/components/bounty_card.rs b/crates/carpet-ui/src/components/bounty_card.rs new file mode 100644 index 0000000..f5b2750 --- /dev/null +++ b/crates/carpet-ui/src/components/bounty_card.rs @@ -0,0 +1,51 @@ +use dioxus::prelude::*; + +use crate::routes::Route; +use crate::types::{BountyDisplay, BountyStatus}; + +#[component] +pub fn BountyCard(bounty: BountyDisplay) -> Element { + let (badge_class, badge_text) = match bounty.status { + BountyStatus::Open => ( + "bg-emerald-400/10 text-emerald-400 border border-emerald-400/20", + "Open", + ), + BountyStatus::Fulfilled => ( + "bg-blue-400/10 text-blue-400 border border-blue-400/20", + "Fulfilled", + ), + BountyStatus::Expired => ( + "bg-gray-400/10 text-gray-400 border border-gray-400/20", + "Expired", + ), + }; + + rsx! { + div { class: "bg-gray-900 border border-gray-800 rounded-xl p-5 hover:border-gray-700 transition-colors", + div { class: "flex items-center justify-between mb-3", + span { class: "px-3 py-1 rounded-full text-xs font-medium {badge_class}", + "{badge_text}" + } + span { class: "text-amber-400 font-mono font-bold text-lg", + i { class: "ph ph-lightning mr-1" } + "{bounty.reward_sats} sats" + } + } + h3 { class: "text-gray-100 font-semibold mb-2", + "Bounty for " + Link { + to: Route::ListDetailPage { coordinate: bounty.target_list_coordinate }, + class: "text-orange-500 hover:text-orange-400", + "{bounty.target_list_name}" + } + } + p { class: "text-gray-400 text-sm mb-4", + "{bounty.criteria}" + } + div { class: "flex items-center gap-2 text-gray-500 text-sm", + i { class: "ph ph-user-circle" } + span { "{bounty.creator_name}" } + } + } + } +} diff --git a/crates/carpet-ui/src/components/layout.rs b/crates/carpet-ui/src/components/layout.rs new file mode 100644 index 0000000..565ec92 --- /dev/null +++ b/crates/carpet-ui/src/components/layout.rs @@ -0,0 +1,67 @@ +use dioxus::prelude::*; + +use crate::routes::Route; +use crate::state::nostr::NostrState; +use crate::state::wallet::WalletState; + +#[component] +pub fn MainLayout() -> Element { + let nostr_state: Signal = use_context(); + let wallet_state: Signal = use_context(); + + let relay_count = nostr_state.read().connected_relays.len(); + let ln_balance = wallet_state.read().ln_balance_sats; + + rsx! { + div { class: "min-h-screen bg-gray-950 text-gray-100", + nav { class: "fixed top-0 left-0 right-0 z-50 bg-gray-900/80 backdrop-blur-md border-b border-gray-800", + div { class: "max-w-7xl mx-auto px-4 h-14 flex items-center justify-between", + // Brand + Link { + to: Route::Marketplace {}, + class: "flex items-center gap-2 text-orange-500 font-bold text-lg hover:text-orange-400 transition-colors", + i { class: "ph ph-flying-saucer text-2xl" } + "Magic Carpet" + } + + // Nav links + div { class: "flex items-center gap-1", + NavLink { to: Route::Marketplace {}, icon: "ph-house", label: "Home" } + NavLink { to: Route::ListBrowsePage {}, icon: "ph-list-bullets", label: "Lists" } + NavLink { to: Route::BountyBrowse {}, icon: "ph-hand-coins", label: "Bounties" } + NavLink { to: Route::WalletOverview {}, icon: "ph-wallet", label: "Wallet" } + NavLink { to: Route::Profile {}, icon: "ph-user-circle", label: "Profile" } + } + + // Status + div { class: "flex items-center gap-4", + span { class: "flex items-center gap-1.5 text-sm text-gray-400", + span { class: "w-2 h-2 rounded-full bg-emerald-400" } + "{relay_count} relays" + } + span { class: "flex items-center gap-1 text-amber-400 text-sm font-mono font-medium", + i { class: "ph ph-lightning" } + "{ln_balance} sats" + } + } + } + } + + main { class: "pt-14", + Outlet:: {} + } + } + } +} + +#[component] +fn NavLink(to: Route, icon: &'static str, label: &'static str) -> Element { + rsx! { + Link { + to, + class: "flex items-center gap-1.5 px-3 py-1.5 text-sm text-gray-400 hover:text-gray-200 hover:bg-gray-800 rounded-lg transition-colors", + i { class: "ph {icon}" } + "{label}" + } + } +} diff --git a/crates/carpet-ui/src/components/list_card.rs b/crates/carpet-ui/src/components/list_card.rs new file mode 100644 index 0000000..878a391 --- /dev/null +++ b/crates/carpet-ui/src/components/list_card.rs @@ -0,0 +1,76 @@ +use dioxus::prelude::*; + +use crate::routes::Route; +use crate::types::ListDisplay; + +/// Displays a grid of list cards from context. +#[component] +pub fn ListBrowse() -> Element { + let lists: Signal> = use_context(); + + rsx! { + div { class: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", + for list in lists.read().iter() { + ListCard { key: "{list.coordinate}", list: list.clone() } + } + } + } +} + +/// A single list card for the browse view. +#[component] +pub fn ListCard(list: ListDisplay) -> Element { + let initial = list + .curator_name + .chars() + .next() + .unwrap_or('?') + .to_uppercase() + .to_string(); + + rsx! { + Link { + to: Route::ListDetailPage { coordinate: list.coordinate.clone() }, + class: "block bg-gray-900 border border-gray-800 rounded-xl p-5 hover:border-gray-700 hover:bg-gray-900/80 transition-colors group", + + // Category pills + div { class: "flex flex-wrap gap-1.5 mb-3", + for cat in list.categories.iter() { + span { class: "px-2 py-0.5 text-xs rounded-full bg-gray-800 text-gray-400", + "{cat}" + } + } + } + + // Title + description + h3 { class: "text-gray-100 font-semibold text-lg mb-1 group-hover:text-orange-400 transition-colors", + "{list.name}" + } + p { class: "text-gray-400 text-sm mb-4 line-clamp-2", + "{list.description}" + } + + // Footer: curator + stats + div { class: "flex items-center justify-between", + // Curator + div { class: "flex items-center gap-2", + div { class: "w-7 h-7 rounded-full bg-gray-800 flex items-center justify-center text-xs font-medium text-gray-300", + "{initial}" + } + span { class: "text-gray-500 text-sm", "{list.curator_name}" } + } + // Stats + div { class: "flex items-center gap-3 text-sm text-gray-500", + span { class: "flex items-center gap-1", + i { class: "ph ph-list-bullets" } + "{list.item_count}" + } + span { class: "flex items-center gap-1 text-amber-400/70", + i { class: "ph ph-lightning" } + "{list.zap_count}" + } + } + } + } + } +} diff --git a/crates/carpet-ui/src/components/list_detail.rs b/crates/carpet-ui/src/components/list_detail.rs new file mode 100644 index 0000000..1e3480d --- /dev/null +++ b/crates/carpet-ui/src/components/list_detail.rs @@ -0,0 +1,117 @@ +use dioxus::prelude::*; + +use crate::components::zap_button::ZapButton; +use crate::mock_data; +use crate::types::ListDisplay; + +/// Detail view for a single list (header + items + zap button). +#[component] +pub fn ListDetail(coordinate: String) -> Element { + let lists: Signal> = use_context(); + let list = lists + .read() + .iter() + .find(|l| l.coordinate == coordinate) + .cloned(); + let items = mock_data::mock_items(); + + match list { + Some(list) => { + let initial = list + .curator_name + .chars() + .next() + .unwrap_or('?') + .to_uppercase() + .to_string(); + + let npub_display = list + .curator_nip05 + .clone() + .unwrap_or_else(|| "npub1...".into()); + + rsx! { + div { class: "max-w-4xl mx-auto px-4 py-8", + // Header + div { class: "mb-8", + div { class: "flex flex-wrap gap-2 mb-3", + for cat in list.categories.iter() { + span { class: "px-3 py-1 text-xs rounded-full bg-gray-800 text-gray-400", + "{cat}" + } + } + } + h1 { class: "text-3xl font-bold text-gray-100 mb-2", "{list.name}" } + p { class: "text-gray-400 text-lg", "{list.description}" } + } + + // Curator bar + zap button + div { class: "flex items-center justify-between bg-gray-900 border border-gray-800 rounded-xl p-4 mb-8", + div { class: "flex items-center gap-3", + div { class: "w-10 h-10 rounded-full bg-gray-800 flex items-center justify-center text-sm font-medium text-gray-300", + "{initial}" + } + div { + p { class: "text-gray-100 font-medium", "{list.curator_name}" } + p { class: "text-gray-500 text-sm font-mono", "{npub_display}" } + } + } + ZapButton { coordinate: coordinate.clone() } + } + + // Stats + div { class: "flex items-center gap-6 mb-6 text-sm text-gray-400", + span { class: "flex items-center gap-1.5", + i { class: "ph ph-list-bullets" } + "{list.item_count} items" + } + span { class: "flex items-center gap-1.5 text-amber-400/70", + i { class: "ph ph-lightning" } + "{list.zap_count} zaps" + } + } + + // Items + div { + h2 { class: "text-xl font-semibold text-gray-100 mb-4", "Items" } + div { class: "space-y-1", + for (i, item) in items.iter().enumerate() { + div { + class: if i % 2 == 0 { "bg-gray-900 rounded-lg p-4" } else { "bg-gray-900/50 rounded-lg p-4" }, + div { class: "flex items-start justify-between mb-2", + a { + href: "{item.resource}", + target: "_blank", + class: "text-orange-500 hover:text-orange-400 text-sm font-mono break-all", + "{item.resource}" + } + } + p { class: "text-gray-300 text-sm mb-3", "{item.content}" } + div { class: "flex flex-wrap gap-x-4 gap-y-1 text-xs text-gray-500", + for (key, val) in item.fields.iter() { + span { + span { class: "text-gray-600", "{key}: " } + span { class: "text-gray-400", "{val}" } + } + } + } + } + } + } + } + } + } + } + None => { + rsx! { + div { class: "max-w-4xl mx-auto px-4 py-8", + div { class: "text-center py-20", + i { class: "ph ph-magnifying-glass text-4xl text-gray-600 mb-4" } + h2 { class: "text-xl text-gray-400", "List not found" } + p { class: "text-gray-500 mt-2 font-mono text-sm", "{coordinate}" } + } + } + } + } + } +} diff --git a/crates/carpet-ui/src/components/mod.rs b/crates/carpet-ui/src/components/mod.rs new file mode 100644 index 0000000..2dbbb1a --- /dev/null +++ b/crates/carpet-ui/src/components/mod.rs @@ -0,0 +1,6 @@ +pub mod bounty_card; +pub mod layout; +pub mod list_card; +pub mod list_detail; +pub mod wallet_card; +pub mod zap_button; diff --git a/crates/carpet-ui/src/components/wallet_card.rs b/crates/carpet-ui/src/components/wallet_card.rs new file mode 100644 index 0000000..ed4fea6 --- /dev/null +++ b/crates/carpet-ui/src/components/wallet_card.rs @@ -0,0 +1,56 @@ +use dioxus::prelude::*; + +#[derive(Clone, PartialEq)] +pub enum WalletVariant { + Bitcoin, + Lightning, +} + +#[component] +pub fn WalletCard(variant: WalletVariant, balance_sats: u64) -> Element { + let (icon, label, accent) = match variant { + WalletVariant::Bitcoin => ( + "ph ph-currency-btc", + "Bitcoin (on-chain)", + "text-orange-500", + ), + WalletVariant::Lightning => ("ph ph-lightning", "Lightning", "text-amber-400"), + }; + + let formatted = format_sats(balance_sats); + + rsx! { + div { class: "bg-gray-900 border border-gray-800 rounded-xl p-6", + div { class: "flex items-center gap-3 mb-4", + div { class: "w-10 h-10 rounded-lg bg-gray-800 flex items-center justify-center", + i { class: "{icon} text-xl {accent}" } + } + span { class: "text-gray-400 text-sm font-medium", "{label}" } + } + div { class: "mb-4", + span { class: "text-3xl font-bold font-mono text-gray-100", "{formatted}" } + span { class: "text-gray-500 text-sm ml-2", "sats" } + } + div { class: "flex gap-3", + button { class: "flex-1 py-2 px-4 bg-gray-800 hover:bg-gray-700 text-gray-200 rounded-lg text-sm font-medium transition-colors cursor-pointer", + "Receive" + } + button { class: "flex-1 py-2 px-4 bg-gray-800 hover:bg-gray-700 text-gray-200 rounded-lg text-sm font-medium transition-colors cursor-pointer", + "Send" + } + } + } + } +} + +fn format_sats(sats: u64) -> String { + let s = sats.to_string(); + let mut result = String::new(); + for (i, c) in s.chars().rev().enumerate() { + if i > 0 && i % 3 == 0 { + result.push(','); + } + result.push(c); + } + result.chars().rev().collect() +} diff --git a/crates/carpet-ui/src/components/zap_button.rs b/crates/carpet-ui/src/components/zap_button.rs new file mode 100644 index 0000000..ae241d2 --- /dev/null +++ b/crates/carpet-ui/src/components/zap_button.rs @@ -0,0 +1,15 @@ +use dioxus::prelude::*; + +#[component] +pub fn ZapButton(coordinate: String) -> Element { + rsx! { + button { + class: "inline-flex items-center gap-2 px-6 py-3 bg-amber-400 hover:bg-amber-300 text-gray-950 font-bold rounded-lg transition-colors cursor-pointer", + onclick: move |_| { + tracing::info!("Zap clicked for {}", coordinate); + }, + i { class: "ph ph-lightning text-xl" } + "Zap Curator" + } + } +} diff --git a/crates/carpet-ui/src/main.rs b/crates/carpet-ui/src/main.rs new file mode 100644 index 0000000..481117a --- /dev/null +++ b/crates/carpet-ui/src/main.rs @@ -0,0 +1,12 @@ +#![allow(non_snake_case)] + +mod app; +mod components; +mod mock_data; +mod routes; +mod state; +mod types; + +fn main() { + dioxus::launch(app::App); +} diff --git a/crates/carpet-ui/src/mock_data.rs b/crates/carpet-ui/src/mock_data.rs new file mode 100644 index 0000000..9dcb096 --- /dev/null +++ b/crates/carpet-ui/src/mock_data.rs @@ -0,0 +1,168 @@ +use crate::state::nostr::NostrState; +use crate::state::wallet::WalletState; +use crate::types::{BountyDisplay, BountyStatus, ItemDisplay, ListDisplay}; + +pub fn mock_lists() -> Vec { + vec![ + ListDisplay { + coordinate: "30001:abc123:best-bitcoin-books".into(), + name: "Best Bitcoin Books".into(), + description: "Essential reading for understanding Bitcoin, from technical deep-dives to economic philosophy.".into(), + categories: vec!["Books".into(), "Education".into()], + item_count: 12, + zap_count: 847, + curator_name: "Satoshi Reader".into(), + curator_picture: None, + curator_nip05: Some("reader@bitcoinbooks.com".into()), + }, + ListDisplay { + coordinate: "30001:def456:lightning-wallets".into(), + name: "Lightning Wallets".into(), + description: "The best Lightning Network wallets ranked by usability, features, and sovereignty.".into(), + categories: vec!["Wallets".into(), "Lightning".into()], + item_count: 8, + zap_count: 1203, + curator_name: "LN Explorer".into(), + curator_picture: None, + curator_nip05: Some("explorer@ln.tips".into()), + }, + ListDisplay { + coordinate: "30001:ghi789:nostr-clients".into(), + name: "Nostr Clients".into(), + description: "A comprehensive guide to Nostr clients across all platforms — mobile, desktop, and web.".into(), + categories: vec!["Nostr".into(), "Apps".into()], + item_count: 15, + zap_count: 2100, + curator_name: "Nostr Enthusiast".into(), + curator_picture: None, + curator_nip05: Some("fan@nostr.com".into()), + }, + ListDisplay { + coordinate: "30001:jkl012:bitcoin-podcasts".into(), + name: "Bitcoin Podcasts".into(), + description: "Top podcasts covering Bitcoin technology, economics, and culture.".into(), + categories: vec!["Podcasts".into(), "Media".into()], + item_count: 10, + zap_count: 523, + curator_name: "Pod Collector".into(), + curator_picture: None, + curator_nip05: None, + }, + ListDisplay { + coordinate: "30001:mno345:privacy-tools".into(), + name: "Privacy Tools".into(), + description: "Tools and services for protecting your privacy in the digital age.".into(), + categories: vec!["Privacy".into(), "Security".into()], + item_count: 7, + zap_count: 341, + curator_name: "Privacy Max".into(), + curator_picture: None, + curator_nip05: Some("max@privacytools.io".into()), + }, + ListDisplay { + coordinate: "30001:pqr678:dev-resources".into(), + name: "Bitcoin Dev Resources".into(), + description: "Libraries, frameworks, and learning resources for Bitcoin developers.".into(), + categories: vec!["Development".into(), "Education".into()], + item_count: 20, + zap_count: 1580, + curator_name: "Dev Builder".into(), + curator_picture: None, + curator_nip05: Some("builder@devs.bitcoin".into()), + }, + ] +} + +pub fn mock_bounties() -> Vec { + vec![ + BountyDisplay { + d_tag: "bounty-001".into(), + target_list_name: "Best Bitcoin Books".into(), + target_list_coordinate: "30001:abc123:best-bitcoin-books".into(), + reward_sats: 50_000, + criteria: "Add 3 books published in 2025 covering Bitcoin Layer 2 protocols".into(), + status: BountyStatus::Open, + creator_name: "Bookworm".into(), + }, + BountyDisplay { + d_tag: "bounty-002".into(), + target_list_name: "Nostr Clients".into(), + target_list_coordinate: "30001:ghi789:nostr-clients".into(), + reward_sats: 25_000, + criteria: "Review and rate all listed clients on NIP-44 support".into(), + status: BountyStatus::Open, + creator_name: "NIP Checker".into(), + }, + BountyDisplay { + d_tag: "bounty-003".into(), + target_list_name: "Privacy Tools".into(), + target_list_coordinate: "30001:mno345:privacy-tools".into(), + reward_sats: 100_000, + criteria: "Add Tor-based tools and verify each tool's open-source status".into(), + status: BountyStatus::Fulfilled, + creator_name: "Privacy Max".into(), + }, + ] +} + +pub fn mock_items() -> Vec { + vec![ + ItemDisplay { + resource: "https://www.amazon.com/Bitcoin-Standard-Decentralized-Alternative-Central/dp/1119473861".into(), + content: "The foundational text on Bitcoin's economic significance. Saifedean Ammous makes the case for Bitcoin as sound money.".into(), + fields: vec![ + ("Author".into(), "Saifedean Ammous".into()), + ("Year".into(), "2018".into()), + ("Rating".into(), "5/5".into()), + ], + }, + ItemDisplay { + resource: "https://www.amazon.com/Mastering-Bitcoin-Programming-Open-Blockchain/dp/1491954388".into(), + content: "The technical bible for Bitcoin developers. Covers everything from keys to mining to the protocol.".into(), + fields: vec![ + ("Author".into(), "Andreas M. Antonopoulos".into()), + ("Year".into(), "2017".into()), + ("Rating".into(), "5/5".into()), + ], + }, + ItemDisplay { + resource: "https://www.amazon.com/Broken-Money-Financial-System-Failing/dp/B0CG8837J5".into(), + content: "A deep exploration of monetary history and how Bitcoin fits into the evolution of money.".into(), + fields: vec![ + ("Author".into(), "Lyn Alden".into()), + ("Year".into(), "2023".into()), + ("Rating".into(), "4.5/5".into()), + ], + }, + ItemDisplay { + resource: "https://www.amazon.com/Sovereign-Individual-Mastering-Transition-Information/dp/0684832720".into(), + content: "Prescient predictions about the impact of digital technology on society and economics.".into(), + fields: vec![ + ("Author".into(), "James Dale Davidson".into()), + ("Year".into(), "1999".into()), + ("Rating".into(), "4/5".into()), + ], + }, + ] +} + +pub fn nostr_state() -> NostrState { + NostrState { + connected_relays: vec![ + "wss://relay.damus.io".into(), + "wss://nos.lol".into(), + "wss://relay.nostr.band".into(), + ], + is_connecting: false, + has_signer: true, + npub: Some("npub1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef12345678".into()), + } +} + +pub fn wallet_state() -> WalletState { + WalletState { + btc_balance_sats: 1_250_000, + ln_balance_sats: 350_000, + is_loading: false, + } +} diff --git a/crates/carpet-ui/src/routes.rs b/crates/carpet-ui/src/routes.rs new file mode 100644 index 0000000..bf16ed1 --- /dev/null +++ b/crates/carpet-ui/src/routes.rs @@ -0,0 +1,219 @@ +use dioxus::prelude::*; + +use crate::components::bounty_card::BountyCard; +use crate::components::layout::MainLayout; +use crate::components::list_card::ListBrowse; +use crate::components::list_detail::ListDetail; +use crate::components::wallet_card::{WalletCard, WalletVariant}; +use crate::mock_data; +use crate::state::nostr::NostrState; +use crate::state::wallet::WalletState; + +#[derive(Routable, Clone, PartialEq)] +pub enum Route { + #[layout(MainLayout)] + #[route("/")] + Marketplace {}, + + #[route("/lists")] + ListBrowsePage {}, + + #[route("/lists/:coordinate")] + ListDetailPage { coordinate: String }, + + #[route("/bounties")] + BountyBrowse {}, + + #[route("/wallet")] + WalletOverview {}, + + #[route("/profile")] + Profile {}, +} + +// --- Page components --- + +#[component] +fn Marketplace() -> Element { + rsx! { + div { class: "max-w-7xl mx-auto px-4 py-8", + // Hero + div { class: "text-center mb-10", + h1 { class: "text-4xl font-bold text-gray-100 mb-3", + "Discover Curated Lists" + } + p { class: "text-gray-400 text-lg max-w-2xl mx-auto", + "A decentralized marketplace for community-curated lists, powered by Nostr and Lightning." + } + } + + // Search + div { class: "max-w-xl mx-auto mb-8", + div { class: "relative", + i { class: "ph ph-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-gray-500" } + input { + r#type: "text", + placeholder: "Search lists...", + class: "w-full bg-gray-900 border border-gray-800 rounded-lg pl-10 pr-4 py-2.5 text-gray-200 placeholder-gray-500 focus:outline-none focus:border-gray-700", + } + } + } + + // Category filters + div { class: "flex flex-wrap justify-center gap-2 mb-8", + for cat in ["All", "Books", "Wallets", "Nostr", "Podcasts", "Privacy", "Development"] { + button { + class: if cat == "All" { + "px-4 py-1.5 text-sm rounded-full bg-orange-500 text-white font-medium cursor-pointer" + } else { + "px-4 py-1.5 text-sm rounded-full bg-gray-900 text-gray-400 hover:bg-gray-800 hover:text-gray-200 transition-colors border border-gray-800 cursor-pointer" + }, + "{cat}" + } + } + } + + // Grid + ListBrowse {} + } + } +} + +#[component] +fn ListBrowsePage() -> Element { + let lists: Signal> = use_context(); + let count = lists.read().len(); + + rsx! { + div { class: "max-w-7xl mx-auto px-4 py-8", + div { class: "flex items-center justify-between mb-6", + div { class: "flex items-center gap-3", + h1 { class: "text-2xl font-bold text-gray-100", "Browse Lists" } + span { class: "px-2.5 py-0.5 text-xs rounded-full bg-gray-800 text-gray-400 font-mono", + "{count}" + } + } + div { class: "relative", + i { class: "ph ph-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-gray-500" } + input { + r#type: "text", + placeholder: "Search...", + class: "bg-gray-900 border border-gray-800 rounded-lg pl-10 pr-4 py-2 text-sm text-gray-200 placeholder-gray-500 focus:outline-none focus:border-gray-700", + } + } + } + ListBrowse {} + } + } +} + +#[component] +fn ListDetailPage(coordinate: String) -> Element { + rsx! { + ListDetail { coordinate } + } +} + +#[component] +fn BountyBrowse() -> Element { + let bounties = mock_data::mock_bounties(); + + rsx! { + div { class: "max-w-7xl mx-auto px-4 py-8", + div { class: "flex items-center gap-3 mb-6", + h1 { class: "text-2xl font-bold text-gray-100", "Active Bounties" } + span { class: "px-2.5 py-0.5 text-xs rounded-full bg-gray-800 text-gray-400 font-mono", + "{bounties.len()}" + } + } + div { class: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", + for bounty in bounties { + BountyCard { bounty } + } + } + } + } +} + +#[component] +fn WalletOverview() -> Element { + let wallet_state: Signal = use_context(); + let wallet = wallet_state.read(); + + rsx! { + div { class: "max-w-3xl mx-auto px-4 py-8", + h1 { class: "text-2xl font-bold text-gray-100 mb-6", "Wallet" } + div { class: "grid grid-cols-1 md:grid-cols-2 gap-4", + WalletCard { variant: WalletVariant::Bitcoin, balance_sats: wallet.btc_balance_sats } + WalletCard { variant: WalletVariant::Lightning, balance_sats: wallet.ln_balance_sats } + } + } + } +} + +#[component] +fn Profile() -> Element { + let nostr_state: Signal = use_context(); + let nostr = nostr_state.read(); + + let npub_display = nostr + .npub + .as_ref() + .map(|n| { + if n.len() > 20 { + format!("{}...{}", &n[..12], &n[n.len() - 8..]) + } else { + n.clone() + } + }) + .unwrap_or_else(|| "Not connected".into()); + + rsx! { + div { class: "max-w-3xl mx-auto px-4 py-8", + // Profile header + div { class: "bg-gray-900 border border-gray-800 rounded-xl p-6 mb-6", + div { class: "flex items-center gap-4 mb-4", + div { class: "w-16 h-16 rounded-full bg-gray-800 flex items-center justify-center text-2xl font-bold text-orange-500", + "M" + } + div { + h1 { class: "text-2xl font-bold text-gray-100", "Magic Carpet User" } + p { class: "text-gray-500 text-sm font-mono flex items-center gap-2", + "{npub_display}" + button { class: "text-gray-600 hover:text-gray-400 transition-colors cursor-pointer", + i { class: "ph ph-copy" } + } + } + } + } + } + + // Relays + div { class: "bg-gray-900 border border-gray-800 rounded-xl p-6 mb-6", + h2 { class: "text-lg font-semibold text-gray-100 mb-4 flex items-center gap-2", + i { class: "ph ph-globe text-gray-400" } + "Connected Relays" + } + div { class: "space-y-2", + for relay in nostr.connected_relays.iter() { + div { class: "flex items-center gap-2 text-sm", + span { class: "w-2 h-2 rounded-full bg-emerald-400" } + span { class: "text-gray-300 font-mono", "{relay}" } + } + } + } + } + + // Key management + div { class: "bg-gray-900 border border-gray-800 rounded-xl p-6", + h2 { class: "text-lg font-semibold text-gray-100 mb-4 flex items-center gap-2", + i { class: "ph ph-key text-gray-400" } + "Key Management" + } + p { class: "text-gray-400 text-sm", + "Key import, export, and NIP-46 remote signer configuration coming soon." + } + } + } + } +} diff --git a/crates/carpet-ui/src/state/marketplace.rs b/crates/carpet-ui/src/state/marketplace.rs new file mode 100644 index 0000000..7cfd4b8 --- /dev/null +++ b/crates/carpet-ui/src/state/marketplace.rs @@ -0,0 +1,7 @@ +/// Marketplace view state tracked in the UI. +#[derive(Debug, Clone, Default)] +pub struct MarketplaceState { + pub search_query: String, + pub selected_category: Option, + pub is_loading: bool, +} diff --git a/crates/carpet-ui/src/state/mod.rs b/crates/carpet-ui/src/state/mod.rs new file mode 100644 index 0000000..eb06767 --- /dev/null +++ b/crates/carpet-ui/src/state/mod.rs @@ -0,0 +1,3 @@ +pub mod marketplace; +pub mod nostr; +pub mod wallet; diff --git a/crates/carpet-ui/src/state/nostr.rs b/crates/carpet-ui/src/state/nostr.rs new file mode 100644 index 0000000..197e11d --- /dev/null +++ b/crates/carpet-ui/src/state/nostr.rs @@ -0,0 +1,8 @@ +/// Nostr connection state tracked in the UI. +#[derive(Debug, Clone, Default)] +pub struct NostrState { + pub connected_relays: Vec, + pub is_connecting: bool, + pub has_signer: bool, + pub npub: Option, +} diff --git a/crates/carpet-ui/src/state/wallet.rs b/crates/carpet-ui/src/state/wallet.rs new file mode 100644 index 0000000..f4e525e --- /dev/null +++ b/crates/carpet-ui/src/state/wallet.rs @@ -0,0 +1,7 @@ +/// Wallet balances tracked in the UI. +#[derive(Debug, Clone, Default)] +pub struct WalletState { + pub btc_balance_sats: u64, + pub ln_balance_sats: u64, + pub is_loading: bool, +} diff --git a/crates/carpet-ui/src/types.rs b/crates/carpet-ui/src/types.rs new file mode 100644 index 0000000..5de2124 --- /dev/null +++ b/crates/carpet-ui/src/types.rs @@ -0,0 +1,37 @@ +#[derive(Debug, Clone, PartialEq)] +pub struct ListDisplay { + pub coordinate: String, + pub name: String, + pub description: String, + pub categories: Vec, + pub item_count: usize, + pub zap_count: u64, + pub curator_name: String, + pub curator_picture: Option, + pub curator_nip05: Option, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct BountyDisplay { + pub d_tag: String, + pub target_list_name: String, + pub target_list_coordinate: String, + pub reward_sats: u64, + pub criteria: String, + pub status: BountyStatus, + pub creator_name: String, +} + +#[derive(Debug, Clone, PartialEq)] +pub enum BountyStatus { + Open, + Fulfilled, + Expired, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct ItemDisplay { + pub resource: String, + pub content: String, + pub fields: Vec<(String, String)>, +} diff --git a/crates/nostr-lib/Cargo.toml b/crates/nostr-lib/Cargo.toml new file mode 100644 index 0000000..138c3ee --- /dev/null +++ b/crates/nostr-lib/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "nostr-lib" +version = "0.1.0" +edition.workspace = true + +[dependencies] +dcosl-core = { path = "../../../dcosl-core" } +nostr-sdk = { version = "0.44", features = ["nip57"] } +phoenixd-lib = { path = "../phoenixd-lib" } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } + +[package.metadata.cargo-machete] +ignored = ["tokio", "tracing"] diff --git a/crates/nostr-lib/src/error.rs b/crates/nostr-lib/src/error.rs new file mode 100644 index 0000000..3e46b28 --- /dev/null +++ b/crates/nostr-lib/src/error.rs @@ -0,0 +1,31 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum NostrLibError { + #[error("Relay connection failed: {url}")] + RelayConnection { url: String }, + + #[error("Event publish failed: {reason}")] + PublishFailed { reason: String }, + + #[error("Protocol error: {0}")] + Protocol(#[from] dcosl_core::DcoslError), + + #[error("Zap error: {reason}")] + Zap { reason: String }, + + #[error("Profile not found for pubkey: {pubkey}")] + ProfileNotFound { pubkey: String }, + + #[error("Missing lud16 in profile for pubkey: {pubkey}")] + MissingLud16 { pubkey: String }, + + #[error("LNURL error: {reason}")] + Lnurl { reason: String }, + + #[error("PhoenixD error: {0}")] + Phoenixd(#[from] phoenixd_lib::PhoenixdError), + + #[error("Nostr SDK error: {0}")] + Sdk(String), +} diff --git a/crates/nostr-lib/src/filters.rs b/crates/nostr-lib/src/filters.rs new file mode 100644 index 0000000..ad81ef8 --- /dev/null +++ b/crates/nostr-lib/src/filters.rs @@ -0,0 +1,53 @@ +use nostr_sdk::prelude::*; + +use crate::types::kinds; + +/// Build a filter for `DCoSL` list headers (kinds 9998 + 39998). +pub fn list_headers_filter(author: Option, hashtag: Option<&str>) -> Filter { + let mut filter = Filter::new().kinds(vec![kinds::HEADER_REGULAR, kinds::HEADER]); + + if let Some(pk) = author { + filter = filter.author(pk); + } + if let Some(t) = hashtag { + filter = filter.hashtag(t); + } + + filter +} + +/// Build a filter for list items matching a parent z-ref. +pub fn list_items_filter(z_ref: &str) -> Filter { + Filter::new() + .kinds(vec![kinds::ITEM_REGULAR, kinds::ITEM]) + .custom_tag(SingleLetterTag::lowercase(Alphabet::Z), z_ref.to_string()) +} + +/// Build a filter for bounties (NIP-99 kind 30402) with bounty hashtag. +pub fn bounties_filter(target_coordinate: Option<&str>) -> Filter { + let mut filter = Filter::new().kind(kinds::BOUNTY).hashtag("bounty"); + + if let Some(coord) = target_coordinate { + filter = filter.custom_tag(SingleLetterTag::lowercase(Alphabet::A), coord.to_string()); + } + + filter +} + +/// Build a filter for zap receipts (kind 9735) targeting a specific event or coordinate. +pub fn zap_receipts_filter(target_pubkey: PublicKey) -> Filter { + Filter::new().kind(kinds::ZAP_RECEIPT).pubkey(target_pubkey) +} + +/// Build a filter for profile metadata (kind 0). +pub fn profile_filter(pubkey: PublicKey) -> Filter { + Filter::new().kind(Kind::Metadata).author(pubkey).limit(1) +} + +/// Build a filter for relay list (NIP-65 kind 10002). +pub fn relay_list_filter(pubkey: PublicKey) -> Filter { + Filter::new() + .kind(kinds::RELAY_LIST) + .author(pubkey) + .limit(1) +} diff --git a/crates/nostr-lib/src/lib.rs b/crates/nostr-lib/src/lib.rs new file mode 100644 index 0000000..a1d7f0e --- /dev/null +++ b/crates/nostr-lib/src/lib.rs @@ -0,0 +1,14 @@ +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::must_use_candidate)] + +pub mod error; +pub mod filters; +pub mod profile; +pub mod service; +pub mod types; +pub mod zap; + +pub use error::NostrLibError; +pub use service::NostrService; +pub use types::*; diff --git a/crates/nostr-lib/src/profile.rs b/crates/nostr-lib/src/profile.rs new file mode 100644 index 0000000..880d8ad --- /dev/null +++ b/crates/nostr-lib/src/profile.rs @@ -0,0 +1,71 @@ +use std::time::Duration; + +use nostr_sdk::prelude::*; + +use crate::error::NostrLibError; +use crate::filters; +use crate::types::ProfileMetadata; + +const FETCH_TIMEOUT: Duration = Duration::from_secs(10); + +/// Fetch kind 0 profile metadata for a pubkey. +pub async fn fetch_profile( + client: &Client, + pubkey: PublicKey, +) -> Result { + let filter = filters::profile_filter(pubkey); + let events = client + .fetch_events(filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + let event = events + .into_iter() + .next() + .ok_or(NostrLibError::ProfileNotFound { + pubkey: pubkey.to_hex(), + })?; + + serde_json::from_str(&event.content).map_err(|_| NostrLibError::ProfileNotFound { + pubkey: pubkey.to_hex(), + }) +} + +/// Extract lud16 (Lightning Address) from a profile. +pub async fn fetch_lud16(client: &Client, pubkey: PublicKey) -> Result { + let profile = fetch_profile(client, pubkey).await?; + profile.lud16.ok_or(NostrLibError::MissingLud16 { + pubkey: pubkey.to_hex(), + }) +} + +/// Fetch NIP-65 relay list (kind 10002) for a pubkey. +pub async fn fetch_relay_list( + client: &Client, + pubkey: PublicKey, +) -> Result, NostrLibError> { + let filter = filters::relay_list_filter(pubkey); + let events = client + .fetch_events(filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + let Some(event) = events.into_iter().next() else { + return Ok(vec![]); + }; + + let relays: Vec = event + .tags + .iter() + .filter_map(|t| { + let parts = t.as_slice(); + if parts.first().map(String::as_str) == Some("r") { + parts.get(1).cloned() + } else { + None + } + }) + .collect(); + + Ok(relays) +} diff --git a/crates/nostr-lib/src/service.rs b/crates/nostr-lib/src/service.rs new file mode 100644 index 0000000..b934820 --- /dev/null +++ b/crates/nostr-lib/src/service.rs @@ -0,0 +1,271 @@ +use std::collections::HashSet; +use std::time::Duration; + +use nostr_sdk::prelude::*; + +use crate::error::NostrLibError; +use crate::filters; +use crate::types::{MarketplaceList, kinds}; + +const FETCH_TIMEOUT: Duration = Duration::from_secs(10); +const FETCH_PAGE_SIZE: usize = 500; + +/// Commands that the UI can send to the `NostrService`. +#[derive(Debug)] +pub enum NostrCommand { + /// Connect to a relay URL. + AddRelay(String), + /// Disconnect from a relay URL. + RemoveRelay(String), + /// Publish a header event. + PublishHeader { + params: dcosl_core::header::HeaderParams, + addressable: bool, + }, + /// Publish an item event. + PublishItem { + parent_z_ref: String, + resource: String, + fields: Vec, + content: Option, + }, +} + +/// Marketplace-aware Nostr client wrapping `nostr_sdk::Client`. +pub struct NostrService { + client: Client, +} + +impl NostrService { + pub fn new(keys: Keys) -> Self { + let client = Client::builder().signer(keys).build(); + Self { client } + } + + pub fn new_readonly() -> Self { + let client = Client::default(); + Self { client } + } + + pub fn client(&self) -> &Client { + &self.client + } + + pub async fn add_relay(&self, url: &str) -> Result<(), NostrLibError> { + self.client + .add_relay(url) + .await + .map_err(|_| NostrLibError::RelayConnection { + url: url.to_string(), + })?; + Ok(()) + } + + pub async fn connect(&self) { + self.client.connect().await; + } + + pub async fn disconnect(&self) { + self.client.disconnect().await; + } + + /// Fetch all list headers, optionally filtered. + pub async fn fetch_headers( + &self, + author: Option, + hashtag: Option<&str>, + ) -> Result, NostrLibError> { + let filter = filters::list_headers_filter(author, hashtag); + self.fetch_all_events(filter).await + } + + /// Fetch items for a list by z-ref. + pub async fn fetch_items(&self, z_ref: &str) -> Result, NostrLibError> { + let filter = filters::list_items_filter(z_ref); + let events = self + .client + .fetch_events(filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + Ok(events.into_iter().collect()) + } + + /// Fetch a full `MarketplaceList` by coordinate. + pub async fn fetch_marketplace_list( + &self, + coordinate: &str, + ) -> Result { + let (kind_num, pubkey, d_tag) = dcosl_core::item::parse_coordinate_str(coordinate)?; + + // Fetch header + let header_filter = Filter::new() + .kind(Kind::Custom(kind_num)) + .author(pubkey) + .custom_tag(SingleLetterTag::lowercase(Alphabet::D), d_tag.clone()) + .limit(1); + + let header_events = self + .client + .fetch_events(header_filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + let header = header_events.into_iter().next().ok_or_else(|| { + NostrLibError::Sdk(format!("Header not found for coordinate: {coordinate}")) + })?; + + // Fetch items + let items = self.fetch_items(coordinate).await?; + + // Extract metadata from header tags + let header_json = dcosl_core::query::event_to_json(&header); + let name = header_json["name"] + .as_str() + .unwrap_or("Unknown") + .to_string(); + let plural_name = header_json["plural_name"].as_str().map(String::from); + let description = header_json["description"].as_str().map(String::from); + + let categories: Vec = header + .tags + .iter() + .filter_map(|t| { + let parts = t.as_slice(); + if parts.first().map(String::as_str) == Some("t") { + parts.get(1).cloned() + } else { + None + } + }) + .collect(); + + // Try to fetch curator profile + let curator_profile = crate::profile::fetch_profile(&self.client, pubkey) + .await + .ok(); + + Ok(MarketplaceList { + header, + items, + coordinate: coordinate.to_string(), + name, + plural_name, + description, + categories, + zap_count: 0, // TODO: count zap receipts + curator_pubkey: pubkey, + curator_profile, + }) + } + + /// Publish a header event and return it. + pub async fn publish_header( + &self, + params: dcosl_core::header::HeaderParams, + addressable: bool, + ) -> Result { + let kind = if addressable { + kinds::HEADER + } else { + kinds::HEADER_REGULAR + }; + + let tags = dcosl_core::header::build_header_tags(¶ms); + let builder = EventBuilder::new(kind, "").tags(tags); + + let output = self.client.send_event_builder(builder).await.map_err(|e| { + NostrLibError::PublishFailed { + reason: e.to_string(), + } + })?; + + // Fetch the published event back + let filter = Filter::new().id(output.val).limit(1); + let events = self + .client + .fetch_events(filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + events + .into_iter() + .next() + .ok_or_else(|| NostrLibError::PublishFailed { + reason: "Event published but not found on relay".to_string(), + }) + } + + /// Publish an item event and return its ID. + pub async fn publish_item( + &self, + parent_z_ref: &str, + resource: &str, + fields: &[String], + content: Option<&str>, + d_tag: Option<&str>, + ) -> Result { + let tags = dcosl_core::item::build_item_tags( + parent_z_ref, + resource, + fields, + d_tag, + Some("magic-carpet"), + ); + + let builder = EventBuilder::new(kinds::ITEM, content.unwrap_or("")).tags(tags); + + let output = self.client.send_event_builder(builder).await.map_err(|e| { + NostrLibError::PublishFailed { + reason: e.to_string(), + } + })?; + + Ok(output.val) + } + + /// Paginated fetch with dedupe (same pattern as wokhei). + async fn fetch_all_events(&self, base_filter: Filter) -> Result, NostrLibError> { + let mut all_events: Vec = Vec::new(); + let mut seen_ids: HashSet = HashSet::new(); + let mut until_secs: Option = None; + + loop { + let mut filter = base_filter.clone().limit(FETCH_PAGE_SIZE); + if let Some(secs) = until_secs { + filter = filter.until(Timestamp::from_secs(secs)); + } + + let batch = self + .client + .fetch_events(filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + if batch.is_empty() { + break; + } + + let mut oldest_created_at = u64::MAX; + for event in batch.iter() { + oldest_created_at = oldest_created_at.min(event.created_at.as_secs()); + let event_id = event.id.to_hex(); + if seen_ids.insert(event_id) { + all_events.push(event.clone()); + } + } + + if batch.len() < FETCH_PAGE_SIZE || oldest_created_at == 0 { + break; + } + + let next_until = oldest_created_at.saturating_sub(1); + if until_secs == Some(next_until) { + break; + } + until_secs = Some(next_until); + } + + Ok(all_events) + } +} diff --git a/crates/nostr-lib/src/types.rs b/crates/nostr-lib/src/types.rs new file mode 100644 index 0000000..b4fb09a --- /dev/null +++ b/crates/nostr-lib/src/types.rs @@ -0,0 +1,72 @@ +use nostr_sdk::prelude::*; +use serde::{Deserialize, Serialize}; + +/// A marketplace list: header event + items + metadata. +#[derive(Debug, Clone)] +pub struct MarketplaceList { + pub header: Event, + pub items: Vec, + pub coordinate: String, + pub name: String, + pub plural_name: Option, + pub description: Option, + pub categories: Vec, + pub zap_count: u64, + pub curator_pubkey: PublicKey, + pub curator_profile: Option, +} + +/// Curator profile metadata (kind 0). +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ProfileMetadata { + pub name: Option, + pub about: Option, + pub picture: Option, + pub nip05: Option, + pub lud16: Option, + pub display_name: Option, +} + +/// A bounty targeting a specific list (NIP-99 kind 30402). +#[derive(Debug, Clone)] +pub struct Bounty { + pub event: Event, + pub d_tag: String, + pub target_list_coordinate: String, + pub reward_sats: u64, + pub criteria: String, + pub expiry: Option, + pub status: BountyStatus, + pub creator_pubkey: PublicKey, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum BountyStatus { + Open, + Fulfilled, + Expired, +} + +/// Links a list update event to a bounty it fulfills. +#[derive(Debug, Clone)] +pub struct BountyFulfillment { + pub bounty_id: String, + pub update_event_id: EventId, + pub updater_pubkey: PublicKey, + pub zap_receipt_id: Option, +} + +/// `DCoSL` event kinds used in the marketplace. +pub mod kinds { + use nostr_sdk::Kind; + + pub const HEADER: Kind = Kind::Custom(39998); + pub const HEADER_REGULAR: Kind = Kind::Custom(9998); + pub const ITEM: Kind = Kind::Custom(39999); + pub const ITEM_REGULAR: Kind = Kind::Custom(9999); + pub const BOUNTY: Kind = Kind::Custom(30402); + pub const ZAP_REQUEST: Kind = Kind::Custom(9734); + pub const ZAP_RECEIPT: Kind = Kind::Custom(9735); + pub const PROFILE_METADATA: Kind = Kind::Custom(0); + pub const RELAY_LIST: Kind = Kind::Custom(10002); +} diff --git a/crates/nostr-lib/src/zap.rs b/crates/nostr-lib/src/zap.rs new file mode 100644 index 0000000..840881d --- /dev/null +++ b/crates/nostr-lib/src/zap.rs @@ -0,0 +1,118 @@ +use nostr_sdk::prelude::*; + +use crate::error::NostrLibError; +use crate::profile; + +/// Construct a NIP-57 zap request (kind 9734). +/// +/// This returns the zap request event — it should be sent to the LNURL callback, +/// NOT published to relays. +#[allow(clippy::too_many_arguments)] +pub fn build_zap_request( + _client: &Client, + signer: &Keys, + recipient_pubkey: PublicKey, + target_event_id: Option, + target_coordinate: Option, + amount_msats: u64, + relay_urls: Vec, + content: Option, +) -> Result { + let relay_urls: Vec = relay_urls + .into_iter() + .filter_map(|u| RelayUrl::parse(&u).ok()) + .collect(); + + let mut zap_data = ZapRequestData::new(recipient_pubkey, relay_urls) + .amount(amount_msats) + .message(content.unwrap_or_default()); + + if let Some(event_id) = target_event_id { + zap_data = zap_data.event_id(event_id); + } + if let Some(coord) = target_coordinate { + // Parse coordinate and add as `a` tag + let (kind_num, pubkey, d_tag) = dcosl_core::item::parse_coordinate_str(&coord)?; + let coordinate = Coordinate::new(Kind::Custom(kind_num), pubkey).identifier(d_tag); + zap_data = zap_data.event_coordinate(coordinate); + } + + let zap_request = EventBuilder::public_zap_request(zap_data) + .sign_with_keys(signer) + .map_err(|e| NostrLibError::Zap { + reason: e.to_string(), + })?; + + Ok(zap_request) +} + +/// Resolve a recipient's LNURL callback URL from their lud16. +/// +/// lud16 format: `user@domain` → `https://domain/.well-known/lnurlp/user` +pub fn lud16_to_lnurl_callback(lud16: &str) -> Result { + let (user, domain) = lud16.split_once('@').ok_or(NostrLibError::Lnurl { + reason: format!("Invalid lud16 format: {lud16}"), + })?; + + Ok(format!("https://{domain}/.well-known/lnurlp/{user}")) +} + +/// Full NIP-57 zap flow: +/// 1. Fetch recipient's lud16 from kind 0 profile +/// 2. Build zap request event +/// 3. Return (`zap_request`, `lnurl_callback`) for the caller to send +pub async fn prepare_zap( + client: &Client, + signer: &Keys, + recipient_pubkey: PublicKey, + target_event_id: Option, + target_coordinate: Option, + amount_msats: u64, + content: Option, +) -> Result<(Event, String), NostrLibError> { + let lud16 = profile::fetch_lud16(client, recipient_pubkey).await?; + let callback_url = lud16_to_lnurl_callback(&lud16)?; + + // Use recipient's relay list for zap routing + let relay_urls = profile::fetch_relay_list(client, recipient_pubkey).await?; + let relay_urls = if relay_urls.is_empty() { + // Fallback to connected relays + client + .relays() + .await + .keys() + .map(std::string::ToString::to_string) + .collect() + } else { + relay_urls + }; + + let zap_request = build_zap_request( + client, + signer, + recipient_pubkey, + target_event_id, + target_coordinate, + amount_msats, + relay_urls, + content, + )?; + + Ok((zap_request, callback_url)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn lud16_to_lnurl_valid() { + let url = lud16_to_lnurl_callback("user@example.com").unwrap(); + assert_eq!(url, "https://example.com/.well-known/lnurlp/user"); + } + + #[test] + fn lud16_to_lnurl_invalid_format() { + assert!(lud16_to_lnurl_callback("no-at-sign").is_err()); + } +} diff --git a/crates/phoenixd-agcli/src/main.rs b/crates/phoenixd-agcli/src/main.rs index ce63814..df8ecdd 100644 --- a/crates/phoenixd-agcli/src/main.rs +++ b/crates/phoenixd-agcli/src/main.rs @@ -7,6 +7,7 @@ use agcli::{ use phoenixd_lib::PhoenixdError; use serde_json::json; +#[allow(clippy::needless_pass_by_value)] fn err(e: PhoenixdError) -> CommandError { let (code, retryable) = match &e { PhoenixdError::Http(_) => ("HTTP_ERROR", true), @@ -28,136 +29,126 @@ fn build_client() -> Result { fn info_command() -> Command { Command::new("info", "Show PhoenixD node info") .usage("phoenixd-agcli info") - .handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - Box::pin(async move { - let client = build_client()?; - let info = client.node_info().await.map_err(err)?; - Ok(CommandOutput::new(json!(info)).next_actions(vec![ - NextAction::new("phoenixd-agcli balance", "Check balance"), - NextAction::new("phoenixd-agcli channels", "List channels"), - ])) - }) - }, - ) + .handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + Box::pin(async move { + let client = build_client()?; + let info = client.node_info().await.map_err(err)?; + Ok(CommandOutput::new(json!(info)).next_actions(vec![ + NextAction::new("phoenixd-agcli balance", "Check balance"), + NextAction::new("phoenixd-agcli channels", "List channels"), + ])) + }) + }) } fn balance_command() -> Command { Command::new("balance", "Show wallet balance") .usage("phoenixd-agcli balance") - .handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - Box::pin(async move { - let client = build_client()?; - let balance = client.get_balance().await.map_err(err)?; - Ok(CommandOutput::new(json!(balance)).next_actions(vec![ - NextAction::new( - "phoenixd-agcli invoice --amount --description ", - "Create an invoice to receive", - ), - NextAction::new( - "phoenixd-agcli pay --invoice ", - "Pay an invoice", - ), - ])) - }) - }, - ) + .handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + Box::pin(async move { + let client = build_client()?; + let balance = client.get_balance().await.map_err(err)?; + Ok(CommandOutput::new(json!(balance)).next_actions(vec![ + NextAction::new( + "phoenixd-agcli invoice --amount --description ", + "Create an invoice to receive", + ), + NextAction::new("phoenixd-agcli pay --invoice ", "Pay an invoice"), + ])) + }) + }) } fn invoice_command() -> Command { Command::new("invoice", "Create a BOLT11 invoice") .usage("phoenixd-agcli invoice --amount --description ") - .handler( - |req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let amount_str = req.flag("amount").map(String::from); - let description = req - .flag("description") - .unwrap_or("magic-carpet invoice") - .to_string(); - let external_id = req.flag("external-id").map(String::from); - - Box::pin(async move { - let amount: u64 = amount_str - .ok_or_else(|| { - CommandError::new( - "--amount is required", - "MISSING_ARG", - "Provide --amount=", - ) - })? - .parse() - .map_err(|_| { - CommandError::new( - "--amount must be a number", - "INVALID_ARGS", - "Provide amount in satoshis", - ) - })?; - - let client = build_client()?; - let invoice = client - .create_invoice(amount, &description, external_id.as_deref()) - .await - .map_err(err)?; - - Ok(CommandOutput::new(json!(invoice)).next_actions(vec![ - NextAction::new( - "phoenixd-agcli balance", - "Check balance after payment", - ), - ])) - }) - }, - ) -} - -fn pay_command() -> Command { - Command::new("pay", "Pay a BOLT11 invoice") - .usage("phoenixd-agcli pay --invoice ") - .handler( - |req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let bolt11 = req.flag("invoice").map(String::from); - - Box::pin(async move { - let bolt11 = bolt11.ok_or_else(|| { + .handler(|req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let amount_str = req.flag("amount").map(String::from); + let description = req + .flag("description") + .unwrap_or("magic-carpet invoice") + .to_string(); + let external_id = req.flag("external-id").map(String::from); + + Box::pin(async move { + let amount: u64 = amount_str + .ok_or_else(|| { CommandError::new( - "--invoice is required", + "--amount is required", "MISSING_ARG", - "Provide --invoice=", + "Provide --amount=", + ) + })? + .parse() + .map_err(|_| { + CommandError::new( + "--amount must be a number", + "INVALID_ARGS", + "Provide amount in satoshis", ) })?; - let client = build_client()?; - let result = client.pay_invoice(&bolt11).await.map_err(err)?; + let client = build_client()?; + let invoice = client + .create_invoice(amount, &description, external_id.as_deref()) + .await + .map_err(err)?; + + Ok( + CommandOutput::new(json!(invoice)).next_actions(vec![NextAction::new( + "phoenixd-agcli balance", + "Check balance after payment", + )]), + ) + }) + }) +} - Ok(CommandOutput::new(json!(result)).next_actions(vec![ - NextAction::new("phoenixd-agcli balance", "Check updated balance"), - ])) - }) - }, - ) +fn pay_command() -> Command { + Command::new("pay", "Pay a BOLT11 invoice") + .usage("phoenixd-agcli pay --invoice ") + .handler(|req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let bolt11 = req.flag("invoice").map(String::from); + + Box::pin(async move { + let bolt11 = bolt11.ok_or_else(|| { + CommandError::new( + "--invoice is required", + "MISSING_ARG", + "Provide --invoice=", + ) + })?; + + let client = build_client()?; + let result = client.pay_invoice(&bolt11).await.map_err(err)?; + + Ok( + CommandOutput::new(json!(result)).next_actions(vec![NextAction::new( + "phoenixd-agcli balance", + "Check updated balance", + )]), + ) + }) + }) } fn channels_command() -> Command { Command::new("channels", "List channels") .usage("phoenixd-agcli channels") - .handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - Box::pin(async move { - let client = build_client()?; - let channels = client.list_channels().await.map_err(err)?; - Ok(CommandOutput::new(json!({ - "count": channels.len(), - "channels": channels, - })) - .next_actions(vec![ - NextAction::new("phoenixd-agcli info", "Node info"), - NextAction::new("phoenixd-agcli balance", "Balance"), - ])) - }) - }, - ) + .handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + Box::pin(async move { + let client = build_client()?; + let channels = client.list_channels().await.map_err(err)?; + Ok(CommandOutput::new(json!({ + "count": channels.len(), + "channels": channels, + })) + .next_actions(vec![ + NextAction::new("phoenixd-agcli info", "Node info"), + NextAction::new("phoenixd-agcli balance", "Balance"), + ])) + }) + }) } #[tokio::main] diff --git a/crates/phoenixd-lib/src/client.rs b/crates/phoenixd-lib/src/client.rs index fdb75e4..e3961d3 100644 --- a/crates/phoenixd-lib/src/client.rs +++ b/crates/phoenixd-lib/src/client.rs @@ -1,8 +1,10 @@ -use reqwest::header::{AUTHORIZATION, HeaderValue}; use reqwest::Client; +use reqwest::header::{AUTHORIZATION, HeaderValue}; use crate::error::PhoenixdError; -use crate::types::*; +use crate::types::{ + ChannelInfo, IncomingPayment, Invoice, NodeInfo, OutgoingPayment, PaymentResult, WalletBalance, +}; pub struct PhoenixdClient { http: Client, @@ -117,10 +119,7 @@ impl PhoenixdClient { Ok(()) } - pub async fn get_incoming_payment( - &self, - hash: &str, - ) -> Result { + pub async fn get_incoming_payment(&self, hash: &str) -> Result { let resp = self .http .get(format!("{}/payments/incoming/{hash}", self.base_url)) @@ -130,10 +129,7 @@ impl PhoenixdClient { Self::handle_response(resp).await } - pub async fn get_outgoing_payment( - &self, - id: &str, - ) -> Result { + pub async fn get_outgoing_payment(&self, id: &str) -> Result { let resp = self .http .get(format!("{}/payments/outgoing/{id}", self.base_url)) @@ -151,8 +147,6 @@ impl PhoenixdClient { return Err(PhoenixdError::Api { message: text }); } let text = resp.text().await?; - serde_json::from_str(&text).map_err(|e| { - PhoenixdError::Deserialize(format!("{e}: {text}")) - }) + serde_json::from_str(&text).map_err(|e| PhoenixdError::Deserialize(format!("{e}: {text}"))) } } diff --git a/crates/phoenixd-lib/src/lib.rs b/crates/phoenixd-lib/src/lib.rs index 546d2a3..daede96 100644 --- a/crates/phoenixd-lib/src/lib.rs +++ b/crates/phoenixd-lib/src/lib.rs @@ -1,3 +1,7 @@ +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::must_use_candidate)] + pub mod client; pub mod error; pub mod types; diff --git a/docker-compose.phoenixd.yml b/docker-compose.phoenixd.yml new file mode 100644 index 0000000..895f6b5 --- /dev/null +++ b/docker-compose.phoenixd.yml @@ -0,0 +1,13 @@ +services: + phoenixd: + image: acinq/phoenixd:latest + container_name: phoenixd + restart: unless-stopped + command: --agree-to-terms-of-service --http-bind-ip=0.0.0.0 + volumes: + - phoenixd-data:/phoenix/.phoenix + ports: + - "127.0.0.1:9740:9740" + +volumes: + phoenixd-data: diff --git a/justfile b/justfile index 08496f8..d58f20f 100644 --- a/justfile +++ b/justfile @@ -76,3 +76,19 @@ e2e-run: e2e-down: docker compose down -v + +# Build Tailwind CSS for carpet-ui (watch mode) +dx-tw: + npx @tailwindcss/cli -i crates/carpet-ui/input.css -o crates/carpet-ui/assets/tailwind.css --watch + +# Build Tailwind CSS once (for CI / before build) +dx-tw-build: + npx @tailwindcss/cli -i crates/carpet-ui/input.css -o crates/carpet-ui/assets/tailwind.css + +# Serve carpet-ui for web development +dx-web: + dx serve -p carpet-ui --platform web + +# Serve carpet-ui as a desktop app +dx-desktop: + dx serve -p carpet-ui --platform desktop diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9454a0f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,991 @@ +{ + "name": "magic-carpet", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@tailwindcss/cli": "^4.2.1", + "tailwindcss": "^4.2.1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@tailwindcss/cli": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.2.1.tgz", + "integrity": "sha512-b7MGn51IA80oSG+7fuAgzfQ+7pZBgjzbqwmiv6NO7/+a1sev32cGqnwhscT7h0EcAvMa9r7gjRylqOH8Xhc4DA==", + "license": "MIT", + "dependencies": { + "@parcel/watcher": "^2.5.1", + "@tailwindcss/node": "4.2.1", + "@tailwindcss/oxide": "4.2.1", + "enhanced-resolve": "^5.19.0", + "mri": "^1.2.0", + "picocolors": "^1.1.1", + "tailwindcss": "4.2.1" + }, + "bin": { + "tailwindcss": "dist/index.mjs" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", + "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.19.0", + "jiti": "^2.6.1", + "lightningcss": "1.31.1", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.2.1" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", + "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==", + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.2.1", + "@tailwindcss/oxide-darwin-arm64": "4.2.1", + "@tailwindcss/oxide-darwin-x64": "4.2.1", + "@tailwindcss/oxide-freebsd-x64": "4.2.1", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", + "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", + "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", + "@tailwindcss/oxide-linux-x64-musl": "4.2.1", + "@tailwindcss/oxide-wasm32-wasi": "4.2.1", + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", + "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz", + "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz", + "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz", + "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz", + "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz", + "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz", + "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz", + "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz", + "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz", + "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz", + "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.8.1", + "@emnapi/runtime": "^1.8.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.1", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", + "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz", + "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", + "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/lightningcss": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", + "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.31.1", + "lightningcss-darwin-arm64": "1.31.1", + "lightningcss-darwin-x64": "1.31.1", + "lightningcss-freebsd-x64": "1.31.1", + "lightningcss-linux-arm-gnueabihf": "1.31.1", + "lightningcss-linux-arm64-gnu": "1.31.1", + "lightningcss-linux-arm64-musl": "1.31.1", + "lightningcss-linux-x64-gnu": "1.31.1", + "lightningcss-linux-x64-musl": "1.31.1", + "lightningcss-win32-arm64-msvc": "1.31.1", + "lightningcss-win32-x64-msvc": "1.31.1" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", + "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", + "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", + "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", + "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", + "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", + "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", + "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", + "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", + "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", + "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", + "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tailwindcss": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", + "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..7d24e87 --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "@tailwindcss/cli": "^4.2.1", + "tailwindcss": "^4.2.1" + } +} diff --git a/phoenixd.justfile b/phoenixd.justfile new file mode 100644 index 0000000..10b7036 --- /dev/null +++ b/phoenixd.justfile @@ -0,0 +1,156 @@ +# phoenixd Docker management and API commands + +compose := "docker compose -f docker-compose.phoenixd.yml" +vault := "phoenixd" + +# Start phoenixd +up: + {{compose}} up -d + @echo "phoenixd starting... run 'just -f phoenixd.justfile backup-to-1p' after first start" + +# Stop phoenixd +down: + {{compose}} down + +# Stop and destroy volume (CAUTION: deletes seed + channels) +nuke: + {{compose}} down -v + +# Show logs +logs *args: + {{compose}} logs {{args}} + +# Follow logs +follow: + {{compose}} logs -f + +# Create dedicated 1Password vault (run once, idempotent) +setup-1p: + op vault get {{vault}} >/dev/null 2>&1 || op vault create {{vault}} + @echo "1Password vault '{{vault}}' ready" + +# Backup seed + password to 1Password (idempotent — updates if item exists) +backup-to-1p: + #!/usr/bin/env bash + set -euo pipefail + SEED=$(docker exec phoenixd cat /phoenix/.phoenix/seed.dat) + PW=$(docker exec phoenixd cat /phoenix/.phoenix/phoenix.conf | grep http-password | cut -d= -f2) + NODE_ID=$(docker exec phoenixd /phoenix/phoenix-cli getinfo | jq -r .nodeId) + if op item get "phoenixd mainnet" --vault="{{vault}}" >/dev/null 2>&1; then + op item edit "phoenixd mainnet" --vault="{{vault}}" \ + "seed=${SEED}" \ + "http-password=${PW}" \ + "node-id=${NODE_ID}" + echo "Updated existing item in 1Password vault '{{vault}}'" + else + op item create \ + --category="Secure Note" \ + --vault="{{vault}}" \ + --title="phoenixd mainnet" \ + "seed=${SEED}" \ + "http-password=${PW}" \ + "node-id=${NODE_ID}" + echo "Created new item in 1Password vault '{{vault}}'" + fi + +# Show the seed from 1Password +seed: + @op item get "phoenixd mainnet" --vault={{vault}} --fields seed --reveal + +# Verify running node ID matches 1Password backup +verify-node: + #!/usr/bin/env bash + set -euo pipefail + LIVE=$(docker exec phoenixd /phoenix/phoenix-cli getinfo | jq -r .nodeId) + STORED=$(op item get "phoenixd mainnet" --vault={{vault}} --fields node-id --reveal) + if [ "$LIVE" = "$STORED" ]; then + echo "✅ Node ID matches: $LIVE" + else + echo "❌ MISMATCH" + echo " Running: $LIVE" + echo " 1Password: $STORED" + exit 1 + fi + +# --- API commands via phoenix-cli (password auto-read from config) --- + +# Shorthand for docker exec +cli := "docker exec phoenixd /phoenix/phoenix-cli" + +# Get node info +info: + {{cli}} getinfo + +# Get balance +balance: + {{cli}} getbalance + +# List channels +channels: + {{cli}} listchannels + +# Estimate liquidity fees for an amount +estimate-fees amount: + {{cli}} estimateliquidityfees --amountSat={{amount}} + +# Create invoice: just -f phoenixd.justfile invoice 1000 "test payment" +invoice amount desc="magic-carpet": + {{cli}} createinvoice --amountSat={{amount}} --desc="{{desc}}" + +# Create invoice and display as QR code: just -f phoenixd.justfile qr-invoice 3000 "initial funding" +qr-invoice amount desc="magic-carpet": + #!/usr/bin/env bash + set -euo pipefail + BOLT11=$({{cli}} createinvoice --amountSat={{amount}} --desc="{{desc}}" | jq -r .serialized) + echo "$BOLT11" + echo "$BOLT11" | qrencode -t ANSIUTF8 + +# Create a reusable offer (amount optional) +offer desc="magic-carpet" amount="": + #!/usr/bin/env bash + ARGS="--desc={{desc}}" + [ -n "{{amount}}" ] && ARGS="$ARGS --amountSat={{amount}}" + {{cli}} createoffer $ARGS + +# Get default offer (reusable invoice) +get-offer: + {{cli}} getoffer + +# Get Lightning address (requires a channel) +ln-address: + {{cli}} getlnaddress + +# Pay a BOLT11 invoice +pay bolt11: + {{cli}} payinvoice --invoice={{bolt11}} + +# Scan a QR code via webcam and pay the invoice +scan-pay: + #!/usr/bin/env bash + set -euo pipefail + BOLT11=$(python3 scripts/scan_qr.py) + echo "" + echo "Invoice: $BOLT11" + read -p "Pay this invoice? [y/N] " confirm + [[ "$confirm" =~ ^[Yy]$ ]] || { echo "Cancelled."; exit 0; } + {{cli}} payinvoice --invoice="$BOLT11" + +# Pay a Lightning offer +pay-offer offer amount: + {{cli}} payoffer --offer={{offer}} --amountSat={{amount}} + +# List incoming payments +incoming: + {{cli}} listincomingpayments + +# Get incoming payment by hash +incoming-payment hash: + {{cli}} getincomingpayment --hash={{hash}} + +# List outgoing payments +outgoing: + {{cli}} listoutgoingpayments + +# Get outgoing payment by UUID or hash +outgoing-payment id: + {{cli}} getoutgoingpayment --uuid={{id}} diff --git a/scripts/scan_qr.py b/scripts/scan_qr.py new file mode 100755 index 0000000..e14b93b --- /dev/null +++ b/scripts/scan_qr.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +"""Scan a Lightning invoice QR code via webcam and print the BOLT11 string.""" +import sys +import cv2 +from pyzbar.pyzbar import decode + +cap = cv2.VideoCapture(0) +if not cap.isOpened(): + print("Error: cannot open webcam", file=sys.stderr) + sys.exit(1) + +print("Point webcam at a Lightning invoice QR code. Press 'q' to quit.", file=sys.stderr) + +while True: + ret, frame = cap.read() + if not ret: + break + for obj in decode(frame): + data = obj.data.decode("utf-8").strip() + # Strip lightning: URI scheme if present + if data.lower().startswith("lightning:"): + data = data[len("lightning:"):] + if data.lower().startswith("lnbc"): + cap.release() + cv2.destroyAllWindows() + print(data) + sys.exit(0) + cv2.imshow("Scan QR - press q to quit", frame) + if cv2.waitKey(1) & 0xFF == ord("q"): + break + +cap.release() +cv2.destroyAllWindows() +print("No invoice scanned", file=sys.stderr) +sys.exit(1)