diff --git a/.github/workflows/tools-ci.yml b/.github/workflows/tools-ci.yml index 5d21de78..c9e9dd6d 100644 --- a/.github/workflows/tools-ci.yml +++ b/.github/workflows/tools-ci.yml @@ -5,7 +5,8 @@ on: branches: - main paths: - - tools/** + - tools/blueprint-client/** + - tools/dctl/** concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.gitignore b/.gitignore index 6d5a3210..c7fefa6e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,8 +10,7 @@ tmp __debug_* node_modules -/services/core/blueprint/web-client/target/release/* -/services/core/blueprint/web-client/target/wasm32-unknown-unknown/* +target/ main dist @@ -19,4 +18,5 @@ go.work go.work.sum # ignore user specific vscode settings -.vscode/settings.json \ No newline at end of file +.vscode/settings.json +assets/* \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 7af157b2..e9dd4dfd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,6 +12,7 @@ "program": "tools/blueprint-client/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "CMD": "make_cluster" } @@ -24,6 +25,7 @@ "program": "tools/blueprint-client/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "CMD": "cluster_stats" } @@ -36,6 +38,7 @@ "program": "tools/blueprint-client/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "CMD": "set_value" } @@ -48,6 +51,7 @@ "program": "tools/blueprint-client/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "CMD": "get_value" } @@ -60,6 +64,7 @@ "program": "tools/blueprint-client/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "CMD": "load_test_key_value" } @@ -72,6 +77,7 @@ "program": "tools/blueprint-client/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "CMD": "list_all" } @@ -84,6 +90,7 @@ "program": "tools/blueprint-client/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "CMD": "init_process" } @@ -96,6 +103,7 @@ "program": "tools/blueprint-client/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "CMD": "synchronize" } @@ -108,6 +116,7 @@ "program": "services/core/blueprint/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "DRAFT_CONFIG": "tests/blueprint/node_1.yaml" }, @@ -120,6 +129,7 @@ "program": "services/core/blueprint/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "DRAFT_CONFIG": "tests/blueprint/node_2.yaml" }, @@ -132,6 +142,7 @@ "program": "services/core/blueprint/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "DRAFT_CONFIG": "tests/blueprint/node_3.yaml" }, @@ -144,10 +155,63 @@ "program": "services/core/catalyst/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "DRAFT_CONFIG": "services/core/catalyst/config.yaml" }, }, + { + "name": "Producer", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "services/examples/producer/main.go", + "cwd": "${workspaceFolder}", + "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", + "env": { + "DRAFT_CONFIG": "services/examples/producer/config.yaml" + }, + }, + { + "name": "Consumer", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "services/examples/consumer/main.go", + "cwd": "${workspaceFolder}", + "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", + "env": { + "DRAFT_CONFIG": "services/examples/consumer/config.yaml" + }, + }, + { + "name": "Producer 2 (echo)", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "services/examples/producer2/main.go", + "cwd": "${workspaceFolder}", + "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", + "env": { + "DRAFT_CONFIG": "services/examples/producer2/config.yaml" + }, + }, + { + "name": "Consumer 2 (echo)", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "services/examples/consumer2/main.go", + "cwd": "${workspaceFolder}", + "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", + "env": { + "DRAFT_CONFIG": "services/examples/consumer2/config.yaml" + }, + }, { "name": "dctl - Produce", "type": "go", @@ -156,6 +220,7 @@ "program": "tools/dctl/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "args": ["broker", "produce"], }, { @@ -166,6 +231,7 @@ "program": "tools/dctl/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "args": ["broker", "consume"], }, { @@ -176,6 +242,7 @@ "program": "services/core/fuse/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "DRAFT_CONFIG": "services/core/fuse/config.yaml" }, @@ -188,6 +255,7 @@ "program": "services/examples/file_host/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "DRAFT_CONFIG": "services/examples/file_host/config.yaml" }, @@ -200,10 +268,37 @@ "program": "services/examples/echo/main.go", "cwd": "${workspaceFolder}", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "env": { "DRAFT_CONFIG": "services/examples/echo/config.yaml" }, }, + { + "name": "Auth", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "services/core/auth/main.go", + "cwd": "${workspaceFolder}", + "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", + "env": { + "DRAFT_CONFIG": "services/core/auth/config.yaml" + }, + }, + { + "name": "Auth Example", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "services/examples/auth/main.go", + "cwd": "${workspaceFolder}", + "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", + "env": { + "DRAFT_CONFIG": "services/examples/auth/config.yaml" + }, + }, { "name": "Plugins (test)", "type": "go", @@ -212,10 +307,21 @@ "program": "tests/plugins/main.go", "cwd": "${workspaceFolder}/tests/plugins", "debugAdapter": "dlv-dap", + "gcflags": "all=-N -l", "args": [ "run" ] }, + { + "name": "Docs: Website", + "type": "node", + "request": "launch", + "runtimeExecutable": "hugo", + "runtimeArgs": ["server"], + "cwd": "${workspaceFolder}/docs/website", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + }, ], "compounds": [ { @@ -226,6 +332,22 @@ "Blueprint_3" ], "stopAll": true, + }, + { + "name": "Echo Services", + "configurations": [ + "Producer 2 (echo)", + "Consumer 2 (echo)" + ], + "stopAll": true, + }, + { + "name": "Auth (core + example)", + "configurations": [ + "Auth", + "Auth Example" + ], + "stopAll": true, } ] -} \ No newline at end of file +} diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..671de3c2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,6408 @@ +# This file is automatically @generated by Cargo. +# 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 = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ashpd" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093" +dependencies = [ + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.8.5", + "serde", + "serde_repr", + "tokio", + "url", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "itoa 1.0.18", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 0.1.2", + "tower 0.4.13", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[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 = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.4", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "blueprint-pwa" +version = "0.1.0" +dependencies = [ + "dioxus", + "dioxus-logger", + "dotenv", + "draft-api", + "once_cell", + "prost 0.12.6", + "reqwest", + "serde", + "serde_json", + "web-sys", +] + +[[package]] +name = "bumpalo" +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" + +[[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 = "cc" +version = "1.2.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cesu8" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation 0.1.2", + "core-foundation 0.9.4", + "core-graphics 0.23.2", + "foreign-types 0.5.0", + "libc", + "objc", +] + +[[package]] +name = "cocoa" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad36507aeb7e16159dfe68db81ccc27571c3ccd4b76fb2fb72fc59e7a4b1b64c" +dependencies = [ + "bitflags 2.11.0", + "block", + "cocoa-foundation 0.2.1", + "core-foundation 0.10.1", + "core-graphics 0.24.0", + "foreign-types 0.5.0", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81411967c50ee9a1fc11365f8c585f863a22a9697c89239c452292c40ba79b0d" +dependencies = [ + "bitflags 2.11.0", + "block", + "core-foundation 0.10.1", + "core-graphics-types 0.2.0", + "objc", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "const-serialize" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08259976d62c715c4826cb4a3d64a3a9e5c5f68f964ff6087319857f569f93a6" +dependencies = [ + "const-serialize-macro", + "serde", +] + +[[package]] +name = "const-serialize-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04382d0d9df7434af6b1b49ea1a026ef39df1b0738b1cc373368cf175354f6eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "convert_case" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types 0.5.0", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", + "core-graphics-types 0.2.0", + "foreign-types 0.5.0", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa 0.4.8", + "matches", + "phf 0.8.0", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" + +[[package]] +name = "derive_more" +version = "0.99.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +dependencies = [ + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dioxus" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a247114500f1a78e87022defa8173de847accfada8e8809dfae23a118a580c" +dependencies = [ + "dioxus-cli-config", + "dioxus-config-macro", + "dioxus-core", + "dioxus-core-macro", + "dioxus-desktop", + "dioxus-devtools", + "dioxus-document", + "dioxus-fullstack", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-logger", + "dioxus-mobile", + "dioxus-router", + "dioxus-signals", + "dioxus-web", + "manganis", + "warnings", +] + +[[package]] +name = "dioxus-cli-config" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd16948f1ffdb068dd9a64812158073a4250e2af4e98ea31fdac0312e6bce86" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "dioxus-config-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75cbf582fbb1c32d34a1042ea675469065574109c95154468710a4d73ee98b49" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "dioxus-core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c03f451a119e47433c16e2d8eb5b15bf7d6e6734eb1a4c47574e6711dadff8d" +dependencies = [ + "const_format", + "dioxus-core-types", + "futures-channel", + "futures-util", + "generational-box", + "longest-increasing-subsequence", + "rustc-hash", + "rustversion", + "serde", + "slab", + "slotmap", + "tracing", + "warnings", +] + +[[package]] +name = "dioxus-core-macro" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "105c954caaaedf8cd10f3d1ba576b01e18aa8d33ad435182125eefe488cf0064" +dependencies = [ + "convert_case 0.6.0", + "dioxus-rsx", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-core-types" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91a82fccfa48574eb7aa183e297769540904694844598433a9eb55896ad9f93b" +dependencies = [ + "once_cell", +] + +[[package]] +name = "dioxus-desktop" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b0cca3e7a10a4a3df37ea52c4cc7a53e5c9233489e03ee3f2829471fc3099a" +dependencies = [ + "async-trait", + "base64 0.22.1", + "cocoa 0.25.0", + "core-foundation 0.9.4", + "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", + "generational-box", + "global-hotkey", + "infer", + "jni", + "lazy-js-bundle", + "muda 0.11.5", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "objc_id", + "once_cell", + "rfd", + "rustc-hash", + "serde", + "serde_json", + "signal-hook", + "slab", + "tao", + "thiserror 1.0.69", + "tokio", + "tracing", + "tray-icon", + "urlencoding", + "webbrowser", + "wry", +] + +[[package]] +name = "dioxus-devtools" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a7300f1e8181218187b03502044157eef04e0a25b518117c5ef9ae1096880" +dependencies = [ + "dioxus-core", + "dioxus-devtools-types", + "dioxus-signals", + "serde", + "serde_json", + "tracing", + "tungstenite", + "warnings", +] + +[[package]] +name = "dioxus-devtools-types" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f62434973c0c9c5a3bc42e9cd5e7070401c2062a437fb5528f318c3e42ebf4ff" +dependencies = [ + "dioxus-core", + "serde", +] + +[[package]] +name = "dioxus-document" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "802a2014d1662b6615eec0a275745822ee4fc66aacd9d0f2fb33d6c8da79b8f2" +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.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe99b48a1348eec385b5c4bd3e80fd863b0d3b47257d34e2ddc58754dec5d128" +dependencies = [ + "base64 0.22.1", + "bytes", + "ciborium", + "dioxus-desktop", + "dioxus-devtools", + "dioxus-history", + "dioxus-lib", + "dioxus-mobile", + "dioxus-web", + "dioxus_server_macro", + "futures-channel", + "futures-util", + "generational-box", + "once_cell", + "serde", + "server_fn", + "tracing", + "web-sys", +] + +[[package]] +name = "dioxus-grpc" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d73fd2ab81456633ed32e836127e882cba563b97498f9342063b589329943ce9" +dependencies = [ + "convert_case 0.8.0", + "tonic-build 0.13.1", +] + +[[package]] +name = "dioxus-history" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ae4e22616c698f35b60727313134955d885de2d32e83689258e586ebc9b7909" +dependencies = [ + "dioxus-core", + "tracing", +] + +[[package]] +name = "dioxus-hooks" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "948e2b3f20d9d4b2c300aaa60281b1755f3298684448920b27106da5841896d0" +dependencies = [ + "dioxus-core", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "rustversion", + "slab", + "tracing", + "warnings", +] + +[[package]] +name = "dioxus-html" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c9a40e6fee20ce7990095492dedb6a753eebe05e67d28271a249de74dc796d" +dependencies = [ + "async-trait", + "dioxus-core", + "dioxus-core-macro", + "dioxus-core-types", + "dioxus-hooks", + "dioxus-html-internal-macro", + "enumset", + "euclid", + "futures-channel", + "generational-box", + "keyboard-types", + "lazy-js-bundle", + "rustversion", + "serde", + "serde_json", + "serde_repr", + "tracing", +] + +[[package]] +name = "dioxus-html-internal-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43ba87b53688a2c9f619ecdf4b3b955bc1f08bd0570a80a0d626c405f6d14a76" +dependencies = [ + "convert_case 0.6.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-interpreter-js" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330707b10ca75cb0eb05f9e5f8d80217cd0d7e62116a8277ae363c1a09b57a22" +dependencies = [ + "dioxus-core", + "dioxus-core-types", + "dioxus-html", + "js-sys", + "lazy-js-bundle", + "rustc-hash", + "serde", + "sledgehammer_bindgen", + "sledgehammer_utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "dioxus-lib" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5405b71aa9b8b0c3e0d22728f12f34217ca5277792bd315878cc6ecab7301b72" +dependencies = [ + "dioxus-config-macro", + "dioxus-core", + "dioxus-core-macro", + "dioxus-document", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-rsx", + "dioxus-signals", + "warnings", +] + +[[package]] +name = "dioxus-logger" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545961e752f6c8bf59c274951b3c8b18a106db6ad2f9e2035b29e1f2a3e899b1" +dependencies = [ + "console_error_panic_hook", + "dioxus-cli-config", + "tracing", + "tracing-subscriber", + "tracing-wasm", +] + +[[package]] +name = "dioxus-mobile" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1295388909f427758993f32a571e0f8698d6ce0f125fa0e81b8bfdec3fa952" +dependencies = [ + "dioxus-cli-config", + "dioxus-desktop", + "dioxus-lib", + "jni", + "libc", + "once_cell", +] + +[[package]] +name = "dioxus-router" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7266a76fc9e4a91f56499d1d1aecfff7168952b6627a6008b4e9748d6bf863e4" +dependencies = [ + "dioxus-cli-config", + "dioxus-history", + "dioxus-lib", + "dioxus-router-macro", + "rustversion", + "tracing", + "url", + "urlencoding", +] + +[[package]] +name = "dioxus-router-macro" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2743ffb79e9a7d33d779c87d6deea2a6c047d0736012f95d63b909b83f0a6fd2" +dependencies = [ + "proc-macro2", + "quote", + "slab", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-rsx" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb588e05800b5a7eb90b2f40fca5bbd7626e823fb5e1ba21e011de649b45aa1" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-signals" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10e032dbb3a2c0386ec8b8ee59bc20b5aeb67038147c855801237b45b13d72ac" +dependencies = [ + "dioxus-core", + "futures-channel", + "futures-util", + "generational-box", + "once_cell", + "parking_lot", + "rustc-hash", + "tracing", + "warnings", +] + +[[package]] +name = "dioxus-web" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7c12475c3d360058b8afe1b68eb6dfc9cbb7dcd760aed37c5f85c561c83ed1" +dependencies = [ + "async-trait", + "ciborium", + "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", + "js-sys", + "lazy-js-bundle", + "rustc-hash", + "serde", + "serde-wasm-bindgen", + "serde_json", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "dioxus_server_macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "371a5b21989a06b53c5092e977b3f75d0e60a65a4c15a2aa1d07014c3b2dda97" +dependencies = [ + "proc-macro2", + "quote", + "server_fn_macro", + "syn 2.0.117", +] + +[[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 = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", +] + +[[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.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +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 = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "draft-api" +version = "0.1.0" +dependencies = [ + "dioxus-grpc", + "prost 0.12.6", + "prost-build 0.12.6", + "prost-types 0.12.6", + "tonic", + "tonic-build 0.11.0", + "tonic-web", +] + +[[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 = "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 = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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 = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1f" + +[[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 = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[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 = "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 = "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-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[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-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" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe" +dependencies = [ + "gdk", + "gdkx11-sys", + "gio", + "glib", + "libc", + "x11", +] + +[[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.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a673cf4fb0ea6a91aa86c08695756dfe875277a912cdbf33db9a9f62d47ed82b" +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 = "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", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[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", + "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 = "global-hotkey" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b436093d1598b05e3b7fddc097b2bad32763f53a1beb25ab6f9718c6a60acd09" +dependencies = [ + "bitflags 2.11.0", + "cocoa 0.25.0", + "crossbeam-channel", + "keyboard-types", + "objc", + "once_cell", + "thiserror 1.0.69", + "windows-sys 0.52.0", + "x11-dl", +] + +[[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 1.4.0", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror 1.0.69", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[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.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.13.1", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[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 1.4.0", + "indexmap 2.13.1", + "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.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[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 = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.18", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa 1.0.18", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.4.0", +] + +[[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 1.4.0", + "http-body 1.0.1", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + +[[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 = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa 1.0.18", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2 0.4.13", + "http 1.4.0", + "http-body 1.0.1", + "httparse", + "itoa 1.0.18", + "pin-project-lite", + "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 1.4.0", + "hyper 1.9.0", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper 0.14.32", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[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 1.9.0", + "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 1.4.0", + "http-body 1.0.1", + "hyper 1.9.0", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2 0.6.3", + "system-configuration", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +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 = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "infer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6c16b11a665b26aeeb9b1d7f954cdeb034be38dd00adab4f2ae921a8fee804" +dependencies = [ + "cfb", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[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.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[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 = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "js-sys" +version = "0.3.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +dependencies = [ + "cfg-if", + "futures-util", + "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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +dependencies = [ + "cssparser", + "html5ever", + "indexmap 1.9.3", + "matches", + "selectors", +] + +[[package]] +name = "lazy-js-bundle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49596223b9d9d4947a14a25c142a6e7d8ab3f27eb3ade269d238bb8b5c267e2" + +[[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", + "once_cell", +] + +[[package]] +name = "libc" +version = "0.2.184" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[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 = "libredox" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[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 = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[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.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317af44b15e7605b85f04525449a3bb631753040156c9b318e6cba8a3ea4ef73" +dependencies = [ + "const-serialize", + "manganis-core", + "manganis-macro", +] + +[[package]] +name = "manganis-core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c38bee65cc725b2bba23b5dbb290f57c8be8fadbe2043fb7e2ce73022ea06519" +dependencies = [ + "const-serialize", + "dioxus-cli-config", + "dioxus-core-types", + "serde", +] + +[[package]] +name = "manganis-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f4f71310913c40174d9f0cfcbcb127dad0329ecdb3945678a120db22d3d065" +dependencies = [ + "dunce", + "manganis-core", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.61.2", +] + +[[package]] +name = "muda" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c47e7625990fc1af2226ea4f34fb2412b03c12639fcb91868581eb3a6893453" +dependencies = [ + "cocoa 0.25.0", + "crossbeam-channel", + "gtk", + "keyboard-types", + "libxdo", + "objc", + "once_cell", + "png", + "thiserror 1.0.69", + "windows-sys 0.52.0", +] + +[[package]] +name = "muda" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdae9c00e61cc0579bcac625e8ad22104c60548a025bfc972dc83868a28e1484" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "libxdo", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "once_cell", + "png", + "thiserror 1.0.69", + "windows-sys 0.59.0", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "native-tls" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.11.0", + "jni-sys 0.3.1", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle 0.6.2", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", + "objc_exception", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.0", + "dispatch2", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.11.0", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.11.0", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "openssl" +version = "0.10.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" +dependencies = [ + "bitflags 2.11.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "openssl-sys" +version = "0.9.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[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" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset 0.4.2", + "indexmap 2.13.1", +] + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset 0.5.7", + "indexmap 2.13.1", +] + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_macros", + "phf_shared 0.8.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[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.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.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 = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +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 = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +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 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.10+spec-1.1.0", +] + +[[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 = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "version_check", +] + +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive 0.12.6", +] + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive 0.13.5", +] + +[[package]] +name = "prost-build" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +dependencies = [ + "bytes", + "heck 0.5.0", + "itertools 0.12.1", + "log", + "multimap", + "once_cell", + "petgraph 0.6.5", + "prettyplease", + "prost 0.12.6", + "prost-types 0.12.6", + "regex", + "syn 2.0.117", + "tempfile", +] + +[[package]] +name = "prost-build" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +dependencies = [ + "heck 0.5.0", + "itertools 0.14.0", + "log", + "multimap", + "once_cell", + "petgraph 0.7.1", + "prettyplease", + "prost 0.13.5", + "prost-types 0.13.5", + "regex", + "syn 2.0.117", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost 0.12.6", +] + +[[package]] +name = "prost-types" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost 0.13.5", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[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 2.11.0", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 2.0.18", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.13", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.9.0", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "js-sys", + "log", + "mime", + "mime_guess", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.2", + "tokio", + "tokio-native-tls", + "tokio-util", + "tower 0.5.3", + "tower-http 0.6.8", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "rfd" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a73a7337fc24366edfca76ec521f51877b114e42dab584008209cca6719251" +dependencies = [ + "ashpd", + "block", + "dispatch", + "js-sys", + "log", + "objc", + "objc-foundation", + "objc_id", + "pollster", + "raw-window-handle 0.6.2", + "urlencoding", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[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 2.11.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more", + "fxhash", + "log", + "matches", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", + "thin-slice", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa 1.0.18", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_qs" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0431a35568651e363364210c91983c1da5eb29404d9f0928b67d4ebcfa7d330c" +dependencies = [ + "percent-encoding", + "serde", + "thiserror 1.0.69", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.18", + "ryu", + "serde", +] + +[[package]] +name = "server_fn" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fae7a3038a32e5a34ba32c6c45eb4852f8affaf8b794ebfcd4b1099e2d62ebe" +dependencies = [ + "bytes", + "const_format", + "dashmap", + "futures", + "gloo-net", + "http 1.4.0", + "js-sys", + "once_cell", + "reqwest", + "send_wrapper", + "serde", + "serde_json", + "serde_qs", + "server_fn_macro_default", + "thiserror 1.0.69", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "xxhash-rust", +] + +[[package]] +name = "server_fn_macro" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaaf648c6967aef78177c0610478abb5a3455811f401f3c62d10ae9bd3901a1" +dependencies = [ + "const_format", + "convert_case 0.6.0", + "proc-macro2", + "quote", + "syn 2.0.117", + "xxhash-rust", +] + +[[package]] +name = "server_fn_macro_default" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2aa8119b558a17992e0ac1fd07f080099564f24532858811ce04f742542440" +dependencies = [ + "server_fn_macro", + "syn 2.0.117", +] + +[[package]] +name = "servo_arc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +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" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[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", +] + +[[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.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.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 = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.11.3", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "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.30.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da" +dependencies = [ + "bitflags 2.11.0", + "cocoa 0.26.1", + "core-foundation 0.10.1", + "core-graphics 0.24.0", + "crossbeam-channel", + "dispatch", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "instant", + "jni", + "lazy_static", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "scopeguard", + "tao-macros", + "unicode-segmentation", + "url", + "windows", + "windows-core", + "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.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix", + "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 = "thin-slice" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.6.3", + "tokio-macros", + "tracing", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bd86198d9ee903fedd2f9a2e72014287c0d9167e4ae43b5853007205dda1b76" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "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", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "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 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.13.1", + "toml_datetime 0.6.3", + "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 2.13.1", + "serde", + "serde_spanned", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.25.10+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" +dependencies = [ + "indexmap 2.13.1", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.1", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.1", +] + +[[package]] +name = "tonic" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.21.7", + "bytes", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost 0.12.6", + "tokio", + "tokio-stream", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4ef6dd70a610078cb4e338a0f79d06bc759ff1b22d2120c2ff02ae264ba9c2" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build 0.12.6", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tonic-build" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac6f67be712d12f0b41328db3137e0d0757645d8904b4cb7d51cd9c2279e847" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build 0.13.5", + "prost-types 0.13.5", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tonic-web" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc3b0e1cedbf19fdfb78ef3d672cb9928e0a91a9cb4629cc0c916e8cff8aaaa1" +dependencies = [ + "base64 0.21.7", + "bytes", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "pin-project", + "tokio-stream", + "tonic", + "tower-http 0.4.4", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand 0.8.5", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 1.0.2", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +dependencies = [ + "bitflags 2.11.0", + "bytes", + "futures-core", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "http-range-header", + "pin-project-lite", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags 2.11.0", + "bytes", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower 0.5.3", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[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.19.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadd75f5002e2513eaa19b2365f533090cc3e93abd38788452d9ea85cff7b48a" +dependencies = [ + "crossbeam-channel", + "dirs", + "libappindicator", + "muda 0.15.3", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "once_cell", + "png", + "thiserror 2.0.18", + "windows-sys 0.59.0", +] + +[[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.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 1.4.0", + "httparse", + "log", + "rand 0.8.5", + "sha1", + "thiserror 1.0.69", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", + "serde_derive", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "vcpkg" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.1", + "wasm-encoder", + "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 = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap 2.13.1", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webbrowser" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" +dependencies = [ + "core-foundation 0.9.4", + "home", + "jni", + "log", + "ndk-context", + "objc", + "raw-window-handle 0.5.2", + "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 = "webview2-com" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61ff3d9d0ee4efcb461b14eb3acfda2702d10dc329f339303fc3e57215ae2c" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows", + "windows-core", + "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.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886" +dependencies = [ + "thiserror 1.0.69", + "windows", + "windows-core", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +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.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result 0.2.0", + "windows-strings 0.1.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[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 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +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.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.13.1", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap 2.13.1", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.1", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "wry" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac0099a336829fbf54c26b5f620c68980ebbe37196772aeaf6118df4931b5cb0" +dependencies = [ + "base64 0.22.1", + "block", + "cocoa 0.26.1", + "core-graphics 0.24.0", + "crossbeam-channel", + "dpi", + "dunce", + "gdkx11", + "gtk", + "html5ever", + "http 1.4.0", + "javascriptcore-rs", + "jni", + "kuchikiki", + "libc", + "ndk", + "objc", + "objc_id", + "once_cell", + "percent-encoding", + "raw-window-handle 0.6.2", + "sha2", + "soup3", + "tao-macros", + "thiserror 1.0.69", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows", + "windows-core", + "windows-version", + "x11-dl", +] + +[[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 = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zbus" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +dependencies = [ + "async-broadcast", + "async-process", + "async-recursion", + "async-trait", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tokio", + "tracing", + "uds_windows", + "windows-sys 0.52.0", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zvariant" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "url", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] diff --git a/README.md b/README.md index 904cceb7..8e270c82 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,67 @@ The Draft Chassis provides all the necessary pieces to create Draft processes (s `dctl` is a command line tool that provides a set of commands to simplify working with a Draft system. It performs tasks like building protobufs, running services locally, and managing local infrastructure. +### Core Service RPC Interactions + +The diagram below shows the RPC interfaces exposed by each core service and how they call one another at runtime. All services embed the Chassis, which handles registration and route advertisement on their behalf. + +```mermaid +graph TD + subgraph Blueprint["Blueprint — Registry & Consensus"] + SD["ServiceDiscoveryService + ────────────────────── + Initialize() + Synchronize() ⟵ bidi stream + Finalize() + ReportHealth() + Query()"] + + KV["KeyValueService + ────────────────────── + Set() + Get() + Delete() + List()"] + end + + subgraph Fuse["Fuse — Router & Ingress"] + NET["NetworkingService + ────────────────────── + AddRoute() + ListRoutes() + DeleteRoute()"] + + XDS["xDS Services (Envoy control plane) + ────────────────────── + AggregatedDiscoveryService + EndpointDiscoveryService + ClusterDiscoveryService + RouteDiscoveryService + ListenerDiscoveryService"] + end + + subgraph Catalyst["Catalyst — Message Broker"] + PROD["ProducerService + ────────────────────── + Produce() ⟵ bidi stream"] + + CONS["ConsumerService + ────────────────────── + Consume() ⟵ server stream"] + end + + Chassis["Chassis + (embedded by all services)"] + + Chassis -->|"Initialize()\nSynchronize()"| SD + Chassis -->|"Get() — resolve Fuse address"| KV + Chassis -->|"AddRoute() — register service route"| NET + + Fuse -->|"Set() — persist routes & fuse address\nList() — sync route cache"| KV +``` + +**Startup order**: Blueprint → Catalyst → Fuse → application services. All services depend on Blueprint being available first, and all services register their routes with Fuse before accepting traffic. + ## Project Structure diff --git a/api/Cargo.lock b/api/Cargo.lock new file mode 100644 index 00000000..30d95ffc --- /dev/null +++ b/api/Cargo.lock @@ -0,0 +1,6913 @@ +# This file is automatically @generated by Cargo. +# 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 = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "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 = "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-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.18", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375082f007bd67184fb9c0374614b29f9aaa604ec301635f72338bb65386a53d" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "axum" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +dependencies = [ + "axum-core", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "multer", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[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", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[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 = "bitstream-io" +version = "4.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" +dependencies = [ + "no_std_io2", +] + +[[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 = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "built" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[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 = "cc" +version = "1.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "charset" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f927b07c74ba84c7e5fe4db2baeb3e996ab2688992e39ac68ce3220a677c7e" +dependencies = [ + "base64", + "encoding_rs", +] + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "cocoa" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad36507aeb7e16159dfe68db81ccc27571c3ccd4b76fb2fb72fc59e7a4b1b64c" +dependencies = [ + "bitflags 2.11.0", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics 0.24.0", + "foreign-types 0.5.0", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81411967c50ee9a1fc11365f8c585f863a22a9697c89239c452292c40ba79b0d" +dependencies = [ + "bitflags 2.11.0", + "block", + "core-foundation", + "core-graphics-types", + "objc", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "const-serialize" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad7154afa56de2f290e3c82c2c6dc4f5b282b6870903f56ef3509aba95866edc" +dependencies = [ + "const-serialize-macro 0.7.2", +] + +[[package]] +name = "const-serialize" +version = "0.8.0-alpha.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e42cd5aabba86f128b3763da1fec1491c0f728ce99245062cd49b6f9e6d235b" +dependencies = [ + "const-serialize 0.7.2", + "const-serialize-macro 0.8.0-alpha.0", + "serde", +] + +[[package]] +name = "const-serialize-macro" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f160aad86b4343e8d4e261fee9965c3005b2fd6bc117d172ab65948779e4acf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "const-serialize-macro" +version = "0.8.0-alpha.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42571ed01eb46d2e1adcf99c8ca576f081e46f2623d13500eba70d1d99a4c439" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "const-str" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0664d2867b4a32697dfe655557f5c3b187e9b605b38612a748e5ec99811d160" + +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "content_disposition" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc14a88e1463ddd193906285abe5c360c7e8564e05ccc5d501755f7fbc9ca9c" +dependencies = [ + "charset", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "convert_case" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "cookie" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "cookie_store" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" +dependencies = [ + "cookie", + "document-features", + "idna", + "log", + "publicsuffix", + "serde", + "serde_derive", + "serde_json", + "time", + "url", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.11.0", + "core-foundation", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" +dependencies = [ + "bitflags 2.11.0", + "core-foundation", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.11.0", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.29.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "matches", + "phf 0.10.1", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "data-encoding" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_more" +version = "0.99.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +dependencies = [ + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case 0.10.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dioxus" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b5fd24c3d394e5a8cfc15b8319da5f853c9d27471a9f46ace0653761499740" +dependencies = [ + "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-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-logger", + "dioxus-signals", + "dioxus-stores", + "dioxus-web", + "manganis", + "subsecond", + "warnings", +] + +[[package]] +name = "dioxus-asset-resolver" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8b546050ecfc7fcd310be344b2f3a2a79f21554c5a9e8df28e7a07e9b36009b" +dependencies = [ + "dioxus-cli-config", + "http", + "infer", + "jni 0.21.1", + "js-sys", + "ndk", + "ndk-context", + "ndk-sys", + "percent-encoding", + "thiserror 2.0.18", + "tokio", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "dioxus-cli-config" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ad73f0ff638cd27466d389cd57f0975f909b66130dc1c25d5212d4041e5352" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "dioxus-config-macro" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e004bc8b958031117d373db2b5e0ab9d7e763751de129dd36f00ef7e318333cd" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "dioxus-config-macros" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808a9994a9a2623e6b6890b6cc68def24bd669177ec4713684447fb46418c256" + +[[package]] +name = "dioxus-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "247ed8d679a13232641f1c84ba22246623fae01320b4c22db225c0b4f2fa7398" +dependencies = [ + "anyhow", + "const_format", + "dioxus-core-types", + "futures-channel", + "futures-util", + "generational-box", + "longest-increasing-subsequence", + "rustc-hash 2.1.2", + "rustversion", + "serde", + "slab", + "slotmap", + "subsecond", + "tracing", +] + +[[package]] +name = "dioxus-core-macro" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75fbe64029b90144041f8521300c7b3508e6c48caea3244de2ff5d1ade15390c" +dependencies = [ + "convert_case 0.8.0", + "dioxus-rsx", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-core-types" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbfea5c8946e0745b254b5c33c515d81b3ba638f33c2a532ed06730392394d4d" + +[[package]] +name = "dioxus-desktop" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00c82f695d1214e41482badc0f8d0057b256c077a2827ade637f925f4097f1f6" +dependencies = [ + "anyhow", + "async-trait", + "base64", + "bytes", + "cocoa", + "core-foundation", + "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", + "generational-box", + "global-hotkey", + "image", + "infer", + "jni 0.21.1", + "lazy-js-bundle", + "libc", + "muda", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "objc_id", + "percent-encoding", + "rand 0.9.4", + "rfd", + "rustc-hash 2.1.2", + "serde", + "serde_json", + "signal-hook", + "slab", + "subtle", + "tao", + "thiserror 2.0.18", + "tokio", + "tracing", + "tray-icon", + "tungstenite 0.28.0", + "webbrowser", + "wry", +] + +[[package]] +name = "dioxus-devtools" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d30370fa78266aed3f3d9119dea2de9e92a0348941dbfa777f7a669f2ea375" +dependencies = [ + "dioxus-cli-config", + "dioxus-core", + "dioxus-devtools-types", + "dioxus-signals", + "serde", + "serde_json", + "subsecond", + "thiserror 2.0.18", + "tracing", + "tungstenite 0.28.0", +] + +[[package]] +name = "dioxus-devtools-types" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3907a2b61cf56039f047da6a37317a03d9e15411753bc40e5e34a27e405ac320" +dependencies = [ + "dioxus-core", + "serde", + "subsecond-types", +] + +[[package]] +name = "dioxus-document" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b75a1809af7c13546ae4487c8b02ab80cc4d059e7db5a5d090374ceaa71d5b" +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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ee56dd65fbf1222fa6a2749c3f821df28facf1832854b43d480b547a096f6d" +dependencies = [ + "anyhow", + "async-stream", + "async-tungstenite", + "axum", + "axum-core", + "base64", + "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", + "js-sys", + "mime", + "pin-project", + "reqwest", + "rustversion", + "send_wrapper", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "thiserror 2.0.18", + "tokio-util", + "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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40d33a447cb158acdb61787b2ff52dd8a0f9a9f20e95e5c5fe9873f01c2b55b" +dependencies = [ + "anyhow", + "axum-core", + "base64", + "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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c06eb66bce50d5f47b793e6af5fc2e0a511bf2b4fa2423cf86e35023d8f17e6" +dependencies = [ + "const_format", + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", + "xxhash-rust", +] + +[[package]] +name = "dioxus-grpc" +version = "0.1.0" +dependencies = [ + "convert_case 0.8.0", + "tonic-build 0.13.1", +] + +[[package]] +name = "dioxus-history" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1d8024afd482956eadae2c43d0b1e73e584adb724ac09be87f268d52002387b" +dependencies = [ + "dioxus-core", + "tracing", +] + +[[package]] +name = "dioxus-hooks" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233b5e168a7c38c4bf96d0f390221a72a5a28bb31ce2dcf6d2af879dc561ef42" +dependencies = [ + "dioxus-core", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "rustversion", + "slab", + "tracing", +] + +[[package]] +name = "dioxus-html" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4abf4ad27eee650d1ab8ebe13591e8b0ee595fa5a5dd236be13a5b7b3fab678d" +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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "025e107e677f790f4ed648a189e36f51ae014e5341902b97313e4eae626cffa2" +dependencies = [ + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-interpreter-js" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57caa76427d8ec4105ccca44ff8c511055688af732a094b9fe9ef3547d2a11b2" +dependencies = [ + "dioxus-core", + "dioxus-core-types", + "dioxus-html", + "js-sys", + "lazy-js-bundle", + "rustc-hash 2.1.2", + "serde", + "sledgehammer_bindgen", + "sledgehammer_utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "dioxus-logger" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cbbee192b1b12fccb444a5b04d809710cfce4d27b792129fea6c845fae7f329" +dependencies = [ + "dioxus-cli-config", + "tracing", + "tracing-subscriber", + "tracing-wasm", +] + +[[package]] +name = "dioxus-rsx" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37fb07e40e9734946511659668ea3675ed214b60889e7aa7f0a5a85271518475" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "rustversion", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-signals" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5393fd579f42c6547bf47ec0a2dedf2a366cd541d31deedc1059a096e6c35798" +dependencies = [ + "dioxus-core", + "futures-channel", + "futures-util", + "generational-box", + "parking_lot", + "rustc-hash 2.1.2", + "tracing", + "warnings", +] + +[[package]] +name = "dioxus-stores" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c59f52e8194439604dd35f8c540456c22b4a4b076930e424d0289f98ea3cb4" +dependencies = [ + "dioxus-core", + "dioxus-signals", + "dioxus-stores-macro", + "generational-box", +] + +[[package]] +name = "dioxus-stores-macro" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "737600865572cecf60ff934f88252bd4144f4ca189e0e570b7a780e8f0e01a1f" +dependencies = [ + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-web" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176eb0a5ee8251203a816b413a64fdc014b43e53d4245f769b1b0c2035b88ac3" +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.2", + "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 = "draft-api" +version = "0.1.0" +dependencies = [ + "dioxus", + "dioxus-grpc", + "prost 0.14.3", + "prost-types 0.14.3", + "serde", + "tokio", + "tonic", + "tonic-prost", + "tonic-prost-build", + "tonic-web", + "tonic-web-wasm-client", + "tower-http", +] + +[[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 = "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 = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "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 = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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 = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[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 = "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 = "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-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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68d74be1fbe3bba37604bdfd61403f26af9f6324cf325053abd89d60c22e799" +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 = "gif" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" +dependencies = [ + "color_quant", + "weezl", +] + +[[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 = "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.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "headers" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" +dependencies = [ + "base64", + "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 = "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 = "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.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +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 = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png 0.18.1", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", + "serde", + "serde_core", +] + +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +dependencies = [ + "cfb", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "inventory" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" +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.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[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 = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link 0.2.1", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[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.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +dependencies = [ + "cfg-if", + "futures-util", + "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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebbde2c5796719fbd82d6b8ec0be3dacf1f70c2876dee0f2c001632794d6641f" + +[[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 = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + +[[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.184" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" +dependencies = [ + "arbitrary", + "cc", +] + +[[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.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[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 = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e06225f29a781d86afdfafa562de09621f2ace377136ae2ae9ca9e72a29b920" +dependencies = [ + "const-serialize 0.7.2", + "const-serialize 0.8.0-alpha.0", + "jni 0.21.1", + "manganis-core", + "manganis-macro", + "ndk-context", + "objc2", + "thiserror 2.0.18", +] + +[[package]] +name = "manganis-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774ddc382b4fb30f3fdcf2418131cbac5e6111f00e6c7ddf9e598ef3b2b4cd91" +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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "731c83c89d831f341fb46eba0aefdfb3433f77a3f78a8b08d9d88746613a8f8b" +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 = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[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 = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.61.2", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "muda" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9fec5a4e89860383d778d10563a605838f8f0b2f9303868937e5ff32e86177" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "libxdo", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "once_cell", + "png 0.17.16", + "thiserror 2.0.18", + "windows-sys 0.60.2", +] + +[[package]] +name = "multer" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "memchr", + "mime", + "spin", + "version_check", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "native-tls" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.11.0", + "jni-sys 0.3.1", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle 0.6.2", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "no_std_io2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b51ed7824b6e07d354605f4abb3d9d300350701299da96642ee084f5ce631550" +dependencies = [ + "memchr", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", + "objc2-exception-helper", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.0", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.11.0", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-exception-helper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" +dependencies = [ + "cc", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.11.0", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-web-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "openssl" +version = "0.10.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" +dependencies = [ + "bitflags 2.11.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "openssl-sys" +version = "0.9.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", +] + +[[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 = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[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 = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.11.0", + "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 = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +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 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.11+spec-1.1.0", +] + +[[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 = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "version_check", +] + +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive 0.13.5", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive 0.14.3", +] + +[[package]] +name = "prost-build" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +dependencies = [ + "heck 0.5.0", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph 0.7.1", + "prettyplease", + "prost 0.13.5", + "prost-types 0.13.5", + "regex", + "syn 2.0.117", + "tempfile", +] + +[[package]] +name = "prost-build" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" +dependencies = [ + "heck 0.5.0", + "itertools", + "log", + "multimap", + "petgraph 0.8.3", + "prettyplease", + "prost 0.14.3", + "prost-types 0.14.3", + "pulldown-cmark", + "pulldown-cmark-to-cmark", + "regex", + "syn 2.0.117", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost-types" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost 0.13.5", +] + +[[package]] +name = "prost-types" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" +dependencies = [ + "prost 0.14.3", +] + +[[package]] +name = "psl-types" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" + +[[package]] +name = "publicsuffix" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" +dependencies = [ + "idna", + "psl-types", +] + +[[package]] +name = "pulldown-cmark" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" +dependencies = [ + "bitflags 2.11.0", + "memchr", + "unicase", +] + +[[package]] +name = "pulldown-cmark-to-cmark" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" +dependencies = [ + "pulldown-cmark", +] + +[[package]] +name = "pxfm" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.2", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring", + "rustc-hash 2.1.2", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +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 = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.4", + "rand_chacha 0.9.0", + "simd_helpers", + "thiserror 2.0.18", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[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 = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 2.0.18", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64", + "bytes", + "cookie", + "cookie_store", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", + "webpki-roots", +] + +[[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]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[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 2.11.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c2c118cb077cca2822033836dfb1b975355dfb784b5e8da48f7b6c5db74e60e" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.11.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "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.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +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" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[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 = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.11.3", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] + +[[package]] +name = "subsecond" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feae81a4a7ca6d0bcf70c385a43b7dbacbff527f0805cb0a4043ce2c2c559a2c" +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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85256ee192cbdf00473e48e6133863b125dd4f772fddfbc97287ec7a61458c25" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9103edf55f2da3c82aea4c7fab7c4241032bfeea0e71fa557d98e00e7ce7cc20" +dependencies = [ + "bitflags 2.11.0", + "block2", + "core-foundation", + "core-graphics 0.25.0", + "crossbeam-channel", + "dispatch2", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "jni 0.21.1", + "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", + "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.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "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", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime 0.6.3", + "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 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.25.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.1", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.1", +] + +[[package]] +name = "tonic" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" +dependencies = [ + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "socket2", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac6f67be712d12f0b41328db3137e0d0757645d8904b4cb7d51cd9c2279e847" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build 0.13.5", + "prost-types 0.13.5", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tonic-build" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tonic-prost" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" +dependencies = [ + "bytes", + "prost 0.14.3", + "tonic", +] + +[[package]] +name = "tonic-prost-build" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build 0.14.3", + "prost-types 0.14.3", + "quote", + "syn 2.0.117", + "tempfile", + "tonic-build 0.14.5", +] + +[[package]] +name = "tonic-web" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29453d84de05f4f1b573db22e6f9f6c95c189a6089a440c9a098aa9dea009299" +dependencies = [ + "base64", + "bytes", + "http", + "http-body", + "pin-project", + "tokio-stream", + "tonic", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-web-wasm-client" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0469c353de5f665c95f898074b5b004b500c6722214c3249f1dc79c0a2a3f6" +dependencies = [ + "base64", + "byteorder", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "httparse", + "js-sys", + "pin-project", + "thiserror 2.0.18", + "tonic", + "tower-service", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.5.0", + "web-sys", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags 2.11.0", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "once_cell", + "regex-automata", + "sharded-slab", + "thread_local", + "tracing", + "tracing-core", +] + +[[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 0.17.16", + "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.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.4", + "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", + "native-tls", + "rand 0.9.4", + "rustls", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[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" + +[[package]] +name = "uuid" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "vcpkg" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webbrowser" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc95580916af1e68ff6a7be07446fc5db73ebf71cf092de939bbf5f7e189f72" +dependencies = [ + "core-foundation", + "jni 0.22.4", + "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-roots" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +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", + "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", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +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", + "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", +] + +[[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", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core", + "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", + "windows-link 0.1.3", +] + +[[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]] +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]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +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 = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "wry" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2" +dependencies = [ + "base64", + "block2", + "cookie", + "crossbeam-channel", + "dirs", + "dpi", + "dunce", + "gtk", + "html5ever", + "http", + "javascriptcore-rs", + "jni 0.21.1", + "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", + "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 = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] diff --git a/api/Cargo.toml b/api/Cargo.toml new file mode 100644 index 00000000..f96806c1 --- /dev/null +++ b/api/Cargo.toml @@ -0,0 +1,63 @@ +[package] +name = "draft-api" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] + dioxus = { version = "0.7" } + dioxus-grpc = { path = "../tools/dioxus-grpc", default-features = false } + prost = "0.14.3" + serde = { version = "1", features = ["derive"] } + tokio = { version = "1", optional = true, features = ["full"] } + tonic = { version = "0.14", default-features = false, features = ["codegen"] } + tonic-prost = { version = "0.14" } + tonic-web = { version = "0.14.5" } + tonic-web-wasm-client = { version = "0.9.1", optional = true } + tower-http = { version = "0.6", features = ["cors", "trace"], optional = true } + prost-types = "0.14" + +[build-dependencies] + dioxus-grpc = { path = "../tools/dioxus-grpc", features = ["web"] } + tonic-prost-build = { version = "0.14" } + +[features] + default = [] + # Client /server + clnt = [] + srv = [ + "dep:tokio", + "dep:tower-http", + "tonic-prost-build/transport", + "tonic/router", + "tonic/server", + "tonic/transport", + ] + # Platforms + mobile = [ + "dep:tokio", + "dioxus/mobile", + "tonic-prost-build/transport", + "tonic/router", + "tonic/server", + "tonic/transport", + ] + web = ["dep:tonic-web-wasm-client", "dioxus-grpc/web", "dioxus/web"] + + +[[bin]] + name = "helloworld" + path = "src/basic.rs" + + +[profile] + + [profile.wasm-dev] + inherits = "dev" + opt-level = 1 + + [profile.server-dev] + inherits = "dev" + + [profile.android-dev] + inherits = "dev" diff --git a/api/README.md b/api/README.md index 10bbb5e9..437a2f0d 100644 --- a/api/README.md +++ b/api/README.md @@ -1,9 +1,10 @@ # API -To serve as the home for type definitions, rpc service's, model's, validation of messages, and gateway generation. -All of the above are declared in [protocol buffer's]() and compiled using [buf]() inside of a docker container -to reduce protoc compiler, and compiler plugin environment dependencies. -## Generating files for local testing +Home for type definitions, RPC services, models, message validation, and gateway generation. +All definitions are declared in [Protocol Buffers](https://protobuf.dev/) and compiled using +[buf](https://buf.build/) inside a Docker container to reduce environment dependencies. + +## Generating protobuf files ### Using `dctl` @@ -14,16 +15,72 @@ dctl api init dctl api build ``` -Any time you want to regenerate your protos just run `dctl api build` again. +Run `dctl api build` any time you modify a `.proto` file. -## Using locally generated files +## Rust code generation -To use the generated files locally, you will need to add a `replace` to the project's go.mod: +The `draft-api` crate generates Rust gRPC types and Dioxus web hooks directly from the +`.proto` files via `build.rs`. No manual step is needed — generation runs automatically +as part of a normal `cargo build`. -```go.mod -... +### What `build.rs` does -replace github.com/steady-bytes/draft/api => ../../../api +1. Finds every `.proto` file under `core/registry/key_value/v1/`. +2. Runs `tonic_prost_build` to compile gRPC client code and prost message types, writing + them to `src/proto/`. A `src/proto/mod.rs` is then generated by discovering those output + files (tonic-build names them by proto package, e.g. `core.registry.key_value.v1.rs`, + so dots are replaced with underscores for valid Rust module names). +3. Runs `dioxus_grpc::generate_hooks` to generate reactive Dioxus hooks, writing them to + `src/hook/`. Stale `.dx.rs` files are deleted first so removed services don't linger. + A `src/hook/mod.rs` is then generated in the same discovery manner. + +### Generated files + +| File | Contents | +|------|----------| +| `src/proto/core.registry.key_value.v1.rs` | Prost message types (`SetRequest`, `GetRequest`, `ListRequest`, `Value`, …) and the `KeyValueServiceClient` gRPC client | +| `src/proto/mod.rs` | Auto-generated module declarations (do not edit) | +| `src/hook/core.registry.key_value.v1.dx.rs` | Dioxus hooks: `use_key_value_service_service()` and typed `set`/`get`/`list`/`delete` methods backed by `use_resource` | +| `src/hook/mod.rs` | Auto-generated module declarations (do not edit) | + +### Adding a new service + +1. Add or modify `.proto` files under `core/registry//v1/`. +2. Run `cargo build` — new types and hooks are generated automatically. + +## Running the example application + +`src/basic.rs` is a Dioxus web app called the **Blueprint Key/Value Explorer**. It lets you +set, get, and list key/value pairs stored in a running Blueprint instance. + +### Prerequisites + +- [Dioxus CLI](https://dioxuslabs.com/learn/0.6/getting_started): `cargo install dioxus-cli` +- A Blueprint instance listening on `http://127.0.0.1:2221` (start the Draft core stack with + `dctl infra start` and then run Blueprint) + +### Running -... +From the `api/` directory: + +```shell +dx serve --features web +``` + +Then open `http://localhost:8080` in your browser. + +### What the app does + +| Button | Action | +|--------|--------| +| **Set** | Stores the key/value pair in Blueprint | +| **Get** | Fetches the value for the current key and displays it below the inputs | +| **List** | Lists all `Value`-typed entries in Blueprint and renders them in the table | + +## Using locally generated files in a Go module + +Add a `replace` directive to the consuming module's `go.mod`: + +``` +replace github.com/steady-bytes/draft/api => ../../../api ``` diff --git a/api/buf.lock b/api/buf.lock index 851707c5..c01e763b 100644 --- a/api/buf.lock +++ b/api/buf.lock @@ -9,8 +9,8 @@ deps: - remote: buf.build owner: googleapis repository: googleapis - commit: 61b203b9a9164be9a834f58c37be6f62 - digest: shake256:e619113001d6e284ee8a92b1561e5d4ea89a47b28bf0410815cb2fa23914df8be9f1a6a98dcf069f5bc2d829a2cfb1ac614863be45cd4f8a5ad8606c5f200224 + commit: c17df5b2beca46928cc87d5656bd5343 + digest: shake256:c62ecead9b13485a02893cd678a6c81e40879bf00ea509bbc6fd8f1b2cc33eccf6a85c259b08d1e0f052f693cbfc7dfda236e9665b1d6869b8e1132a794a61e2 - remote: buf.build owner: srikrsna repository: protoc-gen-gotag diff --git a/api/build.rs b/api/build.rs new file mode 100644 index 00000000..28aa0788 --- /dev/null +++ b/api/build.rs @@ -0,0 +1,100 @@ +use std::io::Result; + +fn main() -> Result<()> { + let current_dir = std::env::current_dir()?.to_str().expect("build.rs").to_string(); + let proto_out_dir = format!("{current_dir}/src/proto"); + let hook_out_dir = format!("{current_dir}/src/hook"); + + let proto_dirs = [ + "./core/registry/key_value/v1/", + "./core/registry/service_discovery/v1/", + "./core/control_plane/networking/v1/", + "./core/message_broker/actors/v1/", + ]; + + let protos_to_compile: Vec<_> = proto_dirs + .iter() + .flat_map(|dir| { + std::fs::read_dir(dir) + .unwrap_or_else(|_| panic!("could not read {dir}")) + .flatten() + .filter(|entry| { + entry.path().extension().map(|ext| ext == "proto").unwrap_or(false) + }) + .filter(|entry| entry.path().is_file()) + .map(|entry| entry.path()) + .collect::>() + }) + .collect(); + + tonic_prost_build::configure() + .out_dir(&proto_out_dir) + .build_server(false) + .build_client(true) + .build_transport(false) + .type_attribute( + "core.registry.key_value.v1.NodePosition", + "#[derive(serde::Serialize, serde::Deserialize)]", + ) + .type_attribute( + "core.registry.key_value.v1.ClusterLayout", + "#[derive(serde::Serialize, serde::Deserialize)]", + ) + .type_attribute( + "core.registry.key_value.v1.NavigationItem", + "#[derive(serde::Serialize, serde::Deserialize)]", + ) + .type_attribute( + "core.registry.key_value.v1.NavigationSection", + "#[derive(serde::Serialize, serde::Deserialize)]", + ) + .type_attribute( + "core.registry.key_value.v1.NavigationConfig", + "#[derive(serde::Serialize, serde::Deserialize)]", + ) + .compile_protos(&protos_to_compile, &[".".into()])?; + + // Generate proto/mod.rs by discovering tonic-build's actual output files. + // tonic-build names outputs by proto package (e.g. core.registry.key_value.v1.rs), not by + // source filename, so we discover what was generated rather than deriving from source names. + // Module names replace dots with underscores since dots are invalid in Rust identifiers. + let proto_mod_content = std::fs::read_dir(&proto_out_dir)? + .flatten() + .filter(|e| { + let name = e.file_name().into_string().unwrap_or_default(); + name.ends_with(".rs") && name != "mod.rs" + }) + .fold(String::new(), |acc, entry| { + let name = entry.file_name().into_string().unwrap_or_default(); + let module_name = name.replace(".rs", "").replace('.', "_"); + acc + &format!("#[path = \"./{name}\"]\npub mod {module_name};\n") + }); + std::fs::write(format!("{proto_out_dir}/mod.rs"), proto_mod_content)?; + + // Remove stale hook files before regenerating so deleted services don't linger. + for entry in std::fs::read_dir(&hook_out_dir)?.flatten() { + if entry.file_name().to_str().map(|n| n.ends_with(".dx.rs")).unwrap_or(false) { + std::fs::remove_file(entry.path())?; + } + } + + dioxus_grpc::generate_hooks( + &protos_to_compile, + &["."], + &Some(hook_out_dir.as_str()), + Some("crate::proto"), + )?; + + // Generate hook/mod.rs from the .dx.rs files written above. + let hook_mod_content = std::fs::read_dir(&hook_out_dir)? + .flatten() + .filter(|e| e.file_name().to_str().map(|n| n.ends_with(".dx.rs")).unwrap_or(false)) + .fold(String::new(), |acc, entry| { + let name = entry.file_name().into_string().unwrap_or_default(); + let module_name = name.replace(".dx.rs", "").replace('.', "_"); + acc + &format!("#[path = \"./{name}\"]\npub mod {module_name};\n") + }); + std::fs::write(format!("{hook_out_dir}/mod.rs"), hook_mod_content)?; + + Ok(()) +} diff --git a/api/core/authentication/basic/v1/service.pb.go b/api/core/authentication/basic/v1/service.pb.go index c38239d1..f23e8815 100644 --- a/api/core/authentication/basic/v1/service.pb.go +++ b/api/core/authentication/basic/v1/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: core/authentication/basic/v1/service.proto @@ -14,6 +14,7 @@ import ( timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -80,25 +81,22 @@ func (LookupEntityKeys) EnumDescriptor() ([]byte, []int) { // ID, username, password, email, and timestamps for creation and updates of the Entity values. // A combination of these fields uniquely identifies an entity within the system and allows for authentication. type Entity struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` + Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"` + Email string `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id" bun:"id" csv:"id" pg:"id" yaml:"id"` - Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username" bun:"username" csv:"username" pg:"username" yaml:"username"` - Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password" bun:"password" csv:"password" pg:"password" yaml:"password"` - Email string `protobuf:"bytes,4,opt,name=email,proto3" json:"email" bun:"email" csv:"email" pg:"email" yaml:"email"` - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at" bun:"created_at" csv:"created_at" pg:"created_at" yaml:"created_at"` - UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at" bun:"updated_at" csv:"updated_at" pg:"updated_at" yaml:"updated_at"` + sizeCache protoimpl.SizeCache } func (x *Entity) Reset() { *x = Entity{} - if protoimpl.UnsafeEnabled { - mi := &file_core_authentication_basic_v1_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_authentication_basic_v1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Entity) String() string { @@ -109,7 +107,7 @@ func (*Entity) ProtoMessage() {} func (x *Entity) ProtoReflect() protoreflect.Message { mi := &file_core_authentication_basic_v1_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -171,25 +169,22 @@ func (x *Entity) GetUpdatedAt() *timestamppb.Timestamp { // The token is used to authenticate the user in subsequent requests, allowing them to access protected resources // without needing to re-enter their credentials. type Session struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"` + RefreshToken string `protobuf:"bytes,4,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"` unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id" bun:"id" csv:"id" pg:"id" yaml:"id"` - UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id" bun:"user_id" csv:"user_id" pg:"user_id" yaml:"user_id"` - Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token" bun:"token" csv:"token" pg:"token" yaml:"token"` - RefreshToken string `protobuf:"bytes,4,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token" bun:"refresh_token" csv:"refresh_token" pg:"refresh_token" yaml:"refresh_token"` - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at" bun:"created_at" csv:"created_at" pg:"created_at" yaml:"created_at"` - ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at" bun:"expires_at" csv:"expires_at" pg:"expires_at" yaml:"expires_at"` + sizeCache protoimpl.SizeCache } func (x *Session) Reset() { *x = Session{} - if protoimpl.UnsafeEnabled { - mi := &file_core_authentication_basic_v1_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_authentication_basic_v1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Session) String() string { @@ -200,7 +195,7 @@ func (*Session) ProtoMessage() {} func (x *Session) ProtoReflect() protoreflect.Message { mi := &file_core_authentication_basic_v1_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -259,69 +254,41 @@ func (x *Session) GetExpiresAt() *timestamppb.Timestamp { var File_core_authentication_basic_v1_service_proto protoreflect.FileDescriptor -var file_core_authentication_basic_v1_service_proto_rawDesc = []byte{ - 0x0a, 0x2a, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x62, 0x61, 0x73, 0x69, 0x63, 0x2f, 0x76, 0x31, 0x2f, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x62, 0x61, 0x73, 0x69, 0x63, 0x2e, 0x76, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xdc, 0x01, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xe3, - 0x01, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x66, - 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x39, - 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, - 0x65, 0x73, 0x41, 0x74, 0x2a, 0x8c, 0x01, 0x0a, 0x10, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x21, 0x0a, 0x1d, 0x4c, 0x4f, 0x4f, - 0x4b, 0x55, 0x50, 0x5f, 0x45, 0x4e, 0x54, 0x49, 0x54, 0x59, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, - 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x5f, 0x45, 0x4e, 0x54, 0x49, 0x54, 0x59, 0x5f, 0x4b, 0x45, - 0x59, 0x5f, 0x49, 0x44, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, - 0x5f, 0x45, 0x4e, 0x54, 0x49, 0x54, 0x59, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x55, 0x53, 0x45, 0x52, - 0x4e, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, - 0x5f, 0x45, 0x4e, 0x54, 0x49, 0x54, 0x59, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x45, 0x4d, 0x41, 0x49, - 0x4c, 0x10, 0x03, 0x42, 0x40, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, - 0x72, 0x61, 0x66, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x62, 0x61, 0x73, - 0x69, 0x63, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_core_authentication_basic_v1_service_proto_rawDesc = "" + + "\n" + + "*core/authentication/basic/v1/service.proto\x12\x1ccore.authentication.basic.v1\x1a\x19google/protobuf/any.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17validate/validate.proto\"\xdc\x01\n" + + "\x06Entity\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x1a\n" + + "\busername\x18\x02 \x01(\tR\busername\x12\x1a\n" + + "\bpassword\x18\x03 \x01(\tR\bpassword\x12\x14\n" + + "\x05email\x18\x04 \x01(\tR\x05email\x129\n" + + "\n" + + "created_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x129\n" + + "\n" + + "updated_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\"\xe3\x01\n" + + "\aSession\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x17\n" + + "\auser_id\x18\x02 \x01(\tR\x06userId\x12\x14\n" + + "\x05token\x18\x03 \x01(\tR\x05token\x12#\n" + + "\rrefresh_token\x18\x04 \x01(\tR\frefreshToken\x129\n" + + "\n" + + "created_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x129\n" + + "\n" + + "expires_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt*\x8c\x01\n" + + "\x10LookupEntityKeys\x12!\n" + + "\x1dLOOKUP_ENTITY_KEY_UNSPECIFIED\x10\x00\x12\x18\n" + + "\x14LOOKUP_ENTITY_KEY_ID\x10\x01\x12\x1e\n" + + "\x1aLOOKUP_ENTITY_KEY_USERNAME\x10\x02\x12\x1b\n" + + "\x17LOOKUP_ENTITY_KEY_EMAIL\x10\x03B@Z>github.com/steady-bytes/draft/api/core/authentication/basic/v1b\x06proto3" var ( file_core_authentication_basic_v1_service_proto_rawDescOnce sync.Once - file_core_authentication_basic_v1_service_proto_rawDescData = file_core_authentication_basic_v1_service_proto_rawDesc + file_core_authentication_basic_v1_service_proto_rawDescData []byte ) func file_core_authentication_basic_v1_service_proto_rawDescGZIP() []byte { file_core_authentication_basic_v1_service_proto_rawDescOnce.Do(func() { - file_core_authentication_basic_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_authentication_basic_v1_service_proto_rawDescData) + file_core_authentication_basic_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_authentication_basic_v1_service_proto_rawDesc), len(file_core_authentication_basic_v1_service_proto_rawDesc))) }) return file_core_authentication_basic_v1_service_proto_rawDescData } @@ -351,37 +318,11 @@ func file_core_authentication_basic_v1_service_proto_init() { if File_core_authentication_basic_v1_service_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_core_authentication_basic_v1_service_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*Entity); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_authentication_basic_v1_service_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*Session); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_core_authentication_basic_v1_service_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_authentication_basic_v1_service_proto_rawDesc), len(file_core_authentication_basic_v1_service_proto_rawDesc)), NumEnums: 1, NumMessages: 2, NumExtensions: 0, @@ -393,7 +334,6 @@ func file_core_authentication_basic_v1_service_proto_init() { MessageInfos: file_core_authentication_basic_v1_service_proto_msgTypes, }.Build() File_core_authentication_basic_v1_service_proto = out.File - file_core_authentication_basic_v1_service_proto_rawDesc = nil file_core_authentication_basic_v1_service_proto_goTypes = nil file_core_authentication_basic_v1_service_proto_depIdxs = nil } diff --git a/api/core/authentication/basic/v1/service.pb.validate.go b/api/core/authentication/basic/v1/service.pb.validate.go index fdc7d469..24a3091e 100644 --- a/api/core/authentication/basic/v1/service.pb.validate.go +++ b/api/core/authentication/basic/v1/service.pb.validate.go @@ -135,7 +135,7 @@ type EntityMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m EntityMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -299,7 +299,7 @@ type SessionMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m SessionMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/core/consensus/fsm/v1/fsm.pb.go b/api/core/consensus/fsm/v1/fsm.pb.go index aa9cdb55..dd0797fc 100644 --- a/api/core/consensus/fsm/v1/fsm.pb.go +++ b/api/core/consensus/fsm/v1/fsm.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: core/consensus/fsm/v1/fsm.proto @@ -12,6 +12,7 @@ import ( anypb "google.golang.org/protobuf/types/known/anypb" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -71,22 +72,19 @@ func (Operation) EnumDescriptor() ([]byte, []int) { } type CommandPayload struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Operation Operation `protobuf:"varint,1,opt,name=operation,proto3,enum=core.consensus.fsm.v1.Operation" json:"operation,omitempty"` + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + Value *anypb.Any `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields - - Operation Operation `protobuf:"varint,1,opt,name=operation,proto3,enum=core.consensus.fsm.v1.Operation" json:"operation" bun:"operation" csv:"operation" pg:"operation" yaml:"operation"` - Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key" bun:"key" csv:"key" pg:"key" yaml:"key"` - Value *anypb.Any `protobuf:"bytes,3,opt,name=value,proto3" json:"value" bun:"value" csv:"value" pg:"value" yaml:"value"` + sizeCache protoimpl.SizeCache } func (x *CommandPayload) Reset() { *x = CommandPayload{} - if protoimpl.UnsafeEnabled { - mi := &file_core_consensus_fsm_v1_fsm_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_consensus_fsm_v1_fsm_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CommandPayload) String() string { @@ -97,7 +95,7 @@ func (*CommandPayload) ProtoMessage() {} func (x *CommandPayload) ProtoReflect() protoreflect.Message { mi := &file_core_consensus_fsm_v1_fsm_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -135,39 +133,27 @@ func (x *CommandPayload) GetValue() *anypb.Any { var File_core_consensus_fsm_v1_fsm_proto protoreflect.FileDescriptor -var file_core_consensus_fsm_v1_fsm_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2f, 0x66, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x73, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x15, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, - 0x73, 0x2e, 0x66, 0x73, 0x6d, 0x2e, 0x76, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x8e, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x3e, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2e, 0x66, 0x73, 0x6d, 0x2e, 0x76, - 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x2a, 0x34, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x12, 0x0a, 0x0e, 0x4e, 0x55, 0x4c, 0x4c, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x45, 0x54, 0x10, 0x01, 0x12, 0x0a, - 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, 0x2d, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, - 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2f, 0x66, - 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_core_consensus_fsm_v1_fsm_proto_rawDesc = "" + + "\n" + + "\x1fcore/consensus/fsm/v1/fsm.proto\x12\x15core.consensus.fsm.v1\x1a\x19google/protobuf/any.proto\"\x8e\x01\n" + + "\x0eCommandPayload\x12>\n" + + "\toperation\x18\x01 \x01(\x0e2 .core.consensus.fsm.v1.OperationR\toperation\x12\x10\n" + + "\x03key\x18\x02 \x01(\tR\x03key\x12*\n" + + "\x05value\x18\x03 \x01(\v2\x14.google.protobuf.AnyR\x05value*4\n" + + "\tOperation\x12\x12\n" + + "\x0eNULL_OPERATION\x10\x00\x12\a\n" + + "\x03SET\x10\x01\x12\n" + + "\n" + + "\x06DELETE\x10\x02B9Z7github.com/steady-bytes/draft/api/core/consensus/fsm/v1b\x06proto3" var ( file_core_consensus_fsm_v1_fsm_proto_rawDescOnce sync.Once - file_core_consensus_fsm_v1_fsm_proto_rawDescData = file_core_consensus_fsm_v1_fsm_proto_rawDesc + file_core_consensus_fsm_v1_fsm_proto_rawDescData []byte ) func file_core_consensus_fsm_v1_fsm_proto_rawDescGZIP() []byte { file_core_consensus_fsm_v1_fsm_proto_rawDescOnce.Do(func() { - file_core_consensus_fsm_v1_fsm_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_consensus_fsm_v1_fsm_proto_rawDescData) + file_core_consensus_fsm_v1_fsm_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_consensus_fsm_v1_fsm_proto_rawDesc), len(file_core_consensus_fsm_v1_fsm_proto_rawDesc))) }) return file_core_consensus_fsm_v1_fsm_proto_rawDescData } @@ -194,25 +180,11 @@ func file_core_consensus_fsm_v1_fsm_proto_init() { if File_core_consensus_fsm_v1_fsm_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_core_consensus_fsm_v1_fsm_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*CommandPayload); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_core_consensus_fsm_v1_fsm_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_consensus_fsm_v1_fsm_proto_rawDesc), len(file_core_consensus_fsm_v1_fsm_proto_rawDesc)), NumEnums: 1, NumMessages: 1, NumExtensions: 0, @@ -224,7 +196,6 @@ func file_core_consensus_fsm_v1_fsm_proto_init() { MessageInfos: file_core_consensus_fsm_v1_fsm_proto_msgTypes, }.Build() File_core_consensus_fsm_v1_fsm_proto = out.File - file_core_consensus_fsm_v1_fsm_proto_rawDesc = nil file_core_consensus_fsm_v1_fsm_proto_goTypes = nil file_core_consensus_fsm_v1_fsm_proto_depIdxs = nil } diff --git a/api/core/consensus/fsm/v1/fsm.pb.validate.go b/api/core/consensus/fsm/v1/fsm.pb.validate.go index d59e62db..fbad966f 100644 --- a/api/core/consensus/fsm/v1/fsm.pb.validate.go +++ b/api/core/consensus/fsm/v1/fsm.pb.validate.go @@ -104,7 +104,7 @@ type CommandPayloadMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m CommandPayloadMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/core/consensus/raft/v1/service.pb.go b/api/core/consensus/raft/v1/service.pb.go index 52eb1ffd..6eee9d40 100644 --- a/api/core/consensus/raft/v1/service.pb.go +++ b/api/core/consensus/raft/v1/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: core/consensus/raft/v1/service.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -21,21 +22,18 @@ const ( ) type JoinRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + RaftAddress string `protobuf:"bytes,2,opt,name=raft_address,json=raftAddress,proto3" json:"raft_address,omitempty"` unknownFields protoimpl.UnknownFields - - NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id" bun:"node_id" csv:"node_id" pg:"node_id" yaml:"node_id"` - RaftAddress string `protobuf:"bytes,2,opt,name=raft_address,json=raftAddress,proto3" json:"raft_address" bun:"raft_address" csv:"raft_address" pg:"raft_address" yaml:"raft_address"` + sizeCache protoimpl.SizeCache } func (x *JoinRequest) Reset() { *x = JoinRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_consensus_raft_v1_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_consensus_raft_v1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *JoinRequest) String() string { @@ -46,7 +44,7 @@ func (*JoinRequest) ProtoMessage() {} func (x *JoinRequest) ProtoReflect() protoreflect.Message { mi := &file_core_consensus_raft_v1_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -76,21 +74,18 @@ func (x *JoinRequest) GetRaftAddress() string { } type JoinResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + RaftAddress string `protobuf:"bytes,2,opt,name=raft_address,json=raftAddress,proto3" json:"raft_address,omitempty"` unknownFields protoimpl.UnknownFields - - NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id" bun:"node_id" csv:"node_id" pg:"node_id" yaml:"node_id"` - RaftAddress string `protobuf:"bytes,2,opt,name=raft_address,json=raftAddress,proto3" json:"raft_address" bun:"raft_address" csv:"raft_address" pg:"raft_address" yaml:"raft_address"` + sizeCache protoimpl.SizeCache } func (x *JoinResponse) Reset() { *x = JoinResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_consensus_raft_v1_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_consensus_raft_v1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *JoinResponse) String() string { @@ -101,7 +96,7 @@ func (*JoinResponse) ProtoMessage() {} func (x *JoinResponse) ProtoReflect() protoreflect.Message { mi := &file_core_consensus_raft_v1_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -131,20 +126,17 @@ func (x *JoinResponse) GetRaftAddress() string { } type RemoveRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` unknownFields protoimpl.UnknownFields - - NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id" bun:"node_id" csv:"node_id" pg:"node_id" yaml:"node_id"` + sizeCache protoimpl.SizeCache } func (x *RemoveRequest) Reset() { *x = RemoveRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_consensus_raft_v1_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_consensus_raft_v1_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *RemoveRequest) String() string { @@ -155,7 +147,7 @@ func (*RemoveRequest) ProtoMessage() {} func (x *RemoveRequest) ProtoReflect() protoreflect.Message { mi := &file_core_consensus_raft_v1_service_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -178,20 +170,17 @@ func (x *RemoveRequest) GetNodeId() string { } type RemoveResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` unknownFields protoimpl.UnknownFields - - NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id" bun:"node_id" csv:"node_id" pg:"node_id" yaml:"node_id"` + sizeCache protoimpl.SizeCache } func (x *RemoveResponse) Reset() { *x = RemoveResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_consensus_raft_v1_service_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_consensus_raft_v1_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *RemoveResponse) String() string { @@ -202,7 +191,7 @@ func (*RemoveResponse) ProtoMessage() {} func (x *RemoveResponse) ProtoReflect() protoreflect.Message { mi := &file_core_consensus_raft_v1_service_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -225,20 +214,17 @@ func (x *RemoveResponse) GetNodeId() string { } type StatsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` unknownFields protoimpl.UnknownFields - - NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id" bun:"node_id" csv:"node_id" pg:"node_id" yaml:"node_id"` + sizeCache protoimpl.SizeCache } func (x *StatsRequest) Reset() { *x = StatsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_consensus_raft_v1_service_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_consensus_raft_v1_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *StatsRequest) String() string { @@ -249,7 +235,7 @@ func (*StatsRequest) ProtoMessage() {} func (x *StatsRequest) ProtoReflect() protoreflect.Message { mi := &file_core_consensus_raft_v1_service_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -272,21 +258,18 @@ func (x *StatsRequest) GetNodeId() string { } type StatsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + Stats *Stats `protobuf:"bytes,2,opt,name=stats,proto3" json:"stats,omitempty"` unknownFields protoimpl.UnknownFields - - NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id" bun:"node_id" csv:"node_id" pg:"node_id" yaml:"node_id"` - Stats *Stats `protobuf:"bytes,2,opt,name=stats,proto3" json:"stats" bun:"stats" csv:"stats" pg:"stats" yaml:"stats"` + sizeCache protoimpl.SizeCache } func (x *StatsResponse) Reset() { *x = StatsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_consensus_raft_v1_service_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_consensus_raft_v1_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *StatsResponse) String() string { @@ -297,7 +280,7 @@ func (*StatsResponse) ProtoMessage() {} func (x *StatsResponse) ProtoReflect() protoreflect.Message { mi := &file_core_consensus_raft_v1_service_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -327,20 +310,17 @@ func (x *StatsResponse) GetStats() *Stats { } type Stats struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Stats map[string]string `protobuf:"bytes,1,rep,name=stats,proto3" json:"stats,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` unknownFields protoimpl.UnknownFields - - Stats map[string]string `protobuf:"bytes,1,rep,name=stats,proto3" json:"stats" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" bun:"stats" csv:"stats" pg:"stats" yaml:"stats"` + sizeCache protoimpl.SizeCache } func (x *Stats) Reset() { *x = Stats{} - if protoimpl.UnsafeEnabled { - mi := &file_core_consensus_raft_v1_service_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_consensus_raft_v1_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Stats) String() string { @@ -351,7 +331,7 @@ func (*Stats) ProtoMessage() {} func (x *Stats) ProtoReflect() protoreflect.Message { mi := &file_core_consensus_raft_v1_service_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -375,75 +355,43 @@ func (x *Stats) GetStats() map[string]string { var File_core_consensus_raft_v1_service_proto protoreflect.FileDescriptor -var file_core_consensus_raft_v1_service_proto_rawDesc = []byte{ - 0x0a, 0x24, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2e, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x22, 0x49, - 0x0a, 0x0b, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, - 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x61, - 0x66, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x4a, 0x0a, 0x0c, 0x4a, 0x6f, 0x69, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, - 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x61, 0x66, 0x74, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x28, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, - 0x29, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x27, 0x0a, 0x0c, 0x53, 0x74, - 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, - 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, - 0x65, 0x49, 0x64, 0x22, 0x5d, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x33, 0x0a, - 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2e, 0x72, 0x61, - 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, - 0x74, 0x73, 0x22, 0x81, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x3e, 0x0a, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2e, 0x72, 0x61, 0x66, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x1a, 0x38, 0x0a, 0x0a, - 0x53, 0x74, 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0x95, 0x02, 0x0a, 0x0b, 0x52, 0x61, 0x66, 0x74, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x53, 0x0a, 0x04, 0x4a, 0x6f, 0x69, 0x6e, 0x12, 0x23, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2e, - 0x72, 0x61, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x73, 0x75, 0x73, 0x2e, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x69, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x59, 0x0a, 0x06, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2e, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2e, 0x72, 0x61, - 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x56, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, - 0x24, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2e, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2e, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x3a, - 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x65, - 0x61, 0x64, 0x79, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, 0x72, 0x61, 0x66, 0x74, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} +const file_core_consensus_raft_v1_service_proto_rawDesc = "" + + "\n" + + "$core/consensus/raft/v1/service.proto\x12\x16core.consensus.raft.v1\"I\n" + + "\vJoinRequest\x12\x17\n" + + "\anode_id\x18\x01 \x01(\tR\x06nodeId\x12!\n" + + "\fraft_address\x18\x02 \x01(\tR\vraftAddress\"J\n" + + "\fJoinResponse\x12\x17\n" + + "\anode_id\x18\x01 \x01(\tR\x06nodeId\x12!\n" + + "\fraft_address\x18\x02 \x01(\tR\vraftAddress\"(\n" + + "\rRemoveRequest\x12\x17\n" + + "\anode_id\x18\x01 \x01(\tR\x06nodeId\")\n" + + "\x0eRemoveResponse\x12\x17\n" + + "\anode_id\x18\x01 \x01(\tR\x06nodeId\"'\n" + + "\fStatsRequest\x12\x17\n" + + "\anode_id\x18\x01 \x01(\tR\x06nodeId\"]\n" + + "\rStatsResponse\x12\x17\n" + + "\anode_id\x18\x01 \x01(\tR\x06nodeId\x123\n" + + "\x05stats\x18\x02 \x01(\v2\x1d.core.consensus.raft.v1.StatsR\x05stats\"\x81\x01\n" + + "\x05Stats\x12>\n" + + "\x05stats\x18\x01 \x03(\v2(.core.consensus.raft.v1.Stats.StatsEntryR\x05stats\x1a8\n" + + "\n" + + "StatsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x012\x95\x02\n" + + "\vRaftService\x12S\n" + + "\x04Join\x12#.core.consensus.raft.v1.JoinRequest\x1a$.core.consensus.raft.v1.JoinResponse\"\x00\x12Y\n" + + "\x06Remove\x12%.core.consensus.raft.v1.RemoveRequest\x1a&.core.consensus.raft.v1.RemoveResponse\"\x00\x12V\n" + + "\x05Stats\x12$.core.consensus.raft.v1.StatsRequest\x1a%.core.consensus.raft.v1.StatsResponse\"\x00B:Z8github.com/steady-bytes/draft/api/core/consensus/raft/v1b\x06proto3" var ( file_core_consensus_raft_v1_service_proto_rawDescOnce sync.Once - file_core_consensus_raft_v1_service_proto_rawDescData = file_core_consensus_raft_v1_service_proto_rawDesc + file_core_consensus_raft_v1_service_proto_rawDescData []byte ) func file_core_consensus_raft_v1_service_proto_rawDescGZIP() []byte { file_core_consensus_raft_v1_service_proto_rawDescOnce.Do(func() { - file_core_consensus_raft_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_consensus_raft_v1_service_proto_rawDescData) + file_core_consensus_raft_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_consensus_raft_v1_service_proto_rawDesc), len(file_core_consensus_raft_v1_service_proto_rawDesc))) }) return file_core_consensus_raft_v1_service_proto_rawDescData } @@ -480,97 +428,11 @@ func file_core_consensus_raft_v1_service_proto_init() { if File_core_consensus_raft_v1_service_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_core_consensus_raft_v1_service_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*JoinRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_consensus_raft_v1_service_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*JoinResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_consensus_raft_v1_service_proto_msgTypes[2].Exporter = func(v any, i int) any { - switch v := v.(*RemoveRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_consensus_raft_v1_service_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*RemoveResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_consensus_raft_v1_service_proto_msgTypes[4].Exporter = func(v any, i int) any { - switch v := v.(*StatsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_consensus_raft_v1_service_proto_msgTypes[5].Exporter = func(v any, i int) any { - switch v := v.(*StatsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_consensus_raft_v1_service_proto_msgTypes[6].Exporter = func(v any, i int) any { - switch v := v.(*Stats); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_core_consensus_raft_v1_service_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_consensus_raft_v1_service_proto_rawDesc), len(file_core_consensus_raft_v1_service_proto_rawDesc)), NumEnums: 0, NumMessages: 8, NumExtensions: 0, @@ -581,7 +443,6 @@ func file_core_consensus_raft_v1_service_proto_init() { MessageInfos: file_core_consensus_raft_v1_service_proto_msgTypes, }.Build() File_core_consensus_raft_v1_service_proto = out.File - file_core_consensus_raft_v1_service_proto_rawDesc = nil file_core_consensus_raft_v1_service_proto_goTypes = nil file_core_consensus_raft_v1_service_proto_depIdxs = nil } diff --git a/api/core/consensus/raft/v1/service.pb.validate.go b/api/core/consensus/raft/v1/service.pb.validate.go index fa3a6a04..3221c475 100644 --- a/api/core/consensus/raft/v1/service.pb.validate.go +++ b/api/core/consensus/raft/v1/service.pb.validate.go @@ -74,7 +74,7 @@ type JoinRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m JoinRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -177,7 +177,7 @@ type JoinResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m JoinResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -279,7 +279,7 @@ type RemoveRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m RemoveRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -381,7 +381,7 @@ type RemoveResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m RemoveResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -482,7 +482,7 @@ type StatsRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m StatsRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -613,7 +613,7 @@ type StatsResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m StatsResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -713,7 +713,7 @@ type StatsMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m StatsMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/core/consensus/raft/v1/v1connect/service.connect.go b/api/core/consensus/raft/v1/v1connect/service.connect.go index 21975789..e91e05e6 100644 --- a/api/core/consensus/raft/v1/v1connect/service.connect.go +++ b/api/core/consensus/raft/v1/v1connect/service.connect.go @@ -41,14 +41,6 @@ const ( RaftServiceStatsProcedure = "/core.consensus.raft.v1.RaftService/Stats" ) -// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. -var ( - raftServiceServiceDescriptor = v1.File_core_consensus_raft_v1_service_proto.Services().ByName("RaftService") - raftServiceJoinMethodDescriptor = raftServiceServiceDescriptor.Methods().ByName("Join") - raftServiceRemoveMethodDescriptor = raftServiceServiceDescriptor.Methods().ByName("Remove") - raftServiceStatsMethodDescriptor = raftServiceServiceDescriptor.Methods().ByName("Stats") -) - // RaftServiceClient is a client for the core.consensus.raft.v1.RaftService service. type RaftServiceClient interface { // Join the raft cluster @@ -68,23 +60,24 @@ type RaftServiceClient interface { // http://api.acme.com or https://acme.com/grpc). func NewRaftServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) RaftServiceClient { baseURL = strings.TrimRight(baseURL, "/") + raftServiceMethods := v1.File_core_consensus_raft_v1_service_proto.Services().ByName("RaftService").Methods() return &raftServiceClient{ join: connect.NewClient[v1.JoinRequest, v1.JoinResponse]( httpClient, baseURL+RaftServiceJoinProcedure, - connect.WithSchema(raftServiceJoinMethodDescriptor), + connect.WithSchema(raftServiceMethods.ByName("Join")), connect.WithClientOptions(opts...), ), remove: connect.NewClient[v1.RemoveRequest, v1.RemoveResponse]( httpClient, baseURL+RaftServiceRemoveProcedure, - connect.WithSchema(raftServiceRemoveMethodDescriptor), + connect.WithSchema(raftServiceMethods.ByName("Remove")), connect.WithClientOptions(opts...), ), stats: connect.NewClient[v1.StatsRequest, v1.StatsResponse]( httpClient, baseURL+RaftServiceStatsProcedure, - connect.WithSchema(raftServiceStatsMethodDescriptor), + connect.WithSchema(raftServiceMethods.ByName("Stats")), connect.WithClientOptions(opts...), ), } @@ -128,22 +121,23 @@ type RaftServiceHandler interface { // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. func NewRaftServiceHandler(svc RaftServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + raftServiceMethods := v1.File_core_consensus_raft_v1_service_proto.Services().ByName("RaftService").Methods() raftServiceJoinHandler := connect.NewUnaryHandler( RaftServiceJoinProcedure, svc.Join, - connect.WithSchema(raftServiceJoinMethodDescriptor), + connect.WithSchema(raftServiceMethods.ByName("Join")), connect.WithHandlerOptions(opts...), ) raftServiceRemoveHandler := connect.NewUnaryHandler( RaftServiceRemoveProcedure, svc.Remove, - connect.WithSchema(raftServiceRemoveMethodDescriptor), + connect.WithSchema(raftServiceMethods.ByName("Remove")), connect.WithHandlerOptions(opts...), ) raftServiceStatsHandler := connect.NewUnaryHandler( RaftServiceStatsProcedure, svc.Stats, - connect.WithSchema(raftServiceStatsMethodDescriptor), + connect.WithSchema(raftServiceMethods.ByName("Stats")), connect.WithHandlerOptions(opts...), ) return "/core.consensus.raft.v1.RaftService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/api/core/control_plane/networking/v1/service.pb.go b/api/core/control_plane/networking/v1/service.pb.go index 4e0b087c..f3d04d80 100644 --- a/api/core/control_plane/networking/v1/service.pb.go +++ b/api/core/control_plane/networking/v1/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: core/control_plane/networking/v1/service.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -121,26 +122,80 @@ func (DeleteRouteCode) EnumDescriptor() ([]byte, []int) { return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{1} } +// AuthPolicy controls how Fuse configures the Envoy ext_authz filter for a route. +type AuthPolicy int32 + +const ( + // No auth check — route is public. + AuthPolicy_AUTH_POLICY_BYPASS AuthPolicy = 0 + // Any valid token is accepted. + AuthPolicy_AUTH_POLICY_AUTHENTICATED AuthPolicy = 1 + // Token must belong to one of the required_groups. + AuthPolicy_AUTH_POLICY_GROUPS AuthPolicy = 2 + // Token must carry all of the required_scopes. + AuthPolicy_AUTH_POLICY_SCOPES AuthPolicy = 3 +) + +// Enum value maps for AuthPolicy. +var ( + AuthPolicy_name = map[int32]string{ + 0: "AUTH_POLICY_BYPASS", + 1: "AUTH_POLICY_AUTHENTICATED", + 2: "AUTH_POLICY_GROUPS", + 3: "AUTH_POLICY_SCOPES", + } + AuthPolicy_value = map[string]int32{ + "AUTH_POLICY_BYPASS": 0, + "AUTH_POLICY_AUTHENTICATED": 1, + "AUTH_POLICY_GROUPS": 2, + "AUTH_POLICY_SCOPES": 3, + } +) + +func (x AuthPolicy) Enum() *AuthPolicy { + p := new(AuthPolicy) + *p = x + return p +} + +func (x AuthPolicy) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AuthPolicy) Descriptor() protoreflect.EnumDescriptor { + return file_core_control_plane_networking_v1_service_proto_enumTypes[2].Descriptor() +} + +func (AuthPolicy) Type() protoreflect.EnumType { + return &file_core_control_plane_networking_v1_service_proto_enumTypes[2] +} + +func (x AuthPolicy) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AuthPolicy.Descriptor instead. +func (AuthPolicy) EnumDescriptor() ([]byte, []int) { + return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{2} +} + // AddRouteRequest - Add a route to the networking configuration type AddRouteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // should this be the route type from envoy config. So that I can use the same proto // or should I make an internal proto and convert them back and forth // An advantage of using the envoy `Route` proto is that it's already ubuqitous in the // wild. A disadvantage is that it's a bit more complex than what I need. - Route *Route `protobuf:"bytes,1,opt,name=route,proto3" json:"route" bun:"route" csv:"route" pg:"route" yaml:"route"` + Route *Route `protobuf:"bytes,1,opt,name=route,proto3" json:"route,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AddRouteRequest) Reset() { *x = AddRouteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AddRouteRequest) String() string { @@ -151,7 +206,7 @@ func (*AddRouteRequest) ProtoMessage() {} func (x *AddRouteRequest) ProtoReflect() protoreflect.Message { mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -177,20 +232,17 @@ func (x *AddRouteRequest) GetRoute() *Route { // was received doesn't mean it was successful. The `code` field is used to determine the success of the // route entry. type AddRouteResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Code AddRouteResponseCode `protobuf:"varint,1,opt,name=code,proto3,enum=core.control_plane.networking.v1.AddRouteResponseCode" json:"code,omitempty"` unknownFields protoimpl.UnknownFields - - Code AddRouteResponseCode `protobuf:"varint,1,opt,name=code,proto3,enum=core.control_plane.networking.v1.AddRouteResponseCode" json:"code" bun:"code" csv:"code" pg:"code" yaml:"code"` + sizeCache protoimpl.SizeCache } func (x *AddRouteResponse) Reset() { *x = AddRouteResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *AddRouteResponse) String() string { @@ -201,7 +253,7 @@ func (*AddRouteResponse) ProtoMessage() {} func (x *AddRouteResponse) ProtoReflect() protoreflect.Message { mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -224,18 +276,16 @@ func (x *AddRouteResponse) GetCode() AddRouteResponseCode { } type ListRoutesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListRoutesRequest) Reset() { *x = ListRoutesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ListRoutesRequest) String() string { @@ -246,7 +296,7 @@ func (*ListRoutesRequest) ProtoMessage() {} func (x *ListRoutesRequest) ProtoReflect() protoreflect.Message { mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -262,20 +312,17 @@ func (*ListRoutesRequest) Descriptor() ([]byte, []int) { } type ListRoutesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Routes []*Route `protobuf:"bytes,1,rep,name=routes,proto3" json:"routes,omitempty"` unknownFields protoimpl.UnknownFields - - Routes []*Route `protobuf:"bytes,1,rep,name=routes,proto3" json:"routes" bun:"routes" csv:"routes" pg:"routes" yaml:"routes"` + sizeCache protoimpl.SizeCache } func (x *ListRoutesResponse) Reset() { *x = ListRoutesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ListRoutesResponse) String() string { @@ -286,7 +333,7 @@ func (*ListRoutesResponse) ProtoMessage() {} func (x *ListRoutesResponse) ProtoReflect() protoreflect.Message { mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -309,21 +356,18 @@ func (x *ListRoutesResponse) GetRoutes() []*Route { } type DeleteRouteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // route names must be unique making name the primary identifier of a route - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name" bun:"name" csv:"name" pg:"name" yaml:"name"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DeleteRouteRequest) Reset() { *x = DeleteRouteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DeleteRouteRequest) String() string { @@ -334,7 +378,7 @@ func (*DeleteRouteRequest) ProtoMessage() {} func (x *DeleteRouteRequest) ProtoReflect() protoreflect.Message { mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -357,20 +401,17 @@ func (x *DeleteRouteRequest) GetName() string { } type DeleteRouteResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Code DeleteRouteCode `protobuf:"varint,1,opt,name=code,proto3,enum=core.control_plane.networking.v1.DeleteRouteCode" json:"code,omitempty"` unknownFields protoimpl.UnknownFields - - Code DeleteRouteCode `protobuf:"varint,1,opt,name=code,proto3,enum=core.control_plane.networking.v1.DeleteRouteCode" json:"code" bun:"code" csv:"code" pg:"code" yaml:"code"` + sizeCache protoimpl.SizeCache } func (x *DeleteRouteResponse) Reset() { *x = DeleteRouteResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DeleteRouteResponse) String() string { @@ -381,7 +422,7 @@ func (*DeleteRouteResponse) ProtoMessage() {} func (x *DeleteRouteResponse) ProtoReflect() protoreflect.Message { mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -403,33 +444,104 @@ func (x *DeleteRouteResponse) GetCode() DeleteRouteCode { return DeleteRouteCode_INVALID_DELETE_ROUTE_RESPONSE_CODE } +// RouteAuth declares the authentication policy for a single route. When absent or +// enabled=false the route is public and no ext_authz check is performed. +type RouteAuth struct { + state protoimpl.MessageState `protogen:"open.v1"` + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Policy AuthPolicy `protobuf:"varint,2,opt,name=policy,proto3,enum=core.control_plane.networking.v1.AuthPolicy" json:"policy,omitempty"` + // Groups the caller must belong to (AUTH_POLICY_GROUPS). + RequiredGroups []string `protobuf:"bytes,3,rep,name=required_groups,json=requiredGroups,proto3" json:"required_groups,omitempty"` + // OAuth2 scopes required on the token (AUTH_POLICY_SCOPES). + RequiredScopes []string `protobuf:"bytes,4,rep,name=required_scopes,json=requiredScopes,proto3" json:"required_scopes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RouteAuth) Reset() { + *x = RouteAuth{} + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RouteAuth) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteAuth) ProtoMessage() {} + +func (x *RouteAuth) ProtoReflect() protoreflect.Message { + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RouteAuth.ProtoReflect.Descriptor instead. +func (*RouteAuth) Descriptor() ([]byte, []int) { + return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{6} +} + +func (x *RouteAuth) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *RouteAuth) GetPolicy() AuthPolicy { + if x != nil { + return x.Policy + } + return AuthPolicy_AUTH_POLICY_BYPASS +} + +func (x *RouteAuth) GetRequiredGroups() []string { + if x != nil { + return x.RequiredGroups + } + return nil +} + +func (x *RouteAuth) GetRequiredScopes() []string { + if x != nil { + return x.RequiredScopes + } + return nil +} + // Route - Close match to the `Route` proto in envoy. Anything that can't be inferred by the draft // framework needs to be added by the `process` adding the route configuration. // // The process will register individual routes, while cluster and virtual host configuration will be handled by the framework. // current integration is `process` -> `fuse` -> `envoy` type Route struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Name for the route - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name" bun:"name" csv:"name" pg:"name" yaml:"name"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Route matching parameters - Match *RouteMatch `protobuf:"bytes,2,opt,name=match,proto3" json:"match" bun:"match" csv:"match" pg:"match" yaml:"match"` + Match *RouteMatch `protobuf:"bytes,2,opt,name=match,proto3" json:"match,omitempty"` // Endpoint parameters - Endpoint *Endpoint `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint" bun:"endpoint" csv:"endpoint" pg:"endpoint" yaml:"endpoint"` + Endpoint *Endpoint `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"` // EnableHTTP2 enables HTTP2 support - EnableHttp2 bool `protobuf:"varint,4,opt,name=enable_http2,json=enableHttp2,proto3" json:"enable_http_2" bun:"enable_http_2" csv:"enable_http_2" pg:"enable_http_2" yaml:"enable_http_2"` + EnableHttp2 bool `protobuf:"varint,4,opt,name=enable_http2,json=enableHttp2,proto3" json:"enable_http2,omitempty"` + // Auth declares the authentication policy for this route. Optional; defaults to bypass. + Auth *RouteAuth `protobuf:"bytes,5,opt,name=auth,proto3" json:"auth,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Route) Reset() { *x = Route{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Route) String() string { @@ -439,8 +551,8 @@ func (x *Route) String() string { func (*Route) ProtoMessage() {} func (x *Route) ProtoReflect() protoreflect.Message { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[7] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -452,7 +564,7 @@ func (x *Route) ProtoReflect() protoreflect.Message { // Deprecated: Use Route.ProtoReflect.Descriptor instead. func (*Route) Descriptor() ([]byte, []int) { - return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{6} + return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{7} } func (x *Route) GetName() string { @@ -483,25 +595,29 @@ func (x *Route) GetEnableHttp2() bool { return false } +func (x *Route) GetAuth() *RouteAuth { + if x != nil { + return x.Auth + } + return nil +} + // parameters for the endpoint a route will map to type Endpoint struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // host represents the address of the endpoint (upstream). can be either a hostname or an ip address - Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host" bun:"host" csv:"host" pg:"host" yaml:"host"` + Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` // port represents the port on the host of the endpoint (upstream) - Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port" bun:"port" csv:"port" pg:"port" yaml:"port"` + Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Endpoint) Reset() { *x = Endpoint{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Endpoint) String() string { @@ -511,8 +627,8 @@ func (x *Endpoint) String() string { func (*Endpoint) ProtoMessage() {} func (x *Endpoint) ProtoReflect() protoreflect.Message { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[8] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -524,7 +640,7 @@ func (x *Endpoint) ProtoReflect() protoreflect.Message { // Deprecated: Use Endpoint.ProtoReflect.Descriptor instead. func (*Endpoint) Descriptor() ([]byte, []int) { - return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{7} + return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{8} } func (x *Endpoint) GetHost() string { @@ -543,38 +659,35 @@ func (x *Endpoint) GetPort() uint32 { // parameters for matching a route type RouteMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // domains for the url a configured in `fuse` but the path to be matched of a route is configured by the `process` // (ie. api.draft.com/health -> /health) - Prefix string `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix" bun:"prefix" csv:"prefix" pg:"prefix" yaml:"prefix"` + Prefix string `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` // option to match headers of a request // TODO -> implement pre 1.0 relase of `fuse` - Headers *HeaderMatchOptions `protobuf:"bytes,2,opt,name=headers,proto3,oneof" json:"headers" bun:"headers" csv:"headers" pg:"headers" yaml:"headers"` + Headers *HeaderMatchOptions `protobuf:"bytes,2,opt,name=headers,proto3,oneof" json:"headers,omitempty"` // options to simplify the matching of a route for grpc. Most request will be grpc and this configuration // makes that integration easier. // TODO -> implement pre 1.0 relase of `fuse` - GrpcMatchOptions *GrpcMatchOptions `protobuf:"bytes,3,opt,name=grpc_match_options,json=grpcMatchOptions,proto3,oneof" json:"grpc_match_options" bun:"grpc_match_options" csv:"grpc_match_options" pg:"grpc_match_options" yaml:"grpc_match_options"` + GrpcMatchOptions *GrpcMatchOptions `protobuf:"bytes,3,opt,name=grpc_match_options,json=grpcMatchOptions,proto3,oneof" json:"grpc_match_options,omitempty"` // REF: Envoy // Specifies a set of dynamic metadata that a route must match. // The router will check the dynamic metadata against all the specified dynamic metadata matchers. // If the number of specified dynamic metadata matchers is nonzero, they all must match the // dynamic metadata for a match to occur. // TODO -> implement pre 2.0 relase of `fuse` - DynamicMetadata *DynamicMetadata `protobuf:"bytes,4,opt,name=dynamic_metadata,json=dynamicMetadata,proto3,oneof" json:"dynamic_metadata" bun:"dynamic_metadata" csv:"dynamic_metadata" pg:"dynamic_metadata" yaml:"dynamic_metadata"` + DynamicMetadata *DynamicMetadata `protobuf:"bytes,4,opt,name=dynamic_metadata,json=dynamicMetadata,proto3,oneof" json:"dynamic_metadata,omitempty"` // Host address for the route - Host string `protobuf:"bytes,5,opt,name=host,proto3" json:"host" bun:"host" csv:"host" pg:"host" yaml:"host"` + Host string `protobuf:"bytes,5,opt,name=host,proto3" json:"host,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RouteMatch) Reset() { *x = RouteMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *RouteMatch) String() string { @@ -584,8 +697,8 @@ func (x *RouteMatch) String() string { func (*RouteMatch) ProtoMessage() {} func (x *RouteMatch) ProtoReflect() protoreflect.Message { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[9] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -597,7 +710,7 @@ func (x *RouteMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use RouteMatch.ProtoReflect.Descriptor instead. func (*RouteMatch) Descriptor() ([]byte, []int) { - return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{8} + return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{9} } func (x *RouteMatch) GetPrefix() string { @@ -638,21 +751,18 @@ func (x *RouteMatch) GetHost() string { // consider using the `key/value` from `blueprint` key/value store // TODO -> implement pre 1.0 relase of `fuse` type HeaderMatchOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key" bun:"key" csv:"key" pg:"key" yaml:"key"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value" bun:"value" csv:"value" pg:"value" yaml:"value"` + sizeCache protoimpl.SizeCache } func (x *HeaderMatchOptions) Reset() { *x = HeaderMatchOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *HeaderMatchOptions) String() string { @@ -662,8 +772,8 @@ func (x *HeaderMatchOptions) String() string { func (*HeaderMatchOptions) ProtoMessage() {} func (x *HeaderMatchOptions) ProtoReflect() protoreflect.Message { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[10] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -675,7 +785,7 @@ func (x *HeaderMatchOptions) ProtoReflect() protoreflect.Message { // Deprecated: Use HeaderMatchOptions.ProtoReflect.Descriptor instead. func (*HeaderMatchOptions) Descriptor() ([]byte, []int) { - return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{9} + return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{10} } func (x *HeaderMatchOptions) GetKey() string { @@ -696,18 +806,16 @@ func (x *HeaderMatchOptions) GetValue() string { // should make the integration easier. // TODO -> implement pre 1.0 relase of `fuse` type GrpcMatchOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GrpcMatchOptions) Reset() { *x = GrpcMatchOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GrpcMatchOptions) String() string { @@ -717,8 +825,8 @@ func (x *GrpcMatchOptions) String() string { func (*GrpcMatchOptions) ProtoMessage() {} func (x *GrpcMatchOptions) ProtoReflect() protoreflect.Message { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[11] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -730,25 +838,23 @@ func (x *GrpcMatchOptions) ProtoReflect() protoreflect.Message { // Deprecated: Use GrpcMatchOptions.ProtoReflect.Descriptor instead. func (*GrpcMatchOptions) Descriptor() ([]byte, []int) { - return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{10} + return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{11} } // DynamicMetadata - Specifies a set of dynamic metadata that a route must match. Dynamic metadata can be used in a variety of ways // and is a powerful feature of envoy `fuse` will most likely use this feature to add additional information to the route. // TODO -> implement pre 2.0 relase of `fuse` type DynamicMetadata struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DynamicMetadata) Reset() { *x = DynamicMetadata{} - if protoimpl.UnsafeEnabled { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DynamicMetadata) String() string { @@ -758,8 +864,8 @@ func (x *DynamicMetadata) String() string { func (*DynamicMetadata) ProtoMessage() {} func (x *DynamicMetadata) ProtoReflect() protoreflect.Message { - mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_core_control_plane_networking_v1_service_proto_msgTypes[12] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -771,186 +877,131 @@ func (x *DynamicMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use DynamicMetadata.ProtoReflect.Descriptor instead. func (*DynamicMetadata) Descriptor() ([]byte, []int) { - return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{11} + return file_core_control_plane_networking_v1_service_proto_rawDescGZIP(), []int{12} } var File_core_control_plane_networking_v1_service_proto protoreflect.FileDescriptor -var file_core_control_plane_networking_v1_service_proto_rawDesc = []byte{ - 0x0a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2f, - 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, - 0x76, 0x31, 0x22, 0x50, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x05, 0x72, - 0x6f, 0x75, 0x74, 0x65, 0x22, 0x5e, 0x0a, 0x10, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, - 0x63, 0x6f, 0x64, 0x65, 0x22, 0x13, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x55, 0x0a, 0x12, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3f, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x27, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, - 0x22, 0x28, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x5c, 0x0a, 0x13, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x45, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x31, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x43, 0x6f, - 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0xca, 0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x42, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, - 0x74, 0x63, 0x68, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x46, 0x0a, 0x08, 0x65, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x68, 0x74, 0x74, - 0x70, 0x32, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x48, 0x74, 0x74, 0x70, 0x32, 0x22, 0x32, 0x0a, 0x08, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x8f, 0x03, 0x0a, 0x0a, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, - 0x12, 0x53, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, - 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x73, 0x88, 0x01, 0x01, 0x12, 0x65, 0x0a, 0x12, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x32, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, - 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x70, 0x63, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x01, 0x52, 0x10, 0x67, 0x72, 0x70, 0x63, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x88, 0x01, 0x01, 0x12, 0x61, 0x0a, 0x10, - 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, - 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x02, 0x52, 0x0f, 0x64, 0x79, 0x6e, - 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x88, 0x01, 0x01, 0x12, - 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, - 0x6f, 0x73, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x42, - 0x15, 0x0a, 0x13, 0x5f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x64, 0x79, 0x6e, 0x61, 0x6d, - 0x69, 0x63, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3c, 0x0a, 0x12, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x47, 0x72, 0x70, - 0x63, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x11, 0x0a, - 0x0f, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2a, 0x63, 0x0a, 0x14, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x1f, 0x49, 0x4e, 0x56, 0x41, - 0x4c, 0x49, 0x44, 0x5f, 0x41, 0x44, 0x44, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x52, 0x45, - 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x10, 0x00, 0x12, 0x06, 0x0a, - 0x02, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, - 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, - 0x45, 0x53, 0x54, 0x10, 0x03, 0x2a, 0x66, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x26, 0x0a, 0x22, 0x49, 0x4e, 0x56, 0x41, - 0x4c, 0x49, 0x44, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, - 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x10, 0x00, - 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, - 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, - 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x32, 0x81, 0x03, - 0x0a, 0x11, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x73, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, - 0x31, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x79, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, - 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x7c, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x6e, 0x65, - 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, 0x72, 0x61, - 0x66, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_core_control_plane_networking_v1_service_proto_rawDesc = "" + + "\n" + + ".core/control_plane/networking/v1/service.proto\x12 core.control_plane.networking.v1\"P\n" + + "\x0fAddRouteRequest\x12=\n" + + "\x05route\x18\x01 \x01(\v2'.core.control_plane.networking.v1.RouteR\x05route\"^\n" + + "\x10AddRouteResponse\x12J\n" + + "\x04code\x18\x01 \x01(\x0e26.core.control_plane.networking.v1.AddRouteResponseCodeR\x04code\"\x13\n" + + "\x11ListRoutesRequest\"U\n" + + "\x12ListRoutesResponse\x12?\n" + + "\x06routes\x18\x01 \x03(\v2'.core.control_plane.networking.v1.RouteR\x06routes\"(\n" + + "\x12DeleteRouteRequest\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\"\\\n" + + "\x13DeleteRouteResponse\x12E\n" + + "\x04code\x18\x01 \x01(\x0e21.core.control_plane.networking.v1.DeleteRouteCodeR\x04code\"\xbd\x01\n" + + "\tRouteAuth\x12\x18\n" + + "\aenabled\x18\x01 \x01(\bR\aenabled\x12D\n" + + "\x06policy\x18\x02 \x01(\x0e2,.core.control_plane.networking.v1.AuthPolicyR\x06policy\x12'\n" + + "\x0frequired_groups\x18\x03 \x03(\tR\x0erequiredGroups\x12'\n" + + "\x0frequired_scopes\x18\x04 \x03(\tR\x0erequiredScopes\"\x8b\x02\n" + + "\x05Route\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12B\n" + + "\x05match\x18\x02 \x01(\v2,.core.control_plane.networking.v1.RouteMatchR\x05match\x12F\n" + + "\bendpoint\x18\x03 \x01(\v2*.core.control_plane.networking.v1.EndpointR\bendpoint\x12!\n" + + "\fenable_http2\x18\x04 \x01(\bR\venableHttp2\x12?\n" + + "\x04auth\x18\x05 \x01(\v2+.core.control_plane.networking.v1.RouteAuthR\x04auth\"2\n" + + "\bEndpoint\x12\x12\n" + + "\x04host\x18\x01 \x01(\tR\x04host\x12\x12\n" + + "\x04port\x18\x02 \x01(\rR\x04port\"\x8f\x03\n" + + "\n" + + "RouteMatch\x12\x16\n" + + "\x06prefix\x18\x01 \x01(\tR\x06prefix\x12S\n" + + "\aheaders\x18\x02 \x01(\v24.core.control_plane.networking.v1.HeaderMatchOptionsH\x00R\aheaders\x88\x01\x01\x12e\n" + + "\x12grpc_match_options\x18\x03 \x01(\v22.core.control_plane.networking.v1.GrpcMatchOptionsH\x01R\x10grpcMatchOptions\x88\x01\x01\x12a\n" + + "\x10dynamic_metadata\x18\x04 \x01(\v21.core.control_plane.networking.v1.DynamicMetadataH\x02R\x0fdynamicMetadata\x88\x01\x01\x12\x12\n" + + "\x04host\x18\x05 \x01(\tR\x04hostB\n" + + "\n" + + "\b_headersB\x15\n" + + "\x13_grpc_match_optionsB\x13\n" + + "\x11_dynamic_metadata\"<\n" + + "\x12HeaderMatchOptions\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value\"\x12\n" + + "\x10GrpcMatchOptions\"\x11\n" + + "\x0fDynamicMetadata*c\n" + + "\x14AddRouteResponseCode\x12#\n" + + "\x1fINVALID_ADD_ROUTE_RESPONSE_CODE\x10\x00\x12\x06\n" + + "\x02OK\x10\x01\x12\t\n" + + "\x05ERROR\x10\x02\x12\x13\n" + + "\x0fINVALID_REQUEST\x10\x03*f\n" + + "\x0fDeleteRouteCode\x12&\n" + + "\"INVALID_DELETE_ROUTE_RESPONSE_CODE\x10\x00\x12\x13\n" + + "\x0fDELETE_ROUTE_OK\x10\x01\x12\x16\n" + + "\x12DELETE_ROUTE_ERROR\x10\x02*s\n" + + "\n" + + "AuthPolicy\x12\x16\n" + + "\x12AUTH_POLICY_BYPASS\x10\x00\x12\x1d\n" + + "\x19AUTH_POLICY_AUTHENTICATED\x10\x01\x12\x16\n" + + "\x12AUTH_POLICY_GROUPS\x10\x02\x12\x16\n" + + "\x12AUTH_POLICY_SCOPES\x10\x032\x81\x03\n" + + "\x11NetworkingService\x12s\n" + + "\bAddRoute\x121.core.control_plane.networking.v1.AddRouteRequest\x1a2.core.control_plane.networking.v1.AddRouteResponse\"\x00\x12y\n" + + "\n" + + "ListRoutes\x123.core.control_plane.networking.v1.ListRoutesRequest\x1a4.core.control_plane.networking.v1.ListRoutesResponse\"\x00\x12|\n" + + "\vDeleteRoute\x124.core.control_plane.networking.v1.DeleteRouteRequest\x1a5.core.control_plane.networking.v1.DeleteRouteResponse\"\x00BDZBgithub.com/steady-bytes/draft/api/core/control_plane/networking/v1b\x06proto3" var ( file_core_control_plane_networking_v1_service_proto_rawDescOnce sync.Once - file_core_control_plane_networking_v1_service_proto_rawDescData = file_core_control_plane_networking_v1_service_proto_rawDesc + file_core_control_plane_networking_v1_service_proto_rawDescData []byte ) func file_core_control_plane_networking_v1_service_proto_rawDescGZIP() []byte { file_core_control_plane_networking_v1_service_proto_rawDescOnce.Do(func() { - file_core_control_plane_networking_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_control_plane_networking_v1_service_proto_rawDescData) + file_core_control_plane_networking_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_control_plane_networking_v1_service_proto_rawDesc), len(file_core_control_plane_networking_v1_service_proto_rawDesc))) }) return file_core_control_plane_networking_v1_service_proto_rawDescData } -var file_core_control_plane_networking_v1_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_core_control_plane_networking_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_core_control_plane_networking_v1_service_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_core_control_plane_networking_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_core_control_plane_networking_v1_service_proto_goTypes = []any{ (AddRouteResponseCode)(0), // 0: core.control_plane.networking.v1.AddRouteResponseCode (DeleteRouteCode)(0), // 1: core.control_plane.networking.v1.DeleteRouteCode - (*AddRouteRequest)(nil), // 2: core.control_plane.networking.v1.AddRouteRequest - (*AddRouteResponse)(nil), // 3: core.control_plane.networking.v1.AddRouteResponse - (*ListRoutesRequest)(nil), // 4: core.control_plane.networking.v1.ListRoutesRequest - (*ListRoutesResponse)(nil), // 5: core.control_plane.networking.v1.ListRoutesResponse - (*DeleteRouteRequest)(nil), // 6: core.control_plane.networking.v1.DeleteRouteRequest - (*DeleteRouteResponse)(nil), // 7: core.control_plane.networking.v1.DeleteRouteResponse - (*Route)(nil), // 8: core.control_plane.networking.v1.Route - (*Endpoint)(nil), // 9: core.control_plane.networking.v1.Endpoint - (*RouteMatch)(nil), // 10: core.control_plane.networking.v1.RouteMatch - (*HeaderMatchOptions)(nil), // 11: core.control_plane.networking.v1.HeaderMatchOptions - (*GrpcMatchOptions)(nil), // 12: core.control_plane.networking.v1.GrpcMatchOptions - (*DynamicMetadata)(nil), // 13: core.control_plane.networking.v1.DynamicMetadata + (AuthPolicy)(0), // 2: core.control_plane.networking.v1.AuthPolicy + (*AddRouteRequest)(nil), // 3: core.control_plane.networking.v1.AddRouteRequest + (*AddRouteResponse)(nil), // 4: core.control_plane.networking.v1.AddRouteResponse + (*ListRoutesRequest)(nil), // 5: core.control_plane.networking.v1.ListRoutesRequest + (*ListRoutesResponse)(nil), // 6: core.control_plane.networking.v1.ListRoutesResponse + (*DeleteRouteRequest)(nil), // 7: core.control_plane.networking.v1.DeleteRouteRequest + (*DeleteRouteResponse)(nil), // 8: core.control_plane.networking.v1.DeleteRouteResponse + (*RouteAuth)(nil), // 9: core.control_plane.networking.v1.RouteAuth + (*Route)(nil), // 10: core.control_plane.networking.v1.Route + (*Endpoint)(nil), // 11: core.control_plane.networking.v1.Endpoint + (*RouteMatch)(nil), // 12: core.control_plane.networking.v1.RouteMatch + (*HeaderMatchOptions)(nil), // 13: core.control_plane.networking.v1.HeaderMatchOptions + (*GrpcMatchOptions)(nil), // 14: core.control_plane.networking.v1.GrpcMatchOptions + (*DynamicMetadata)(nil), // 15: core.control_plane.networking.v1.DynamicMetadata } var file_core_control_plane_networking_v1_service_proto_depIdxs = []int32{ - 8, // 0: core.control_plane.networking.v1.AddRouteRequest.route:type_name -> core.control_plane.networking.v1.Route + 10, // 0: core.control_plane.networking.v1.AddRouteRequest.route:type_name -> core.control_plane.networking.v1.Route 0, // 1: core.control_plane.networking.v1.AddRouteResponse.code:type_name -> core.control_plane.networking.v1.AddRouteResponseCode - 8, // 2: core.control_plane.networking.v1.ListRoutesResponse.routes:type_name -> core.control_plane.networking.v1.Route + 10, // 2: core.control_plane.networking.v1.ListRoutesResponse.routes:type_name -> core.control_plane.networking.v1.Route 1, // 3: core.control_plane.networking.v1.DeleteRouteResponse.code:type_name -> core.control_plane.networking.v1.DeleteRouteCode - 10, // 4: core.control_plane.networking.v1.Route.match:type_name -> core.control_plane.networking.v1.RouteMatch - 9, // 5: core.control_plane.networking.v1.Route.endpoint:type_name -> core.control_plane.networking.v1.Endpoint - 11, // 6: core.control_plane.networking.v1.RouteMatch.headers:type_name -> core.control_plane.networking.v1.HeaderMatchOptions - 12, // 7: core.control_plane.networking.v1.RouteMatch.grpc_match_options:type_name -> core.control_plane.networking.v1.GrpcMatchOptions - 13, // 8: core.control_plane.networking.v1.RouteMatch.dynamic_metadata:type_name -> core.control_plane.networking.v1.DynamicMetadata - 2, // 9: core.control_plane.networking.v1.NetworkingService.AddRoute:input_type -> core.control_plane.networking.v1.AddRouteRequest - 4, // 10: core.control_plane.networking.v1.NetworkingService.ListRoutes:input_type -> core.control_plane.networking.v1.ListRoutesRequest - 6, // 11: core.control_plane.networking.v1.NetworkingService.DeleteRoute:input_type -> core.control_plane.networking.v1.DeleteRouteRequest - 3, // 12: core.control_plane.networking.v1.NetworkingService.AddRoute:output_type -> core.control_plane.networking.v1.AddRouteResponse - 5, // 13: core.control_plane.networking.v1.NetworkingService.ListRoutes:output_type -> core.control_plane.networking.v1.ListRoutesResponse - 7, // 14: core.control_plane.networking.v1.NetworkingService.DeleteRoute:output_type -> core.control_plane.networking.v1.DeleteRouteResponse - 12, // [12:15] is the sub-list for method output_type - 9, // [9:12] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 2, // 4: core.control_plane.networking.v1.RouteAuth.policy:type_name -> core.control_plane.networking.v1.AuthPolicy + 12, // 5: core.control_plane.networking.v1.Route.match:type_name -> core.control_plane.networking.v1.RouteMatch + 11, // 6: core.control_plane.networking.v1.Route.endpoint:type_name -> core.control_plane.networking.v1.Endpoint + 9, // 7: core.control_plane.networking.v1.Route.auth:type_name -> core.control_plane.networking.v1.RouteAuth + 13, // 8: core.control_plane.networking.v1.RouteMatch.headers:type_name -> core.control_plane.networking.v1.HeaderMatchOptions + 14, // 9: core.control_plane.networking.v1.RouteMatch.grpc_match_options:type_name -> core.control_plane.networking.v1.GrpcMatchOptions + 15, // 10: core.control_plane.networking.v1.RouteMatch.dynamic_metadata:type_name -> core.control_plane.networking.v1.DynamicMetadata + 3, // 11: core.control_plane.networking.v1.NetworkingService.AddRoute:input_type -> core.control_plane.networking.v1.AddRouteRequest + 5, // 12: core.control_plane.networking.v1.NetworkingService.ListRoutes:input_type -> core.control_plane.networking.v1.ListRoutesRequest + 7, // 13: core.control_plane.networking.v1.NetworkingService.DeleteRoute:input_type -> core.control_plane.networking.v1.DeleteRouteRequest + 4, // 14: core.control_plane.networking.v1.NetworkingService.AddRoute:output_type -> core.control_plane.networking.v1.AddRouteResponse + 6, // 15: core.control_plane.networking.v1.NetworkingService.ListRoutes:output_type -> core.control_plane.networking.v1.ListRoutesResponse + 8, // 16: core.control_plane.networking.v1.NetworkingService.DeleteRoute:output_type -> core.control_plane.networking.v1.DeleteRouteResponse + 14, // [14:17] is the sub-list for method output_type + 11, // [11:14] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_core_control_plane_networking_v1_service_proto_init() } @@ -958,160 +1009,14 @@ func file_core_control_plane_networking_v1_service_proto_init() { if File_core_control_plane_networking_v1_service_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_core_control_plane_networking_v1_service_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*AddRouteRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*AddRouteResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[2].Exporter = func(v any, i int) any { - switch v := v.(*ListRoutesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*ListRoutesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[4].Exporter = func(v any, i int) any { - switch v := v.(*DeleteRouteRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[5].Exporter = func(v any, i int) any { - switch v := v.(*DeleteRouteResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[6].Exporter = func(v any, i int) any { - switch v := v.(*Route); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[7].Exporter = func(v any, i int) any { - switch v := v.(*Endpoint); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[8].Exporter = func(v any, i int) any { - switch v := v.(*RouteMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[9].Exporter = func(v any, i int) any { - switch v := v.(*HeaderMatchOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[10].Exporter = func(v any, i int) any { - switch v := v.(*GrpcMatchOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[11].Exporter = func(v any, i int) any { - switch v := v.(*DynamicMetadata); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_core_control_plane_networking_v1_service_proto_msgTypes[8].OneofWrappers = []any{} + file_core_control_plane_networking_v1_service_proto_msgTypes[9].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_core_control_plane_networking_v1_service_proto_rawDesc, - NumEnums: 2, - NumMessages: 12, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_control_plane_networking_v1_service_proto_rawDesc), len(file_core_control_plane_networking_v1_service_proto_rawDesc)), + NumEnums: 3, + NumMessages: 13, NumExtensions: 0, NumServices: 1, }, @@ -1121,7 +1026,6 @@ func file_core_control_plane_networking_v1_service_proto_init() { MessageInfos: file_core_control_plane_networking_v1_service_proto_msgTypes, }.Build() File_core_control_plane_networking_v1_service_proto = out.File - file_core_control_plane_networking_v1_service_proto_rawDesc = nil file_core_control_plane_networking_v1_service_proto_goTypes = nil file_core_control_plane_networking_v1_service_proto_depIdxs = nil } diff --git a/api/core/control_plane/networking/v1/service.pb.validate.go b/api/core/control_plane/networking/v1/service.pb.validate.go index dc82885a..3ea3f133 100644 --- a/api/core/control_plane/networking/v1/service.pb.validate.go +++ b/api/core/control_plane/networking/v1/service.pb.validate.go @@ -100,7 +100,7 @@ type AddRouteRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m AddRouteRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -202,7 +202,7 @@ type AddRouteResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m AddRouteResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -302,7 +302,7 @@ type ListRoutesRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ListRoutesRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -438,7 +438,7 @@ type ListRoutesResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ListRoutesResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -542,7 +542,7 @@ type DeleteRouteRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m DeleteRouteRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -646,7 +646,7 @@ type DeleteRouteResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m DeleteRouteResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -712,6 +712,109 @@ var _ interface { ErrorName() string } = DeleteRouteResponseValidationError{} +// Validate checks the field values on RouteAuth with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *RouteAuth) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on RouteAuth with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in RouteAuthMultiError, or nil +// if none found. +func (m *RouteAuth) ValidateAll() error { + return m.validate(true) +} + +func (m *RouteAuth) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Enabled + + // no validation rules for Policy + + if len(errors) > 0 { + return RouteAuthMultiError(errors) + } + + return nil +} + +// RouteAuthMultiError is an error wrapping multiple validation errors returned +// by RouteAuth.ValidateAll() if the designated constraints aren't met. +type RouteAuthMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m RouteAuthMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m RouteAuthMultiError) AllErrors() []error { return m } + +// RouteAuthValidationError is the validation error returned by +// RouteAuth.Validate if the designated constraints aren't met. +type RouteAuthValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e RouteAuthValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e RouteAuthValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e RouteAuthValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e RouteAuthValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e RouteAuthValidationError) ErrorName() string { return "RouteAuthValidationError" } + +// Error satisfies the builtin error interface +func (e RouteAuthValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteAuth.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = RouteAuthValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = RouteAuthValidationError{} + // Validate checks the field values on Route with the rules defined in the // proto definition for this message. If any rules are violated, the first // error encountered is returned, or nil if there are no violations. @@ -795,6 +898,35 @@ func (m *Route) validate(all bool) error { // no validation rules for EnableHttp2 + if all { + switch v := interface{}(m.GetAuth()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, RouteValidationError{ + field: "Auth", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, RouteValidationError{ + field: "Auth", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetAuth()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteValidationError{ + field: "Auth", + reason: "embedded message failed validation", + cause: err, + } + } + } + if len(errors) > 0 { return RouteMultiError(errors) } @@ -808,7 +940,7 @@ type RouteMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m RouteMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -911,7 +1043,7 @@ type EndpointMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m EndpointMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -1113,7 +1245,7 @@ type RouteMatchMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m RouteMatchMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -1217,7 +1349,7 @@ type HeaderMatchOptionsMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m HeaderMatchOptionsMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -1319,7 +1451,7 @@ type GrpcMatchOptionsMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m GrpcMatchOptionsMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -1419,7 +1551,7 @@ type DynamicMetadataMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m DynamicMetadataMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/core/control_plane/networking/v1/service.proto b/api/core/control_plane/networking/v1/service.proto index b4172f4f..21118ade 100644 --- a/api/core/control_plane/networking/v1/service.proto +++ b/api/core/control_plane/networking/v1/service.proto @@ -8,7 +8,7 @@ option go_package = "github.com/steady-bytes/draft/api/core/control_plane/networ // make endpoints available outside of the system (public, or private). To efficiently route traffic to the correct process, the // networking configuration is used to configure the `Envoy` proxy. The `Envoy` proxy is used to route traffic to the correct process // based on the provided `Route` configuration when the process registers to the system in this case `fuse`. -// +// // 1. The `NetworkingService` is a `core` service implemented in `fuse` // 2. Alot of the networking configuration is specific for `Envoy`. The `Route` proto is an example of this. It's basically a one to one mapping // of all fields that can't already be inferred by the `draft` framework. @@ -69,9 +69,32 @@ message DeleteRouteResponse { // Primary Networking Primitives +// AuthPolicy controls how Fuse configures the Envoy ext_authz filter for a route. +enum AuthPolicy { + // No auth check — route is public. + AUTH_POLICY_BYPASS = 0; + // Any valid token is accepted. + AUTH_POLICY_AUTHENTICATED = 1; + // Token must belong to one of the required_groups. + AUTH_POLICY_GROUPS = 2; + // Token must carry all of the required_scopes. + AUTH_POLICY_SCOPES = 3; +} + +// RouteAuth declares the authentication policy for a single route. When absent or +// enabled=false the route is public and no ext_authz check is performed. +message RouteAuth { + bool enabled = 1; + AuthPolicy policy = 2; + // Groups the caller must belong to (AUTH_POLICY_GROUPS). + repeated string required_groups = 3; + // OAuth2 scopes required on the token (AUTH_POLICY_SCOPES). + repeated string required_scopes = 4; +} + // Route - Close match to the `Route` proto in envoy. Anything that can't be inferred by the draft // framework needs to be added by the `process` adding the route configuration. -// +// // The process will register individual routes, while cluster and virtual host configuration will be handled by the framework. // current integration is `process` -> `fuse` -> `envoy` message Route { @@ -83,6 +106,8 @@ message Route { Endpoint endpoint = 3; // EnableHTTP2 enables HTTP2 support bool enable_http2 = 4; + // Auth declares the authentication policy for this route. Optional; defaults to bypass. + RouteAuth auth = 5; } // parameters for the endpoint a route will map to diff --git a/api/core/control_plane/networking/v1/v1connect/service.connect.go b/api/core/control_plane/networking/v1/v1connect/service.connect.go index fd85bf42..d886ba40 100644 --- a/api/core/control_plane/networking/v1/v1connect/service.connect.go +++ b/api/core/control_plane/networking/v1/v1connect/service.connect.go @@ -44,14 +44,6 @@ const ( NetworkingServiceDeleteRouteProcedure = "/core.control_plane.networking.v1.NetworkingService/DeleteRoute" ) -// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. -var ( - networkingServiceServiceDescriptor = v1.File_core_control_plane_networking_v1_service_proto.Services().ByName("NetworkingService") - networkingServiceAddRouteMethodDescriptor = networkingServiceServiceDescriptor.Methods().ByName("AddRoute") - networkingServiceListRoutesMethodDescriptor = networkingServiceServiceDescriptor.Methods().ByName("ListRoutes") - networkingServiceDeleteRouteMethodDescriptor = networkingServiceServiceDescriptor.Methods().ByName("DeleteRoute") -) - // NetworkingServiceClient is a client for the core.control_plane.networking.v1.NetworkingService // service. type NetworkingServiceClient interface { @@ -74,23 +66,24 @@ type NetworkingServiceClient interface { // http://api.acme.com or https://acme.com/grpc). func NewNetworkingServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) NetworkingServiceClient { baseURL = strings.TrimRight(baseURL, "/") + networkingServiceMethods := v1.File_core_control_plane_networking_v1_service_proto.Services().ByName("NetworkingService").Methods() return &networkingServiceClient{ addRoute: connect.NewClient[v1.AddRouteRequest, v1.AddRouteResponse]( httpClient, baseURL+NetworkingServiceAddRouteProcedure, - connect.WithSchema(networkingServiceAddRouteMethodDescriptor), + connect.WithSchema(networkingServiceMethods.ByName("AddRoute")), connect.WithClientOptions(opts...), ), listRoutes: connect.NewClient[v1.ListRoutesRequest, v1.ListRoutesResponse]( httpClient, baseURL+NetworkingServiceListRoutesProcedure, - connect.WithSchema(networkingServiceListRoutesMethodDescriptor), + connect.WithSchema(networkingServiceMethods.ByName("ListRoutes")), connect.WithClientOptions(opts...), ), deleteRoute: connect.NewClient[v1.DeleteRouteRequest, v1.DeleteRouteResponse]( httpClient, baseURL+NetworkingServiceDeleteRouteProcedure, - connect.WithSchema(networkingServiceDeleteRouteMethodDescriptor), + connect.WithSchema(networkingServiceMethods.ByName("DeleteRoute")), connect.WithClientOptions(opts...), ), } @@ -136,22 +129,23 @@ type NetworkingServiceHandler interface { // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. func NewNetworkingServiceHandler(svc NetworkingServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + networkingServiceMethods := v1.File_core_control_plane_networking_v1_service_proto.Services().ByName("NetworkingService").Methods() networkingServiceAddRouteHandler := connect.NewUnaryHandler( NetworkingServiceAddRouteProcedure, svc.AddRoute, - connect.WithSchema(networkingServiceAddRouteMethodDescriptor), + connect.WithSchema(networkingServiceMethods.ByName("AddRoute")), connect.WithHandlerOptions(opts...), ) networkingServiceListRoutesHandler := connect.NewUnaryHandler( NetworkingServiceListRoutesProcedure, svc.ListRoutes, - connect.WithSchema(networkingServiceListRoutesMethodDescriptor), + connect.WithSchema(networkingServiceMethods.ByName("ListRoutes")), connect.WithHandlerOptions(opts...), ) networkingServiceDeleteRouteHandler := connect.NewUnaryHandler( NetworkingServiceDeleteRouteProcedure, svc.DeleteRoute, - connect.WithSchema(networkingServiceDeleteRouteMethodDescriptor), + connect.WithSchema(networkingServiceMethods.ByName("DeleteRoute")), connect.WithHandlerOptions(opts...), ) return "/core.control_plane.networking.v1.NetworkingService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/api/core/message_broker/actors/v1/consumer.pb.go b/api/core/message_broker/actors/v1/consumer.pb.go index 23575fce..776b9958 100644 --- a/api/core/message_broker/actors/v1/consumer.pb.go +++ b/api/core/message_broker/actors/v1/consumer.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: core/message_broker/actors/v1/consumer.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -21,20 +22,17 @@ const ( ) type ConsumeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Message *CloudEvent `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` unknownFields protoimpl.UnknownFields - - Message *CloudEvent `protobuf:"bytes,1,opt,name=message,proto3" json:"message" bun:"message" csv:"message" pg:"message" yaml:"message"` + sizeCache protoimpl.SizeCache } func (x *ConsumeRequest) Reset() { *x = ConsumeRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_message_broker_actors_v1_consumer_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_message_broker_actors_v1_consumer_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ConsumeRequest) String() string { @@ -45,7 +43,7 @@ func (*ConsumeRequest) ProtoMessage() {} func (x *ConsumeRequest) ProtoReflect() protoreflect.Message { mi := &file_core_message_broker_actors_v1_consumer_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -68,20 +66,17 @@ func (x *ConsumeRequest) GetMessage() *CloudEvent { } type ConsumeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Message *CloudEvent `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` unknownFields protoimpl.UnknownFields - - Message *CloudEvent `protobuf:"bytes,1,opt,name=message,proto3" json:"message" bun:"message" csv:"message" pg:"message" yaml:"message"` + sizeCache protoimpl.SizeCache } func (x *ConsumeResponse) Reset() { *x = ConsumeResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_message_broker_actors_v1_consumer_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_message_broker_actors_v1_consumer_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ConsumeResponse) String() string { @@ -92,7 +87,7 @@ func (*ConsumeResponse) ProtoMessage() {} func (x *ConsumeResponse) ProtoReflect() protoreflect.Message { mi := &file_core_message_broker_actors_v1_consumer_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -116,48 +111,24 @@ func (x *ConsumeResponse) GetMessage() *CloudEvent { var File_core_message_broker_actors_v1_consumer_proto protoreflect.FileDescriptor -var file_core_message_broker_actors_v1_consumer_proto_rawDesc = []byte{ - 0x0a, 0x2c, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, - 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x76, 0x31, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, - 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x2a, 0x63, - 0x6f, 0x72, 0x65, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, - 0x65, 0x72, 0x2f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x6f, 0x64, - 0x65, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x55, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, - 0x65, 0x72, 0x2e, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, - 0x75, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x22, 0x56, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x63, 0x74, 0x6f, 0x72, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x78, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x12, 0x6c, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x12, - 0x2d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, - 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, - 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x30, 0x01, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, 0x72, - 0x61, 0x66, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2f, 0x61, 0x63, 0x74, 0x6f, - 0x72, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_core_message_broker_actors_v1_consumer_proto_rawDesc = "" + + "\n" + + ",core/message_broker/actors/v1/consumer.proto\x12\x1dcore.message_broker.actors.v1\x1a*core/message_broker/actors/v1/models.proto\"U\n" + + "\x0eConsumeRequest\x12C\n" + + "\amessage\x18\x01 \x01(\v2).core.message_broker.actors.v1.CloudEventR\amessage\"V\n" + + "\x0fConsumeResponse\x12C\n" + + "\amessage\x18\x01 \x01(\v2).core.message_broker.actors.v1.CloudEventR\amessage2x\n" + + "\bConsumer\x12l\n" + + "\aConsume\x12-.core.message_broker.actors.v1.ConsumeRequest\x1a..core.message_broker.actors.v1.ConsumeResponse\"\x000\x01BAZ?github.com/steady-bytes/draft/api/core/message_broker/actors/v1b\x06proto3" var ( file_core_message_broker_actors_v1_consumer_proto_rawDescOnce sync.Once - file_core_message_broker_actors_v1_consumer_proto_rawDescData = file_core_message_broker_actors_v1_consumer_proto_rawDesc + file_core_message_broker_actors_v1_consumer_proto_rawDescData []byte ) func file_core_message_broker_actors_v1_consumer_proto_rawDescGZIP() []byte { file_core_message_broker_actors_v1_consumer_proto_rawDescOnce.Do(func() { - file_core_message_broker_actors_v1_consumer_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_message_broker_actors_v1_consumer_proto_rawDescData) + file_core_message_broker_actors_v1_consumer_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_consumer_proto_rawDesc), len(file_core_message_broker_actors_v1_consumer_proto_rawDesc))) }) return file_core_message_broker_actors_v1_consumer_proto_rawDescData } @@ -186,37 +157,11 @@ func file_core_message_broker_actors_v1_consumer_proto_init() { return } file_core_message_broker_actors_v1_models_proto_init() - if !protoimpl.UnsafeEnabled { - file_core_message_broker_actors_v1_consumer_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*ConsumeRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_message_broker_actors_v1_consumer_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*ConsumeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_core_message_broker_actors_v1_consumer_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_consumer_proto_rawDesc), len(file_core_message_broker_actors_v1_consumer_proto_rawDesc)), NumEnums: 0, NumMessages: 2, NumExtensions: 0, @@ -227,7 +172,6 @@ func file_core_message_broker_actors_v1_consumer_proto_init() { MessageInfos: file_core_message_broker_actors_v1_consumer_proto_msgTypes, }.Build() File_core_message_broker_actors_v1_consumer_proto = out.File - file_core_message_broker_actors_v1_consumer_proto_rawDesc = nil file_core_message_broker_actors_v1_consumer_proto_goTypes = nil file_core_message_broker_actors_v1_consumer_proto_depIdxs = nil } diff --git a/api/core/message_broker/actors/v1/consumer.pb.validate.go b/api/core/message_broker/actors/v1/consumer.pb.validate.go index f5745c13..27e63226 100644 --- a/api/core/message_broker/actors/v1/consumer.pb.validate.go +++ b/api/core/message_broker/actors/v1/consumer.pb.validate.go @@ -100,7 +100,7 @@ type ConsumeRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ConsumeRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -229,7 +229,7 @@ type ConsumeResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ConsumeResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/core/message_broker/actors/v1/metrics.pb.go b/api/core/message_broker/actors/v1/metrics.pb.go new file mode 100644 index 00000000..27ca7d21 --- /dev/null +++ b/api/core/message_broker/actors/v1/metrics.pb.go @@ -0,0 +1,445 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: core/message_broker/actors/v1/metrics.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GetTopicSeriesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + EventType string `protobuf:"bytes,1,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` + WindowSeconds int32 `protobuf:"varint,2,opt,name=window_seconds,json=windowSeconds,proto3" json:"window_seconds,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTopicSeriesRequest) Reset() { + *x = GetTopicSeriesRequest{} + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTopicSeriesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTopicSeriesRequest) ProtoMessage() {} + +func (x *GetTopicSeriesRequest) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTopicSeriesRequest.ProtoReflect.Descriptor instead. +func (*GetTopicSeriesRequest) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_metrics_proto_rawDescGZIP(), []int{0} +} + +func (x *GetTopicSeriesRequest) GetEventType() string { + if x != nil { + return x.EventType + } + return "" +} + +func (x *GetTopicSeriesRequest) GetWindowSeconds() int32 { + if x != nil { + return x.WindowSeconds + } + return 0 +} + +type SeriesPoint struct { + state protoimpl.MessageState `protogen:"open.v1"` + TimestampMs int64 `protobuf:"varint,1,opt,name=timestamp_ms,json=timestampMs,proto3" json:"timestamp_ms,omitempty"` + Count uint32 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SeriesPoint) Reset() { + *x = SeriesPoint{} + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SeriesPoint) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SeriesPoint) ProtoMessage() {} + +func (x *SeriesPoint) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SeriesPoint.ProtoReflect.Descriptor instead. +func (*SeriesPoint) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_metrics_proto_rawDescGZIP(), []int{1} +} + +func (x *SeriesPoint) GetTimestampMs() int64 { + if x != nil { + return x.TimestampMs + } + return 0 +} + +func (x *SeriesPoint) GetCount() uint32 { + if x != nil { + return x.Count + } + return 0 +} + +type GetTopicSeriesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Points []*SeriesPoint `protobuf:"bytes,1,rep,name=points,proto3" json:"points,omitempty"` + BucketSecs int32 `protobuf:"varint,2,opt,name=bucket_secs,json=bucketSecs,proto3" json:"bucket_secs,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTopicSeriesResponse) Reset() { + *x = GetTopicSeriesResponse{} + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTopicSeriesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTopicSeriesResponse) ProtoMessage() {} + +func (x *GetTopicSeriesResponse) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTopicSeriesResponse.ProtoReflect.Descriptor instead. +func (*GetTopicSeriesResponse) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_metrics_proto_rawDescGZIP(), []int{2} +} + +func (x *GetTopicSeriesResponse) GetPoints() []*SeriesPoint { + if x != nil { + return x.Points + } + return nil +} + +func (x *GetTopicSeriesResponse) GetBucketSecs() int32 { + if x != nil { + return x.BucketSecs + } + return 0 +} + +type GetMetricsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // window_seconds is the lookback window for all metrics. 0 defaults to 300 (5 min). + WindowSeconds int32 `protobuf:"varint,1,opt,name=window_seconds,json=windowSeconds,proto3" json:"window_seconds,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetMetricsRequest) Reset() { + *x = GetMetricsRequest{} + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetMetricsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMetricsRequest) ProtoMessage() {} + +func (x *GetMetricsRequest) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMetricsRequest.ProtoReflect.Descriptor instead. +func (*GetMetricsRequest) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_metrics_proto_rawDescGZIP(), []int{3} +} + +func (x *GetMetricsRequest) GetWindowSeconds() int32 { + if x != nil { + return x.WindowSeconds + } + return 0 +} + +// EdgeVolume reports the event count for one (source, event_type) pair. +type EdgeVolume struct { + state protoimpl.MessageState `protogen:"open.v1"` + Source string `protobuf:"bytes,1,opt,name=source,proto3" json:"source,omitempty"` + EventType string `protobuf:"bytes,2,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` + Count uint32 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EdgeVolume) Reset() { + *x = EdgeVolume{} + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EdgeVolume) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EdgeVolume) ProtoMessage() {} + +func (x *EdgeVolume) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EdgeVolume.ProtoReflect.Descriptor instead. +func (*EdgeVolume) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_metrics_proto_rawDescGZIP(), []int{4} +} + +func (x *EdgeVolume) GetSource() string { + if x != nil { + return x.Source + } + return "" +} + +func (x *EdgeVolume) GetEventType() string { + if x != nil { + return x.EventType + } + return "" +} + +func (x *EdgeVolume) GetCount() uint32 { + if x != nil { + return x.Count + } + return 0 +} + +type GetMetricsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + EdgeVolumes []*EdgeVolume `protobuf:"bytes,1,rep,name=edge_volumes,json=edgeVolumes,proto3" json:"edge_volumes,omitempty"` + MedianLatencyMs float64 `protobuf:"fixed64,2,opt,name=median_latency_ms,json=medianLatencyMs,proto3" json:"median_latency_ms,omitempty"` + P95LatencyMs float64 `protobuf:"fixed64,3,opt,name=p95_latency_ms,json=p95LatencyMs,proto3" json:"p95_latency_ms,omitempty"` + TotalMessagesPerMin uint32 `protobuf:"varint,4,opt,name=total_messages_per_min,json=totalMessagesPerMin,proto3" json:"total_messages_per_min,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetMetricsResponse) Reset() { + *x = GetMetricsResponse{} + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetMetricsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMetricsResponse) ProtoMessage() {} + +func (x *GetMetricsResponse) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_metrics_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMetricsResponse.ProtoReflect.Descriptor instead. +func (*GetMetricsResponse) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_metrics_proto_rawDescGZIP(), []int{5} +} + +func (x *GetMetricsResponse) GetEdgeVolumes() []*EdgeVolume { + if x != nil { + return x.EdgeVolumes + } + return nil +} + +func (x *GetMetricsResponse) GetMedianLatencyMs() float64 { + if x != nil { + return x.MedianLatencyMs + } + return 0 +} + +func (x *GetMetricsResponse) GetP95LatencyMs() float64 { + if x != nil { + return x.P95LatencyMs + } + return 0 +} + +func (x *GetMetricsResponse) GetTotalMessagesPerMin() uint32 { + if x != nil { + return x.TotalMessagesPerMin + } + return 0 +} + +var File_core_message_broker_actors_v1_metrics_proto protoreflect.FileDescriptor + +const file_core_message_broker_actors_v1_metrics_proto_rawDesc = "" + + "\n" + + "+core/message_broker/actors/v1/metrics.proto\x12\x1dcore.message_broker.actors.v1\"]\n" + + "\x15GetTopicSeriesRequest\x12\x1d\n" + + "\n" + + "event_type\x18\x01 \x01(\tR\teventType\x12%\n" + + "\x0ewindow_seconds\x18\x02 \x01(\x05R\rwindowSeconds\"F\n" + + "\vSeriesPoint\x12!\n" + + "\ftimestamp_ms\x18\x01 \x01(\x03R\vtimestampMs\x12\x14\n" + + "\x05count\x18\x02 \x01(\rR\x05count\"}\n" + + "\x16GetTopicSeriesResponse\x12B\n" + + "\x06points\x18\x01 \x03(\v2*.core.message_broker.actors.v1.SeriesPointR\x06points\x12\x1f\n" + + "\vbucket_secs\x18\x02 \x01(\x05R\n" + + "bucketSecs\":\n" + + "\x11GetMetricsRequest\x12%\n" + + "\x0ewindow_seconds\x18\x01 \x01(\x05R\rwindowSeconds\"Y\n" + + "\n" + + "EdgeVolume\x12\x16\n" + + "\x06source\x18\x01 \x01(\tR\x06source\x12\x1d\n" + + "\n" + + "event_type\x18\x02 \x01(\tR\teventType\x12\x14\n" + + "\x05count\x18\x03 \x01(\rR\x05count\"\xe9\x01\n" + + "\x12GetMetricsResponse\x12L\n" + + "\fedge_volumes\x18\x01 \x03(\v2).core.message_broker.actors.v1.EdgeVolumeR\vedgeVolumes\x12*\n" + + "\x11median_latency_ms\x18\x02 \x01(\x01R\x0fmedianLatencyMs\x12$\n" + + "\x0ep95_latency_ms\x18\x03 \x01(\x01R\fp95LatencyMs\x123\n" + + "\x16total_messages_per_min\x18\x04 \x01(\rR\x13totalMessagesPerMin2\xff\x01\n" + + "\aMetrics\x12s\n" + + "\n" + + "GetMetrics\x120.core.message_broker.actors.v1.GetMetricsRequest\x1a1.core.message_broker.actors.v1.GetMetricsResponse\"\x00\x12\x7f\n" + + "\x0eGetTopicSeries\x124.core.message_broker.actors.v1.GetTopicSeriesRequest\x1a5.core.message_broker.actors.v1.GetTopicSeriesResponse\"\x00BAZ?github.com/steady-bytes/draft/api/core/message_broker/actors/v1b\x06proto3" + +var ( + file_core_message_broker_actors_v1_metrics_proto_rawDescOnce sync.Once + file_core_message_broker_actors_v1_metrics_proto_rawDescData []byte +) + +func file_core_message_broker_actors_v1_metrics_proto_rawDescGZIP() []byte { + file_core_message_broker_actors_v1_metrics_proto_rawDescOnce.Do(func() { + file_core_message_broker_actors_v1_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_metrics_proto_rawDesc), len(file_core_message_broker_actors_v1_metrics_proto_rawDesc))) + }) + return file_core_message_broker_actors_v1_metrics_proto_rawDescData +} + +var file_core_message_broker_actors_v1_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_core_message_broker_actors_v1_metrics_proto_goTypes = []any{ + (*GetTopicSeriesRequest)(nil), // 0: core.message_broker.actors.v1.GetTopicSeriesRequest + (*SeriesPoint)(nil), // 1: core.message_broker.actors.v1.SeriesPoint + (*GetTopicSeriesResponse)(nil), // 2: core.message_broker.actors.v1.GetTopicSeriesResponse + (*GetMetricsRequest)(nil), // 3: core.message_broker.actors.v1.GetMetricsRequest + (*EdgeVolume)(nil), // 4: core.message_broker.actors.v1.EdgeVolume + (*GetMetricsResponse)(nil), // 5: core.message_broker.actors.v1.GetMetricsResponse +} +var file_core_message_broker_actors_v1_metrics_proto_depIdxs = []int32{ + 1, // 0: core.message_broker.actors.v1.GetTopicSeriesResponse.points:type_name -> core.message_broker.actors.v1.SeriesPoint + 4, // 1: core.message_broker.actors.v1.GetMetricsResponse.edge_volumes:type_name -> core.message_broker.actors.v1.EdgeVolume + 3, // 2: core.message_broker.actors.v1.Metrics.GetMetrics:input_type -> core.message_broker.actors.v1.GetMetricsRequest + 0, // 3: core.message_broker.actors.v1.Metrics.GetTopicSeries:input_type -> core.message_broker.actors.v1.GetTopicSeriesRequest + 5, // 4: core.message_broker.actors.v1.Metrics.GetMetrics:output_type -> core.message_broker.actors.v1.GetMetricsResponse + 2, // 5: core.message_broker.actors.v1.Metrics.GetTopicSeries:output_type -> core.message_broker.actors.v1.GetTopicSeriesResponse + 4, // [4:6] is the sub-list for method output_type + 2, // [2:4] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_core_message_broker_actors_v1_metrics_proto_init() } +func file_core_message_broker_actors_v1_metrics_proto_init() { + if File_core_message_broker_actors_v1_metrics_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_metrics_proto_rawDesc), len(file_core_message_broker_actors_v1_metrics_proto_rawDesc)), + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_core_message_broker_actors_v1_metrics_proto_goTypes, + DependencyIndexes: file_core_message_broker_actors_v1_metrics_proto_depIdxs, + MessageInfos: file_core_message_broker_actors_v1_metrics_proto_msgTypes, + }.Build() + File_core_message_broker_actors_v1_metrics_proto = out.File + file_core_message_broker_actors_v1_metrics_proto_goTypes = nil + file_core_message_broker_actors_v1_metrics_proto_depIdxs = nil +} diff --git a/api/core/message_broker/actors/v1/metrics.pb.validate.go b/api/core/message_broker/actors/v1/metrics.pb.validate.go new file mode 100644 index 00000000..9a0cc492 --- /dev/null +++ b/api/core/message_broker/actors/v1/metrics.pb.validate.go @@ -0,0 +1,734 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: core/message_broker/actors/v1/metrics.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on GetTopicSeriesRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetTopicSeriesRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetTopicSeriesRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetTopicSeriesRequestMultiError, or nil if none found. +func (m *GetTopicSeriesRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GetTopicSeriesRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for EventType + + // no validation rules for WindowSeconds + + if len(errors) > 0 { + return GetTopicSeriesRequestMultiError(errors) + } + + return nil +} + +// GetTopicSeriesRequestMultiError is an error wrapping multiple validation +// errors returned by GetTopicSeriesRequest.ValidateAll() if the designated +// constraints aren't met. +type GetTopicSeriesRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetTopicSeriesRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetTopicSeriesRequestMultiError) AllErrors() []error { return m } + +// GetTopicSeriesRequestValidationError is the validation error returned by +// GetTopicSeriesRequest.Validate if the designated constraints aren't met. +type GetTopicSeriesRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetTopicSeriesRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetTopicSeriesRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetTopicSeriesRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetTopicSeriesRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetTopicSeriesRequestValidationError) ErrorName() string { + return "GetTopicSeriesRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e GetTopicSeriesRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetTopicSeriesRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetTopicSeriesRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetTopicSeriesRequestValidationError{} + +// Validate checks the field values on SeriesPoint with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *SeriesPoint) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on SeriesPoint with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in SeriesPointMultiError, or +// nil if none found. +func (m *SeriesPoint) ValidateAll() error { + return m.validate(true) +} + +func (m *SeriesPoint) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for TimestampMs + + // no validation rules for Count + + if len(errors) > 0 { + return SeriesPointMultiError(errors) + } + + return nil +} + +// SeriesPointMultiError is an error wrapping multiple validation errors +// returned by SeriesPoint.ValidateAll() if the designated constraints aren't met. +type SeriesPointMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m SeriesPointMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m SeriesPointMultiError) AllErrors() []error { return m } + +// SeriesPointValidationError is the validation error returned by +// SeriesPoint.Validate if the designated constraints aren't met. +type SeriesPointValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e SeriesPointValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e SeriesPointValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e SeriesPointValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e SeriesPointValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e SeriesPointValidationError) ErrorName() string { return "SeriesPointValidationError" } + +// Error satisfies the builtin error interface +func (e SeriesPointValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSeriesPoint.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = SeriesPointValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = SeriesPointValidationError{} + +// Validate checks the field values on GetTopicSeriesResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetTopicSeriesResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetTopicSeriesResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetTopicSeriesResponseMultiError, or nil if none found. +func (m *GetTopicSeriesResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GetTopicSeriesResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetPoints() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetTopicSeriesResponseValidationError{ + field: fmt.Sprintf("Points[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetTopicSeriesResponseValidationError{ + field: fmt.Sprintf("Points[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetTopicSeriesResponseValidationError{ + field: fmt.Sprintf("Points[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + // no validation rules for BucketSecs + + if len(errors) > 0 { + return GetTopicSeriesResponseMultiError(errors) + } + + return nil +} + +// GetTopicSeriesResponseMultiError is an error wrapping multiple validation +// errors returned by GetTopicSeriesResponse.ValidateAll() if the designated +// constraints aren't met. +type GetTopicSeriesResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetTopicSeriesResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetTopicSeriesResponseMultiError) AllErrors() []error { return m } + +// GetTopicSeriesResponseValidationError is the validation error returned by +// GetTopicSeriesResponse.Validate if the designated constraints aren't met. +type GetTopicSeriesResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetTopicSeriesResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetTopicSeriesResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetTopicSeriesResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetTopicSeriesResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetTopicSeriesResponseValidationError) ErrorName() string { + return "GetTopicSeriesResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GetTopicSeriesResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetTopicSeriesResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetTopicSeriesResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetTopicSeriesResponseValidationError{} + +// Validate checks the field values on GetMetricsRequest with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *GetMetricsRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetMetricsRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetMetricsRequestMultiError, or nil if none found. +func (m *GetMetricsRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GetMetricsRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for WindowSeconds + + if len(errors) > 0 { + return GetMetricsRequestMultiError(errors) + } + + return nil +} + +// GetMetricsRequestMultiError is an error wrapping multiple validation errors +// returned by GetMetricsRequest.ValidateAll() if the designated constraints +// aren't met. +type GetMetricsRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetMetricsRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetMetricsRequestMultiError) AllErrors() []error { return m } + +// GetMetricsRequestValidationError is the validation error returned by +// GetMetricsRequest.Validate if the designated constraints aren't met. +type GetMetricsRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetMetricsRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetMetricsRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetMetricsRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetMetricsRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetMetricsRequestValidationError) ErrorName() string { + return "GetMetricsRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e GetMetricsRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetMetricsRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetMetricsRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetMetricsRequestValidationError{} + +// Validate checks the field values on EdgeVolume with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *EdgeVolume) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on EdgeVolume with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in EdgeVolumeMultiError, or +// nil if none found. +func (m *EdgeVolume) ValidateAll() error { + return m.validate(true) +} + +func (m *EdgeVolume) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Source + + // no validation rules for EventType + + // no validation rules for Count + + if len(errors) > 0 { + return EdgeVolumeMultiError(errors) + } + + return nil +} + +// EdgeVolumeMultiError is an error wrapping multiple validation errors +// returned by EdgeVolume.ValidateAll() if the designated constraints aren't met. +type EdgeVolumeMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m EdgeVolumeMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m EdgeVolumeMultiError) AllErrors() []error { return m } + +// EdgeVolumeValidationError is the validation error returned by +// EdgeVolume.Validate if the designated constraints aren't met. +type EdgeVolumeValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e EdgeVolumeValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e EdgeVolumeValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e EdgeVolumeValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e EdgeVolumeValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e EdgeVolumeValidationError) ErrorName() string { return "EdgeVolumeValidationError" } + +// Error satisfies the builtin error interface +func (e EdgeVolumeValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEdgeVolume.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = EdgeVolumeValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = EdgeVolumeValidationError{} + +// Validate checks the field values on GetMetricsResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetMetricsResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetMetricsResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetMetricsResponseMultiError, or nil if none found. +func (m *GetMetricsResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GetMetricsResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetEdgeVolumes() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetMetricsResponseValidationError{ + field: fmt.Sprintf("EdgeVolumes[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetMetricsResponseValidationError{ + field: fmt.Sprintf("EdgeVolumes[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetMetricsResponseValidationError{ + field: fmt.Sprintf("EdgeVolumes[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + // no validation rules for MedianLatencyMs + + // no validation rules for P95LatencyMs + + // no validation rules for TotalMessagesPerMin + + if len(errors) > 0 { + return GetMetricsResponseMultiError(errors) + } + + return nil +} + +// GetMetricsResponseMultiError is an error wrapping multiple validation errors +// returned by GetMetricsResponse.ValidateAll() if the designated constraints +// aren't met. +type GetMetricsResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetMetricsResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetMetricsResponseMultiError) AllErrors() []error { return m } + +// GetMetricsResponseValidationError is the validation error returned by +// GetMetricsResponse.Validate if the designated constraints aren't met. +type GetMetricsResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetMetricsResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetMetricsResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetMetricsResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetMetricsResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetMetricsResponseValidationError) ErrorName() string { + return "GetMetricsResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GetMetricsResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetMetricsResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetMetricsResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetMetricsResponseValidationError{} diff --git a/api/core/message_broker/actors/v1/metrics.proto b/api/core/message_broker/actors/v1/metrics.proto new file mode 100644 index 00000000..68103f83 --- /dev/null +++ b/api/core/message_broker/actors/v1/metrics.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; + +package core.message_broker.actors.v1; + +option go_package = "github.com/steady-bytes/draft/api/core/message_broker/actors/v1"; + +service Metrics { + // GetMetrics returns pre-computed throughput and latency metrics derived from + // ClickHouse aggregates over the requested time window. + rpc GetMetrics(GetMetricsRequest) returns (GetMetricsResponse) {} + // GetTopicSeries returns a time-bucketed message count for one event_type, + // suitable for rendering a line chart over the requested window. + rpc GetTopicSeries(GetTopicSeriesRequest) returns (GetTopicSeriesResponse) {} +} + +message GetTopicSeriesRequest { + string event_type = 1; + int32 window_seconds = 2; +} + +message SeriesPoint { + int64 timestamp_ms = 1; + uint32 count = 2; +} + +message GetTopicSeriesResponse { + repeated SeriesPoint points = 1; + int32 bucket_secs = 2; +} + +message GetMetricsRequest { + // window_seconds is the lookback window for all metrics. 0 defaults to 300 (5 min). + int32 window_seconds = 1; +} + +// EdgeVolume reports the event count for one (source, event_type) pair. +message EdgeVolume { + string source = 1; + string event_type = 2; + uint32 count = 3; +} + +message GetMetricsResponse { + repeated EdgeVolume edge_volumes = 1; + double median_latency_ms = 2; + double p95_latency_ms = 3; + uint32 total_messages_per_min = 4; +} diff --git a/api/core/message_broker/actors/v1/models.pb.go b/api/core/message_broker/actors/v1/models.pb.go index cbfb690a..8747f9a3 100644 --- a/api/core/message_broker/actors/v1/models.pb.go +++ b/api/core/message_broker/actors/v1/models.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: core/message_broker/actors/v1/models.proto @@ -13,6 +13,7 @@ import ( timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -31,34 +32,31 @@ const ( // // REF: [https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/cloudevents.proto] type CloudEvent struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Required Attributes - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id" bun:"id" csv:"id" pg:"id" yaml:"id"` - Source string `protobuf:"bytes,2,opt,name=source,proto3" json:"source" bun:"source" csv:"source" pg:"source" yaml:"source"` // URI-reference - SpecVersion string `protobuf:"bytes,3,opt,name=spec_version,json=specVersion,proto3" json:"spec_version" bun:"spec_version" csv:"spec_version" pg:"spec_version" yaml:"spec_version"` - Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type" bun:"type" csv:"type" pg:"type" yaml:"type"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Source string `protobuf:"bytes,2,opt,name=source,proto3" json:"source,omitempty"` // URI-reference + SpecVersion string `protobuf:"bytes,3,opt,name=spec_version,json=specVersion,proto3" json:"spec_version,omitempty"` + Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"` // Optional & Extension Attributes - Attributes map[string]*CloudEvent_CloudEventAttributeValue `protobuf:"bytes,5,rep,name=attributes,proto3" json:"attributes" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" bun:"attributes" csv:"attributes" pg:"attributes" yaml:"attributes"` + Attributes map[string]*CloudEvent_CloudEventAttributeValue `protobuf:"bytes,5,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // -- CloudEvent Data (Bytes, Text, or Proto) // - // Types that are assignable to Data: + // Types that are valid to be assigned to Data: // // *CloudEvent_BinaryData // *CloudEvent_TextData // *CloudEvent_ProtoData - Data isCloudEvent_Data `protobuf_oneof:"data"` + Data isCloudEvent_Data `protobuf_oneof:"data"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CloudEvent) Reset() { *x = CloudEvent{} - if protoimpl.UnsafeEnabled { - mi := &file_core_message_broker_actors_v1_models_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_message_broker_actors_v1_models_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CloudEvent) String() string { @@ -69,7 +67,7 @@ func (*CloudEvent) ProtoMessage() {} func (x *CloudEvent) ProtoReflect() protoreflect.Message { mi := &file_core_message_broker_actors_v1_models_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -119,30 +117,36 @@ func (x *CloudEvent) GetAttributes() map[string]*CloudEvent_CloudEventAttributeV return nil } -func (m *CloudEvent) GetData() isCloudEvent_Data { - if m != nil { - return m.Data +func (x *CloudEvent) GetData() isCloudEvent_Data { + if x != nil { + return x.Data } return nil } func (x *CloudEvent) GetBinaryData() []byte { - if x, ok := x.GetData().(*CloudEvent_BinaryData); ok { - return x.BinaryData + if x != nil { + if x, ok := x.Data.(*CloudEvent_BinaryData); ok { + return x.BinaryData + } } return nil } func (x *CloudEvent) GetTextData() string { - if x, ok := x.GetData().(*CloudEvent_TextData); ok { - return x.TextData + if x != nil { + if x, ok := x.Data.(*CloudEvent_TextData); ok { + return x.TextData + } } return "" } func (x *CloudEvent) GetProtoData() *anypb.Any { - if x, ok := x.GetData().(*CloudEvent_ProtoData); ok { - return x.ProtoData + if x != nil { + if x, ok := x.Data.(*CloudEvent_ProtoData); ok { + return x.ProtoData + } } return nil } @@ -152,15 +156,15 @@ type isCloudEvent_Data interface { } type CloudEvent_BinaryData struct { - BinaryData []byte `protobuf:"bytes,6,opt,name=binary_data,json=binaryData,proto3,oneof" bun:"binary_data" csv:"binary_data" json:"binary_data" pg:"binary_data" yaml:"binary_data"` + BinaryData []byte `protobuf:"bytes,6,opt,name=binary_data,json=binaryData,proto3,oneof"` } type CloudEvent_TextData struct { - TextData string `protobuf:"bytes,7,opt,name=text_data,json=textData,proto3,oneof" bun:"text_data" csv:"text_data" json:"text_data" pg:"text_data" yaml:"text_data"` + TextData string `protobuf:"bytes,7,opt,name=text_data,json=textData,proto3,oneof"` } type CloudEvent_ProtoData struct { - ProtoData *anypb.Any `protobuf:"bytes,8,opt,name=proto_data,json=protoData,proto3,oneof" bun:"proto_data" csv:"proto_data" json:"proto_data" pg:"proto_data" yaml:"proto_data"` + ProtoData *anypb.Any `protobuf:"bytes,8,opt,name=proto_data,json=protoData,proto3,oneof"` } func (*CloudEvent_BinaryData) isCloudEvent_Data() {} @@ -172,20 +176,17 @@ func (*CloudEvent_ProtoData) isCloudEvent_Data() {} // * // CloudEvent Protobuf Batch Format type CloudEventBatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Events []*CloudEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` unknownFields protoimpl.UnknownFields - - Events []*CloudEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events" bun:"events" csv:"events" pg:"events" yaml:"events"` + sizeCache protoimpl.SizeCache } func (x *CloudEventBatch) Reset() { *x = CloudEventBatch{} - if protoimpl.UnsafeEnabled { - mi := &file_core_message_broker_actors_v1_models_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_message_broker_actors_v1_models_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CloudEventBatch) String() string { @@ -196,7 +197,7 @@ func (*CloudEventBatch) ProtoMessage() {} func (x *CloudEventBatch) ProtoReflect() protoreflect.Message { mi := &file_core_message_broker_actors_v1_models_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -219,11 +220,8 @@ func (x *CloudEventBatch) GetEvents() []*CloudEvent { } type CloudEvent_CloudEventAttributeValue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Attr: + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Attr: // // *CloudEvent_CloudEventAttributeValue_CeBoolean // *CloudEvent_CloudEventAttributeValue_CeInteger @@ -232,16 +230,16 @@ type CloudEvent_CloudEventAttributeValue struct { // *CloudEvent_CloudEventAttributeValue_CeUri // *CloudEvent_CloudEventAttributeValue_CeUriRef // *CloudEvent_CloudEventAttributeValue_CeTimestamp - Attr isCloudEvent_CloudEventAttributeValue_Attr `protobuf_oneof:"attr"` + Attr isCloudEvent_CloudEventAttributeValue_Attr `protobuf_oneof:"attr"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CloudEvent_CloudEventAttributeValue) Reset() { *x = CloudEvent_CloudEventAttributeValue{} - if protoimpl.UnsafeEnabled { - mi := &file_core_message_broker_actors_v1_models_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_message_broker_actors_v1_models_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CloudEvent_CloudEventAttributeValue) String() string { @@ -252,7 +250,7 @@ func (*CloudEvent_CloudEventAttributeValue) ProtoMessage() {} func (x *CloudEvent_CloudEventAttributeValue) ProtoReflect() protoreflect.Message { mi := &file_core_message_broker_actors_v1_models_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -267,58 +265,72 @@ func (*CloudEvent_CloudEventAttributeValue) Descriptor() ([]byte, []int) { return file_core_message_broker_actors_v1_models_proto_rawDescGZIP(), []int{0, 1} } -func (m *CloudEvent_CloudEventAttributeValue) GetAttr() isCloudEvent_CloudEventAttributeValue_Attr { - if m != nil { - return m.Attr +func (x *CloudEvent_CloudEventAttributeValue) GetAttr() isCloudEvent_CloudEventAttributeValue_Attr { + if x != nil { + return x.Attr } return nil } func (x *CloudEvent_CloudEventAttributeValue) GetCeBoolean() bool { - if x, ok := x.GetAttr().(*CloudEvent_CloudEventAttributeValue_CeBoolean); ok { - return x.CeBoolean + if x != nil { + if x, ok := x.Attr.(*CloudEvent_CloudEventAttributeValue_CeBoolean); ok { + return x.CeBoolean + } } return false } func (x *CloudEvent_CloudEventAttributeValue) GetCeInteger() int32 { - if x, ok := x.GetAttr().(*CloudEvent_CloudEventAttributeValue_CeInteger); ok { - return x.CeInteger + if x != nil { + if x, ok := x.Attr.(*CloudEvent_CloudEventAttributeValue_CeInteger); ok { + return x.CeInteger + } } return 0 } func (x *CloudEvent_CloudEventAttributeValue) GetCeString() string { - if x, ok := x.GetAttr().(*CloudEvent_CloudEventAttributeValue_CeString); ok { - return x.CeString + if x != nil { + if x, ok := x.Attr.(*CloudEvent_CloudEventAttributeValue_CeString); ok { + return x.CeString + } } return "" } func (x *CloudEvent_CloudEventAttributeValue) GetCeBytes() []byte { - if x, ok := x.GetAttr().(*CloudEvent_CloudEventAttributeValue_CeBytes); ok { - return x.CeBytes + if x != nil { + if x, ok := x.Attr.(*CloudEvent_CloudEventAttributeValue_CeBytes); ok { + return x.CeBytes + } } return nil } func (x *CloudEvent_CloudEventAttributeValue) GetCeUri() string { - if x, ok := x.GetAttr().(*CloudEvent_CloudEventAttributeValue_CeUri); ok { - return x.CeUri + if x != nil { + if x, ok := x.Attr.(*CloudEvent_CloudEventAttributeValue_CeUri); ok { + return x.CeUri + } } return "" } func (x *CloudEvent_CloudEventAttributeValue) GetCeUriRef() string { - if x, ok := x.GetAttr().(*CloudEvent_CloudEventAttributeValue_CeUriRef); ok { - return x.CeUriRef + if x != nil { + if x, ok := x.Attr.(*CloudEvent_CloudEventAttributeValue_CeUriRef); ok { + return x.CeUriRef + } } return "" } func (x *CloudEvent_CloudEventAttributeValue) GetCeTimestamp() *timestamppb.Timestamp { - if x, ok := x.GetAttr().(*CloudEvent_CloudEventAttributeValue_CeTimestamp); ok { - return x.CeTimestamp + if x != nil { + if x, ok := x.Attr.(*CloudEvent_CloudEventAttributeValue_CeTimestamp); ok { + return x.CeTimestamp + } } return nil } @@ -372,83 +384,50 @@ func (*CloudEvent_CloudEventAttributeValue_CeTimestamp) isCloudEvent_CloudEventA var File_core_message_broker_actors_v1_models_proto protoreflect.FileDescriptor -var file_core_message_broker_actors_v1_models_proto_rawDesc = []byte{ - 0x0a, 0x2a, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, - 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x76, 0x31, 0x2f, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, - 0x72, 0x2e, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe8, 0x05, 0x0a, 0x0a, 0x43, 0x6c, 0x6f, 0x75, - 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x21, - 0x0a, 0x0c, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x70, 0x65, 0x63, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x59, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, - 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x12, 0x21, 0x0a, 0x0b, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0a, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x44, - 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x09, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x74, 0x65, 0x78, 0x74, 0x44, 0x61, - 0x74, 0x61, 0x12, 0x35, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x48, 0x00, 0x52, 0x09, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x81, 0x01, 0x0a, 0x0f, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x58, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, - 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6c, 0x6f, 0x75, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x9a, 0x02, - 0x0a, 0x18, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x63, 0x65, - 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, - 0x52, 0x09, 0x63, 0x65, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x12, 0x1f, 0x0a, 0x0a, 0x63, - 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, - 0x00, 0x52, 0x09, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x09, - 0x63, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x00, 0x52, 0x08, 0x63, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x08, 0x63, - 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, - 0x07, 0x63, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x17, 0x0a, 0x06, 0x63, 0x65, 0x5f, 0x75, - 0x72, 0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x63, 0x65, 0x55, 0x72, - 0x69, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x65, 0x5f, 0x75, 0x72, 0x69, 0x5f, 0x72, 0x65, 0x66, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x63, 0x65, 0x55, 0x72, 0x69, 0x52, 0x65, - 0x66, 0x12, 0x3f, 0x0a, 0x0c, 0x63, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x74, 0x74, 0x72, 0x42, 0x06, 0x0a, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x22, 0x54, 0x0a, 0x0f, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x41, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x63, 0x74, 0x6f, - 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, 0x2d, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x2f, 0x64, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, - 0x72, 0x65, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, - 0x72, 0x2f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, -} +const file_core_message_broker_actors_v1_models_proto_rawDesc = "" + + "\n" + + "*core/message_broker/actors/v1/models.proto\x12\x1dcore.message_broker.actors.v1\x1a\x19google/protobuf/any.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xe8\x05\n" + + "\n" + + "CloudEvent\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x16\n" + + "\x06source\x18\x02 \x01(\tR\x06source\x12!\n" + + "\fspec_version\x18\x03 \x01(\tR\vspecVersion\x12\x12\n" + + "\x04type\x18\x04 \x01(\tR\x04type\x12Y\n" + + "\n" + + "attributes\x18\x05 \x03(\v29.core.message_broker.actors.v1.CloudEvent.AttributesEntryR\n" + + "attributes\x12!\n" + + "\vbinary_data\x18\x06 \x01(\fH\x00R\n" + + "binaryData\x12\x1d\n" + + "\ttext_data\x18\a \x01(\tH\x00R\btextData\x125\n" + + "\n" + + "proto_data\x18\b \x01(\v2\x14.google.protobuf.AnyH\x00R\tprotoData\x1a\x81\x01\n" + + "\x0fAttributesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12X\n" + + "\x05value\x18\x02 \x01(\v2B.core.message_broker.actors.v1.CloudEvent.CloudEventAttributeValueR\x05value:\x028\x01\x1a\x9a\x02\n" + + "\x18CloudEventAttributeValue\x12\x1f\n" + + "\n" + + "ce_boolean\x18\x01 \x01(\bH\x00R\tceBoolean\x12\x1f\n" + + "\n" + + "ce_integer\x18\x02 \x01(\x05H\x00R\tceInteger\x12\x1d\n" + + "\tce_string\x18\x03 \x01(\tH\x00R\bceString\x12\x1b\n" + + "\bce_bytes\x18\x04 \x01(\fH\x00R\aceBytes\x12\x17\n" + + "\x06ce_uri\x18\x05 \x01(\tH\x00R\x05ceUri\x12\x1e\n" + + "\n" + + "ce_uri_ref\x18\x06 \x01(\tH\x00R\bceUriRef\x12?\n" + + "\fce_timestamp\x18\a \x01(\v2\x1a.google.protobuf.TimestampH\x00R\vceTimestampB\x06\n" + + "\x04attrB\x06\n" + + "\x04data\"T\n" + + "\x0fCloudEventBatch\x12A\n" + + "\x06events\x18\x01 \x03(\v2).core.message_broker.actors.v1.CloudEventR\x06eventsBAZ?github.com/steady-bytes/draft/api/core/message_broker/actors/v1b\x06proto3" var ( file_core_message_broker_actors_v1_models_proto_rawDescOnce sync.Once - file_core_message_broker_actors_v1_models_proto_rawDescData = file_core_message_broker_actors_v1_models_proto_rawDesc + file_core_message_broker_actors_v1_models_proto_rawDescData []byte ) func file_core_message_broker_actors_v1_models_proto_rawDescGZIP() []byte { file_core_message_broker_actors_v1_models_proto_rawDescOnce.Do(func() { - file_core_message_broker_actors_v1_models_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_message_broker_actors_v1_models_proto_rawDescData) + file_core_message_broker_actors_v1_models_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_models_proto_rawDesc), len(file_core_message_broker_actors_v1_models_proto_rawDesc))) }) return file_core_message_broker_actors_v1_models_proto_rawDescData } @@ -480,44 +459,6 @@ func file_core_message_broker_actors_v1_models_proto_init() { if File_core_message_broker_actors_v1_models_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_core_message_broker_actors_v1_models_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*CloudEvent); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_message_broker_actors_v1_models_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*CloudEventBatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_message_broker_actors_v1_models_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*CloudEvent_CloudEventAttributeValue); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } file_core_message_broker_actors_v1_models_proto_msgTypes[0].OneofWrappers = []any{ (*CloudEvent_BinaryData)(nil), (*CloudEvent_TextData)(nil), @@ -536,7 +477,7 @@ func file_core_message_broker_actors_v1_models_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_core_message_broker_actors_v1_models_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_models_proto_rawDesc), len(file_core_message_broker_actors_v1_models_proto_rawDesc)), NumEnums: 0, NumMessages: 4, NumExtensions: 0, @@ -547,7 +488,6 @@ func file_core_message_broker_actors_v1_models_proto_init() { MessageInfos: file_core_message_broker_actors_v1_models_proto_msgTypes, }.Build() File_core_message_broker_actors_v1_models_proto = out.File - file_core_message_broker_actors_v1_models_proto_rawDesc = nil file_core_message_broker_actors_v1_models_proto_goTypes = nil file_core_message_broker_actors_v1_models_proto_depIdxs = nil } diff --git a/api/core/message_broker/actors/v1/models.pb.validate.go b/api/core/message_broker/actors/v1/models.pb.validate.go index d116c705..89d1b3a9 100644 --- a/api/core/message_broker/actors/v1/models.pb.validate.go +++ b/api/core/message_broker/actors/v1/models.pb.validate.go @@ -194,7 +194,7 @@ type CloudEventMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m CloudEventMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -328,7 +328,7 @@ type CloudEventBatchMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m CloudEventBatchMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -548,7 +548,7 @@ type CloudEvent_CloudEventAttributeValueMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m CloudEvent_CloudEventAttributeValueMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/core/message_broker/actors/v1/models.proto b/api/core/message_broker/actors/v1/models.proto index 100a93e6..b17a2445 100644 --- a/api/core/message_broker/actors/v1/models.proto +++ b/api/core/message_broker/actors/v1/models.proto @@ -64,5 +64,5 @@ message CloudEvent { * */ message CloudEventBatch { - repeated CloudEvent events = 1; + repeated CloudEvent events = 1; } \ No newline at end of file diff --git a/api/core/message_broker/actors/v1/producer.pb.go b/api/core/message_broker/actors/v1/producer.pb.go index 6a19b2c0..c805c7e0 100644 --- a/api/core/message_broker/actors/v1/producer.pb.go +++ b/api/core/message_broker/actors/v1/producer.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: core/message_broker/actors/v1/producer.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -22,20 +23,17 @@ const ( // Send this `Message` to the other `Actors` in the system that are subscribed to this `Message` type ProduceRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Message *CloudEvent `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` unknownFields protoimpl.UnknownFields - - Message *CloudEvent `protobuf:"bytes,1,opt,name=message,proto3" json:"message" bun:"message" csv:"message" pg:"message" yaml:"message"` + sizeCache protoimpl.SizeCache } func (x *ProduceRequest) Reset() { *x = ProduceRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_message_broker_actors_v1_producer_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_message_broker_actors_v1_producer_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ProduceRequest) String() string { @@ -46,7 +44,7 @@ func (*ProduceRequest) ProtoMessage() {} func (x *ProduceRequest) ProtoReflect() protoreflect.Message { mi := &file_core_message_broker_actors_v1_producer_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -69,21 +67,18 @@ func (x *ProduceRequest) GetMessage() *CloudEvent { } type ProduceResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // The message id is returned as a way to acknowledge the message as been committed - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id" bun:"id" csv:"id" pg:"id" yaml:"id"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ProduceResponse) Reset() { *x = ProduceResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_message_broker_actors_v1_producer_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_message_broker_actors_v1_producer_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ProduceResponse) String() string { @@ -94,7 +89,7 @@ func (*ProduceResponse) ProtoMessage() {} func (x *ProduceResponse) ProtoReflect() protoreflect.Message { mi := &file_core_message_broker_actors_v1_producer_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -118,45 +113,24 @@ func (x *ProduceResponse) GetId() string { var File_core_message_broker_actors_v1_producer_proto protoreflect.FileDescriptor -var file_core_message_broker_actors_v1_producer_proto_rawDesc = []byte{ - 0x0a, 0x2c, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, - 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x76, 0x31, 0x2f, - 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, - 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x2a, 0x63, - 0x6f, 0x72, 0x65, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, - 0x65, 0x72, 0x2f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x6f, 0x64, - 0x65, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x55, 0x0a, 0x0e, 0x50, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, - 0x65, 0x72, 0x2e, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, - 0x75, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x22, 0x21, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x32, 0x7a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x12, - 0x6e, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, - 0x2e, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, - 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, - 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, - 0x65, 0x61, 0x64, 0x79, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, 0x72, 0x61, 0x66, 0x74, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, - 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_core_message_broker_actors_v1_producer_proto_rawDesc = "" + + "\n" + + ",core/message_broker/actors/v1/producer.proto\x12\x1dcore.message_broker.actors.v1\x1a*core/message_broker/actors/v1/models.proto\"U\n" + + "\x0eProduceRequest\x12C\n" + + "\amessage\x18\x01 \x01(\v2).core.message_broker.actors.v1.CloudEventR\amessage\"!\n" + + "\x0fProduceResponse\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id2z\n" + + "\bProducer\x12n\n" + + "\aProduce\x12-.core.message_broker.actors.v1.ProduceRequest\x1a..core.message_broker.actors.v1.ProduceResponse\"\x00(\x010\x01BAZ?github.com/steady-bytes/draft/api/core/message_broker/actors/v1b\x06proto3" var ( file_core_message_broker_actors_v1_producer_proto_rawDescOnce sync.Once - file_core_message_broker_actors_v1_producer_proto_rawDescData = file_core_message_broker_actors_v1_producer_proto_rawDesc + file_core_message_broker_actors_v1_producer_proto_rawDescData []byte ) func file_core_message_broker_actors_v1_producer_proto_rawDescGZIP() []byte { file_core_message_broker_actors_v1_producer_proto_rawDescOnce.Do(func() { - file_core_message_broker_actors_v1_producer_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_message_broker_actors_v1_producer_proto_rawDescData) + file_core_message_broker_actors_v1_producer_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_producer_proto_rawDesc), len(file_core_message_broker_actors_v1_producer_proto_rawDesc))) }) return file_core_message_broker_actors_v1_producer_proto_rawDescData } @@ -184,37 +158,11 @@ func file_core_message_broker_actors_v1_producer_proto_init() { return } file_core_message_broker_actors_v1_models_proto_init() - if !protoimpl.UnsafeEnabled { - file_core_message_broker_actors_v1_producer_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*ProduceRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_message_broker_actors_v1_producer_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*ProduceResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_core_message_broker_actors_v1_producer_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_producer_proto_rawDesc), len(file_core_message_broker_actors_v1_producer_proto_rawDesc)), NumEnums: 0, NumMessages: 2, NumExtensions: 0, @@ -225,7 +173,6 @@ func file_core_message_broker_actors_v1_producer_proto_init() { MessageInfos: file_core_message_broker_actors_v1_producer_proto_msgTypes, }.Build() File_core_message_broker_actors_v1_producer_proto = out.File - file_core_message_broker_actors_v1_producer_proto_rawDesc = nil file_core_message_broker_actors_v1_producer_proto_goTypes = nil file_core_message_broker_actors_v1_producer_proto_depIdxs = nil } diff --git a/api/core/message_broker/actors/v1/producer.pb.validate.go b/api/core/message_broker/actors/v1/producer.pb.validate.go index 01aaabf4..7c82f11c 100644 --- a/api/core/message_broker/actors/v1/producer.pb.validate.go +++ b/api/core/message_broker/actors/v1/producer.pb.validate.go @@ -100,7 +100,7 @@ type ProduceRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ProduceRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -202,7 +202,7 @@ type ProduceResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ProduceResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/core/message_broker/actors/v1/query.pb.go b/api/core/message_broker/actors/v1/query.pb.go new file mode 100644 index 00000000..3871be9b --- /dev/null +++ b/api/core/message_broker/actors/v1/query.pb.go @@ -0,0 +1,1341 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: core/message_broker/actors/v1/query.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type OrderDirection int32 + +const ( + OrderDirection_ORDER_DIRECTION_UNSPECIFIED OrderDirection = 0 // treated as ASC + OrderDirection_ORDER_DIRECTION_ASC OrderDirection = 1 + OrderDirection_ORDER_DIRECTION_DESC OrderDirection = 2 +) + +// Enum value maps for OrderDirection. +var ( + OrderDirection_name = map[int32]string{ + 0: "ORDER_DIRECTION_UNSPECIFIED", + 1: "ORDER_DIRECTION_ASC", + 2: "ORDER_DIRECTION_DESC", + } + OrderDirection_value = map[string]int32{ + "ORDER_DIRECTION_UNSPECIFIED": 0, + "ORDER_DIRECTION_ASC": 1, + "ORDER_DIRECTION_DESC": 2, + } +) + +func (x OrderDirection) Enum() *OrderDirection { + p := new(OrderDirection) + *p = x + return p +} + +func (x OrderDirection) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (OrderDirection) Descriptor() protoreflect.EnumDescriptor { + return file_core_message_broker_actors_v1_query_proto_enumTypes[0].Descriptor() +} + +func (OrderDirection) Type() protoreflect.EnumType { + return &file_core_message_broker_actors_v1_query_proto_enumTypes[0] +} + +func (x OrderDirection) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use OrderDirection.Descriptor instead. +func (OrderDirection) EnumDescriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{0} +} + +type UnaryOp int32 + +const ( + UnaryOp_UNARY_OP_UNSPECIFIED UnaryOp = 0 + UnaryOp_UNARY_OP_NOT UnaryOp = 1 // Boolean → Boolean + UnaryOp_UNARY_OP_NEGATE UnaryOp = 2 // Integer → Integer (unary minus) +) + +// Enum value maps for UnaryOp. +var ( + UnaryOp_name = map[int32]string{ + 0: "UNARY_OP_UNSPECIFIED", + 1: "UNARY_OP_NOT", + 2: "UNARY_OP_NEGATE", + } + UnaryOp_value = map[string]int32{ + "UNARY_OP_UNSPECIFIED": 0, + "UNARY_OP_NOT": 1, + "UNARY_OP_NEGATE": 2, + } +) + +func (x UnaryOp) Enum() *UnaryOp { + p := new(UnaryOp) + *p = x + return p +} + +func (x UnaryOp) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (UnaryOp) Descriptor() protoreflect.EnumDescriptor { + return file_core_message_broker_actors_v1_query_proto_enumTypes[1].Descriptor() +} + +func (UnaryOp) Type() protoreflect.EnumType { + return &file_core_message_broker_actors_v1_query_proto_enumTypes[1] +} + +func (x UnaryOp) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use UnaryOp.Descriptor instead. +func (UnaryOp) EnumDescriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{1} +} + +type BinaryOp int32 + +const ( + BinaryOp_BINARY_OP_UNSPECIFIED BinaryOp = 0 + // Logical — Boolean × Boolean → Boolean + // AND and OR short-circuit per the spec. + BinaryOp_BINARY_OP_AND BinaryOp = 1 + BinaryOp_BINARY_OP_OR BinaryOp = 2 + BinaryOp_BINARY_OP_XOR BinaryOp = 3 + // Equality — Boolean | Integer | String × same → Boolean + BinaryOp_BINARY_OP_EQ BinaryOp = 4 // = + BinaryOp_BINARY_OP_NEQ BinaryOp = 5 // != or <> (both map to this variant) + // Ordered comparison — Integer × Integer → Boolean + BinaryOp_BINARY_OP_LT BinaryOp = 6 // < + BinaryOp_BINARY_OP_LTE BinaryOp = 7 // <= + BinaryOp_BINARY_OP_GT BinaryOp = 8 // > + BinaryOp_BINARY_OP_GTE BinaryOp = 9 // >= + // Arithmetic — Integer × Integer → Integer + // Division and modulo by zero return 0 and raise MathError per the spec. + BinaryOp_BINARY_OP_ADD BinaryOp = 10 // + + BinaryOp_BINARY_OP_SUB BinaryOp = 11 // - + BinaryOp_BINARY_OP_MUL BinaryOp = 12 // * + BinaryOp_BINARY_OP_DIV BinaryOp = 13 // / + BinaryOp_BINARY_OP_MOD BinaryOp = 14 // % +) + +// Enum value maps for BinaryOp. +var ( + BinaryOp_name = map[int32]string{ + 0: "BINARY_OP_UNSPECIFIED", + 1: "BINARY_OP_AND", + 2: "BINARY_OP_OR", + 3: "BINARY_OP_XOR", + 4: "BINARY_OP_EQ", + 5: "BINARY_OP_NEQ", + 6: "BINARY_OP_LT", + 7: "BINARY_OP_LTE", + 8: "BINARY_OP_GT", + 9: "BINARY_OP_GTE", + 10: "BINARY_OP_ADD", + 11: "BINARY_OP_SUB", + 12: "BINARY_OP_MUL", + 13: "BINARY_OP_DIV", + 14: "BINARY_OP_MOD", + } + BinaryOp_value = map[string]int32{ + "BINARY_OP_UNSPECIFIED": 0, + "BINARY_OP_AND": 1, + "BINARY_OP_OR": 2, + "BINARY_OP_XOR": 3, + "BINARY_OP_EQ": 4, + "BINARY_OP_NEQ": 5, + "BINARY_OP_LT": 6, + "BINARY_OP_LTE": 7, + "BINARY_OP_GT": 8, + "BINARY_OP_GTE": 9, + "BINARY_OP_ADD": 10, + "BINARY_OP_SUB": 11, + "BINARY_OP_MUL": 12, + "BINARY_OP_DIV": 13, + "BINARY_OP_MOD": 14, + } +) + +func (x BinaryOp) Enum() *BinaryOp { + p := new(BinaryOp) + *p = x + return p +} + +func (x BinaryOp) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (BinaryOp) Descriptor() protoreflect.EnumDescriptor { + return file_core_message_broker_actors_v1_query_proto_enumTypes[2].Descriptor() +} + +func (BinaryOp) Type() protoreflect.EnumType { + return &file_core_message_broker_actors_v1_query_proto_enumTypes[2] +} + +func (x BinaryOp) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use BinaryOp.Descriptor instead. +func (BinaryOp) EnumDescriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{2} +} + +type BuiltinFunction int32 + +const ( + BuiltinFunction_FUNCTION_UNSPECIFIED BuiltinFunction = 0 + // LENGTH(x: String) → Integer + // Returns the number of characters in x. + BuiltinFunction_FUNCTION_LENGTH BuiltinFunction = 1 + // CONCAT(x1, x2, ...: String) → String + // Returns the concatenation of all arguments. Zero args returns "". + BuiltinFunction_FUNCTION_CONCAT BuiltinFunction = 2 + // CONCAT_WS(delimiter: String, x1, x2, ...: String) → String + // Returns arguments joined by delimiter. Zero value args returns "". + BuiltinFunction_FUNCTION_CONCAT_WS BuiltinFunction = 3 + // LOWER(x: String) → String + BuiltinFunction_FUNCTION_LOWER BuiltinFunction = 4 + // UPPER(x: String) → String + BuiltinFunction_FUNCTION_UPPER BuiltinFunction = 5 + // TRIM(x: String) → String + // Removes leading and trailing Unicode whitespace. + BuiltinFunction_FUNCTION_TRIM BuiltinFunction = 6 + // LEFT(x: String, n: Integer) → String + // Returns the first n characters. Returns x when LENGTH(x) <= n. + // Returns x + FunctionEvaluationError when n < 0. + BuiltinFunction_FUNCTION_LEFT BuiltinFunction = 7 + // RIGHT(x: String, n: Integer) → String + // Returns the last n characters. Returns x when LENGTH(x) <= n. + // Returns x + FunctionEvaluationError when n < 0. + BuiltinFunction_FUNCTION_RIGHT BuiltinFunction = 8 + // SUBSTRING(x: String, pos: Integer) → String + // SUBSTRING(x: String, pos: Integer, len: Integer) → String + // 1-indexed. Negative pos counts from the end. pos=0 returns "". + // Returns "" + FunctionEvaluationError when |pos| > LENGTH(x) or len < 0. + BuiltinFunction_FUNCTION_SUBSTRING BuiltinFunction = 9 + // ABS(x: Integer) → Integer + // Returns the absolute value of x. + // ABS(-2147483648) returns 2147483647 + MathError per the spec. + BuiltinFunction_FUNCTION_ABS BuiltinFunction = 10 +) + +// Enum value maps for BuiltinFunction. +var ( + BuiltinFunction_name = map[int32]string{ + 0: "FUNCTION_UNSPECIFIED", + 1: "FUNCTION_LENGTH", + 2: "FUNCTION_CONCAT", + 3: "FUNCTION_CONCAT_WS", + 4: "FUNCTION_LOWER", + 5: "FUNCTION_UPPER", + 6: "FUNCTION_TRIM", + 7: "FUNCTION_LEFT", + 8: "FUNCTION_RIGHT", + 9: "FUNCTION_SUBSTRING", + 10: "FUNCTION_ABS", + } + BuiltinFunction_value = map[string]int32{ + "FUNCTION_UNSPECIFIED": 0, + "FUNCTION_LENGTH": 1, + "FUNCTION_CONCAT": 2, + "FUNCTION_CONCAT_WS": 3, + "FUNCTION_LOWER": 4, + "FUNCTION_UPPER": 5, + "FUNCTION_TRIM": 6, + "FUNCTION_LEFT": 7, + "FUNCTION_RIGHT": 8, + "FUNCTION_SUBSTRING": 9, + "FUNCTION_ABS": 10, + } +) + +func (x BuiltinFunction) Enum() *BuiltinFunction { + p := new(BuiltinFunction) + *p = x + return p +} + +func (x BuiltinFunction) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (BuiltinFunction) Descriptor() protoreflect.EnumDescriptor { + return file_core_message_broker_actors_v1_query_proto_enumTypes[3].Descriptor() +} + +func (BuiltinFunction) Type() protoreflect.EnumType { + return &file_core_message_broker_actors_v1_query_proto_enumTypes[3] +} + +func (x BuiltinFunction) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use BuiltinFunction.Descriptor instead. +func (BuiltinFunction) EnumDescriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{3} +} + +type QueryRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Expression *Expression `protobuf:"bytes,1,opt,name=expression,proto3" json:"expression,omitempty"` + Limit int32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` // 0 = server default; caps historical replay for QueryStream + After string `protobuf:"bytes,3,opt,name=after,proto3" json:"after,omitempty"` // ISO 8601 timestamp — replay events after this point before going live + OrderBy OrderDirection `protobuf:"varint,4,opt,name=order_by,json=orderBy,proto3,enum=core.message_broker.actors.v1.OrderDirection" json:"order_by,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *QueryRequest) Reset() { + *x = QueryRequest{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *QueryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryRequest) ProtoMessage() {} + +func (x *QueryRequest) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryRequest.ProtoReflect.Descriptor instead. +func (*QueryRequest) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{0} +} + +func (x *QueryRequest) GetExpression() *Expression { + if x != nil { + return x.Expression + } + return nil +} + +func (x *QueryRequest) GetLimit() int32 { + if x != nil { + return x.Limit + } + return 0 +} + +func (x *QueryRequest) GetAfter() string { + if x != nil { + return x.After + } + return "" +} + +func (x *QueryRequest) GetOrderBy() OrderDirection { + if x != nil { + return x.OrderBy + } + return OrderDirection_ORDER_DIRECTION_UNSPECIFIED +} + +type QueryResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Events []*CloudEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *QueryResponse) Reset() { + *x = QueryResponse{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *QueryResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryResponse) ProtoMessage() {} + +func (x *QueryResponse) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryResponse.ProtoReflect.Descriptor instead. +func (*QueryResponse) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{1} +} + +func (x *QueryResponse) GetEvents() []*CloudEvent { + if x != nil { + return x.Events + } + return nil +} + +// One event per stream message so the web-client can render each event as it +// arrives rather than waiting for a batch. +type QueryStreamResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Event *CloudEvent `protobuf:"bytes,1,opt,name=event,proto3" json:"event,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *QueryStreamResponse) Reset() { + *x = QueryStreamResponse{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *QueryStreamResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryStreamResponse) ProtoMessage() {} + +func (x *QueryStreamResponse) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryStreamResponse.ProtoReflect.Descriptor instead. +func (*QueryStreamResponse) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{2} +} + +func (x *QueryStreamResponse) GetEvent() *CloudEvent { + if x != nil { + return x.Event + } + return nil +} + +type Expression struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Expr: + // + // *Expression_Literal + // *Expression_Attribute + // *Expression_Unary + // *Expression_Binary + // *Expression_Like + // *Expression_Exists + // *Expression_In + // *Expression_FunctionCall + Expr isExpression_Expr `protobuf_oneof:"expr"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Expression) Reset() { + *x = Expression{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Expression) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Expression) ProtoMessage() {} + +func (x *Expression) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Expression.ProtoReflect.Descriptor instead. +func (*Expression) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{3} +} + +func (x *Expression) GetExpr() isExpression_Expr { + if x != nil { + return x.Expr + } + return nil +} + +func (x *Expression) GetLiteral() *Literal { + if x != nil { + if x, ok := x.Expr.(*Expression_Literal); ok { + return x.Literal + } + } + return nil +} + +func (x *Expression) GetAttribute() *AttributeRef { + if x != nil { + if x, ok := x.Expr.(*Expression_Attribute); ok { + return x.Attribute + } + } + return nil +} + +func (x *Expression) GetUnary() *UnaryExpr { + if x != nil { + if x, ok := x.Expr.(*Expression_Unary); ok { + return x.Unary + } + } + return nil +} + +func (x *Expression) GetBinary() *BinaryExpr { + if x != nil { + if x, ok := x.Expr.(*Expression_Binary); ok { + return x.Binary + } + } + return nil +} + +func (x *Expression) GetLike() *LikeExpr { + if x != nil { + if x, ok := x.Expr.(*Expression_Like); ok { + return x.Like + } + } + return nil +} + +func (x *Expression) GetExists() *ExistsExpr { + if x != nil { + if x, ok := x.Expr.(*Expression_Exists); ok { + return x.Exists + } + } + return nil +} + +func (x *Expression) GetIn() *InExpr { + if x != nil { + if x, ok := x.Expr.(*Expression_In); ok { + return x.In + } + } + return nil +} + +func (x *Expression) GetFunctionCall() *FunctionCall { + if x != nil { + if x, ok := x.Expr.(*Expression_FunctionCall); ok { + return x.FunctionCall + } + } + return nil +} + +type isExpression_Expr interface { + isExpression_Expr() +} + +type Expression_Literal struct { + Literal *Literal `protobuf:"bytes,1,opt,name=literal,proto3,oneof"` +} + +type Expression_Attribute struct { + Attribute *AttributeRef `protobuf:"bytes,2,opt,name=attribute,proto3,oneof"` +} + +type Expression_Unary struct { + Unary *UnaryExpr `protobuf:"bytes,3,opt,name=unary,proto3,oneof"` +} + +type Expression_Binary struct { + Binary *BinaryExpr `protobuf:"bytes,4,opt,name=binary,proto3,oneof"` +} + +type Expression_Like struct { + Like *LikeExpr `protobuf:"bytes,5,opt,name=like,proto3,oneof"` +} + +type Expression_Exists struct { + Exists *ExistsExpr `protobuf:"bytes,6,opt,name=exists,proto3,oneof"` +} + +type Expression_In struct { + In *InExpr `protobuf:"bytes,7,opt,name=in,proto3,oneof"` +} + +type Expression_FunctionCall struct { + FunctionCall *FunctionCall `protobuf:"bytes,8,opt,name=function_call,json=functionCall,proto3,oneof"` +} + +func (*Expression_Literal) isExpression_Expr() {} + +func (*Expression_Attribute) isExpression_Expr() {} + +func (*Expression_Unary) isExpression_Expr() {} + +func (*Expression_Binary) isExpression_Expr() {} + +func (*Expression_Like) isExpression_Expr() {} + +func (*Expression_Exists) isExpression_Expr() {} + +func (*Expression_In) isExpression_Expr() {} + +func (*Expression_FunctionCall) isExpression_Expr() {} + +// The three primitive types defined by the CESQL type system. +// URI, URI-Reference, and Timestamp are represented as string_value. +type Literal struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Value: + // + // *Literal_IntegerValue + // *Literal_BoolValue + // *Literal_StringValue + Value isLiteral_Value `protobuf_oneof:"value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Literal) Reset() { + *x = Literal{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Literal) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Literal) ProtoMessage() {} + +func (x *Literal) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Literal.ProtoReflect.Descriptor instead. +func (*Literal) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{4} +} + +func (x *Literal) GetValue() isLiteral_Value { + if x != nil { + return x.Value + } + return nil +} + +func (x *Literal) GetIntegerValue() int32 { + if x != nil { + if x, ok := x.Value.(*Literal_IntegerValue); ok { + return x.IntegerValue + } + } + return 0 +} + +func (x *Literal) GetBoolValue() bool { + if x != nil { + if x, ok := x.Value.(*Literal_BoolValue); ok { + return x.BoolValue + } + } + return false +} + +func (x *Literal) GetStringValue() string { + if x != nil { + if x, ok := x.Value.(*Literal_StringValue); ok { + return x.StringValue + } + } + return "" +} + +type isLiteral_Value interface { + isLiteral_Value() +} + +type Literal_IntegerValue struct { + IntegerValue int32 `protobuf:"varint,1,opt,name=integer_value,json=integerValue,proto3,oneof"` +} + +type Literal_BoolValue struct { + BoolValue bool `protobuf:"varint,2,opt,name=bool_value,json=boolValue,proto3,oneof"` +} + +type Literal_StringValue struct { + StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,proto3,oneof"` +} + +func (*Literal_IntegerValue) isLiteral_Value() {} + +func (*Literal_BoolValue) isLiteral_Value() {} + +func (*Literal_StringValue) isLiteral_Value() {} + +// References a CloudEvent context attribute or extension by name. +// +// Required attributes (always present): id, source, specversion, type +// Optional attributes: datacontenttype, dataschema, subject, time +// Extensions: any custom attribute added by the event producer +// +// A missing optional or extension attribute evaluates to the zero value of the +// subexpression return type and raises MissingAttributeError per the spec. +type AttributeRef struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AttributeRef) Reset() { + *x = AttributeRef{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AttributeRef) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AttributeRef) ProtoMessage() {} + +func (x *AttributeRef) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AttributeRef.ProtoReflect.Descriptor instead. +func (*AttributeRef) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{5} +} + +func (x *AttributeRef) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type UnaryExpr struct { + state protoimpl.MessageState `protogen:"open.v1"` + Op UnaryOp `protobuf:"varint,1,opt,name=op,proto3,enum=core.message_broker.actors.v1.UnaryOp" json:"op,omitempty"` + Operand *Expression `protobuf:"bytes,2,opt,name=operand,proto3" json:"operand,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UnaryExpr) Reset() { + *x = UnaryExpr{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UnaryExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnaryExpr) ProtoMessage() {} + +func (x *UnaryExpr) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnaryExpr.ProtoReflect.Descriptor instead. +func (*UnaryExpr) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{6} +} + +func (x *UnaryExpr) GetOp() UnaryOp { + if x != nil { + return x.Op + } + return UnaryOp_UNARY_OP_UNSPECIFIED +} + +func (x *UnaryExpr) GetOperand() *Expression { + if x != nil { + return x.Operand + } + return nil +} + +type BinaryExpr struct { + state protoimpl.MessageState `protogen:"open.v1"` + Left *Expression `protobuf:"bytes,1,opt,name=left,proto3" json:"left,omitempty"` + Op BinaryOp `protobuf:"varint,2,opt,name=op,proto3,enum=core.message_broker.actors.v1.BinaryOp" json:"op,omitempty"` + Right *Expression `protobuf:"bytes,3,opt,name=right,proto3" json:"right,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BinaryExpr) Reset() { + *x = BinaryExpr{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BinaryExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BinaryExpr) ProtoMessage() {} + +func (x *BinaryExpr) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BinaryExpr.ProtoReflect.Descriptor instead. +func (*BinaryExpr) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{7} +} + +func (x *BinaryExpr) GetLeft() *Expression { + if x != nil { + return x.Left + } + return nil +} + +func (x *BinaryExpr) GetOp() BinaryOp { + if x != nil { + return x.Op + } + return BinaryOp_BINARY_OP_UNSPECIFIED +} + +func (x *BinaryExpr) GetRight() *Expression { + if x != nil { + return x.Right + } + return nil +} + +// String × String → Boolean +// Pattern syntax: % matches any sequence of characters, +// +// _ matches exactly one character, +// \ escapes a literal % or _. +type LikeExpr struct { + state protoimpl.MessageState `protogen:"open.v1"` + Operand *Expression `protobuf:"bytes,1,opt,name=operand,proto3" json:"operand,omitempty"` + Pattern string `protobuf:"bytes,2,opt,name=pattern,proto3" json:"pattern,omitempty"` // string literal containing the LIKE pattern + Negated bool `protobuf:"varint,3,opt,name=negated,proto3" json:"negated,omitempty"` // true → NOT LIKE + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LikeExpr) Reset() { + *x = LikeExpr{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LikeExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LikeExpr) ProtoMessage() {} + +func (x *LikeExpr) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LikeExpr.ProtoReflect.Descriptor instead. +func (*LikeExpr) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{8} +} + +func (x *LikeExpr) GetOperand() *Expression { + if x != nil { + return x.Operand + } + return nil +} + +func (x *LikeExpr) GetPattern() string { + if x != nil { + return x.Pattern + } + return "" +} + +func (x *LikeExpr) GetNegated() bool { + if x != nil { + return x.Negated + } + return false +} + +// Returns true if the named attribute is present on the CloudEvent. +// Always evaluates true for the four required attributes. +type ExistsExpr struct { + state protoimpl.MessageState `protogen:"open.v1"` + Attribute string `protobuf:"bytes,1,opt,name=attribute,proto3" json:"attribute,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExistsExpr) Reset() { + *x = ExistsExpr{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExistsExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExistsExpr) ProtoMessage() {} + +func (x *ExistsExpr) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExistsExpr.ProtoReflect.Descriptor instead. +func (*ExistsExpr) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{9} +} + +func (x *ExistsExpr) GetAttribute() string { + if x != nil { + return x.Attribute + } + return "" +} + +// expression IN (e1, e2, ...) → Boolean +// The values set must contain at least one element. +type InExpr struct { + state protoimpl.MessageState `protogen:"open.v1"` + Operand *Expression `protobuf:"bytes,1,opt,name=operand,proto3" json:"operand,omitempty"` + Values []*Expression `protobuf:"bytes,2,rep,name=values,proto3" json:"values,omitempty"` + Negated bool `protobuf:"varint,3,opt,name=negated,proto3" json:"negated,omitempty"` // true → NOT IN + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InExpr) Reset() { + *x = InExpr{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InExpr) ProtoMessage() {} + +func (x *InExpr) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InExpr.ProtoReflect.Descriptor instead. +func (*InExpr) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{10} +} + +func (x *InExpr) GetOperand() *Expression { + if x != nil { + return x.Operand + } + return nil +} + +func (x *InExpr) GetValues() []*Expression { + if x != nil { + return x.Values + } + return nil +} + +func (x *InExpr) GetNegated() bool { + if x != nil { + return x.Negated + } + return false +} + +// All built-in CESQL functions are enumerated here. The argument count and +// types for each function are documented below and enforced at evaluation time. +type FunctionCall struct { + state protoimpl.MessageState `protogen:"open.v1"` + Function BuiltinFunction `protobuf:"varint,1,opt,name=function,proto3,enum=core.message_broker.actors.v1.BuiltinFunction" json:"function,omitempty"` + Args []*Expression `protobuf:"bytes,2,rep,name=args,proto3" json:"args,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FunctionCall) Reset() { + *x = FunctionCall{} + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FunctionCall) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FunctionCall) ProtoMessage() {} + +func (x *FunctionCall) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_query_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FunctionCall.ProtoReflect.Descriptor instead. +func (*FunctionCall) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_query_proto_rawDescGZIP(), []int{11} +} + +func (x *FunctionCall) GetFunction() BuiltinFunction { + if x != nil { + return x.Function + } + return BuiltinFunction_FUNCTION_UNSPECIFIED +} + +func (x *FunctionCall) GetArgs() []*Expression { + if x != nil { + return x.Args + } + return nil +} + +var File_core_message_broker_actors_v1_query_proto protoreflect.FileDescriptor + +const file_core_message_broker_actors_v1_query_proto_rawDesc = "" + + "\n" + + ")core/message_broker/actors/v1/query.proto\x12\x1dcore.message_broker.actors.v1\x1a*core/message_broker/actors/v1/models.proto\"\xcf\x01\n" + + "\fQueryRequest\x12I\n" + + "\n" + + "expression\x18\x01 \x01(\v2).core.message_broker.actors.v1.ExpressionR\n" + + "expression\x12\x14\n" + + "\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x14\n" + + "\x05after\x18\x03 \x01(\tR\x05after\x12H\n" + + "\border_by\x18\x04 \x01(\x0e2-.core.message_broker.actors.v1.OrderDirectionR\aorderBy\"R\n" + + "\rQueryResponse\x12A\n" + + "\x06events\x18\x01 \x03(\v2).core.message_broker.actors.v1.CloudEventR\x06events\"V\n" + + "\x13QueryStreamResponse\x12?\n" + + "\x05event\x18\x01 \x01(\v2).core.message_broker.actors.v1.CloudEventR\x05event\"\xbd\x04\n" + + "\n" + + "Expression\x12B\n" + + "\aliteral\x18\x01 \x01(\v2&.core.message_broker.actors.v1.LiteralH\x00R\aliteral\x12K\n" + + "\tattribute\x18\x02 \x01(\v2+.core.message_broker.actors.v1.AttributeRefH\x00R\tattribute\x12@\n" + + "\x05unary\x18\x03 \x01(\v2(.core.message_broker.actors.v1.UnaryExprH\x00R\x05unary\x12C\n" + + "\x06binary\x18\x04 \x01(\v2).core.message_broker.actors.v1.BinaryExprH\x00R\x06binary\x12=\n" + + "\x04like\x18\x05 \x01(\v2'.core.message_broker.actors.v1.LikeExprH\x00R\x04like\x12C\n" + + "\x06exists\x18\x06 \x01(\v2).core.message_broker.actors.v1.ExistsExprH\x00R\x06exists\x127\n" + + "\x02in\x18\a \x01(\v2%.core.message_broker.actors.v1.InExprH\x00R\x02in\x12R\n" + + "\rfunction_call\x18\b \x01(\v2+.core.message_broker.actors.v1.FunctionCallH\x00R\ffunctionCallB\x06\n" + + "\x04expr\"\x7f\n" + + "\aLiteral\x12%\n" + + "\rinteger_value\x18\x01 \x01(\x05H\x00R\fintegerValue\x12\x1f\n" + + "\n" + + "bool_value\x18\x02 \x01(\bH\x00R\tboolValue\x12#\n" + + "\fstring_value\x18\x03 \x01(\tH\x00R\vstringValueB\a\n" + + "\x05value\"\"\n" + + "\fAttributeRef\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\"\x88\x01\n" + + "\tUnaryExpr\x126\n" + + "\x02op\x18\x01 \x01(\x0e2&.core.message_broker.actors.v1.UnaryOpR\x02op\x12C\n" + + "\aoperand\x18\x02 \x01(\v2).core.message_broker.actors.v1.ExpressionR\aoperand\"\xc5\x01\n" + + "\n" + + "BinaryExpr\x12=\n" + + "\x04left\x18\x01 \x01(\v2).core.message_broker.actors.v1.ExpressionR\x04left\x127\n" + + "\x02op\x18\x02 \x01(\x0e2'.core.message_broker.actors.v1.BinaryOpR\x02op\x12?\n" + + "\x05right\x18\x03 \x01(\v2).core.message_broker.actors.v1.ExpressionR\x05right\"\x83\x01\n" + + "\bLikeExpr\x12C\n" + + "\aoperand\x18\x01 \x01(\v2).core.message_broker.actors.v1.ExpressionR\aoperand\x12\x18\n" + + "\apattern\x18\x02 \x01(\tR\apattern\x12\x18\n" + + "\anegated\x18\x03 \x01(\bR\anegated\"*\n" + + "\n" + + "ExistsExpr\x12\x1c\n" + + "\tattribute\x18\x01 \x01(\tR\tattribute\"\xaa\x01\n" + + "\x06InExpr\x12C\n" + + "\aoperand\x18\x01 \x01(\v2).core.message_broker.actors.v1.ExpressionR\aoperand\x12A\n" + + "\x06values\x18\x02 \x03(\v2).core.message_broker.actors.v1.ExpressionR\x06values\x12\x18\n" + + "\anegated\x18\x03 \x01(\bR\anegated\"\x99\x01\n" + + "\fFunctionCall\x12J\n" + + "\bfunction\x18\x01 \x01(\x0e2..core.message_broker.actors.v1.BuiltinFunctionR\bfunction\x12=\n" + + "\x04args\x18\x02 \x03(\v2).core.message_broker.actors.v1.ExpressionR\x04args*d\n" + + "\x0eOrderDirection\x12\x1f\n" + + "\x1bORDER_DIRECTION_UNSPECIFIED\x10\x00\x12\x17\n" + + "\x13ORDER_DIRECTION_ASC\x10\x01\x12\x18\n" + + "\x14ORDER_DIRECTION_DESC\x10\x02*J\n" + + "\aUnaryOp\x12\x18\n" + + "\x14UNARY_OP_UNSPECIFIED\x10\x00\x12\x10\n" + + "\fUNARY_OP_NOT\x10\x01\x12\x13\n" + + "\x0fUNARY_OP_NEGATE\x10\x02*\xab\x02\n" + + "\bBinaryOp\x12\x19\n" + + "\x15BINARY_OP_UNSPECIFIED\x10\x00\x12\x11\n" + + "\rBINARY_OP_AND\x10\x01\x12\x10\n" + + "\fBINARY_OP_OR\x10\x02\x12\x11\n" + + "\rBINARY_OP_XOR\x10\x03\x12\x10\n" + + "\fBINARY_OP_EQ\x10\x04\x12\x11\n" + + "\rBINARY_OP_NEQ\x10\x05\x12\x10\n" + + "\fBINARY_OP_LT\x10\x06\x12\x11\n" + + "\rBINARY_OP_LTE\x10\a\x12\x10\n" + + "\fBINARY_OP_GT\x10\b\x12\x11\n" + + "\rBINARY_OP_GTE\x10\t\x12\x11\n" + + "\rBINARY_OP_ADD\x10\n" + + "\x12\x11\n" + + "\rBINARY_OP_SUB\x10\v\x12\x11\n" + + "\rBINARY_OP_MUL\x10\f\x12\x11\n" + + "\rBINARY_OP_DIV\x10\r\x12\x11\n" + + "\rBINARY_OP_MOD\x10\x0e*\xf9\x01\n" + + "\x0fBuiltinFunction\x12\x18\n" + + "\x14FUNCTION_UNSPECIFIED\x10\x00\x12\x13\n" + + "\x0fFUNCTION_LENGTH\x10\x01\x12\x13\n" + + "\x0fFUNCTION_CONCAT\x10\x02\x12\x16\n" + + "\x12FUNCTION_CONCAT_WS\x10\x03\x12\x12\n" + + "\x0eFUNCTION_LOWER\x10\x04\x12\x12\n" + + "\x0eFUNCTION_UPPER\x10\x05\x12\x11\n" + + "\rFUNCTION_TRIM\x10\x06\x12\x11\n" + + "\rFUNCTION_LEFT\x10\a\x12\x12\n" + + "\x0eFUNCTION_RIGHT\x10\b\x12\x16\n" + + "\x12FUNCTION_SUBSTRING\x10\t\x12\x10\n" + + "\fFUNCTION_ABS\x10\n" + + "2\xe1\x01\n" + + "\x05Query\x12d\n" + + "\x05Query\x12+.core.message_broker.actors.v1.QueryRequest\x1a,.core.message_broker.actors.v1.QueryResponse\"\x00\x12r\n" + + "\vQueryStream\x12+.core.message_broker.actors.v1.QueryRequest\x1a2.core.message_broker.actors.v1.QueryStreamResponse\"\x000\x01BAZ?github.com/steady-bytes/draft/api/core/message_broker/actors/v1b\x06proto3" + +var ( + file_core_message_broker_actors_v1_query_proto_rawDescOnce sync.Once + file_core_message_broker_actors_v1_query_proto_rawDescData []byte +) + +func file_core_message_broker_actors_v1_query_proto_rawDescGZIP() []byte { + file_core_message_broker_actors_v1_query_proto_rawDescOnce.Do(func() { + file_core_message_broker_actors_v1_query_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_query_proto_rawDesc), len(file_core_message_broker_actors_v1_query_proto_rawDesc))) + }) + return file_core_message_broker_actors_v1_query_proto_rawDescData +} + +var file_core_message_broker_actors_v1_query_proto_enumTypes = make([]protoimpl.EnumInfo, 4) +var file_core_message_broker_actors_v1_query_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_core_message_broker_actors_v1_query_proto_goTypes = []any{ + (OrderDirection)(0), // 0: core.message_broker.actors.v1.OrderDirection + (UnaryOp)(0), // 1: core.message_broker.actors.v1.UnaryOp + (BinaryOp)(0), // 2: core.message_broker.actors.v1.BinaryOp + (BuiltinFunction)(0), // 3: core.message_broker.actors.v1.BuiltinFunction + (*QueryRequest)(nil), // 4: core.message_broker.actors.v1.QueryRequest + (*QueryResponse)(nil), // 5: core.message_broker.actors.v1.QueryResponse + (*QueryStreamResponse)(nil), // 6: core.message_broker.actors.v1.QueryStreamResponse + (*Expression)(nil), // 7: core.message_broker.actors.v1.Expression + (*Literal)(nil), // 8: core.message_broker.actors.v1.Literal + (*AttributeRef)(nil), // 9: core.message_broker.actors.v1.AttributeRef + (*UnaryExpr)(nil), // 10: core.message_broker.actors.v1.UnaryExpr + (*BinaryExpr)(nil), // 11: core.message_broker.actors.v1.BinaryExpr + (*LikeExpr)(nil), // 12: core.message_broker.actors.v1.LikeExpr + (*ExistsExpr)(nil), // 13: core.message_broker.actors.v1.ExistsExpr + (*InExpr)(nil), // 14: core.message_broker.actors.v1.InExpr + (*FunctionCall)(nil), // 15: core.message_broker.actors.v1.FunctionCall + (*CloudEvent)(nil), // 16: core.message_broker.actors.v1.CloudEvent +} +var file_core_message_broker_actors_v1_query_proto_depIdxs = []int32{ + 7, // 0: core.message_broker.actors.v1.QueryRequest.expression:type_name -> core.message_broker.actors.v1.Expression + 0, // 1: core.message_broker.actors.v1.QueryRequest.order_by:type_name -> core.message_broker.actors.v1.OrderDirection + 16, // 2: core.message_broker.actors.v1.QueryResponse.events:type_name -> core.message_broker.actors.v1.CloudEvent + 16, // 3: core.message_broker.actors.v1.QueryStreamResponse.event:type_name -> core.message_broker.actors.v1.CloudEvent + 8, // 4: core.message_broker.actors.v1.Expression.literal:type_name -> core.message_broker.actors.v1.Literal + 9, // 5: core.message_broker.actors.v1.Expression.attribute:type_name -> core.message_broker.actors.v1.AttributeRef + 10, // 6: core.message_broker.actors.v1.Expression.unary:type_name -> core.message_broker.actors.v1.UnaryExpr + 11, // 7: core.message_broker.actors.v1.Expression.binary:type_name -> core.message_broker.actors.v1.BinaryExpr + 12, // 8: core.message_broker.actors.v1.Expression.like:type_name -> core.message_broker.actors.v1.LikeExpr + 13, // 9: core.message_broker.actors.v1.Expression.exists:type_name -> core.message_broker.actors.v1.ExistsExpr + 14, // 10: core.message_broker.actors.v1.Expression.in:type_name -> core.message_broker.actors.v1.InExpr + 15, // 11: core.message_broker.actors.v1.Expression.function_call:type_name -> core.message_broker.actors.v1.FunctionCall + 1, // 12: core.message_broker.actors.v1.UnaryExpr.op:type_name -> core.message_broker.actors.v1.UnaryOp + 7, // 13: core.message_broker.actors.v1.UnaryExpr.operand:type_name -> core.message_broker.actors.v1.Expression + 7, // 14: core.message_broker.actors.v1.BinaryExpr.left:type_name -> core.message_broker.actors.v1.Expression + 2, // 15: core.message_broker.actors.v1.BinaryExpr.op:type_name -> core.message_broker.actors.v1.BinaryOp + 7, // 16: core.message_broker.actors.v1.BinaryExpr.right:type_name -> core.message_broker.actors.v1.Expression + 7, // 17: core.message_broker.actors.v1.LikeExpr.operand:type_name -> core.message_broker.actors.v1.Expression + 7, // 18: core.message_broker.actors.v1.InExpr.operand:type_name -> core.message_broker.actors.v1.Expression + 7, // 19: core.message_broker.actors.v1.InExpr.values:type_name -> core.message_broker.actors.v1.Expression + 3, // 20: core.message_broker.actors.v1.FunctionCall.function:type_name -> core.message_broker.actors.v1.BuiltinFunction + 7, // 21: core.message_broker.actors.v1.FunctionCall.args:type_name -> core.message_broker.actors.v1.Expression + 4, // 22: core.message_broker.actors.v1.Query.Query:input_type -> core.message_broker.actors.v1.QueryRequest + 4, // 23: core.message_broker.actors.v1.Query.QueryStream:input_type -> core.message_broker.actors.v1.QueryRequest + 5, // 24: core.message_broker.actors.v1.Query.Query:output_type -> core.message_broker.actors.v1.QueryResponse + 6, // 25: core.message_broker.actors.v1.Query.QueryStream:output_type -> core.message_broker.actors.v1.QueryStreamResponse + 24, // [24:26] is the sub-list for method output_type + 22, // [22:24] is the sub-list for method input_type + 22, // [22:22] is the sub-list for extension type_name + 22, // [22:22] is the sub-list for extension extendee + 0, // [0:22] is the sub-list for field type_name +} + +func init() { file_core_message_broker_actors_v1_query_proto_init() } +func file_core_message_broker_actors_v1_query_proto_init() { + if File_core_message_broker_actors_v1_query_proto != nil { + return + } + file_core_message_broker_actors_v1_models_proto_init() + file_core_message_broker_actors_v1_query_proto_msgTypes[3].OneofWrappers = []any{ + (*Expression_Literal)(nil), + (*Expression_Attribute)(nil), + (*Expression_Unary)(nil), + (*Expression_Binary)(nil), + (*Expression_Like)(nil), + (*Expression_Exists)(nil), + (*Expression_In)(nil), + (*Expression_FunctionCall)(nil), + } + file_core_message_broker_actors_v1_query_proto_msgTypes[4].OneofWrappers = []any{ + (*Literal_IntegerValue)(nil), + (*Literal_BoolValue)(nil), + (*Literal_StringValue)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_query_proto_rawDesc), len(file_core_message_broker_actors_v1_query_proto_rawDesc)), + NumEnums: 4, + NumMessages: 12, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_core_message_broker_actors_v1_query_proto_goTypes, + DependencyIndexes: file_core_message_broker_actors_v1_query_proto_depIdxs, + EnumInfos: file_core_message_broker_actors_v1_query_proto_enumTypes, + MessageInfos: file_core_message_broker_actors_v1_query_proto_msgTypes, + }.Build() + File_core_message_broker_actors_v1_query_proto = out.File + file_core_message_broker_actors_v1_query_proto_goTypes = nil + file_core_message_broker_actors_v1_query_proto_depIdxs = nil +} diff --git a/api/core/message_broker/actors/v1/query.pb.validate.go b/api/core/message_broker/actors/v1/query.pb.validate.go new file mode 100644 index 00000000..b610e123 --- /dev/null +++ b/api/core/message_broker/actors/v1/query.pb.validate.go @@ -0,0 +1,1927 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: core/message_broker/actors/v1/query.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on QueryRequest with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *QueryRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on QueryRequest with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in QueryRequestMultiError, or +// nil if none found. +func (m *QueryRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *QueryRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetExpression()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, QueryRequestValidationError{ + field: "Expression", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, QueryRequestValidationError{ + field: "Expression", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetExpression()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return QueryRequestValidationError{ + field: "Expression", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for Limit + + // no validation rules for After + + // no validation rules for OrderBy + + if len(errors) > 0 { + return QueryRequestMultiError(errors) + } + + return nil +} + +// QueryRequestMultiError is an error wrapping multiple validation errors +// returned by QueryRequest.ValidateAll() if the designated constraints aren't met. +type QueryRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m QueryRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m QueryRequestMultiError) AllErrors() []error { return m } + +// QueryRequestValidationError is the validation error returned by +// QueryRequest.Validate if the designated constraints aren't met. +type QueryRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e QueryRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e QueryRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e QueryRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e QueryRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e QueryRequestValidationError) ErrorName() string { return "QueryRequestValidationError" } + +// Error satisfies the builtin error interface +func (e QueryRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sQueryRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = QueryRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = QueryRequestValidationError{} + +// Validate checks the field values on QueryResponse with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *QueryResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on QueryResponse with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in QueryResponseMultiError, or +// nil if none found. +func (m *QueryResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *QueryResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetEvents() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, QueryResponseValidationError{ + field: fmt.Sprintf("Events[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, QueryResponseValidationError{ + field: fmt.Sprintf("Events[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return QueryResponseValidationError{ + field: fmt.Sprintf("Events[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return QueryResponseMultiError(errors) + } + + return nil +} + +// QueryResponseMultiError is an error wrapping multiple validation errors +// returned by QueryResponse.ValidateAll() if the designated constraints +// aren't met. +type QueryResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m QueryResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m QueryResponseMultiError) AllErrors() []error { return m } + +// QueryResponseValidationError is the validation error returned by +// QueryResponse.Validate if the designated constraints aren't met. +type QueryResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e QueryResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e QueryResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e QueryResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e QueryResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e QueryResponseValidationError) ErrorName() string { return "QueryResponseValidationError" } + +// Error satisfies the builtin error interface +func (e QueryResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sQueryResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = QueryResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = QueryResponseValidationError{} + +// Validate checks the field values on QueryStreamResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *QueryStreamResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on QueryStreamResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// QueryStreamResponseMultiError, or nil if none found. +func (m *QueryStreamResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *QueryStreamResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetEvent()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, QueryStreamResponseValidationError{ + field: "Event", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, QueryStreamResponseValidationError{ + field: "Event", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetEvent()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return QueryStreamResponseValidationError{ + field: "Event", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return QueryStreamResponseMultiError(errors) + } + + return nil +} + +// QueryStreamResponseMultiError is an error wrapping multiple validation +// errors returned by QueryStreamResponse.ValidateAll() if the designated +// constraints aren't met. +type QueryStreamResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m QueryStreamResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m QueryStreamResponseMultiError) AllErrors() []error { return m } + +// QueryStreamResponseValidationError is the validation error returned by +// QueryStreamResponse.Validate if the designated constraints aren't met. +type QueryStreamResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e QueryStreamResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e QueryStreamResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e QueryStreamResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e QueryStreamResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e QueryStreamResponseValidationError) ErrorName() string { + return "QueryStreamResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e QueryStreamResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sQueryStreamResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = QueryStreamResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = QueryStreamResponseValidationError{} + +// Validate checks the field values on Expression with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *Expression) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on Expression with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in ExpressionMultiError, or +// nil if none found. +func (m *Expression) ValidateAll() error { + return m.validate(true) +} + +func (m *Expression) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + switch v := m.Expr.(type) { + case *Expression_Literal: + if v == nil { + err := ExpressionValidationError{ + field: "Expr", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetLiteral()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Literal", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Literal", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetLiteral()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExpressionValidationError{ + field: "Literal", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *Expression_Attribute: + if v == nil { + err := ExpressionValidationError{ + field: "Expr", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetAttribute()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Attribute", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Attribute", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetAttribute()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExpressionValidationError{ + field: "Attribute", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *Expression_Unary: + if v == nil { + err := ExpressionValidationError{ + field: "Expr", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetUnary()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Unary", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Unary", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetUnary()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExpressionValidationError{ + field: "Unary", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *Expression_Binary: + if v == nil { + err := ExpressionValidationError{ + field: "Expr", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetBinary()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Binary", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Binary", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetBinary()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExpressionValidationError{ + field: "Binary", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *Expression_Like: + if v == nil { + err := ExpressionValidationError{ + field: "Expr", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetLike()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Like", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Like", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetLike()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExpressionValidationError{ + field: "Like", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *Expression_Exists: + if v == nil { + err := ExpressionValidationError{ + field: "Expr", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetExists()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Exists", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "Exists", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetExists()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExpressionValidationError{ + field: "Exists", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *Expression_In: + if v == nil { + err := ExpressionValidationError{ + field: "Expr", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetIn()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "In", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "In", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetIn()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExpressionValidationError{ + field: "In", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *Expression_FunctionCall: + if v == nil { + err := ExpressionValidationError{ + field: "Expr", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetFunctionCall()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "FunctionCall", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ExpressionValidationError{ + field: "FunctionCall", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetFunctionCall()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExpressionValidationError{ + field: "FunctionCall", + reason: "embedded message failed validation", + cause: err, + } + } + } + + default: + _ = v // ensures v is used + } + + if len(errors) > 0 { + return ExpressionMultiError(errors) + } + + return nil +} + +// ExpressionMultiError is an error wrapping multiple validation errors +// returned by Expression.ValidateAll() if the designated constraints aren't met. +type ExpressionMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ExpressionMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ExpressionMultiError) AllErrors() []error { return m } + +// ExpressionValidationError is the validation error returned by +// Expression.Validate if the designated constraints aren't met. +type ExpressionValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ExpressionValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ExpressionValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ExpressionValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ExpressionValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ExpressionValidationError) ErrorName() string { return "ExpressionValidationError" } + +// Error satisfies the builtin error interface +func (e ExpressionValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sExpression.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ExpressionValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ExpressionValidationError{} + +// Validate checks the field values on Literal with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *Literal) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on Literal with the rules defined in the +// proto definition for this message. If any rules are violated, the result is +// a list of violation errors wrapped in LiteralMultiError, or nil if none found. +func (m *Literal) ValidateAll() error { + return m.validate(true) +} + +func (m *Literal) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + switch v := m.Value.(type) { + case *Literal_IntegerValue: + if v == nil { + err := LiteralValidationError{ + field: "Value", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + // no validation rules for IntegerValue + case *Literal_BoolValue: + if v == nil { + err := LiteralValidationError{ + field: "Value", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + // no validation rules for BoolValue + case *Literal_StringValue: + if v == nil { + err := LiteralValidationError{ + field: "Value", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + // no validation rules for StringValue + default: + _ = v // ensures v is used + } + + if len(errors) > 0 { + return LiteralMultiError(errors) + } + + return nil +} + +// LiteralMultiError is an error wrapping multiple validation errors returned +// by Literal.ValidateAll() if the designated constraints aren't met. +type LiteralMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m LiteralMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m LiteralMultiError) AllErrors() []error { return m } + +// LiteralValidationError is the validation error returned by Literal.Validate +// if the designated constraints aren't met. +type LiteralValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e LiteralValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e LiteralValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e LiteralValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e LiteralValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e LiteralValidationError) ErrorName() string { return "LiteralValidationError" } + +// Error satisfies the builtin error interface +func (e LiteralValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sLiteral.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = LiteralValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = LiteralValidationError{} + +// Validate checks the field values on AttributeRef with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *AttributeRef) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on AttributeRef with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in AttributeRefMultiError, or +// nil if none found. +func (m *AttributeRef) ValidateAll() error { + return m.validate(true) +} + +func (m *AttributeRef) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Name + + if len(errors) > 0 { + return AttributeRefMultiError(errors) + } + + return nil +} + +// AttributeRefMultiError is an error wrapping multiple validation errors +// returned by AttributeRef.ValidateAll() if the designated constraints aren't met. +type AttributeRefMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m AttributeRefMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m AttributeRefMultiError) AllErrors() []error { return m } + +// AttributeRefValidationError is the validation error returned by +// AttributeRef.Validate if the designated constraints aren't met. +type AttributeRefValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e AttributeRefValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e AttributeRefValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e AttributeRefValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e AttributeRefValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e AttributeRefValidationError) ErrorName() string { return "AttributeRefValidationError" } + +// Error satisfies the builtin error interface +func (e AttributeRefValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAttributeRef.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = AttributeRefValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = AttributeRefValidationError{} + +// Validate checks the field values on UnaryExpr with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *UnaryExpr) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on UnaryExpr with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in UnaryExprMultiError, or nil +// if none found. +func (m *UnaryExpr) ValidateAll() error { + return m.validate(true) +} + +func (m *UnaryExpr) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Op + + if all { + switch v := interface{}(m.GetOperand()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, UnaryExprValidationError{ + field: "Operand", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, UnaryExprValidationError{ + field: "Operand", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetOperand()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return UnaryExprValidationError{ + field: "Operand", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return UnaryExprMultiError(errors) + } + + return nil +} + +// UnaryExprMultiError is an error wrapping multiple validation errors returned +// by UnaryExpr.ValidateAll() if the designated constraints aren't met. +type UnaryExprMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m UnaryExprMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m UnaryExprMultiError) AllErrors() []error { return m } + +// UnaryExprValidationError is the validation error returned by +// UnaryExpr.Validate if the designated constraints aren't met. +type UnaryExprValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e UnaryExprValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e UnaryExprValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e UnaryExprValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e UnaryExprValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e UnaryExprValidationError) ErrorName() string { return "UnaryExprValidationError" } + +// Error satisfies the builtin error interface +func (e UnaryExprValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sUnaryExpr.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = UnaryExprValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = UnaryExprValidationError{} + +// Validate checks the field values on BinaryExpr with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *BinaryExpr) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on BinaryExpr with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in BinaryExprMultiError, or +// nil if none found. +func (m *BinaryExpr) ValidateAll() error { + return m.validate(true) +} + +func (m *BinaryExpr) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetLeft()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, BinaryExprValidationError{ + field: "Left", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, BinaryExprValidationError{ + field: "Left", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetLeft()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BinaryExprValidationError{ + field: "Left", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for Op + + if all { + switch v := interface{}(m.GetRight()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, BinaryExprValidationError{ + field: "Right", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, BinaryExprValidationError{ + field: "Right", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRight()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BinaryExprValidationError{ + field: "Right", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return BinaryExprMultiError(errors) + } + + return nil +} + +// BinaryExprMultiError is an error wrapping multiple validation errors +// returned by BinaryExpr.ValidateAll() if the designated constraints aren't met. +type BinaryExprMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m BinaryExprMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m BinaryExprMultiError) AllErrors() []error { return m } + +// BinaryExprValidationError is the validation error returned by +// BinaryExpr.Validate if the designated constraints aren't met. +type BinaryExprValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e BinaryExprValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e BinaryExprValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e BinaryExprValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e BinaryExprValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e BinaryExprValidationError) ErrorName() string { return "BinaryExprValidationError" } + +// Error satisfies the builtin error interface +func (e BinaryExprValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sBinaryExpr.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = BinaryExprValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = BinaryExprValidationError{} + +// Validate checks the field values on LikeExpr with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *LikeExpr) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on LikeExpr with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in LikeExprMultiError, or nil +// if none found. +func (m *LikeExpr) ValidateAll() error { + return m.validate(true) +} + +func (m *LikeExpr) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetOperand()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, LikeExprValidationError{ + field: "Operand", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, LikeExprValidationError{ + field: "Operand", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetOperand()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return LikeExprValidationError{ + field: "Operand", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for Pattern + + // no validation rules for Negated + + if len(errors) > 0 { + return LikeExprMultiError(errors) + } + + return nil +} + +// LikeExprMultiError is an error wrapping multiple validation errors returned +// by LikeExpr.ValidateAll() if the designated constraints aren't met. +type LikeExprMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m LikeExprMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m LikeExprMultiError) AllErrors() []error { return m } + +// LikeExprValidationError is the validation error returned by +// LikeExpr.Validate if the designated constraints aren't met. +type LikeExprValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e LikeExprValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e LikeExprValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e LikeExprValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e LikeExprValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e LikeExprValidationError) ErrorName() string { return "LikeExprValidationError" } + +// Error satisfies the builtin error interface +func (e LikeExprValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sLikeExpr.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = LikeExprValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = LikeExprValidationError{} + +// Validate checks the field values on ExistsExpr with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *ExistsExpr) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ExistsExpr with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in ExistsExprMultiError, or +// nil if none found. +func (m *ExistsExpr) ValidateAll() error { + return m.validate(true) +} + +func (m *ExistsExpr) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Attribute + + if len(errors) > 0 { + return ExistsExprMultiError(errors) + } + + return nil +} + +// ExistsExprMultiError is an error wrapping multiple validation errors +// returned by ExistsExpr.ValidateAll() if the designated constraints aren't met. +type ExistsExprMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ExistsExprMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ExistsExprMultiError) AllErrors() []error { return m } + +// ExistsExprValidationError is the validation error returned by +// ExistsExpr.Validate if the designated constraints aren't met. +type ExistsExprValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ExistsExprValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ExistsExprValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ExistsExprValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ExistsExprValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ExistsExprValidationError) ErrorName() string { return "ExistsExprValidationError" } + +// Error satisfies the builtin error interface +func (e ExistsExprValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sExistsExpr.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ExistsExprValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ExistsExprValidationError{} + +// Validate checks the field values on InExpr with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *InExpr) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on InExpr with the rules defined in the +// proto definition for this message. If any rules are violated, the result is +// a list of violation errors wrapped in InExprMultiError, or nil if none found. +func (m *InExpr) ValidateAll() error { + return m.validate(true) +} + +func (m *InExpr) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetOperand()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, InExprValidationError{ + field: "Operand", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, InExprValidationError{ + field: "Operand", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetOperand()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return InExprValidationError{ + field: "Operand", + reason: "embedded message failed validation", + cause: err, + } + } + } + + for idx, item := range m.GetValues() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, InExprValidationError{ + field: fmt.Sprintf("Values[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, InExprValidationError{ + field: fmt.Sprintf("Values[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return InExprValidationError{ + field: fmt.Sprintf("Values[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + // no validation rules for Negated + + if len(errors) > 0 { + return InExprMultiError(errors) + } + + return nil +} + +// InExprMultiError is an error wrapping multiple validation errors returned by +// InExpr.ValidateAll() if the designated constraints aren't met. +type InExprMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m InExprMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m InExprMultiError) AllErrors() []error { return m } + +// InExprValidationError is the validation error returned by InExpr.Validate if +// the designated constraints aren't met. +type InExprValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e InExprValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e InExprValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e InExprValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e InExprValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e InExprValidationError) ErrorName() string { return "InExprValidationError" } + +// Error satisfies the builtin error interface +func (e InExprValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sInExpr.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = InExprValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = InExprValidationError{} + +// Validate checks the field values on FunctionCall with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *FunctionCall) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on FunctionCall with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in FunctionCallMultiError, or +// nil if none found. +func (m *FunctionCall) ValidateAll() error { + return m.validate(true) +} + +func (m *FunctionCall) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Function + + for idx, item := range m.GetArgs() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, FunctionCallValidationError{ + field: fmt.Sprintf("Args[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, FunctionCallValidationError{ + field: fmt.Sprintf("Args[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FunctionCallValidationError{ + field: fmt.Sprintf("Args[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return FunctionCallMultiError(errors) + } + + return nil +} + +// FunctionCallMultiError is an error wrapping multiple validation errors +// returned by FunctionCall.ValidateAll() if the designated constraints aren't met. +type FunctionCallMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m FunctionCallMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m FunctionCallMultiError) AllErrors() []error { return m } + +// FunctionCallValidationError is the validation error returned by +// FunctionCall.Validate if the designated constraints aren't met. +type FunctionCallValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e FunctionCallValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e FunctionCallValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e FunctionCallValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e FunctionCallValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e FunctionCallValidationError) ErrorName() string { return "FunctionCallValidationError" } + +// Error satisfies the builtin error interface +func (e FunctionCallValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sFunctionCall.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = FunctionCallValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = FunctionCallValidationError{} diff --git a/api/core/message_broker/actors/v1/query.proto b/api/core/message_broker/actors/v1/query.proto new file mode 100644 index 00000000..1db96ae8 --- /dev/null +++ b/api/core/message_broker/actors/v1/query.proto @@ -0,0 +1,223 @@ +syntax = "proto3"; + +package core.message_broker.actors.v1; + +option go_package = "github.com/steady-bytes/draft/api/core/message_broker/actors/v1"; + +import "core/message_broker/actors/v1/models.proto"; + +// ─── Query Service ──────────────────────────────────────────────────────────── + +service Query { + // Query executes a CESQL expression against stored events and returns all + // matching results in a single response. + rpc Query(QueryRequest) returns (QueryResponse) {} + + // QueryStream opens a persistent server-sent stream. The server first + // replays any stored events that match the expression (subject to `limit` + // and `after`), then continues streaming live events as they flow through + // catalyst in real time. The stream stays open until the client closes it. + rpc QueryStream(QueryRequest) returns (stream QueryStreamResponse) {} +} + +enum OrderDirection { + ORDER_DIRECTION_UNSPECIFIED = 0; // treated as ASC + ORDER_DIRECTION_ASC = 1; + ORDER_DIRECTION_DESC = 2; +} + +message QueryRequest { + Expression expression = 1; + int32 limit = 2; // 0 = server default; caps historical replay for QueryStream + string after = 3; // ISO 8601 timestamp — replay events after this point before going live + OrderDirection order_by = 4; +} + +message QueryResponse { + repeated CloudEvent events = 1; +} + +// One event per stream message so the web-client can render each event as it +// arrives rather than waiting for a batch. +message QueryStreamResponse { + CloudEvent event = 1; +} + +// ─── CESQL Expression Tree ──────────────────────────────────────────────────── +// +// Typed representation of the CloudEvents SQL (CESQL) expression grammar. +// Ref: https://github.com/cloudevents/spec/blob/main/cesql/spec.md + +message Expression { + oneof expr { + Literal literal = 1; + AttributeRef attribute = 2; + UnaryExpr unary = 3; + BinaryExpr binary = 4; + LikeExpr like = 5; + ExistsExpr exists = 6; + InExpr in = 7; + FunctionCall function_call = 8; + } +} + +// ─── Literals ───────────────────────────────────────────────────────────────── + +// The three primitive types defined by the CESQL type system. +// URI, URI-Reference, and Timestamp are represented as string_value. +message Literal { + oneof value { + int32 integer_value = 1; + bool bool_value = 2; + string string_value = 3; + } +} + +// ─── Attribute Reference ────────────────────────────────────────────────────── + +// References a CloudEvent context attribute or extension by name. +// +// Required attributes (always present): id, source, specversion, type +// Optional attributes: datacontenttype, dataschema, subject, time +// Extensions: any custom attribute added by the event producer +// +// A missing optional or extension attribute evaluates to the zero value of the +// subexpression return type and raises MissingAttributeError per the spec. +message AttributeRef { + string name = 1; +} + +// ─── Unary Expressions ──────────────────────────────────────────────────────── + +message UnaryExpr { + UnaryOp op = 1; + Expression operand = 2; +} + +enum UnaryOp { + UNARY_OP_UNSPECIFIED = 0; + UNARY_OP_NOT = 1; // Boolean → Boolean + UNARY_OP_NEGATE = 2; // Integer → Integer (unary minus) +} + +// ─── Binary Expressions ─────────────────────────────────────────────────────── + +message BinaryExpr { + Expression left = 1; + BinaryOp op = 2; + Expression right = 3; +} + +enum BinaryOp { + BINARY_OP_UNSPECIFIED = 0; + + // Logical — Boolean × Boolean → Boolean + // AND and OR short-circuit per the spec. + BINARY_OP_AND = 1; + BINARY_OP_OR = 2; + BINARY_OP_XOR = 3; + + // Equality — Boolean | Integer | String × same → Boolean + BINARY_OP_EQ = 4; // = + BINARY_OP_NEQ = 5; // != or <> (both map to this variant) + + // Ordered comparison — Integer × Integer → Boolean + BINARY_OP_LT = 6; // < + BINARY_OP_LTE = 7; // <= + BINARY_OP_GT = 8; // > + BINARY_OP_GTE = 9; // >= + + // Arithmetic — Integer × Integer → Integer + // Division and modulo by zero return 0 and raise MathError per the spec. + BINARY_OP_ADD = 10; // + + BINARY_OP_SUB = 11; // - + BINARY_OP_MUL = 12; // * + BINARY_OP_DIV = 13; // / + BINARY_OP_MOD = 14; // % +} + +// ─── LIKE ───────────────────────────────────────────────────────────────────── + +// String × String → Boolean +// Pattern syntax: % matches any sequence of characters, +// _ matches exactly one character, +// \ escapes a literal % or _. +message LikeExpr { + Expression operand = 1; + string pattern = 2; // string literal containing the LIKE pattern + bool negated = 3; // true → NOT LIKE +} + +// ─── EXISTS ─────────────────────────────────────────────────────────────────── + +// Returns true if the named attribute is present on the CloudEvent. +// Always evaluates true for the four required attributes. +message ExistsExpr { + string attribute = 1; +} + +// ─── IN ─────────────────────────────────────────────────────────────────────── + +// expression IN (e1, e2, ...) → Boolean +// The values set must contain at least one element. +message InExpr { + Expression operand = 1; + repeated Expression values = 2; + bool negated = 3; // true → NOT IN +} + +// ─── Function Calls ─────────────────────────────────────────────────────────── + +// All built-in CESQL functions are enumerated here. The argument count and +// types for each function are documented below and enforced at evaluation time. +message FunctionCall { + BuiltinFunction function = 1; + repeated Expression args = 2; +} + +enum BuiltinFunction { + FUNCTION_UNSPECIFIED = 0; + + // LENGTH(x: String) → Integer + // Returns the number of characters in x. + FUNCTION_LENGTH = 1; + + // CONCAT(x1, x2, ...: String) → String + // Returns the concatenation of all arguments. Zero args returns "". + FUNCTION_CONCAT = 2; + + // CONCAT_WS(delimiter: String, x1, x2, ...: String) → String + // Returns arguments joined by delimiter. Zero value args returns "". + FUNCTION_CONCAT_WS = 3; + + // LOWER(x: String) → String + FUNCTION_LOWER = 4; + + // UPPER(x: String) → String + FUNCTION_UPPER = 5; + + // TRIM(x: String) → String + // Removes leading and trailing Unicode whitespace. + FUNCTION_TRIM = 6; + + // LEFT(x: String, n: Integer) → String + // Returns the first n characters. Returns x when LENGTH(x) <= n. + // Returns x + FunctionEvaluationError when n < 0. + FUNCTION_LEFT = 7; + + // RIGHT(x: String, n: Integer) → String + // Returns the last n characters. Returns x when LENGTH(x) <= n. + // Returns x + FunctionEvaluationError when n < 0. + FUNCTION_RIGHT = 8; + + // SUBSTRING(x: String, pos: Integer) → String + // SUBSTRING(x: String, pos: Integer, len: Integer) → String + // 1-indexed. Negative pos counts from the end. pos=0 returns "". + // Returns "" + FunctionEvaluationError when |pos| > LENGTH(x) or len < 0. + FUNCTION_SUBSTRING = 9; + + // ABS(x: Integer) → Integer + // Returns the absolute value of x. + // ABS(-2147483648) returns 2147483647 + MathError per the spec. + FUNCTION_ABS = 10; +} diff --git a/api/core/message_broker/actors/v1/resource_metrics.pb.go b/api/core/message_broker/actors/v1/resource_metrics.pb.go new file mode 100644 index 00000000..d9b6e0e7 --- /dev/null +++ b/api/core/message_broker/actors/v1/resource_metrics.pb.go @@ -0,0 +1,232 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: core/message_broker/actors/v1/resource_metrics.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GetResourceMetricsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetResourceMetricsRequest) Reset() { + *x = GetResourceMetricsRequest{} + mi := &file_core_message_broker_actors_v1_resource_metrics_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetResourceMetricsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResourceMetricsRequest) ProtoMessage() {} + +func (x *GetResourceMetricsRequest) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_resource_metrics_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResourceMetricsRequest.ProtoReflect.Descriptor instead. +func (*GetResourceMetricsRequest) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_resource_metrics_proto_rawDescGZIP(), []int{0} +} + +type GetResourceMetricsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Throughput counters — cumulative since process start. + MessagesPublishedTotal uint64 `protobuf:"varint,1,opt,name=messages_published_total,json=messagesPublishedTotal,proto3" json:"messages_published_total,omitempty"` + MessagesDroppedTotal uint64 `protobuf:"varint,2,opt,name=messages_dropped_total,json=messagesDroppedTotal,proto3" json:"messages_dropped_total,omitempty"` + // Ingest buffer — current depth vs max capacity of the store channel. + QueueDepth uint32 `protobuf:"varint,3,opt,name=queue_depth,json=queueDepth,proto3" json:"queue_depth,omitempty"` + QueueCapacity uint32 `protobuf:"varint,4,opt,name=queue_capacity,json=queueCapacity,proto3" json:"queue_capacity,omitempty"` + // Live connection counts. + ActiveConsumers uint32 `protobuf:"varint,5,opt,name=active_consumers,json=activeConsumers,proto3" json:"active_consumers,omitempty"` + ActiveProducers uint32 `protobuf:"varint,6,opt,name=active_producers,json=activeProducers,proto3" json:"active_producers,omitempty"` + // Store flush performance. + StoreFlushP95Ms float64 `protobuf:"fixed64,7,opt,name=store_flush_p95_ms,json=storeFlushP95Ms,proto3" json:"store_flush_p95_ms,omitempty"` + StoreFlushCount uint32 `protobuf:"varint,8,opt,name=store_flush_count,json=storeFlushCount,proto3" json:"store_flush_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetResourceMetricsResponse) Reset() { + *x = GetResourceMetricsResponse{} + mi := &file_core_message_broker_actors_v1_resource_metrics_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetResourceMetricsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResourceMetricsResponse) ProtoMessage() {} + +func (x *GetResourceMetricsResponse) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_resource_metrics_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResourceMetricsResponse.ProtoReflect.Descriptor instead. +func (*GetResourceMetricsResponse) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_resource_metrics_proto_rawDescGZIP(), []int{1} +} + +func (x *GetResourceMetricsResponse) GetMessagesPublishedTotal() uint64 { + if x != nil { + return x.MessagesPublishedTotal + } + return 0 +} + +func (x *GetResourceMetricsResponse) GetMessagesDroppedTotal() uint64 { + if x != nil { + return x.MessagesDroppedTotal + } + return 0 +} + +func (x *GetResourceMetricsResponse) GetQueueDepth() uint32 { + if x != nil { + return x.QueueDepth + } + return 0 +} + +func (x *GetResourceMetricsResponse) GetQueueCapacity() uint32 { + if x != nil { + return x.QueueCapacity + } + return 0 +} + +func (x *GetResourceMetricsResponse) GetActiveConsumers() uint32 { + if x != nil { + return x.ActiveConsumers + } + return 0 +} + +func (x *GetResourceMetricsResponse) GetActiveProducers() uint32 { + if x != nil { + return x.ActiveProducers + } + return 0 +} + +func (x *GetResourceMetricsResponse) GetStoreFlushP95Ms() float64 { + if x != nil { + return x.StoreFlushP95Ms + } + return 0 +} + +func (x *GetResourceMetricsResponse) GetStoreFlushCount() uint32 { + if x != nil { + return x.StoreFlushCount + } + return 0 +} + +var File_core_message_broker_actors_v1_resource_metrics_proto protoreflect.FileDescriptor + +const file_core_message_broker_actors_v1_resource_metrics_proto_rawDesc = "" + + "\n" + + "4core/message_broker/actors/v1/resource_metrics.proto\x12\x1dcore.message_broker.actors.v1\"\x1b\n" + + "\x19GetResourceMetricsRequest\"\x83\x03\n" + + "\x1aGetResourceMetricsResponse\x128\n" + + "\x18messages_published_total\x18\x01 \x01(\x04R\x16messagesPublishedTotal\x124\n" + + "\x16messages_dropped_total\x18\x02 \x01(\x04R\x14messagesDroppedTotal\x12\x1f\n" + + "\vqueue_depth\x18\x03 \x01(\rR\n" + + "queueDepth\x12%\n" + + "\x0equeue_capacity\x18\x04 \x01(\rR\rqueueCapacity\x12)\n" + + "\x10active_consumers\x18\x05 \x01(\rR\x0factiveConsumers\x12)\n" + + "\x10active_producers\x18\x06 \x01(\rR\x0factiveProducers\x12+\n" + + "\x12store_flush_p95_ms\x18\a \x01(\x01R\x0fstoreFlushP95Ms\x12*\n" + + "\x11store_flush_count\x18\b \x01(\rR\x0fstoreFlushCount2\x9f\x01\n" + + "\x0fResourceMetrics\x12\x8b\x01\n" + + "\x12GetResourceMetrics\x128.core.message_broker.actors.v1.GetResourceMetricsRequest\x1a9.core.message_broker.actors.v1.GetResourceMetricsResponse\"\x00BAZ?github.com/steady-bytes/draft/api/core/message_broker/actors/v1b\x06proto3" + +var ( + file_core_message_broker_actors_v1_resource_metrics_proto_rawDescOnce sync.Once + file_core_message_broker_actors_v1_resource_metrics_proto_rawDescData []byte +) + +func file_core_message_broker_actors_v1_resource_metrics_proto_rawDescGZIP() []byte { + file_core_message_broker_actors_v1_resource_metrics_proto_rawDescOnce.Do(func() { + file_core_message_broker_actors_v1_resource_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_resource_metrics_proto_rawDesc), len(file_core_message_broker_actors_v1_resource_metrics_proto_rawDesc))) + }) + return file_core_message_broker_actors_v1_resource_metrics_proto_rawDescData +} + +var file_core_message_broker_actors_v1_resource_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_core_message_broker_actors_v1_resource_metrics_proto_goTypes = []any{ + (*GetResourceMetricsRequest)(nil), // 0: core.message_broker.actors.v1.GetResourceMetricsRequest + (*GetResourceMetricsResponse)(nil), // 1: core.message_broker.actors.v1.GetResourceMetricsResponse +} +var file_core_message_broker_actors_v1_resource_metrics_proto_depIdxs = []int32{ + 0, // 0: core.message_broker.actors.v1.ResourceMetrics.GetResourceMetrics:input_type -> core.message_broker.actors.v1.GetResourceMetricsRequest + 1, // 1: core.message_broker.actors.v1.ResourceMetrics.GetResourceMetrics:output_type -> core.message_broker.actors.v1.GetResourceMetricsResponse + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_core_message_broker_actors_v1_resource_metrics_proto_init() } +func file_core_message_broker_actors_v1_resource_metrics_proto_init() { + if File_core_message_broker_actors_v1_resource_metrics_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_resource_metrics_proto_rawDesc), len(file_core_message_broker_actors_v1_resource_metrics_proto_rawDesc)), + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_core_message_broker_actors_v1_resource_metrics_proto_goTypes, + DependencyIndexes: file_core_message_broker_actors_v1_resource_metrics_proto_depIdxs, + MessageInfos: file_core_message_broker_actors_v1_resource_metrics_proto_msgTypes, + }.Build() + File_core_message_broker_actors_v1_resource_metrics_proto = out.File + file_core_message_broker_actors_v1_resource_metrics_proto_goTypes = nil + file_core_message_broker_actors_v1_resource_metrics_proto_depIdxs = nil +} diff --git a/api/core/message_broker/actors/v1/resource_metrics.pb.validate.go b/api/core/message_broker/actors/v1/resource_metrics.pb.validate.go new file mode 100644 index 00000000..6ff4e88f --- /dev/null +++ b/api/core/message_broker/actors/v1/resource_metrics.pb.validate.go @@ -0,0 +1,256 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: core/message_broker/actors/v1/resource_metrics.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on GetResourceMetricsRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetResourceMetricsRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetResourceMetricsRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetResourceMetricsRequestMultiError, or nil if none found. +func (m *GetResourceMetricsRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GetResourceMetricsRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return GetResourceMetricsRequestMultiError(errors) + } + + return nil +} + +// GetResourceMetricsRequestMultiError is an error wrapping multiple validation +// errors returned by GetResourceMetricsRequest.ValidateAll() if the +// designated constraints aren't met. +type GetResourceMetricsRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetResourceMetricsRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetResourceMetricsRequestMultiError) AllErrors() []error { return m } + +// GetResourceMetricsRequestValidationError is the validation error returned by +// GetResourceMetricsRequest.Validate if the designated constraints aren't met. +type GetResourceMetricsRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetResourceMetricsRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetResourceMetricsRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetResourceMetricsRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetResourceMetricsRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetResourceMetricsRequestValidationError) ErrorName() string { + return "GetResourceMetricsRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e GetResourceMetricsRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetResourceMetricsRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetResourceMetricsRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetResourceMetricsRequestValidationError{} + +// Validate checks the field values on GetResourceMetricsResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetResourceMetricsResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetResourceMetricsResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetResourceMetricsResponseMultiError, or nil if none found. +func (m *GetResourceMetricsResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GetResourceMetricsResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for MessagesPublishedTotal + + // no validation rules for MessagesDroppedTotal + + // no validation rules for QueueDepth + + // no validation rules for QueueCapacity + + // no validation rules for ActiveConsumers + + // no validation rules for ActiveProducers + + // no validation rules for StoreFlushP95Ms + + // no validation rules for StoreFlushCount + + if len(errors) > 0 { + return GetResourceMetricsResponseMultiError(errors) + } + + return nil +} + +// GetResourceMetricsResponseMultiError is an error wrapping multiple +// validation errors returned by GetResourceMetricsResponse.ValidateAll() if +// the designated constraints aren't met. +type GetResourceMetricsResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetResourceMetricsResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetResourceMetricsResponseMultiError) AllErrors() []error { return m } + +// GetResourceMetricsResponseValidationError is the validation error returned +// by GetResourceMetricsResponse.Validate if the designated constraints aren't met. +type GetResourceMetricsResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetResourceMetricsResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetResourceMetricsResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetResourceMetricsResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetResourceMetricsResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetResourceMetricsResponseValidationError) ErrorName() string { + return "GetResourceMetricsResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GetResourceMetricsResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetResourceMetricsResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetResourceMetricsResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetResourceMetricsResponseValidationError{} diff --git a/api/core/message_broker/actors/v1/resource_metrics.proto b/api/core/message_broker/actors/v1/resource_metrics.proto new file mode 100644 index 00000000..c7dd6eda --- /dev/null +++ b/api/core/message_broker/actors/v1/resource_metrics.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; + +package core.message_broker.actors.v1; + +option go_package = "github.com/steady-bytes/draft/api/core/message_broker/actors/v1"; + +service ResourceMetrics { + rpc GetResourceMetrics(GetResourceMetricsRequest) returns (GetResourceMetricsResponse) {} +} + +message GetResourceMetricsRequest {} + +message GetResourceMetricsResponse { + // Throughput counters — cumulative since process start. + uint64 messages_published_total = 1; + uint64 messages_dropped_total = 2; + + // Ingest buffer — current depth vs max capacity of the store channel. + uint32 queue_depth = 3; + uint32 queue_capacity = 4; + + // Live connection counts. + uint32 active_consumers = 5; + uint32 active_producers = 6; + + // Store flush performance. + double store_flush_p95_ms = 7; + uint32 store_flush_count = 8; +} diff --git a/api/core/message_broker/actors/v1/topology.pb.go b/api/core/message_broker/actors/v1/topology.pb.go new file mode 100644 index 00000000..93db142f --- /dev/null +++ b/api/core/message_broker/actors/v1/topology.pb.go @@ -0,0 +1,469 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: core/message_broker/actors/v1/topology.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GetTopologyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTopologyRequest) Reset() { + *x = GetTopologyRequest{} + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTopologyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTopologyRequest) ProtoMessage() {} + +func (x *GetTopologyRequest) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTopologyRequest.ProtoReflect.Descriptor instead. +func (*GetTopologyRequest) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_topology_proto_rawDescGZIP(), []int{0} +} + +type GetTopologyResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Producers []*TopologyNode `protobuf:"bytes,1,rep,name=producers,proto3" json:"producers,omitempty"` + Consumers []*TopologyNode `protobuf:"bytes,2,rep,name=consumers,proto3" json:"consumers,omitempty"` + Edges []*TopologyEdge `protobuf:"bytes,3,rep,name=edges,proto3" json:"edges,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTopologyResponse) Reset() { + *x = GetTopologyResponse{} + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTopologyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTopologyResponse) ProtoMessage() {} + +func (x *GetTopologyResponse) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTopologyResponse.ProtoReflect.Descriptor instead. +func (*GetTopologyResponse) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_topology_proto_rawDescGZIP(), []int{1} +} + +func (x *GetTopologyResponse) GetProducers() []*TopologyNode { + if x != nil { + return x.Producers + } + return nil +} + +func (x *GetTopologyResponse) GetConsumers() []*TopologyNode { + if x != nil { + return x.Consumers + } + return nil +} + +func (x *GetTopologyResponse) GetEdges() []*TopologyEdge { + if x != nil { + return x.Edges + } + return nil +} + +type TopologyNode struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TopologyNode) Reset() { + *x = TopologyNode{} + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TopologyNode) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TopologyNode) ProtoMessage() {} + +func (x *TopologyNode) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TopologyNode.ProtoReflect.Descriptor instead. +func (*TopologyNode) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_topology_proto_rawDescGZIP(), []int{2} +} + +func (x *TopologyNode) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *TopologyNode) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type TopologyEdge struct { + state protoimpl.MessageState `protogen:"open.v1"` + ProducerSource string `protobuf:"bytes,1,opt,name=producer_source,json=producerSource,proto3" json:"producer_source,omitempty"` + ConsumerSource string `protobuf:"bytes,2,opt,name=consumer_source,json=consumerSource,proto3" json:"consumer_source,omitempty"` + EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` + Vol uint32 `protobuf:"varint,4,opt,name=vol,proto3" json:"vol,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TopologyEdge) Reset() { + *x = TopologyEdge{} + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TopologyEdge) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TopologyEdge) ProtoMessage() {} + +func (x *TopologyEdge) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TopologyEdge.ProtoReflect.Descriptor instead. +func (*TopologyEdge) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_topology_proto_rawDescGZIP(), []int{3} +} + +func (x *TopologyEdge) GetProducerSource() string { + if x != nil { + return x.ProducerSource + } + return "" +} + +func (x *TopologyEdge) GetConsumerSource() string { + if x != nil { + return x.ConsumerSource + } + return "" +} + +func (x *TopologyEdge) GetEventType() string { + if x != nil { + return x.EventType + } + return "" +} + +func (x *TopologyEdge) GetVol() uint32 { + if x != nil { + return x.Vol + } + return 0 +} + +type WatchTopologyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WatchTopologyRequest) Reset() { + *x = WatchTopologyRequest{} + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WatchTopologyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchTopologyRequest) ProtoMessage() {} + +func (x *WatchTopologyRequest) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WatchTopologyRequest.ProtoReflect.Descriptor instead. +func (*WatchTopologyRequest) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_topology_proto_rawDescGZIP(), []int{4} +} + +type WatchTopologyResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Event: + // + // *WatchTopologyResponse_ConsumerConnected + // *WatchTopologyResponse_ConsumerDisconnected + // *WatchTopologyResponse_ProducerAppeared + Event isWatchTopologyResponse_Event `protobuf_oneof:"event"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WatchTopologyResponse) Reset() { + *x = WatchTopologyResponse{} + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WatchTopologyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchTopologyResponse) ProtoMessage() {} + +func (x *WatchTopologyResponse) ProtoReflect() protoreflect.Message { + mi := &file_core_message_broker_actors_v1_topology_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WatchTopologyResponse.ProtoReflect.Descriptor instead. +func (*WatchTopologyResponse) Descriptor() ([]byte, []int) { + return file_core_message_broker_actors_v1_topology_proto_rawDescGZIP(), []int{5} +} + +func (x *WatchTopologyResponse) GetEvent() isWatchTopologyResponse_Event { + if x != nil { + return x.Event + } + return nil +} + +func (x *WatchTopologyResponse) GetConsumerConnected() *TopologyNode { + if x != nil { + if x, ok := x.Event.(*WatchTopologyResponse_ConsumerConnected); ok { + return x.ConsumerConnected + } + } + return nil +} + +func (x *WatchTopologyResponse) GetConsumerDisconnected() *TopologyNode { + if x != nil { + if x, ok := x.Event.(*WatchTopologyResponse_ConsumerDisconnected); ok { + return x.ConsumerDisconnected + } + } + return nil +} + +func (x *WatchTopologyResponse) GetProducerAppeared() *TopologyNode { + if x != nil { + if x, ok := x.Event.(*WatchTopologyResponse_ProducerAppeared); ok { + return x.ProducerAppeared + } + } + return nil +} + +type isWatchTopologyResponse_Event interface { + isWatchTopologyResponse_Event() +} + +type WatchTopologyResponse_ConsumerConnected struct { + ConsumerConnected *TopologyNode `protobuf:"bytes,1,opt,name=consumer_connected,json=consumerConnected,proto3,oneof"` +} + +type WatchTopologyResponse_ConsumerDisconnected struct { + ConsumerDisconnected *TopologyNode `protobuf:"bytes,2,opt,name=consumer_disconnected,json=consumerDisconnected,proto3,oneof"` +} + +type WatchTopologyResponse_ProducerAppeared struct { + ProducerAppeared *TopologyNode `protobuf:"bytes,3,opt,name=producer_appeared,json=producerAppeared,proto3,oneof"` +} + +func (*WatchTopologyResponse_ConsumerConnected) isWatchTopologyResponse_Event() {} + +func (*WatchTopologyResponse_ConsumerDisconnected) isWatchTopologyResponse_Event() {} + +func (*WatchTopologyResponse_ProducerAppeared) isWatchTopologyResponse_Event() {} + +var File_core_message_broker_actors_v1_topology_proto protoreflect.FileDescriptor + +const file_core_message_broker_actors_v1_topology_proto_rawDesc = "" + + "\n" + + ",core/message_broker/actors/v1/topology.proto\x12\x1dcore.message_broker.actors.v1\"\x14\n" + + "\x12GetTopologyRequest\"\xee\x01\n" + + "\x13GetTopologyResponse\x12I\n" + + "\tproducers\x18\x01 \x03(\v2+.core.message_broker.actors.v1.TopologyNodeR\tproducers\x12I\n" + + "\tconsumers\x18\x02 \x03(\v2+.core.message_broker.actors.v1.TopologyNodeR\tconsumers\x12A\n" + + "\x05edges\x18\x03 \x03(\v2+.core.message_broker.actors.v1.TopologyEdgeR\x05edges\"2\n" + + "\fTopologyNode\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\"\x91\x01\n" + + "\fTopologyEdge\x12'\n" + + "\x0fproducer_source\x18\x01 \x01(\tR\x0eproducerSource\x12'\n" + + "\x0fconsumer_source\x18\x02 \x01(\tR\x0econsumerSource\x12\x1d\n" + + "\n" + + "event_type\x18\x03 \x01(\tR\teventType\x12\x10\n" + + "\x03vol\x18\x04 \x01(\rR\x03vol\"\x16\n" + + "\x14WatchTopologyRequest\"\xbe\x02\n" + + "\x15WatchTopologyResponse\x12\\\n" + + "\x12consumer_connected\x18\x01 \x01(\v2+.core.message_broker.actors.v1.TopologyNodeH\x00R\x11consumerConnected\x12b\n" + + "\x15consumer_disconnected\x18\x02 \x01(\v2+.core.message_broker.actors.v1.TopologyNodeH\x00R\x14consumerDisconnected\x12Z\n" + + "\x11producer_appeared\x18\x03 \x01(\v2+.core.message_broker.actors.v1.TopologyNodeH\x00R\x10producerAppearedB\a\n" + + "\x05event2\x82\x02\n" + + "\bTopology\x12v\n" + + "\vGetTopology\x121.core.message_broker.actors.v1.GetTopologyRequest\x1a2.core.message_broker.actors.v1.GetTopologyResponse\"\x00\x12~\n" + + "\rWatchTopology\x123.core.message_broker.actors.v1.WatchTopologyRequest\x1a4.core.message_broker.actors.v1.WatchTopologyResponse\"\x000\x01BAZ?github.com/steady-bytes/draft/api/core/message_broker/actors/v1b\x06proto3" + +var ( + file_core_message_broker_actors_v1_topology_proto_rawDescOnce sync.Once + file_core_message_broker_actors_v1_topology_proto_rawDescData []byte +) + +func file_core_message_broker_actors_v1_topology_proto_rawDescGZIP() []byte { + file_core_message_broker_actors_v1_topology_proto_rawDescOnce.Do(func() { + file_core_message_broker_actors_v1_topology_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_topology_proto_rawDesc), len(file_core_message_broker_actors_v1_topology_proto_rawDesc))) + }) + return file_core_message_broker_actors_v1_topology_proto_rawDescData +} + +var file_core_message_broker_actors_v1_topology_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_core_message_broker_actors_v1_topology_proto_goTypes = []any{ + (*GetTopologyRequest)(nil), // 0: core.message_broker.actors.v1.GetTopologyRequest + (*GetTopologyResponse)(nil), // 1: core.message_broker.actors.v1.GetTopologyResponse + (*TopologyNode)(nil), // 2: core.message_broker.actors.v1.TopologyNode + (*TopologyEdge)(nil), // 3: core.message_broker.actors.v1.TopologyEdge + (*WatchTopologyRequest)(nil), // 4: core.message_broker.actors.v1.WatchTopologyRequest + (*WatchTopologyResponse)(nil), // 5: core.message_broker.actors.v1.WatchTopologyResponse +} +var file_core_message_broker_actors_v1_topology_proto_depIdxs = []int32{ + 2, // 0: core.message_broker.actors.v1.GetTopologyResponse.producers:type_name -> core.message_broker.actors.v1.TopologyNode + 2, // 1: core.message_broker.actors.v1.GetTopologyResponse.consumers:type_name -> core.message_broker.actors.v1.TopologyNode + 3, // 2: core.message_broker.actors.v1.GetTopologyResponse.edges:type_name -> core.message_broker.actors.v1.TopologyEdge + 2, // 3: core.message_broker.actors.v1.WatchTopologyResponse.consumer_connected:type_name -> core.message_broker.actors.v1.TopologyNode + 2, // 4: core.message_broker.actors.v1.WatchTopologyResponse.consumer_disconnected:type_name -> core.message_broker.actors.v1.TopologyNode + 2, // 5: core.message_broker.actors.v1.WatchTopologyResponse.producer_appeared:type_name -> core.message_broker.actors.v1.TopologyNode + 0, // 6: core.message_broker.actors.v1.Topology.GetTopology:input_type -> core.message_broker.actors.v1.GetTopologyRequest + 4, // 7: core.message_broker.actors.v1.Topology.WatchTopology:input_type -> core.message_broker.actors.v1.WatchTopologyRequest + 1, // 8: core.message_broker.actors.v1.Topology.GetTopology:output_type -> core.message_broker.actors.v1.GetTopologyResponse + 5, // 9: core.message_broker.actors.v1.Topology.WatchTopology:output_type -> core.message_broker.actors.v1.WatchTopologyResponse + 8, // [8:10] is the sub-list for method output_type + 6, // [6:8] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_core_message_broker_actors_v1_topology_proto_init() } +func file_core_message_broker_actors_v1_topology_proto_init() { + if File_core_message_broker_actors_v1_topology_proto != nil { + return + } + file_core_message_broker_actors_v1_topology_proto_msgTypes[5].OneofWrappers = []any{ + (*WatchTopologyResponse_ConsumerConnected)(nil), + (*WatchTopologyResponse_ConsumerDisconnected)(nil), + (*WatchTopologyResponse_ProducerAppeared)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_message_broker_actors_v1_topology_proto_rawDesc), len(file_core_message_broker_actors_v1_topology_proto_rawDesc)), + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_core_message_broker_actors_v1_topology_proto_goTypes, + DependencyIndexes: file_core_message_broker_actors_v1_topology_proto_depIdxs, + MessageInfos: file_core_message_broker_actors_v1_topology_proto_msgTypes, + }.Build() + File_core_message_broker_actors_v1_topology_proto = out.File + file_core_message_broker_actors_v1_topology_proto_goTypes = nil + file_core_message_broker_actors_v1_topology_proto_depIdxs = nil +} diff --git a/api/core/message_broker/actors/v1/topology.pb.validate.go b/api/core/message_broker/actors/v1/topology.pb.validate.go new file mode 100644 index 00000000..340b8a35 --- /dev/null +++ b/api/core/message_broker/actors/v1/topology.pb.validate.go @@ -0,0 +1,884 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: core/message_broker/actors/v1/topology.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on GetTopologyRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetTopologyRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetTopologyRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetTopologyRequestMultiError, or nil if none found. +func (m *GetTopologyRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GetTopologyRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return GetTopologyRequestMultiError(errors) + } + + return nil +} + +// GetTopologyRequestMultiError is an error wrapping multiple validation errors +// returned by GetTopologyRequest.ValidateAll() if the designated constraints +// aren't met. +type GetTopologyRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetTopologyRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetTopologyRequestMultiError) AllErrors() []error { return m } + +// GetTopologyRequestValidationError is the validation error returned by +// GetTopologyRequest.Validate if the designated constraints aren't met. +type GetTopologyRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetTopologyRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetTopologyRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetTopologyRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetTopologyRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetTopologyRequestValidationError) ErrorName() string { + return "GetTopologyRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e GetTopologyRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetTopologyRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetTopologyRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetTopologyRequestValidationError{} + +// Validate checks the field values on GetTopologyResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetTopologyResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetTopologyResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetTopologyResponseMultiError, or nil if none found. +func (m *GetTopologyResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GetTopologyResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetProducers() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetTopologyResponseValidationError{ + field: fmt.Sprintf("Producers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetTopologyResponseValidationError{ + field: fmt.Sprintf("Producers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetTopologyResponseValidationError{ + field: fmt.Sprintf("Producers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + for idx, item := range m.GetConsumers() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetTopologyResponseValidationError{ + field: fmt.Sprintf("Consumers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetTopologyResponseValidationError{ + field: fmt.Sprintf("Consumers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetTopologyResponseValidationError{ + field: fmt.Sprintf("Consumers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + for idx, item := range m.GetEdges() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetTopologyResponseValidationError{ + field: fmt.Sprintf("Edges[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetTopologyResponseValidationError{ + field: fmt.Sprintf("Edges[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetTopologyResponseValidationError{ + field: fmt.Sprintf("Edges[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return GetTopologyResponseMultiError(errors) + } + + return nil +} + +// GetTopologyResponseMultiError is an error wrapping multiple validation +// errors returned by GetTopologyResponse.ValidateAll() if the designated +// constraints aren't met. +type GetTopologyResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetTopologyResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetTopologyResponseMultiError) AllErrors() []error { return m } + +// GetTopologyResponseValidationError is the validation error returned by +// GetTopologyResponse.Validate if the designated constraints aren't met. +type GetTopologyResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetTopologyResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetTopologyResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetTopologyResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetTopologyResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetTopologyResponseValidationError) ErrorName() string { + return "GetTopologyResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GetTopologyResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetTopologyResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetTopologyResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetTopologyResponseValidationError{} + +// Validate checks the field values on TopologyNode with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *TopologyNode) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on TopologyNode with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in TopologyNodeMultiError, or +// nil if none found. +func (m *TopologyNode) ValidateAll() error { + return m.validate(true) +} + +func (m *TopologyNode) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Id + + // no validation rules for Name + + if len(errors) > 0 { + return TopologyNodeMultiError(errors) + } + + return nil +} + +// TopologyNodeMultiError is an error wrapping multiple validation errors +// returned by TopologyNode.ValidateAll() if the designated constraints aren't met. +type TopologyNodeMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m TopologyNodeMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m TopologyNodeMultiError) AllErrors() []error { return m } + +// TopologyNodeValidationError is the validation error returned by +// TopologyNode.Validate if the designated constraints aren't met. +type TopologyNodeValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e TopologyNodeValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e TopologyNodeValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e TopologyNodeValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e TopologyNodeValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e TopologyNodeValidationError) ErrorName() string { return "TopologyNodeValidationError" } + +// Error satisfies the builtin error interface +func (e TopologyNodeValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTopologyNode.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = TopologyNodeValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = TopologyNodeValidationError{} + +// Validate checks the field values on TopologyEdge with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *TopologyEdge) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on TopologyEdge with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in TopologyEdgeMultiError, or +// nil if none found. +func (m *TopologyEdge) ValidateAll() error { + return m.validate(true) +} + +func (m *TopologyEdge) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for ProducerSource + + // no validation rules for ConsumerSource + + // no validation rules for EventType + + // no validation rules for Vol + + if len(errors) > 0 { + return TopologyEdgeMultiError(errors) + } + + return nil +} + +// TopologyEdgeMultiError is an error wrapping multiple validation errors +// returned by TopologyEdge.ValidateAll() if the designated constraints aren't met. +type TopologyEdgeMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m TopologyEdgeMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m TopologyEdgeMultiError) AllErrors() []error { return m } + +// TopologyEdgeValidationError is the validation error returned by +// TopologyEdge.Validate if the designated constraints aren't met. +type TopologyEdgeValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e TopologyEdgeValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e TopologyEdgeValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e TopologyEdgeValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e TopologyEdgeValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e TopologyEdgeValidationError) ErrorName() string { return "TopologyEdgeValidationError" } + +// Error satisfies the builtin error interface +func (e TopologyEdgeValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTopologyEdge.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = TopologyEdgeValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = TopologyEdgeValidationError{} + +// Validate checks the field values on WatchTopologyRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *WatchTopologyRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on WatchTopologyRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// WatchTopologyRequestMultiError, or nil if none found. +func (m *WatchTopologyRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *WatchTopologyRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return WatchTopologyRequestMultiError(errors) + } + + return nil +} + +// WatchTopologyRequestMultiError is an error wrapping multiple validation +// errors returned by WatchTopologyRequest.ValidateAll() if the designated +// constraints aren't met. +type WatchTopologyRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m WatchTopologyRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m WatchTopologyRequestMultiError) AllErrors() []error { return m } + +// WatchTopologyRequestValidationError is the validation error returned by +// WatchTopologyRequest.Validate if the designated constraints aren't met. +type WatchTopologyRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e WatchTopologyRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e WatchTopologyRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e WatchTopologyRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e WatchTopologyRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e WatchTopologyRequestValidationError) ErrorName() string { + return "WatchTopologyRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e WatchTopologyRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sWatchTopologyRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = WatchTopologyRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = WatchTopologyRequestValidationError{} + +// Validate checks the field values on WatchTopologyResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *WatchTopologyResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on WatchTopologyResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// WatchTopologyResponseMultiError, or nil if none found. +func (m *WatchTopologyResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *WatchTopologyResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + switch v := m.Event.(type) { + case *WatchTopologyResponse_ConsumerConnected: + if v == nil { + err := WatchTopologyResponseValidationError{ + field: "Event", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetConsumerConnected()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, WatchTopologyResponseValidationError{ + field: "ConsumerConnected", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, WatchTopologyResponseValidationError{ + field: "ConsumerConnected", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetConsumerConnected()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WatchTopologyResponseValidationError{ + field: "ConsumerConnected", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *WatchTopologyResponse_ConsumerDisconnected: + if v == nil { + err := WatchTopologyResponseValidationError{ + field: "Event", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetConsumerDisconnected()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, WatchTopologyResponseValidationError{ + field: "ConsumerDisconnected", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, WatchTopologyResponseValidationError{ + field: "ConsumerDisconnected", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetConsumerDisconnected()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WatchTopologyResponseValidationError{ + field: "ConsumerDisconnected", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *WatchTopologyResponse_ProducerAppeared: + if v == nil { + err := WatchTopologyResponseValidationError{ + field: "Event", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetProducerAppeared()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, WatchTopologyResponseValidationError{ + field: "ProducerAppeared", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, WatchTopologyResponseValidationError{ + field: "ProducerAppeared", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetProducerAppeared()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WatchTopologyResponseValidationError{ + field: "ProducerAppeared", + reason: "embedded message failed validation", + cause: err, + } + } + } + + default: + _ = v // ensures v is used + } + + if len(errors) > 0 { + return WatchTopologyResponseMultiError(errors) + } + + return nil +} + +// WatchTopologyResponseMultiError is an error wrapping multiple validation +// errors returned by WatchTopologyResponse.ValidateAll() if the designated +// constraints aren't met. +type WatchTopologyResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m WatchTopologyResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m WatchTopologyResponseMultiError) AllErrors() []error { return m } + +// WatchTopologyResponseValidationError is the validation error returned by +// WatchTopologyResponse.Validate if the designated constraints aren't met. +type WatchTopologyResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e WatchTopologyResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e WatchTopologyResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e WatchTopologyResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e WatchTopologyResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e WatchTopologyResponseValidationError) ErrorName() string { + return "WatchTopologyResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e WatchTopologyResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sWatchTopologyResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = WatchTopologyResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = WatchTopologyResponseValidationError{} diff --git a/api/core/message_broker/actors/v1/topology.proto b/api/core/message_broker/actors/v1/topology.proto new file mode 100644 index 00000000..1fb2b1ce --- /dev/null +++ b/api/core/message_broker/actors/v1/topology.proto @@ -0,0 +1,46 @@ +syntax = "proto3"; + +package core.message_broker.actors.v1; + +option go_package = "github.com/steady-bytes/draft/api/core/message_broker/actors/v1"; + +service Topology { + // GetTopology returns a snapshot of the current event topology: producers + // derived from ClickHouse distinct sources, consumers and edges derived from + // live ConsumeRequest registrations tracked in the broker's atomicMap. + rpc GetTopology(GetTopologyRequest) returns (GetTopologyResponse) {} + + // WatchTopology streams incremental topology deltas as consumers connect or + // disconnect and as new producer sources appear in the event store. + rpc WatchTopology(WatchTopologyRequest) returns (stream WatchTopologyResponse) {} +} + +message GetTopologyRequest {} + +message GetTopologyResponse { + repeated TopologyNode producers = 1; + repeated TopologyNode consumers = 2; + repeated TopologyEdge edges = 3; +} + +message TopologyNode { + string id = 1; + string name = 2; +} + +message TopologyEdge { + string producer_source = 1; + string consumer_source = 2; + string event_type = 3; + uint32 vol = 4; +} + +message WatchTopologyRequest {} + +message WatchTopologyResponse { + oneof event { + TopologyNode consumer_connected = 1; + TopologyNode consumer_disconnected = 2; + TopologyNode producer_appeared = 3; + } +} diff --git a/api/core/message_broker/actors/v1/v1connect/consumer.connect.go b/api/core/message_broker/actors/v1/v1connect/consumer.connect.go index e6a64313..8153c1c8 100644 --- a/api/core/message_broker/actors/v1/v1connect/consumer.connect.go +++ b/api/core/message_broker/actors/v1/v1connect/consumer.connect.go @@ -37,12 +37,6 @@ const ( ConsumerConsumeProcedure = "/core.message_broker.actors.v1.Consumer/Consume" ) -// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. -var ( - consumerServiceDescriptor = v1.File_core_message_broker_actors_v1_consumer_proto.Services().ByName("Consumer") - consumerConsumeMethodDescriptor = consumerServiceDescriptor.Methods().ByName("Consume") -) - // ConsumerClient is a client for the core.message_broker.actors.v1.Consumer service. type ConsumerClient interface { Consume(context.Context, *connect.Request[v1.ConsumeRequest]) (*connect.ServerStreamForClient[v1.ConsumeResponse], error) @@ -57,11 +51,12 @@ type ConsumerClient interface { // http://api.acme.com or https://acme.com/grpc). func NewConsumerClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) ConsumerClient { baseURL = strings.TrimRight(baseURL, "/") + consumerMethods := v1.File_core_message_broker_actors_v1_consumer_proto.Services().ByName("Consumer").Methods() return &consumerClient{ consume: connect.NewClient[v1.ConsumeRequest, v1.ConsumeResponse]( httpClient, baseURL+ConsumerConsumeProcedure, - connect.WithSchema(consumerConsumeMethodDescriptor), + connect.WithSchema(consumerMethods.ByName("Consume")), connect.WithClientOptions(opts...), ), } @@ -88,10 +83,11 @@ type ConsumerHandler interface { // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. func NewConsumerHandler(svc ConsumerHandler, opts ...connect.HandlerOption) (string, http.Handler) { + consumerMethods := v1.File_core_message_broker_actors_v1_consumer_proto.Services().ByName("Consumer").Methods() consumerConsumeHandler := connect.NewServerStreamHandler( ConsumerConsumeProcedure, svc.Consume, - connect.WithSchema(consumerConsumeMethodDescriptor), + connect.WithSchema(consumerMethods.ByName("Consume")), connect.WithHandlerOptions(opts...), ) return "/core.message_broker.actors.v1.Consumer/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/api/core/message_broker/actors/v1/v1connect/metrics.connect.go b/api/core/message_broker/actors/v1/v1connect/metrics.connect.go new file mode 100644 index 00000000..45125651 --- /dev/null +++ b/api/core/message_broker/actors/v1/v1connect/metrics.connect.go @@ -0,0 +1,144 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: core/message_broker/actors/v1/metrics.proto + +package v1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // MetricsName is the fully-qualified name of the Metrics service. + MetricsName = "core.message_broker.actors.v1.Metrics" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // MetricsGetMetricsProcedure is the fully-qualified name of the Metrics's GetMetrics RPC. + MetricsGetMetricsProcedure = "/core.message_broker.actors.v1.Metrics/GetMetrics" + // MetricsGetTopicSeriesProcedure is the fully-qualified name of the Metrics's GetTopicSeries RPC. + MetricsGetTopicSeriesProcedure = "/core.message_broker.actors.v1.Metrics/GetTopicSeries" +) + +// MetricsClient is a client for the core.message_broker.actors.v1.Metrics service. +type MetricsClient interface { + // GetMetrics returns pre-computed throughput and latency metrics derived from + // ClickHouse aggregates over the requested time window. + GetMetrics(context.Context, *connect.Request[v1.GetMetricsRequest]) (*connect.Response[v1.GetMetricsResponse], error) + // GetTopicSeries returns a time-bucketed message count for one event_type, + // suitable for rendering a line chart over the requested window. + GetTopicSeries(context.Context, *connect.Request[v1.GetTopicSeriesRequest]) (*connect.Response[v1.GetTopicSeriesResponse], error) +} + +// NewMetricsClient constructs a client for the core.message_broker.actors.v1.Metrics service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewMetricsClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) MetricsClient { + baseURL = strings.TrimRight(baseURL, "/") + metricsMethods := v1.File_core_message_broker_actors_v1_metrics_proto.Services().ByName("Metrics").Methods() + return &metricsClient{ + getMetrics: connect.NewClient[v1.GetMetricsRequest, v1.GetMetricsResponse]( + httpClient, + baseURL+MetricsGetMetricsProcedure, + connect.WithSchema(metricsMethods.ByName("GetMetrics")), + connect.WithClientOptions(opts...), + ), + getTopicSeries: connect.NewClient[v1.GetTopicSeriesRequest, v1.GetTopicSeriesResponse]( + httpClient, + baseURL+MetricsGetTopicSeriesProcedure, + connect.WithSchema(metricsMethods.ByName("GetTopicSeries")), + connect.WithClientOptions(opts...), + ), + } +} + +// metricsClient implements MetricsClient. +type metricsClient struct { + getMetrics *connect.Client[v1.GetMetricsRequest, v1.GetMetricsResponse] + getTopicSeries *connect.Client[v1.GetTopicSeriesRequest, v1.GetTopicSeriesResponse] +} + +// GetMetrics calls core.message_broker.actors.v1.Metrics.GetMetrics. +func (c *metricsClient) GetMetrics(ctx context.Context, req *connect.Request[v1.GetMetricsRequest]) (*connect.Response[v1.GetMetricsResponse], error) { + return c.getMetrics.CallUnary(ctx, req) +} + +// GetTopicSeries calls core.message_broker.actors.v1.Metrics.GetTopicSeries. +func (c *metricsClient) GetTopicSeries(ctx context.Context, req *connect.Request[v1.GetTopicSeriesRequest]) (*connect.Response[v1.GetTopicSeriesResponse], error) { + return c.getTopicSeries.CallUnary(ctx, req) +} + +// MetricsHandler is an implementation of the core.message_broker.actors.v1.Metrics service. +type MetricsHandler interface { + // GetMetrics returns pre-computed throughput and latency metrics derived from + // ClickHouse aggregates over the requested time window. + GetMetrics(context.Context, *connect.Request[v1.GetMetricsRequest]) (*connect.Response[v1.GetMetricsResponse], error) + // GetTopicSeries returns a time-bucketed message count for one event_type, + // suitable for rendering a line chart over the requested window. + GetTopicSeries(context.Context, *connect.Request[v1.GetTopicSeriesRequest]) (*connect.Response[v1.GetTopicSeriesResponse], error) +} + +// NewMetricsHandler builds an HTTP handler from the service implementation. It returns the path on +// which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewMetricsHandler(svc MetricsHandler, opts ...connect.HandlerOption) (string, http.Handler) { + metricsMethods := v1.File_core_message_broker_actors_v1_metrics_proto.Services().ByName("Metrics").Methods() + metricsGetMetricsHandler := connect.NewUnaryHandler( + MetricsGetMetricsProcedure, + svc.GetMetrics, + connect.WithSchema(metricsMethods.ByName("GetMetrics")), + connect.WithHandlerOptions(opts...), + ) + metricsGetTopicSeriesHandler := connect.NewUnaryHandler( + MetricsGetTopicSeriesProcedure, + svc.GetTopicSeries, + connect.WithSchema(metricsMethods.ByName("GetTopicSeries")), + connect.WithHandlerOptions(opts...), + ) + return "/core.message_broker.actors.v1.Metrics/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case MetricsGetMetricsProcedure: + metricsGetMetricsHandler.ServeHTTP(w, r) + case MetricsGetTopicSeriesProcedure: + metricsGetTopicSeriesHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedMetricsHandler returns CodeUnimplemented from all methods. +type UnimplementedMetricsHandler struct{} + +func (UnimplementedMetricsHandler) GetMetrics(context.Context, *connect.Request[v1.GetMetricsRequest]) (*connect.Response[v1.GetMetricsResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("core.message_broker.actors.v1.Metrics.GetMetrics is not implemented")) +} + +func (UnimplementedMetricsHandler) GetTopicSeries(context.Context, *connect.Request[v1.GetTopicSeriesRequest]) (*connect.Response[v1.GetTopicSeriesResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("core.message_broker.actors.v1.Metrics.GetTopicSeries is not implemented")) +} diff --git a/api/core/message_broker/actors/v1/v1connect/producer.connect.go b/api/core/message_broker/actors/v1/v1connect/producer.connect.go index f8d6e9cf..fa1be9e5 100644 --- a/api/core/message_broker/actors/v1/v1connect/producer.connect.go +++ b/api/core/message_broker/actors/v1/v1connect/producer.connect.go @@ -37,12 +37,6 @@ const ( ProducerProduceProcedure = "/core.message_broker.actors.v1.Producer/Produce" ) -// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. -var ( - producerServiceDescriptor = v1.File_core_message_broker_actors_v1_producer_proto.Services().ByName("Producer") - producerProduceMethodDescriptor = producerServiceDescriptor.Methods().ByName("Produce") -) - // ProducerClient is a client for the core.message_broker.actors.v1.Producer service. type ProducerClient interface { Produce(context.Context) *connect.BidiStreamForClient[v1.ProduceRequest, v1.ProduceResponse] @@ -57,11 +51,12 @@ type ProducerClient interface { // http://api.acme.com or https://acme.com/grpc). func NewProducerClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) ProducerClient { baseURL = strings.TrimRight(baseURL, "/") + producerMethods := v1.File_core_message_broker_actors_v1_producer_proto.Services().ByName("Producer").Methods() return &producerClient{ produce: connect.NewClient[v1.ProduceRequest, v1.ProduceResponse]( httpClient, baseURL+ProducerProduceProcedure, - connect.WithSchema(producerProduceMethodDescriptor), + connect.WithSchema(producerMethods.ByName("Produce")), connect.WithClientOptions(opts...), ), } @@ -88,10 +83,11 @@ type ProducerHandler interface { // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. func NewProducerHandler(svc ProducerHandler, opts ...connect.HandlerOption) (string, http.Handler) { + producerMethods := v1.File_core_message_broker_actors_v1_producer_proto.Services().ByName("Producer").Methods() producerProduceHandler := connect.NewBidiStreamHandler( ProducerProduceProcedure, svc.Produce, - connect.WithSchema(producerProduceMethodDescriptor), + connect.WithSchema(producerMethods.ByName("Produce")), connect.WithHandlerOptions(opts...), ) return "/core.message_broker.actors.v1.Producer/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/api/core/message_broker/actors/v1/v1connect/query.connect.go b/api/core/message_broker/actors/v1/v1connect/query.connect.go new file mode 100644 index 00000000..6b3a80f2 --- /dev/null +++ b/api/core/message_broker/actors/v1/v1connect/query.connect.go @@ -0,0 +1,148 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: core/message_broker/actors/v1/query.proto + +package v1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // QueryName is the fully-qualified name of the Query service. + QueryName = "core.message_broker.actors.v1.Query" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // QueryQueryProcedure is the fully-qualified name of the Query's Query RPC. + QueryQueryProcedure = "/core.message_broker.actors.v1.Query/Query" + // QueryQueryStreamProcedure is the fully-qualified name of the Query's QueryStream RPC. + QueryQueryStreamProcedure = "/core.message_broker.actors.v1.Query/QueryStream" +) + +// QueryClient is a client for the core.message_broker.actors.v1.Query service. +type QueryClient interface { + // Query executes a CESQL expression against stored events and returns all + // matching results in a single response. + Query(context.Context, *connect.Request[v1.QueryRequest]) (*connect.Response[v1.QueryResponse], error) + // QueryStream opens a persistent server-sent stream. The server first + // replays any stored events that match the expression (subject to `limit` + // and `after`), then continues streaming live events as they flow through + // catalyst in real time. The stream stays open until the client closes it. + QueryStream(context.Context, *connect.Request[v1.QueryRequest]) (*connect.ServerStreamForClient[v1.QueryStreamResponse], error) +} + +// NewQueryClient constructs a client for the core.message_broker.actors.v1.Query service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewQueryClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) QueryClient { + baseURL = strings.TrimRight(baseURL, "/") + queryMethods := v1.File_core_message_broker_actors_v1_query_proto.Services().ByName("Query").Methods() + return &queryClient{ + query: connect.NewClient[v1.QueryRequest, v1.QueryResponse]( + httpClient, + baseURL+QueryQueryProcedure, + connect.WithSchema(queryMethods.ByName("Query")), + connect.WithClientOptions(opts...), + ), + queryStream: connect.NewClient[v1.QueryRequest, v1.QueryStreamResponse]( + httpClient, + baseURL+QueryQueryStreamProcedure, + connect.WithSchema(queryMethods.ByName("QueryStream")), + connect.WithClientOptions(opts...), + ), + } +} + +// queryClient implements QueryClient. +type queryClient struct { + query *connect.Client[v1.QueryRequest, v1.QueryResponse] + queryStream *connect.Client[v1.QueryRequest, v1.QueryStreamResponse] +} + +// Query calls core.message_broker.actors.v1.Query.Query. +func (c *queryClient) Query(ctx context.Context, req *connect.Request[v1.QueryRequest]) (*connect.Response[v1.QueryResponse], error) { + return c.query.CallUnary(ctx, req) +} + +// QueryStream calls core.message_broker.actors.v1.Query.QueryStream. +func (c *queryClient) QueryStream(ctx context.Context, req *connect.Request[v1.QueryRequest]) (*connect.ServerStreamForClient[v1.QueryStreamResponse], error) { + return c.queryStream.CallServerStream(ctx, req) +} + +// QueryHandler is an implementation of the core.message_broker.actors.v1.Query service. +type QueryHandler interface { + // Query executes a CESQL expression against stored events and returns all + // matching results in a single response. + Query(context.Context, *connect.Request[v1.QueryRequest]) (*connect.Response[v1.QueryResponse], error) + // QueryStream opens a persistent server-sent stream. The server first + // replays any stored events that match the expression (subject to `limit` + // and `after`), then continues streaming live events as they flow through + // catalyst in real time. The stream stays open until the client closes it. + QueryStream(context.Context, *connect.Request[v1.QueryRequest], *connect.ServerStream[v1.QueryStreamResponse]) error +} + +// NewQueryHandler builds an HTTP handler from the service implementation. It returns the path on +// which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewQueryHandler(svc QueryHandler, opts ...connect.HandlerOption) (string, http.Handler) { + queryMethods := v1.File_core_message_broker_actors_v1_query_proto.Services().ByName("Query").Methods() + queryQueryHandler := connect.NewUnaryHandler( + QueryQueryProcedure, + svc.Query, + connect.WithSchema(queryMethods.ByName("Query")), + connect.WithHandlerOptions(opts...), + ) + queryQueryStreamHandler := connect.NewServerStreamHandler( + QueryQueryStreamProcedure, + svc.QueryStream, + connect.WithSchema(queryMethods.ByName("QueryStream")), + connect.WithHandlerOptions(opts...), + ) + return "/core.message_broker.actors.v1.Query/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case QueryQueryProcedure: + queryQueryHandler.ServeHTTP(w, r) + case QueryQueryStreamProcedure: + queryQueryStreamHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedQueryHandler returns CodeUnimplemented from all methods. +type UnimplementedQueryHandler struct{} + +func (UnimplementedQueryHandler) Query(context.Context, *connect.Request[v1.QueryRequest]) (*connect.Response[v1.QueryResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("core.message_broker.actors.v1.Query.Query is not implemented")) +} + +func (UnimplementedQueryHandler) QueryStream(context.Context, *connect.Request[v1.QueryRequest], *connect.ServerStream[v1.QueryStreamResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("core.message_broker.actors.v1.Query.QueryStream is not implemented")) +} diff --git a/api/core/message_broker/actors/v1/v1connect/resource_metrics.connect.go b/api/core/message_broker/actors/v1/v1connect/resource_metrics.connect.go new file mode 100644 index 00000000..ff0a8a54 --- /dev/null +++ b/api/core/message_broker/actors/v1/v1connect/resource_metrics.connect.go @@ -0,0 +1,111 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: core/message_broker/actors/v1/resource_metrics.proto + +package v1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // ResourceMetricsName is the fully-qualified name of the ResourceMetrics service. + ResourceMetricsName = "core.message_broker.actors.v1.ResourceMetrics" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // ResourceMetricsGetResourceMetricsProcedure is the fully-qualified name of the ResourceMetrics's + // GetResourceMetrics RPC. + ResourceMetricsGetResourceMetricsProcedure = "/core.message_broker.actors.v1.ResourceMetrics/GetResourceMetrics" +) + +// ResourceMetricsClient is a client for the core.message_broker.actors.v1.ResourceMetrics service. +type ResourceMetricsClient interface { + GetResourceMetrics(context.Context, *connect.Request[v1.GetResourceMetricsRequest]) (*connect.Response[v1.GetResourceMetricsResponse], error) +} + +// NewResourceMetricsClient constructs a client for the +// core.message_broker.actors.v1.ResourceMetrics service. By default, it uses the Connect protocol +// with the binary Protobuf Codec, asks for gzipped responses, and sends uncompressed requests. To +// use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or connect.WithGRPCWeb() +// options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewResourceMetricsClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) ResourceMetricsClient { + baseURL = strings.TrimRight(baseURL, "/") + resourceMetricsMethods := v1.File_core_message_broker_actors_v1_resource_metrics_proto.Services().ByName("ResourceMetrics").Methods() + return &resourceMetricsClient{ + getResourceMetrics: connect.NewClient[v1.GetResourceMetricsRequest, v1.GetResourceMetricsResponse]( + httpClient, + baseURL+ResourceMetricsGetResourceMetricsProcedure, + connect.WithSchema(resourceMetricsMethods.ByName("GetResourceMetrics")), + connect.WithClientOptions(opts...), + ), + } +} + +// resourceMetricsClient implements ResourceMetricsClient. +type resourceMetricsClient struct { + getResourceMetrics *connect.Client[v1.GetResourceMetricsRequest, v1.GetResourceMetricsResponse] +} + +// GetResourceMetrics calls core.message_broker.actors.v1.ResourceMetrics.GetResourceMetrics. +func (c *resourceMetricsClient) GetResourceMetrics(ctx context.Context, req *connect.Request[v1.GetResourceMetricsRequest]) (*connect.Response[v1.GetResourceMetricsResponse], error) { + return c.getResourceMetrics.CallUnary(ctx, req) +} + +// ResourceMetricsHandler is an implementation of the core.message_broker.actors.v1.ResourceMetrics +// service. +type ResourceMetricsHandler interface { + GetResourceMetrics(context.Context, *connect.Request[v1.GetResourceMetricsRequest]) (*connect.Response[v1.GetResourceMetricsResponse], error) +} + +// NewResourceMetricsHandler builds an HTTP handler from the service implementation. It returns the +// path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewResourceMetricsHandler(svc ResourceMetricsHandler, opts ...connect.HandlerOption) (string, http.Handler) { + resourceMetricsMethods := v1.File_core_message_broker_actors_v1_resource_metrics_proto.Services().ByName("ResourceMetrics").Methods() + resourceMetricsGetResourceMetricsHandler := connect.NewUnaryHandler( + ResourceMetricsGetResourceMetricsProcedure, + svc.GetResourceMetrics, + connect.WithSchema(resourceMetricsMethods.ByName("GetResourceMetrics")), + connect.WithHandlerOptions(opts...), + ) + return "/core.message_broker.actors.v1.ResourceMetrics/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case ResourceMetricsGetResourceMetricsProcedure: + resourceMetricsGetResourceMetricsHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedResourceMetricsHandler returns CodeUnimplemented from all methods. +type UnimplementedResourceMetricsHandler struct{} + +func (UnimplementedResourceMetricsHandler) GetResourceMetrics(context.Context, *connect.Request[v1.GetResourceMetricsRequest]) (*connect.Response[v1.GetResourceMetricsResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("core.message_broker.actors.v1.ResourceMetrics.GetResourceMetrics is not implemented")) +} diff --git a/api/core/message_broker/actors/v1/v1connect/topology.connect.go b/api/core/message_broker/actors/v1/v1connect/topology.connect.go new file mode 100644 index 00000000..fc402e47 --- /dev/null +++ b/api/core/message_broker/actors/v1/v1connect/topology.connect.go @@ -0,0 +1,146 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: core/message_broker/actors/v1/topology.proto + +package v1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // TopologyName is the fully-qualified name of the Topology service. + TopologyName = "core.message_broker.actors.v1.Topology" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // TopologyGetTopologyProcedure is the fully-qualified name of the Topology's GetTopology RPC. + TopologyGetTopologyProcedure = "/core.message_broker.actors.v1.Topology/GetTopology" + // TopologyWatchTopologyProcedure is the fully-qualified name of the Topology's WatchTopology RPC. + TopologyWatchTopologyProcedure = "/core.message_broker.actors.v1.Topology/WatchTopology" +) + +// TopologyClient is a client for the core.message_broker.actors.v1.Topology service. +type TopologyClient interface { + // GetTopology returns a snapshot of the current event topology: producers + // derived from ClickHouse distinct sources, consumers and edges derived from + // live ConsumeRequest registrations tracked in the broker's atomicMap. + GetTopology(context.Context, *connect.Request[v1.GetTopologyRequest]) (*connect.Response[v1.GetTopologyResponse], error) + // WatchTopology streams incremental topology deltas as consumers connect or + // disconnect and as new producer sources appear in the event store. + WatchTopology(context.Context, *connect.Request[v1.WatchTopologyRequest]) (*connect.ServerStreamForClient[v1.WatchTopologyResponse], error) +} + +// NewTopologyClient constructs a client for the core.message_broker.actors.v1.Topology service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewTopologyClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) TopologyClient { + baseURL = strings.TrimRight(baseURL, "/") + topologyMethods := v1.File_core_message_broker_actors_v1_topology_proto.Services().ByName("Topology").Methods() + return &topologyClient{ + getTopology: connect.NewClient[v1.GetTopologyRequest, v1.GetTopologyResponse]( + httpClient, + baseURL+TopologyGetTopologyProcedure, + connect.WithSchema(topologyMethods.ByName("GetTopology")), + connect.WithClientOptions(opts...), + ), + watchTopology: connect.NewClient[v1.WatchTopologyRequest, v1.WatchTopologyResponse]( + httpClient, + baseURL+TopologyWatchTopologyProcedure, + connect.WithSchema(topologyMethods.ByName("WatchTopology")), + connect.WithClientOptions(opts...), + ), + } +} + +// topologyClient implements TopologyClient. +type topologyClient struct { + getTopology *connect.Client[v1.GetTopologyRequest, v1.GetTopologyResponse] + watchTopology *connect.Client[v1.WatchTopologyRequest, v1.WatchTopologyResponse] +} + +// GetTopology calls core.message_broker.actors.v1.Topology.GetTopology. +func (c *topologyClient) GetTopology(ctx context.Context, req *connect.Request[v1.GetTopologyRequest]) (*connect.Response[v1.GetTopologyResponse], error) { + return c.getTopology.CallUnary(ctx, req) +} + +// WatchTopology calls core.message_broker.actors.v1.Topology.WatchTopology. +func (c *topologyClient) WatchTopology(ctx context.Context, req *connect.Request[v1.WatchTopologyRequest]) (*connect.ServerStreamForClient[v1.WatchTopologyResponse], error) { + return c.watchTopology.CallServerStream(ctx, req) +} + +// TopologyHandler is an implementation of the core.message_broker.actors.v1.Topology service. +type TopologyHandler interface { + // GetTopology returns a snapshot of the current event topology: producers + // derived from ClickHouse distinct sources, consumers and edges derived from + // live ConsumeRequest registrations tracked in the broker's atomicMap. + GetTopology(context.Context, *connect.Request[v1.GetTopologyRequest]) (*connect.Response[v1.GetTopologyResponse], error) + // WatchTopology streams incremental topology deltas as consumers connect or + // disconnect and as new producer sources appear in the event store. + WatchTopology(context.Context, *connect.Request[v1.WatchTopologyRequest], *connect.ServerStream[v1.WatchTopologyResponse]) error +} + +// NewTopologyHandler builds an HTTP handler from the service implementation. It returns the path on +// which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewTopologyHandler(svc TopologyHandler, opts ...connect.HandlerOption) (string, http.Handler) { + topologyMethods := v1.File_core_message_broker_actors_v1_topology_proto.Services().ByName("Topology").Methods() + topologyGetTopologyHandler := connect.NewUnaryHandler( + TopologyGetTopologyProcedure, + svc.GetTopology, + connect.WithSchema(topologyMethods.ByName("GetTopology")), + connect.WithHandlerOptions(opts...), + ) + topologyWatchTopologyHandler := connect.NewServerStreamHandler( + TopologyWatchTopologyProcedure, + svc.WatchTopology, + connect.WithSchema(topologyMethods.ByName("WatchTopology")), + connect.WithHandlerOptions(opts...), + ) + return "/core.message_broker.actors.v1.Topology/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case TopologyGetTopologyProcedure: + topologyGetTopologyHandler.ServeHTTP(w, r) + case TopologyWatchTopologyProcedure: + topologyWatchTopologyHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedTopologyHandler returns CodeUnimplemented from all methods. +type UnimplementedTopologyHandler struct{} + +func (UnimplementedTopologyHandler) GetTopology(context.Context, *connect.Request[v1.GetTopologyRequest]) (*connect.Response[v1.GetTopologyResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("core.message_broker.actors.v1.Topology.GetTopology is not implemented")) +} + +func (UnimplementedTopologyHandler) WatchTopology(context.Context, *connect.Request[v1.WatchTopologyRequest], *connect.ServerStream[v1.WatchTopologyResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("core.message_broker.actors.v1.Topology.WatchTopology is not implemented")) +} diff --git a/api/core/registry/key_value/v1/cluster_layout.pb.go b/api/core/registry/key_value/v1/cluster_layout.pb.go new file mode 100644 index 00000000..22d43ed9 --- /dev/null +++ b/api/core/registry/key_value/v1/cluster_layout.pb.go @@ -0,0 +1,186 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: core/registry/key_value/v1/cluster_layout.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type NodePosition struct { + state protoimpl.MessageState `protogen:"open.v1"` + X float32 `protobuf:"fixed32,1,opt,name=x,proto3" json:"x,omitempty"` + Y float32 `protobuf:"fixed32,2,opt,name=y,proto3" json:"y,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NodePosition) Reset() { + *x = NodePosition{} + mi := &file_core_registry_key_value_v1_cluster_layout_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NodePosition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodePosition) ProtoMessage() {} + +func (x *NodePosition) ProtoReflect() protoreflect.Message { + mi := &file_core_registry_key_value_v1_cluster_layout_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodePosition.ProtoReflect.Descriptor instead. +func (*NodePosition) Descriptor() ([]byte, []int) { + return file_core_registry_key_value_v1_cluster_layout_proto_rawDescGZIP(), []int{0} +} + +func (x *NodePosition) GetX() float32 { + if x != nil { + return x.X + } + return 0 +} + +func (x *NodePosition) GetY() float32 { + if x != nil { + return x.Y + } + return 0 +} + +type ClusterLayout struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Node label → canvas position. Keyed by label so layout is resilient + // to nodes being added or removed from the graph. + Positions map[string]*NodePosition `protobuf:"bytes,1,rep,name=positions,proto3" json:"positions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ClusterLayout) Reset() { + *x = ClusterLayout{} + mi := &file_core_registry_key_value_v1_cluster_layout_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClusterLayout) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClusterLayout) ProtoMessage() {} + +func (x *ClusterLayout) ProtoReflect() protoreflect.Message { + mi := &file_core_registry_key_value_v1_cluster_layout_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClusterLayout.ProtoReflect.Descriptor instead. +func (*ClusterLayout) Descriptor() ([]byte, []int) { + return file_core_registry_key_value_v1_cluster_layout_proto_rawDescGZIP(), []int{1} +} + +func (x *ClusterLayout) GetPositions() map[string]*NodePosition { + if x != nil { + return x.Positions + } + return nil +} + +var File_core_registry_key_value_v1_cluster_layout_proto protoreflect.FileDescriptor + +const file_core_registry_key_value_v1_cluster_layout_proto_rawDesc = "" + + "\n" + + "/core/registry/key_value/v1/cluster_layout.proto\x12\x1acore.registry.key_value.v1\"*\n" + + "\fNodePosition\x12\f\n" + + "\x01x\x18\x01 \x01(\x02R\x01x\x12\f\n" + + "\x01y\x18\x02 \x01(\x02R\x01y\"\xcf\x01\n" + + "\rClusterLayout\x12V\n" + + "\tpositions\x18\x01 \x03(\v28.core.registry.key_value.v1.ClusterLayout.PositionsEntryR\tpositions\x1af\n" + + "\x0ePositionsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12>\n" + + "\x05value\x18\x02 \x01(\v2(.core.registry.key_value.v1.NodePositionR\x05value:\x028\x01B>Z core.registry.key_value.v1.ClusterLayout.PositionsEntry + 0, // 1: core.registry.key_value.v1.ClusterLayout.PositionsEntry.value:type_name -> core.registry.key_value.v1.NodePosition + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_core_registry_key_value_v1_cluster_layout_proto_init() } +func file_core_registry_key_value_v1_cluster_layout_proto_init() { + if File_core_registry_key_value_v1_cluster_layout_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_registry_key_value_v1_cluster_layout_proto_rawDesc), len(file_core_registry_key_value_v1_cluster_layout_proto_rawDesc)), + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_core_registry_key_value_v1_cluster_layout_proto_goTypes, + DependencyIndexes: file_core_registry_key_value_v1_cluster_layout_proto_depIdxs, + MessageInfos: file_core_registry_key_value_v1_cluster_layout_proto_msgTypes, + }.Build() + File_core_registry_key_value_v1_cluster_layout_proto = out.File + file_core_registry_key_value_v1_cluster_layout_proto_goTypes = nil + file_core_registry_key_value_v1_cluster_layout_proto_depIdxs = nil +} diff --git a/api/core/registry/key_value/v1/cluster_layout.pb.validate.go b/api/core/registry/key_value/v1/cluster_layout.pb.validate.go new file mode 100644 index 00000000..03e2c190 --- /dev/null +++ b/api/core/registry/key_value/v1/cluster_layout.pb.validate.go @@ -0,0 +1,285 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: core/registry/key_value/v1/cluster_layout.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on NodePosition with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *NodePosition) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on NodePosition with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in NodePositionMultiError, or +// nil if none found. +func (m *NodePosition) ValidateAll() error { + return m.validate(true) +} + +func (m *NodePosition) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for X + + // no validation rules for Y + + if len(errors) > 0 { + return NodePositionMultiError(errors) + } + + return nil +} + +// NodePositionMultiError is an error wrapping multiple validation errors +// returned by NodePosition.ValidateAll() if the designated constraints aren't met. +type NodePositionMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m NodePositionMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m NodePositionMultiError) AllErrors() []error { return m } + +// NodePositionValidationError is the validation error returned by +// NodePosition.Validate if the designated constraints aren't met. +type NodePositionValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e NodePositionValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e NodePositionValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e NodePositionValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e NodePositionValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e NodePositionValidationError) ErrorName() string { return "NodePositionValidationError" } + +// Error satisfies the builtin error interface +func (e NodePositionValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sNodePosition.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = NodePositionValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = NodePositionValidationError{} + +// Validate checks the field values on ClusterLayout with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *ClusterLayout) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClusterLayout with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in ClusterLayoutMultiError, or +// nil if none found. +func (m *ClusterLayout) ValidateAll() error { + return m.validate(true) +} + +func (m *ClusterLayout) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + { + sorted_keys := make([]string, len(m.GetPositions())) + i := 0 + for key := range m.GetPositions() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetPositions()[key] + _ = val + + // no validation rules for Positions[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ClusterLayoutValidationError{ + field: fmt.Sprintf("Positions[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ClusterLayoutValidationError{ + field: fmt.Sprintf("Positions[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterLayoutValidationError{ + field: fmt.Sprintf("Positions[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + if len(errors) > 0 { + return ClusterLayoutMultiError(errors) + } + + return nil +} + +// ClusterLayoutMultiError is an error wrapping multiple validation errors +// returned by ClusterLayout.ValidateAll() if the designated constraints +// aren't met. +type ClusterLayoutMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClusterLayoutMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClusterLayoutMultiError) AllErrors() []error { return m } + +// ClusterLayoutValidationError is the validation error returned by +// ClusterLayout.Validate if the designated constraints aren't met. +type ClusterLayoutValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClusterLayoutValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClusterLayoutValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClusterLayoutValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClusterLayoutValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClusterLayoutValidationError) ErrorName() string { return "ClusterLayoutValidationError" } + +// Error satisfies the builtin error interface +func (e ClusterLayoutValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClusterLayout.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClusterLayoutValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClusterLayoutValidationError{} diff --git a/api/core/registry/key_value/v1/cluster_layout.proto b/api/core/registry/key_value/v1/cluster_layout.proto new file mode 100644 index 00000000..c1651d9a --- /dev/null +++ b/api/core/registry/key_value/v1/cluster_layout.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package core.registry.key_value.v1; + +option go_package = "github.com/steady-bytes/draft/api/core/registry/key_value/v1"; + +message NodePosition { + float x = 1; + float y = 2; +} + +message ClusterLayout { + // Node label → canvas position. Keyed by label so layout is resilient + // to nodes being added or removed from the graph. + map positions = 1; +} diff --git a/api/core/registry/key_value/v1/data_definition_lang.pb.go b/api/core/registry/key_value/v1/data_definition_lang.pb.go index 23eca0de..a2a4e261 100644 --- a/api/core/registry/key_value/v1/data_definition_lang.pb.go +++ b/api/core/registry/key_value/v1/data_definition_lang.pb.go @@ -1,18 +1,18 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: core/registry/key_value/v1/data_definition_lang.proto package v1 import ( - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" anypb "google.golang.org/protobuf/types/known/anypb" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -83,21 +83,18 @@ func (Operation) EnumDescriptor() ([]byte, []int) { // Standard ID to be used in the whole system type ID struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // generated system uuid - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid" bun:"uuid" csv:"uuid" pg:"uuid" yaml:"uuid"` + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ID) Reset() { *x = ID{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_data_definition_lang_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_data_definition_lang_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ID) String() string { @@ -108,7 +105,7 @@ func (*ID) ProtoMessage() {} func (x *ID) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_data_definition_lang_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -132,31 +129,28 @@ func (x *ID) GetUuid() string { // Statement is the root node of the query. It's the entry point to the query system. type Statement struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // select * from `kind` - Kind *anypb.Any `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind" bun:"kind" csv:"kind" pg:"kind" yaml:"kind"` + Kind *anypb.Any `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"` // The operation to perform on the `kind` object - Operation Operation `protobuf:"varint,2,opt,name=operation,proto3,enum=core.registry.key_value.v1.Operation" json:"operation" bun:"operation" csv:"operation" pg:"operation" yaml:"operation"` + Operation Operation `protobuf:"varint,2,opt,name=operation,proto3,enum=core.registry.key_value.v1.Operation" json:"operation,omitempty"` // The `where` clause is used to filter the results of the query. // - // Types that are assignable to Where: + // Types that are valid to be assigned to Where: // // *Statement_IsAll // *Statement_Id // *Statement_KeyVal - Where isStatement_Where `protobuf_oneof:"where"` + Where isStatement_Where `protobuf_oneof:"where"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Statement) Reset() { *x = Statement{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_data_definition_lang_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_data_definition_lang_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Statement) String() string { @@ -167,7 +161,7 @@ func (*Statement) ProtoMessage() {} func (x *Statement) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_data_definition_lang_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -196,30 +190,36 @@ func (x *Statement) GetOperation() Operation { return Operation_NONE } -func (m *Statement) GetWhere() isStatement_Where { - if m != nil { - return m.Where +func (x *Statement) GetWhere() isStatement_Where { + if x != nil { + return x.Where } return nil } func (x *Statement) GetIsAll() bool { - if x, ok := x.GetWhere().(*Statement_IsAll); ok { - return x.IsAll + if x != nil { + if x, ok := x.Where.(*Statement_IsAll); ok { + return x.IsAll + } } return false } func (x *Statement) GetId() *ID { - if x, ok := x.GetWhere().(*Statement_Id); ok { - return x.Id + if x != nil { + if x, ok := x.Where.(*Statement_Id); ok { + return x.Id + } } return nil } func (x *Statement) GetKeyVal() *Equal { - if x, ok := x.GetWhere().(*Statement_KeyVal); ok { - return x.KeyVal + if x != nil { + if x, ok := x.Where.(*Statement_KeyVal); ok { + return x.KeyVal + } } return nil } @@ -230,18 +230,18 @@ type isStatement_Where interface { type Statement_IsAll struct { // return all `kinds` - `select * from `courses` - IsAll bool `protobuf:"varint,3,opt,name=is_all,json=isAll,proto3,oneof" bun:"is_all" csv:"is_all" json:"is_all" pg:"is_all" yaml:"is_all"` + IsAll bool `protobuf:"varint,3,opt,name=is_all,json=isAll,proto3,oneof"` } type Statement_Id struct { // return a `kind` that matches the `ID` - `select * from courses where id = "123" - Id *ID `protobuf:"bytes,4,opt,name=id,proto3,oneof" bun:"id" csv:"id" json:"id" pg:"id" yaml:"id"` + Id *ID `protobuf:"bytes,4,opt,name=id,proto3,oneof"` } type Statement_KeyVal struct { // return all `kind`'s that equal the key/value pairs fields // `select * from courses where name = "Payne Stewart"` - KeyVal *Equal `protobuf:"bytes,5,opt,name=key_val,json=keyVal,proto3,oneof" bun:"key_val" csv:"key_val" json:"key_val" pg:"key_val" yaml:"key_val"` + KeyVal *Equal `protobuf:"bytes,5,opt,name=key_val,json=keyVal,proto3,oneof"` } func (*Statement_IsAll) isStatement_Where() {} @@ -251,21 +251,18 @@ func (*Statement_Id) isStatement_Where() {} func (*Statement_KeyVal) isStatement_Where() {} type Equal struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // of the `Kind` being queried return the values that match the key/value pairs below - Match map[string]string `protobuf:"bytes,1,rep,name=match,proto3" json:"match" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" bun:"match" csv:"match" pg:"match" yaml:"match"` + Match map[string]string `protobuf:"bytes,1,rep,name=match,proto3" json:"match,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Equal) Reset() { *x = Equal{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_data_definition_lang_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_data_definition_lang_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Equal) String() string { @@ -276,7 +273,7 @@ func (*Equal) ProtoMessage() {} func (x *Equal) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_data_definition_lang_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -300,63 +297,43 @@ func (x *Equal) GetMatch() map[string]string { var File_core_registry_key_value_v1_data_definition_lang_proto protoreflect.FileDescriptor -var file_core_registry_key_value_v1_data_definition_lang_proto_rawDesc = []byte{ - 0x0a, 0x35, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, - 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x61, 0x74, - 0x61, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x6e, - 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2e, 0x76, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x22, 0x0a, 0x02, 0x49, 0x44, 0x12, 0x1c, 0x0a, - 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, - 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0x8c, 0x02, 0x0a, 0x09, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x6b, - 0x69, 0x6e, 0x64, 0x12, 0x43, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x06, 0x69, 0x73, 0x5f, 0x61, - 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x05, 0x69, 0x73, 0x41, 0x6c, - 0x6c, 0x12, 0x30, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, - 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x44, 0x48, 0x00, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x3c, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x6b, 0x65, 0x79, 0x56, 0x61, - 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x77, 0x68, 0x65, 0x72, 0x65, 0x22, 0x85, 0x01, 0x0a, 0x05, 0x45, - 0x71, 0x75, 0x61, 0x6c, 0x12, 0x42, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x38, 0x0a, 0x0a, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x2a, 0x45, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, 0x4c, - 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, - 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x0a, 0x0a, - 0x06, 0x49, 0x4e, 0x53, 0x45, 0x52, 0x54, 0x10, 0x04, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, 0x2d, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, - 0x6f, 0x72, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x79, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} +const file_core_registry_key_value_v1_data_definition_lang_proto_rawDesc = "" + + "\n" + + "5core/registry/key_value/v1/data_definition_lang.proto\x12\x1acore.registry.key_value.v1\x1a\x19google/protobuf/any.proto\"\x18\n" + + "\x02ID\x12\x12\n" + + "\x04uuid\x18\x01 \x01(\tR\x04uuid\"\x8c\x02\n" + + "\tStatement\x12(\n" + + "\x04kind\x18\x01 \x01(\v2\x14.google.protobuf.AnyR\x04kind\x12C\n" + + "\toperation\x18\x02 \x01(\x0e2%.core.registry.key_value.v1.OperationR\toperation\x12\x17\n" + + "\x06is_all\x18\x03 \x01(\bH\x00R\x05isAll\x120\n" + + "\x02id\x18\x04 \x01(\v2\x1e.core.registry.key_value.v1.IDH\x00R\x02id\x12<\n" + + "\akey_val\x18\x05 \x01(\v2!.core.registry.key_value.v1.EqualH\x00R\x06keyValB\a\n" + + "\x05where\"\x85\x01\n" + + "\x05Equal\x12B\n" + + "\x05match\x18\x01 \x03(\v2,.core.registry.key_value.v1.Equal.MatchEntryR\x05match\x1a8\n" + + "\n" + + "MatchEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01*E\n" + + "\tOperation\x12\b\n" + + "\x04NONE\x10\x00\x12\n" + + "\n" + + "\x06SELECT\x10\x01\x12\n" + + "\n" + + "\x06DELETE\x10\x02\x12\n" + + "\n" + + "\x06UPDATE\x10\x03\x12\n" + + "\n" + + "\x06INSERT\x10\x04B>Z 0 { return IDMultiError(errors) @@ -78,21 +65,13 @@ func (m *ID) validate(all bool) error { return nil } -func (m *ID) _validateUuid(uuid string) error { - if matched := _data_definition_lang_uuidPattern.MatchString(uuid); !matched { - return errors.New("invalid uuid format") - } - - return nil -} - // IDMultiError is an error wrapping multiple validation errors returned by // ID.ValidateAll() if the designated constraints aren't met. type IDMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m IDMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -321,7 +300,7 @@ type StatementMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m StatementMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -421,7 +400,7 @@ type EqualMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m EqualMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/core/registry/key_value/v1/data_definition_lang.proto b/api/core/registry/key_value/v1/data_definition_lang.proto index a22b1105..b6be1029 100644 --- a/api/core/registry/key_value/v1/data_definition_lang.proto +++ b/api/core/registry/key_value/v1/data_definition_lang.proto @@ -5,12 +5,11 @@ package core.registry.key_value.v1; option go_package = "github.com/steady-bytes/draft/api/core/registry/key_value/v1"; import "google/protobuf/any.proto"; -import "validate/validate.proto"; // Standard ID to be used in the whole system message ID { // generated system uuid - string uuid = 1 [(validate.rules).string.uuid = true]; + string uuid = 1; } // Statement is the root node of the query. It's the entry point to the query system. diff --git a/api/core/registry/key_value/v1/models.pb.go b/api/core/registry/key_value/v1/models.pb.go index 9e9d0738..4a341b27 100644 --- a/api/core/registry/key_value/v1/models.pb.go +++ b/api/core/registry/key_value/v1/models.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: core/registry/key_value/v1/models.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -22,20 +23,17 @@ const ( // Value - The message that is used to save a value in the `key_value` store. type Value struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` unknownFields protoimpl.UnknownFields - - Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data" bun:"data" csv:"data" pg:"data" yaml:"data"` + sizeCache protoimpl.SizeCache } func (x *Value) Reset() { *x = Value{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_models_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_models_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Value) String() string { @@ -46,7 +44,7 @@ func (*Value) ProtoMessage() {} func (x *Value) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_models_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -70,28 +68,20 @@ func (x *Value) GetData() string { var File_core_registry_key_value_v1_models_proto protoreflect.FileDescriptor -var file_core_registry_key_value_v1_models_proto_rawDesc = []byte{ - 0x0a, 0x27, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, - 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x6f, 0x64, - 0x65, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x1b, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, 0x72, - 0x61, 0x66, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2f, - 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_core_registry_key_value_v1_models_proto_rawDesc = "" + + "\n" + + "'core/registry/key_value/v1/models.proto\x12\x1acore.registry.key_value.v1\"\x1b\n" + + "\x05Value\x12\x12\n" + + "\x04data\x18\x01 \x01(\tR\x04dataB>ZZ core.registry.key_value.v1.NavigationItem + 1, // 1: core.registry.key_value.v1.NavigationConfig.sections:type_name -> core.registry.key_value.v1.NavigationSection + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_core_registry_key_value_v1_nav_config_proto_init() } +func file_core_registry_key_value_v1_nav_config_proto_init() { + if File_core_registry_key_value_v1_nav_config_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_registry_key_value_v1_nav_config_proto_rawDesc), len(file_core_registry_key_value_v1_nav_config_proto_rawDesc)), + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_core_registry_key_value_v1_nav_config_proto_goTypes, + DependencyIndexes: file_core_registry_key_value_v1_nav_config_proto_depIdxs, + MessageInfos: file_core_registry_key_value_v1_nav_config_proto_msgTypes, + }.Build() + File_core_registry_key_value_v1_nav_config_proto = out.File + file_core_registry_key_value_v1_nav_config_proto_goTypes = nil + file_core_registry_key_value_v1_nav_config_proto_depIdxs = nil +} diff --git a/api/core/registry/key_value/v1/nav_config.pb.validate.go b/api/core/registry/key_value/v1/nav_config.pb.validate.go new file mode 100644 index 00000000..c0f9f022 --- /dev/null +++ b/api/core/registry/key_value/v1/nav_config.pb.validate.go @@ -0,0 +1,412 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: core/registry/key_value/v1/nav_config.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on NavigationItem with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *NavigationItem) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on NavigationItem with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in NavigationItemMultiError, +// or nil if none found. +func (m *NavigationItem) ValidateAll() error { + return m.validate(true) +} + +func (m *NavigationItem) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Label + + // no validation rules for Path + + if len(errors) > 0 { + return NavigationItemMultiError(errors) + } + + return nil +} + +// NavigationItemMultiError is an error wrapping multiple validation errors +// returned by NavigationItem.ValidateAll() if the designated constraints +// aren't met. +type NavigationItemMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m NavigationItemMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m NavigationItemMultiError) AllErrors() []error { return m } + +// NavigationItemValidationError is the validation error returned by +// NavigationItem.Validate if the designated constraints aren't met. +type NavigationItemValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e NavigationItemValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e NavigationItemValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e NavigationItemValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e NavigationItemValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e NavigationItemValidationError) ErrorName() string { return "NavigationItemValidationError" } + +// Error satisfies the builtin error interface +func (e NavigationItemValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sNavigationItem.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = NavigationItemValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = NavigationItemValidationError{} + +// Validate checks the field values on NavigationSection with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *NavigationSection) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on NavigationSection with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// NavigationSectionMultiError, or nil if none found. +func (m *NavigationSection) ValidateAll() error { + return m.validate(true) +} + +func (m *NavigationSection) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Label + + for idx, item := range m.GetItems() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, NavigationSectionValidationError{ + field: fmt.Sprintf("Items[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, NavigationSectionValidationError{ + field: fmt.Sprintf("Items[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return NavigationSectionValidationError{ + field: fmt.Sprintf("Items[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return NavigationSectionMultiError(errors) + } + + return nil +} + +// NavigationSectionMultiError is an error wrapping multiple validation errors +// returned by NavigationSection.ValidateAll() if the designated constraints +// aren't met. +type NavigationSectionMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m NavigationSectionMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m NavigationSectionMultiError) AllErrors() []error { return m } + +// NavigationSectionValidationError is the validation error returned by +// NavigationSection.Validate if the designated constraints aren't met. +type NavigationSectionValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e NavigationSectionValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e NavigationSectionValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e NavigationSectionValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e NavigationSectionValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e NavigationSectionValidationError) ErrorName() string { + return "NavigationSectionValidationError" +} + +// Error satisfies the builtin error interface +func (e NavigationSectionValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sNavigationSection.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = NavigationSectionValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = NavigationSectionValidationError{} + +// Validate checks the field values on NavigationConfig with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *NavigationConfig) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on NavigationConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// NavigationConfigMultiError, or nil if none found. +func (m *NavigationConfig) ValidateAll() error { + return m.validate(true) +} + +func (m *NavigationConfig) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetSections() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, NavigationConfigValidationError{ + field: fmt.Sprintf("Sections[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, NavigationConfigValidationError{ + field: fmt.Sprintf("Sections[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return NavigationConfigValidationError{ + field: fmt.Sprintf("Sections[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return NavigationConfigMultiError(errors) + } + + return nil +} + +// NavigationConfigMultiError is an error wrapping multiple validation errors +// returned by NavigationConfig.ValidateAll() if the designated constraints +// aren't met. +type NavigationConfigMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m NavigationConfigMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m NavigationConfigMultiError) AllErrors() []error { return m } + +// NavigationConfigValidationError is the validation error returned by +// NavigationConfig.Validate if the designated constraints aren't met. +type NavigationConfigValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e NavigationConfigValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e NavigationConfigValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e NavigationConfigValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e NavigationConfigValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e NavigationConfigValidationError) ErrorName() string { return "NavigationConfigValidationError" } + +// Error satisfies the builtin error interface +func (e NavigationConfigValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sNavigationConfig.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = NavigationConfigValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = NavigationConfigValidationError{} diff --git a/api/core/registry/key_value/v1/nav_config.proto b/api/core/registry/key_value/v1/nav_config.proto new file mode 100644 index 00000000..e89262bc --- /dev/null +++ b/api/core/registry/key_value/v1/nav_config.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package core.registry.key_value.v1; + +option go_package = "github.com/steady-bytes/draft/api/core/registry/key_value/v1"; + +message NavigationItem { + string label = 1; + string path = 2; +} + +message NavigationSection { + string label = 1; + repeated NavigationItem items = 2; +} + +message NavigationConfig { + repeated NavigationSection sections = 1; +} diff --git a/api/core/registry/key_value/v1/service.pb.go b/api/core/registry/key_value/v1/service.pb.go index 31ff6264..d640d95f 100644 --- a/api/core/registry/key_value/v1/service.pb.go +++ b/api/core/registry/key_value/v1/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: core/registry/key_value/v1/service.proto @@ -12,6 +12,7 @@ import ( anypb "google.golang.org/protobuf/types/known/anypb" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -22,21 +23,18 @@ const ( ) type SetRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value *anypb.Any `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key" bun:"key" csv:"key" pg:"key" yaml:"key"` - Value *anypb.Any `protobuf:"bytes,2,opt,name=value,proto3" json:"value" bun:"value" csv:"value" pg:"value" yaml:"value"` + sizeCache protoimpl.SizeCache } func (x *SetRequest) Reset() { *x = SetRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SetRequest) String() string { @@ -47,7 +45,7 @@ func (*SetRequest) ProtoMessage() {} func (x *SetRequest) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -77,20 +75,17 @@ func (x *SetRequest) GetValue() *anypb.Any { } type SetResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key" bun:"key" csv:"key" pg:"key" yaml:"key"` + sizeCache protoimpl.SizeCache } func (x *SetResponse) Reset() { *x = SetResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SetResponse) String() string { @@ -101,7 +96,7 @@ func (*SetResponse) ProtoMessage() {} func (x *SetResponse) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -124,21 +119,18 @@ func (x *SetResponse) GetKey() string { } type GetRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value *anypb.Any `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key" bun:"key" csv:"key" pg:"key" yaml:"key"` - Value *anypb.Any `protobuf:"bytes,2,opt,name=value,proto3" json:"value" bun:"value" csv:"value" pg:"value" yaml:"value"` + sizeCache protoimpl.SizeCache } func (x *GetRequest) Reset() { *x = GetRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GetRequest) String() string { @@ -149,7 +141,7 @@ func (*GetRequest) ProtoMessage() {} func (x *GetRequest) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_service_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -179,20 +171,17 @@ func (x *GetRequest) GetValue() *anypb.Any { } type GetResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Value *anypb.Any `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields - - Value *anypb.Any `protobuf:"bytes,1,opt,name=value,proto3" json:"value" bun:"value" csv:"value" pg:"value" yaml:"value"` + sizeCache protoimpl.SizeCache } func (x *GetResponse) Reset() { *x = GetResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_service_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GetResponse) String() string { @@ -203,7 +192,7 @@ func (*GetResponse) ProtoMessage() {} func (x *GetResponse) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_service_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -226,22 +215,19 @@ func (x *GetResponse) GetValue() *anypb.Any { } type DeleteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key" bun:"key" csv:"key" pg:"key" yaml:"key"` + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // value is only used to determine the underlying type, the content within the type does not matter - Value *anypb.Any `protobuf:"bytes,2,opt,name=value,proto3" json:"value" bun:"value" csv:"value" pg:"value" yaml:"value"` + Value *anypb.Any `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DeleteRequest) Reset() { *x = DeleteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_service_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DeleteRequest) String() string { @@ -252,7 +238,7 @@ func (*DeleteRequest) ProtoMessage() {} func (x *DeleteRequest) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_service_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -282,20 +268,17 @@ func (x *DeleteRequest) GetValue() *anypb.Any { } type DeleteResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key" bun:"key" csv:"key" pg:"key" yaml:"key"` + sizeCache protoimpl.SizeCache } func (x *DeleteResponse) Reset() { *x = DeleteResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_service_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DeleteResponse) String() string { @@ -306,7 +289,7 @@ func (*DeleteResponse) ProtoMessage() {} func (x *DeleteResponse) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_service_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -329,20 +312,17 @@ func (x *DeleteResponse) GetKey() string { } type ListRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Value *anypb.Any `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` unknownFields protoimpl.UnknownFields - - Value *anypb.Any `protobuf:"bytes,1,opt,name=value,proto3" json:"value" bun:"value" csv:"value" pg:"value" yaml:"value"` + sizeCache protoimpl.SizeCache } func (x *ListRequest) Reset() { *x = ListRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_service_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ListRequest) String() string { @@ -353,7 +333,7 @@ func (*ListRequest) ProtoMessage() {} func (x *ListRequest) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_service_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -376,20 +356,17 @@ func (x *ListRequest) GetValue() *anypb.Any { } type ListResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Values map[string]*anypb.Any `protobuf:"bytes,2,rep,name=values,proto3" json:"values,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` unknownFields protoimpl.UnknownFields - - Values map[string]*anypb.Any `protobuf:"bytes,2,rep,name=values,proto3" json:"values" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" bun:"values" csv:"values" pg:"values" yaml:"values"` + sizeCache protoimpl.SizeCache } func (x *ListResponse) Reset() { *x = ListResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_core_registry_key_value_v1_service_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_core_registry_key_value_v1_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ListResponse) String() string { @@ -400,7 +377,7 @@ func (*ListResponse) ProtoMessage() {} func (x *ListResponse) ProtoReflect() protoreflect.Message { mi := &file_core_registry_key_value_v1_service_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -424,90 +401,47 @@ func (x *ListResponse) GetValues() map[string]*anypb.Any { var File_core_registry_key_value_v1_service_proto protoreflect.FileDescriptor -var file_core_registry_key_value_v1_service_proto_rawDesc = []byte{ - 0x0a, 0x28, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, - 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0x4a, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1f, 0x0a, - 0x0b, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x4a, - 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x39, 0x0a, 0x0b, 0x47, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4d, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x22, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x39, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x22, 0xad, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x1a, 0x4f, 0x0a, 0x0b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x32, 0x85, 0x03, 0x0a, 0x0f, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x12, 0x26, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, - 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x58, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x61, 0x0a, 0x06, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, - 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x28, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, - 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x3e, 0x5a, 0x3c, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, - 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x6b, - 0x65, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, -} +const file_core_registry_key_value_v1_service_proto_rawDesc = "" + + "\n" + + "(core/registry/key_value/v1/service.proto\x12\x1acore.registry.key_value.v1\x1a\x19google/protobuf/any.proto\"J\n" + + "\n" + + "SetRequest\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12*\n" + + "\x05value\x18\x02 \x01(\v2\x14.google.protobuf.AnyR\x05value\"\x1f\n" + + "\vSetResponse\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\"J\n" + + "\n" + + "GetRequest\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12*\n" + + "\x05value\x18\x02 \x01(\v2\x14.google.protobuf.AnyR\x05value\"9\n" + + "\vGetResponse\x12*\n" + + "\x05value\x18\x01 \x01(\v2\x14.google.protobuf.AnyR\x05value\"M\n" + + "\rDeleteRequest\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12*\n" + + "\x05value\x18\x02 \x01(\v2\x14.google.protobuf.AnyR\x05value\"\"\n" + + "\x0eDeleteResponse\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\"9\n" + + "\vListRequest\x12*\n" + + "\x05value\x18\x01 \x01(\v2\x14.google.protobuf.AnyR\x05value\"\xad\x01\n" + + "\fListResponse\x12L\n" + + "\x06values\x18\x02 \x03(\v24.core.registry.key_value.v1.ListResponse.ValuesEntryR\x06values\x1aO\n" + + "\vValuesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12*\n" + + "\x05value\x18\x02 \x01(\v2\x14.google.protobuf.AnyR\x05value:\x028\x012\x85\x03\n" + + "\x0fKeyValueService\x12X\n" + + "\x03Set\x12&.core.registry.key_value.v1.SetRequest\x1a'.core.registry.key_value.v1.SetResponse\"\x00\x12X\n" + + "\x03Get\x12&.core.registry.key_value.v1.GetRequest\x1a'.core.registry.key_value.v1.GetResponse\"\x00\x12a\n" + + "\x06Delete\x12).core.registry.key_value.v1.DeleteRequest\x1a*.core.registry.key_value.v1.DeleteResponse\"\x00\x12[\n" + + "\x04List\x12'.core.registry.key_value.v1.ListRequest\x1a(.core.registry.key_value.v1.ListResponse\"\x00B>Z\n" + + "\x05nodes\x18\x01 \x03(\v2(.core.registry.service_discovery.v1.NodeR\x05nodes\"\x93\x01\n" + + "\x04Node\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x18\n" + + "\aaddress\x18\x02 \x01(\tR\aaddress\x12a\n" + + "\x11leadership_status\x18\x03 \x01(\x0e24.core.registry.service_discovery.v1.LeadershipStatusR\x10leadershipStatus\"=\n" + + "\x11InitializeRequest\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" + + "\x05nonce\x18\x02 \x01(\tR\x05nonce\"\xd4\x01\n" + + "\x12InitializeResponse\x12^\n" + + "\x10process_identity\x18\x01 \x01(\v23.core.registry.service_discovery.v1.ProcessIdentityR\x0fprocessIdentity\x12^\n" + + "\rconfiguration\x18\x02 \x01(\v28.core.registry.service_discovery.v1.StartupConfigurationR\rconfiguration\"R\n" + + "\fQueryRequest\x12B\n" + + "\x06filter\x18\x01 \x01(\v2*.core.registry.service_discovery.v1.FilterR\x06filter\"S\n" + + "\x06Filter\x12\x10\n" + + "\x02id\x18\x01 \x01(\tH\x00R\x02id\x12\x16\n" + + "\x05group\x18\x02 \x01(\tH\x00R\x05group\x12\x12\n" + + "\x03all\x18\x03 \x01(\tH\x00R\x03allB\v\n" + + "\tattribute\"\xc6\x01\n" + + "\rQueryResponse\x12O\n" + + "\x04data\x18\x01 \x03(\v2;.core.registry.service_discovery.v1.QueryResponse.DataEntryR\x04data\x1ad\n" + + "\tDataEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12A\n" + + "\x05value\x18\x02 \x01(\v2+.core.registry.service_discovery.v1.ProcessR\x05value:\x028\x01\"#\n" + + "\x0fFinalizeRequest\x12\x10\n" + + "\x03pid\x18\x01 \x01(\tR\x03pid\"$\n" + + "\x10FinalizeResponse\x12\x10\n" + + "\x03pid\x18\x01 \x01(\tR\x03pid\"\x15\n" + + "\x13ReportHealthRequest\"\x16\n" + + "\x14ReportHealthResponse\"\x0e\n" + + "\fWatchRequest\"p\n" + + "\rWatchResponse\x12E\n" + + "\aprocess\x18\x01 \x01(\v2+.core.registry.service_discovery.v1.ProcessR\aprocess\x12\x18\n" + + "\aremoved\x18\x02 \x01(\bR\aremoved*s\n" + + "\x10LeadershipStatus\x12!\n" + + "\x1dLEADERSHIP_STATUS_UNSPECIFIED\x10\x00\x12\x1c\n" + + "\x18LEADERSHIP_STATUS_LEADER\x10\x01\x12\x1e\n" + + "\x1aLEADERSHIP_STATUS_FOLLOWER\x10\x022\xf5\x05\n" + + "\x17ServiceDiscoveryService\x12}\n" + + "\n" + + "Initialize\x125.core.registry.service_discovery.v1.InitializeRequest\x1a6.core.registry.service_discovery.v1.InitializeResponse\"\x00\x12z\n" + + "\vSynchronize\x121.core.registry.service_discovery.v1.ClientDetails\x1a2.core.registry.service_discovery.v1.ClusterDetails\"\x00(\x010\x01\x12w\n" + + "\bFinalize\x123.core.registry.service_discovery.v1.FinalizeRequest\x1a4.core.registry.service_discovery.v1.FinalizeResponse\"\x00\x12\x83\x01\n" + + "\fReportHealth\x127.core.registry.service_discovery.v1.ReportHealthRequest\x1a8.core.registry.service_discovery.v1.ReportHealthResponse\"\x00\x12n\n" + + "\x05Query\x120.core.registry.service_discovery.v1.QueryRequest\x1a1.core.registry.service_discovery.v1.QueryResponse\"\x00\x12p\n" + + "\x05Watch\x120.core.registry.service_discovery.v1.WatchRequest\x1a1.core.registry.service_discovery.v1.WatchResponse\"\x000\x01BFZDgithub.com/steady-bytes/draft/api/core/registry/service_discovery/v1b\x06proto3" + var ( file_core_registry_service_discovery_v1_service_proto_rawDescOnce sync.Once - file_core_registry_service_discovery_v1_service_proto_rawDescData = file_core_registry_service_discovery_v1_service_proto_rawDesc + file_core_registry_service_discovery_v1_service_proto_rawDescData []byte ) func file_core_registry_service_discovery_v1_service_proto_rawDescGZIP() []byte { file_core_registry_service_discovery_v1_service_proto_rawDescOnce.Do(func() { - file_core_registry_service_discovery_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_registry_service_discovery_v1_service_proto_rawDescData) + file_core_registry_service_discovery_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_registry_service_discovery_v1_service_proto_rawDesc), len(file_core_registry_service_discovery_v1_service_proto_rawDesc))) }) return file_core_registry_service_discovery_v1_service_proto_rawDescData } var file_core_registry_service_discovery_v1_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_core_registry_service_discovery_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_core_registry_service_discovery_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_core_registry_service_discovery_v1_service_proto_goTypes = []any{ (LeadershipStatus)(0), // 0: core.registry.service_discovery.v1.LeadershipStatus (*ClientDetails)(nil), // 1: core.registry.service_discovery.v1.ClientDetails @@ -954,44 +914,49 @@ var file_core_registry_service_discovery_v1_service_proto_goTypes = []any{ (*FinalizeResponse)(nil), // 10: core.registry.service_discovery.v1.FinalizeResponse (*ReportHealthRequest)(nil), // 11: core.registry.service_discovery.v1.ReportHealthRequest (*ReportHealthResponse)(nil), // 12: core.registry.service_discovery.v1.ReportHealthResponse - nil, // 13: core.registry.service_discovery.v1.QueryResponse.DataEntry - (ProcessRunningState)(0), // 14: core.registry.service_discovery.v1.ProcessRunningState - (ProcessHealthState)(0), // 15: core.registry.service_discovery.v1.ProcessHealthState - (ProcessKind)(0), // 16: core.registry.service_discovery.v1.ProcessKind - (*GeoPoint)(nil), // 17: core.registry.service_discovery.v1.GeoPoint - (*Metadata)(nil), // 18: core.registry.service_discovery.v1.Metadata - (*ProcessIdentity)(nil), // 19: core.registry.service_discovery.v1.ProcessIdentity - (*StartupConfiguration)(nil), // 20: core.registry.service_discovery.v1.StartupConfiguration - (*Process)(nil), // 21: core.registry.service_discovery.v1.Process + (*WatchRequest)(nil), // 13: core.registry.service_discovery.v1.WatchRequest + (*WatchResponse)(nil), // 14: core.registry.service_discovery.v1.WatchResponse + nil, // 15: core.registry.service_discovery.v1.QueryResponse.DataEntry + (ProcessRunningState)(0), // 16: core.registry.service_discovery.v1.ProcessRunningState + (ProcessHealthState)(0), // 17: core.registry.service_discovery.v1.ProcessHealthState + (ProcessKind)(0), // 18: core.registry.service_discovery.v1.ProcessKind + (*GeoPoint)(nil), // 19: core.registry.service_discovery.v1.GeoPoint + (*Metadata)(nil), // 20: core.registry.service_discovery.v1.Metadata + (*ProcessIdentity)(nil), // 21: core.registry.service_discovery.v1.ProcessIdentity + (*StartupConfiguration)(nil), // 22: core.registry.service_discovery.v1.StartupConfiguration + (*Process)(nil), // 23: core.registry.service_discovery.v1.Process } var file_core_registry_service_discovery_v1_service_proto_depIdxs = []int32{ - 14, // 0: core.registry.service_discovery.v1.ClientDetails.running_state:type_name -> core.registry.service_discovery.v1.ProcessRunningState - 15, // 1: core.registry.service_discovery.v1.ClientDetails.health_state:type_name -> core.registry.service_discovery.v1.ProcessHealthState - 16, // 2: core.registry.service_discovery.v1.ClientDetails.process_kind:type_name -> core.registry.service_discovery.v1.ProcessKind - 17, // 3: core.registry.service_discovery.v1.ClientDetails.location:type_name -> core.registry.service_discovery.v1.GeoPoint - 18, // 4: core.registry.service_discovery.v1.ClientDetails.metadata:type_name -> core.registry.service_discovery.v1.Metadata + 16, // 0: core.registry.service_discovery.v1.ClientDetails.running_state:type_name -> core.registry.service_discovery.v1.ProcessRunningState + 17, // 1: core.registry.service_discovery.v1.ClientDetails.health_state:type_name -> core.registry.service_discovery.v1.ProcessHealthState + 18, // 2: core.registry.service_discovery.v1.ClientDetails.process_kind:type_name -> core.registry.service_discovery.v1.ProcessKind + 19, // 3: core.registry.service_discovery.v1.ClientDetails.location:type_name -> core.registry.service_discovery.v1.GeoPoint + 20, // 4: core.registry.service_discovery.v1.ClientDetails.metadata:type_name -> core.registry.service_discovery.v1.Metadata 3, // 5: core.registry.service_discovery.v1.ClusterDetails.nodes:type_name -> core.registry.service_discovery.v1.Node 0, // 6: core.registry.service_discovery.v1.Node.leadership_status:type_name -> core.registry.service_discovery.v1.LeadershipStatus - 19, // 7: core.registry.service_discovery.v1.InitializeResponse.process_identity:type_name -> core.registry.service_discovery.v1.ProcessIdentity - 20, // 8: core.registry.service_discovery.v1.InitializeResponse.configuration:type_name -> core.registry.service_discovery.v1.StartupConfiguration + 21, // 7: core.registry.service_discovery.v1.InitializeResponse.process_identity:type_name -> core.registry.service_discovery.v1.ProcessIdentity + 22, // 8: core.registry.service_discovery.v1.InitializeResponse.configuration:type_name -> core.registry.service_discovery.v1.StartupConfiguration 7, // 9: core.registry.service_discovery.v1.QueryRequest.filter:type_name -> core.registry.service_discovery.v1.Filter - 13, // 10: core.registry.service_discovery.v1.QueryResponse.data:type_name -> core.registry.service_discovery.v1.QueryResponse.DataEntry - 21, // 11: core.registry.service_discovery.v1.QueryResponse.DataEntry.value:type_name -> core.registry.service_discovery.v1.Process - 4, // 12: core.registry.service_discovery.v1.ServiceDiscoveryService.Initialize:input_type -> core.registry.service_discovery.v1.InitializeRequest - 1, // 13: core.registry.service_discovery.v1.ServiceDiscoveryService.Synchronize:input_type -> core.registry.service_discovery.v1.ClientDetails - 9, // 14: core.registry.service_discovery.v1.ServiceDiscoveryService.Finalize:input_type -> core.registry.service_discovery.v1.FinalizeRequest - 11, // 15: core.registry.service_discovery.v1.ServiceDiscoveryService.ReportHealth:input_type -> core.registry.service_discovery.v1.ReportHealthRequest - 6, // 16: core.registry.service_discovery.v1.ServiceDiscoveryService.Query:input_type -> core.registry.service_discovery.v1.QueryRequest - 5, // 17: core.registry.service_discovery.v1.ServiceDiscoveryService.Initialize:output_type -> core.registry.service_discovery.v1.InitializeResponse - 2, // 18: core.registry.service_discovery.v1.ServiceDiscoveryService.Synchronize:output_type -> core.registry.service_discovery.v1.ClusterDetails - 10, // 19: core.registry.service_discovery.v1.ServiceDiscoveryService.Finalize:output_type -> core.registry.service_discovery.v1.FinalizeResponse - 12, // 20: core.registry.service_discovery.v1.ServiceDiscoveryService.ReportHealth:output_type -> core.registry.service_discovery.v1.ReportHealthResponse - 8, // 21: core.registry.service_discovery.v1.ServiceDiscoveryService.Query:output_type -> core.registry.service_discovery.v1.QueryResponse - 17, // [17:22] is the sub-list for method output_type - 12, // [12:17] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 15, // 10: core.registry.service_discovery.v1.QueryResponse.data:type_name -> core.registry.service_discovery.v1.QueryResponse.DataEntry + 23, // 11: core.registry.service_discovery.v1.WatchResponse.process:type_name -> core.registry.service_discovery.v1.Process + 23, // 12: core.registry.service_discovery.v1.QueryResponse.DataEntry.value:type_name -> core.registry.service_discovery.v1.Process + 4, // 13: core.registry.service_discovery.v1.ServiceDiscoveryService.Initialize:input_type -> core.registry.service_discovery.v1.InitializeRequest + 1, // 14: core.registry.service_discovery.v1.ServiceDiscoveryService.Synchronize:input_type -> core.registry.service_discovery.v1.ClientDetails + 9, // 15: core.registry.service_discovery.v1.ServiceDiscoveryService.Finalize:input_type -> core.registry.service_discovery.v1.FinalizeRequest + 11, // 16: core.registry.service_discovery.v1.ServiceDiscoveryService.ReportHealth:input_type -> core.registry.service_discovery.v1.ReportHealthRequest + 6, // 17: core.registry.service_discovery.v1.ServiceDiscoveryService.Query:input_type -> core.registry.service_discovery.v1.QueryRequest + 13, // 18: core.registry.service_discovery.v1.ServiceDiscoveryService.Watch:input_type -> core.registry.service_discovery.v1.WatchRequest + 5, // 19: core.registry.service_discovery.v1.ServiceDiscoveryService.Initialize:output_type -> core.registry.service_discovery.v1.InitializeResponse + 2, // 20: core.registry.service_discovery.v1.ServiceDiscoveryService.Synchronize:output_type -> core.registry.service_discovery.v1.ClusterDetails + 10, // 21: core.registry.service_discovery.v1.ServiceDiscoveryService.Finalize:output_type -> core.registry.service_discovery.v1.FinalizeResponse + 12, // 22: core.registry.service_discovery.v1.ServiceDiscoveryService.ReportHealth:output_type -> core.registry.service_discovery.v1.ReportHealthResponse + 8, // 23: core.registry.service_discovery.v1.ServiceDiscoveryService.Query:output_type -> core.registry.service_discovery.v1.QueryResponse + 14, // 24: core.registry.service_discovery.v1.ServiceDiscoveryService.Watch:output_type -> core.registry.service_discovery.v1.WatchResponse + 19, // [19:25] is the sub-list for method output_type + 13, // [13:19] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_core_registry_service_discovery_v1_service_proto_init() } @@ -1000,152 +965,6 @@ func file_core_registry_service_discovery_v1_service_proto_init() { return } file_core_registry_service_discovery_v1_models_proto_init() - if !protoimpl.UnsafeEnabled { - file_core_registry_service_discovery_v1_service_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*ClientDetails); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*ClusterDetails); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[2].Exporter = func(v any, i int) any { - switch v := v.(*Node); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*InitializeRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[4].Exporter = func(v any, i int) any { - switch v := v.(*InitializeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[5].Exporter = func(v any, i int) any { - switch v := v.(*QueryRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[6].Exporter = func(v any, i int) any { - switch v := v.(*Filter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[7].Exporter = func(v any, i int) any { - switch v := v.(*QueryResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[8].Exporter = func(v any, i int) any { - switch v := v.(*FinalizeRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[9].Exporter = func(v any, i int) any { - switch v := v.(*FinalizeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[10].Exporter = func(v any, i int) any { - switch v := v.(*ReportHealthRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_registry_service_discovery_v1_service_proto_msgTypes[11].Exporter = func(v any, i int) any { - switch v := v.(*ReportHealthResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } file_core_registry_service_discovery_v1_service_proto_msgTypes[6].OneofWrappers = []any{ (*Filter_Id)(nil), (*Filter_Group)(nil), @@ -1155,9 +974,9 @@ func file_core_registry_service_discovery_v1_service_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_core_registry_service_discovery_v1_service_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_registry_service_discovery_v1_service_proto_rawDesc), len(file_core_registry_service_discovery_v1_service_proto_rawDesc)), NumEnums: 1, - NumMessages: 13, + NumMessages: 15, NumExtensions: 0, NumServices: 1, }, @@ -1167,7 +986,6 @@ func file_core_registry_service_discovery_v1_service_proto_init() { MessageInfos: file_core_registry_service_discovery_v1_service_proto_msgTypes, }.Build() File_core_registry_service_discovery_v1_service_proto = out.File - file_core_registry_service_discovery_v1_service_proto_rawDesc = nil file_core_registry_service_discovery_v1_service_proto_goTypes = nil file_core_registry_service_discovery_v1_service_proto_depIdxs = nil } diff --git a/api/core/registry/service_discovery/v1/service.pb.validate.go b/api/core/registry/service_discovery/v1/service.pb.validate.go index 3d4ae554..a07005c6 100644 --- a/api/core/registry/service_discovery/v1/service.pb.validate.go +++ b/api/core/registry/service_discovery/v1/service.pb.validate.go @@ -146,7 +146,7 @@ type ClientDetailsMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ClientDetailsMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -280,7 +280,7 @@ type ClusterDetailsMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ClusterDetailsMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -384,7 +384,7 @@ type NodeMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m NodeMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -488,7 +488,7 @@ type InitializeRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m InitializeRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -648,7 +648,7 @@ type InitializeResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m InitializeResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -778,7 +778,7 @@ type QueryRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m QueryRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -917,7 +917,7 @@ type FilterMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m FilterMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -1063,7 +1063,7 @@ type QueryResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m QueryResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -1165,7 +1165,7 @@ type FinalizeRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m FinalizeRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -1267,7 +1267,7 @@ type FinalizeResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m FinalizeResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -1367,7 +1367,7 @@ type ReportHealthRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ReportHealthRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -1469,7 +1469,7 @@ type ReportHealthResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ReportHealthResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -1534,3 +1534,233 @@ var _ interface { Cause() error ErrorName() string } = ReportHealthResponseValidationError{} + +// Validate checks the field values on WatchRequest with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *WatchRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on WatchRequest with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in WatchRequestMultiError, or +// nil if none found. +func (m *WatchRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *WatchRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return WatchRequestMultiError(errors) + } + + return nil +} + +// WatchRequestMultiError is an error wrapping multiple validation errors +// returned by WatchRequest.ValidateAll() if the designated constraints aren't met. +type WatchRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m WatchRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m WatchRequestMultiError) AllErrors() []error { return m } + +// WatchRequestValidationError is the validation error returned by +// WatchRequest.Validate if the designated constraints aren't met. +type WatchRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e WatchRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e WatchRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e WatchRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e WatchRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e WatchRequestValidationError) ErrorName() string { return "WatchRequestValidationError" } + +// Error satisfies the builtin error interface +func (e WatchRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sWatchRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = WatchRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = WatchRequestValidationError{} + +// Validate checks the field values on WatchResponse with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *WatchResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on WatchResponse with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in WatchResponseMultiError, or +// nil if none found. +func (m *WatchResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *WatchResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetProcess()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, WatchResponseValidationError{ + field: "Process", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, WatchResponseValidationError{ + field: "Process", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetProcess()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WatchResponseValidationError{ + field: "Process", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for Removed + + if len(errors) > 0 { + return WatchResponseMultiError(errors) + } + + return nil +} + +// WatchResponseMultiError is an error wrapping multiple validation errors +// returned by WatchResponse.ValidateAll() if the designated constraints +// aren't met. +type WatchResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m WatchResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m WatchResponseMultiError) AllErrors() []error { return m } + +// WatchResponseValidationError is the validation error returned by +// WatchResponse.Validate if the designated constraints aren't met. +type WatchResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e WatchResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e WatchResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e WatchResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e WatchResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e WatchResponseValidationError) ErrorName() string { return "WatchResponseValidationError" } + +// Error satisfies the builtin error interface +func (e WatchResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sWatchResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = WatchResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = WatchResponseValidationError{} diff --git a/api/core/registry/service_discovery/v1/service.proto b/api/core/registry/service_discovery/v1/service.proto index 88df8dde..4f4117b0 100644 --- a/api/core/registry/service_discovery/v1/service.proto +++ b/api/core/registry/service_discovery/v1/service.proto @@ -35,6 +35,8 @@ service ServiceDiscoveryService { // Query the registry rpc Query(QueryRequest) returns (QueryResponse) {} + // Watch the registry for process state changes + rpc Watch(WatchRequest) returns (stream WatchResponse) {} } // ProcessDetails - Messages that are sent from the `Process` to the registry. @@ -116,3 +118,10 @@ message FinalizeResponse { message ReportHealthRequest {} message ReportHealthResponse {} + +message WatchRequest {} + +message WatchResponse { + Process process = 1; + bool removed = 2; +} diff --git a/api/core/registry/service_discovery/v1/v1connect/service.connect.go b/api/core/registry/service_discovery/v1/v1connect/service.connect.go index 73aae24d..4057740f 100644 --- a/api/core/registry/service_discovery/v1/v1connect/service.connect.go +++ b/api/core/registry/service_discovery/v1/v1connect/service.connect.go @@ -48,16 +48,9 @@ const ( // ServiceDiscoveryServiceQueryProcedure is the fully-qualified name of the // ServiceDiscoveryService's Query RPC. ServiceDiscoveryServiceQueryProcedure = "/core.registry.service_discovery.v1.ServiceDiscoveryService/Query" -) - -// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. -var ( - serviceDiscoveryServiceServiceDescriptor = v1.File_core_registry_service_discovery_v1_service_proto.Services().ByName("ServiceDiscoveryService") - serviceDiscoveryServiceInitializeMethodDescriptor = serviceDiscoveryServiceServiceDescriptor.Methods().ByName("Initialize") - serviceDiscoveryServiceSynchronizeMethodDescriptor = serviceDiscoveryServiceServiceDescriptor.Methods().ByName("Synchronize") - serviceDiscoveryServiceFinalizeMethodDescriptor = serviceDiscoveryServiceServiceDescriptor.Methods().ByName("Finalize") - serviceDiscoveryServiceReportHealthMethodDescriptor = serviceDiscoveryServiceServiceDescriptor.Methods().ByName("ReportHealth") - serviceDiscoveryServiceQueryMethodDescriptor = serviceDiscoveryServiceServiceDescriptor.Methods().ByName("Query") + // ServiceDiscoveryServiceWatchProcedure is the fully-qualified name of the + // ServiceDiscoveryService's Watch RPC. + ServiceDiscoveryServiceWatchProcedure = "/core.registry.service_discovery.v1.ServiceDiscoveryService/Watch" ) // ServiceDiscoveryServiceClient is a client for the @@ -73,6 +66,8 @@ type ServiceDiscoveryServiceClient interface { ReportHealth(context.Context, *connect.Request[v1.ReportHealthRequest]) (*connect.Response[v1.ReportHealthResponse], error) // Query the registry Query(context.Context, *connect.Request[v1.QueryRequest]) (*connect.Response[v1.QueryResponse], error) + // Watch the registry for process state changes + Watch(context.Context, *connect.Request[v1.WatchRequest]) (*connect.ServerStreamForClient[v1.WatchResponse], error) } // NewServiceDiscoveryServiceClient constructs a client for the @@ -85,35 +80,42 @@ type ServiceDiscoveryServiceClient interface { // http://api.acme.com or https://acme.com/grpc). func NewServiceDiscoveryServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) ServiceDiscoveryServiceClient { baseURL = strings.TrimRight(baseURL, "/") + serviceDiscoveryServiceMethods := v1.File_core_registry_service_discovery_v1_service_proto.Services().ByName("ServiceDiscoveryService").Methods() return &serviceDiscoveryServiceClient{ initialize: connect.NewClient[v1.InitializeRequest, v1.InitializeResponse]( httpClient, baseURL+ServiceDiscoveryServiceInitializeProcedure, - connect.WithSchema(serviceDiscoveryServiceInitializeMethodDescriptor), + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("Initialize")), connect.WithClientOptions(opts...), ), synchronize: connect.NewClient[v1.ClientDetails, v1.ClusterDetails]( httpClient, baseURL+ServiceDiscoveryServiceSynchronizeProcedure, - connect.WithSchema(serviceDiscoveryServiceSynchronizeMethodDescriptor), + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("Synchronize")), connect.WithClientOptions(opts...), ), finalize: connect.NewClient[v1.FinalizeRequest, v1.FinalizeResponse]( httpClient, baseURL+ServiceDiscoveryServiceFinalizeProcedure, - connect.WithSchema(serviceDiscoveryServiceFinalizeMethodDescriptor), + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("Finalize")), connect.WithClientOptions(opts...), ), reportHealth: connect.NewClient[v1.ReportHealthRequest, v1.ReportHealthResponse]( httpClient, baseURL+ServiceDiscoveryServiceReportHealthProcedure, - connect.WithSchema(serviceDiscoveryServiceReportHealthMethodDescriptor), + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("ReportHealth")), connect.WithClientOptions(opts...), ), query: connect.NewClient[v1.QueryRequest, v1.QueryResponse]( httpClient, baseURL+ServiceDiscoveryServiceQueryProcedure, - connect.WithSchema(serviceDiscoveryServiceQueryMethodDescriptor), + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("Query")), + connect.WithClientOptions(opts...), + ), + watch: connect.NewClient[v1.WatchRequest, v1.WatchResponse]( + httpClient, + baseURL+ServiceDiscoveryServiceWatchProcedure, + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("Watch")), connect.WithClientOptions(opts...), ), } @@ -126,6 +128,7 @@ type serviceDiscoveryServiceClient struct { finalize *connect.Client[v1.FinalizeRequest, v1.FinalizeResponse] reportHealth *connect.Client[v1.ReportHealthRequest, v1.ReportHealthResponse] query *connect.Client[v1.QueryRequest, v1.QueryResponse] + watch *connect.Client[v1.WatchRequest, v1.WatchResponse] } // Initialize calls core.registry.service_discovery.v1.ServiceDiscoveryService.Initialize. @@ -153,6 +156,11 @@ func (c *serviceDiscoveryServiceClient) Query(ctx context.Context, req *connect. return c.query.CallUnary(ctx, req) } +// Watch calls core.registry.service_discovery.v1.ServiceDiscoveryService.Watch. +func (c *serviceDiscoveryServiceClient) Watch(ctx context.Context, req *connect.Request[v1.WatchRequest]) (*connect.ServerStreamForClient[v1.WatchResponse], error) { + return c.watch.CallServerStream(ctx, req) +} + // ServiceDiscoveryServiceHandler is an implementation of the // core.registry.service_discovery.v1.ServiceDiscoveryService service. type ServiceDiscoveryServiceHandler interface { @@ -166,6 +174,8 @@ type ServiceDiscoveryServiceHandler interface { ReportHealth(context.Context, *connect.Request[v1.ReportHealthRequest]) (*connect.Response[v1.ReportHealthResponse], error) // Query the registry Query(context.Context, *connect.Request[v1.QueryRequest]) (*connect.Response[v1.QueryResponse], error) + // Watch the registry for process state changes + Watch(context.Context, *connect.Request[v1.WatchRequest], *connect.ServerStream[v1.WatchResponse]) error } // NewServiceDiscoveryServiceHandler builds an HTTP handler from the service implementation. It @@ -174,34 +184,41 @@ type ServiceDiscoveryServiceHandler interface { // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. func NewServiceDiscoveryServiceHandler(svc ServiceDiscoveryServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + serviceDiscoveryServiceMethods := v1.File_core_registry_service_discovery_v1_service_proto.Services().ByName("ServiceDiscoveryService").Methods() serviceDiscoveryServiceInitializeHandler := connect.NewUnaryHandler( ServiceDiscoveryServiceInitializeProcedure, svc.Initialize, - connect.WithSchema(serviceDiscoveryServiceInitializeMethodDescriptor), + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("Initialize")), connect.WithHandlerOptions(opts...), ) serviceDiscoveryServiceSynchronizeHandler := connect.NewBidiStreamHandler( ServiceDiscoveryServiceSynchronizeProcedure, svc.Synchronize, - connect.WithSchema(serviceDiscoveryServiceSynchronizeMethodDescriptor), + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("Synchronize")), connect.WithHandlerOptions(opts...), ) serviceDiscoveryServiceFinalizeHandler := connect.NewUnaryHandler( ServiceDiscoveryServiceFinalizeProcedure, svc.Finalize, - connect.WithSchema(serviceDiscoveryServiceFinalizeMethodDescriptor), + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("Finalize")), connect.WithHandlerOptions(opts...), ) serviceDiscoveryServiceReportHealthHandler := connect.NewUnaryHandler( ServiceDiscoveryServiceReportHealthProcedure, svc.ReportHealth, - connect.WithSchema(serviceDiscoveryServiceReportHealthMethodDescriptor), + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("ReportHealth")), connect.WithHandlerOptions(opts...), ) serviceDiscoveryServiceQueryHandler := connect.NewUnaryHandler( ServiceDiscoveryServiceQueryProcedure, svc.Query, - connect.WithSchema(serviceDiscoveryServiceQueryMethodDescriptor), + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("Query")), + connect.WithHandlerOptions(opts...), + ) + serviceDiscoveryServiceWatchHandler := connect.NewServerStreamHandler( + ServiceDiscoveryServiceWatchProcedure, + svc.Watch, + connect.WithSchema(serviceDiscoveryServiceMethods.ByName("Watch")), connect.WithHandlerOptions(opts...), ) return "/core.registry.service_discovery.v1.ServiceDiscoveryService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -216,6 +233,8 @@ func NewServiceDiscoveryServiceHandler(svc ServiceDiscoveryServiceHandler, opts serviceDiscoveryServiceReportHealthHandler.ServeHTTP(w, r) case ServiceDiscoveryServiceQueryProcedure: serviceDiscoveryServiceQueryHandler.ServeHTTP(w, r) + case ServiceDiscoveryServiceWatchProcedure: + serviceDiscoveryServiceWatchHandler.ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -244,3 +263,7 @@ func (UnimplementedServiceDiscoveryServiceHandler) ReportHealth(context.Context, func (UnimplementedServiceDiscoveryServiceHandler) Query(context.Context, *connect.Request[v1.QueryRequest]) (*connect.Response[v1.QueryResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("core.registry.service_discovery.v1.ServiceDiscoveryService.Query is not implemented")) } + +func (UnimplementedServiceDiscoveryServiceHandler) Watch(context.Context, *connect.Request[v1.WatchRequest], *connect.ServerStream[v1.WatchResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("core.registry.service_discovery.v1.ServiceDiscoveryService.Watch is not implemented")) +} diff --git a/api/examples/auth/v1/service.pb.go b/api/examples/auth/v1/service.pb.go new file mode 100644 index 00000000..e32ceb07 --- /dev/null +++ b/api/examples/auth/v1/service.pb.go @@ -0,0 +1,272 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: examples/auth/v1/service.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GreetRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GreetRequest) Reset() { + *x = GreetRequest{} + mi := &file_examples_auth_v1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GreetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GreetRequest) ProtoMessage() {} + +func (x *GreetRequest) ProtoReflect() protoreflect.Message { + mi := &file_examples_auth_v1_service_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GreetRequest.ProtoReflect.Descriptor instead. +func (*GreetRequest) Descriptor() ([]byte, []int) { + return file_examples_auth_v1_service_proto_rawDescGZIP(), []int{0} +} + +func (x *GreetRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type GreetResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GreetResponse) Reset() { + *x = GreetResponse{} + mi := &file_examples_auth_v1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GreetResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GreetResponse) ProtoMessage() {} + +func (x *GreetResponse) ProtoReflect() protoreflect.Message { + mi := &file_examples_auth_v1_service_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GreetResponse.ProtoReflect.Descriptor instead. +func (*GreetResponse) Descriptor() ([]byte, []int) { + return file_examples_auth_v1_service_proto_rawDescGZIP(), []int{1} +} + +func (x *GreetResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type SecretRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SecretRequest) Reset() { + *x = SecretRequest{} + mi := &file_examples_auth_v1_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SecretRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SecretRequest) ProtoMessage() {} + +func (x *SecretRequest) ProtoReflect() protoreflect.Message { + mi := &file_examples_auth_v1_service_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SecretRequest.ProtoReflect.Descriptor instead. +func (*SecretRequest) Descriptor() ([]byte, []int) { + return file_examples_auth_v1_service_proto_rawDescGZIP(), []int{2} +} + +type SecretResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The caller's identity as read from the X-Authentik-Username header set by + // the auth service on a successful check. In bypass mode this will be empty. + Caller string `protobuf:"bytes,1,opt,name=caller,proto3" json:"caller,omitempty"` + Secret string `protobuf:"bytes,2,opt,name=secret,proto3" json:"secret,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SecretResponse) Reset() { + *x = SecretResponse{} + mi := &file_examples_auth_v1_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SecretResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SecretResponse) ProtoMessage() {} + +func (x *SecretResponse) ProtoReflect() protoreflect.Message { + mi := &file_examples_auth_v1_service_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SecretResponse.ProtoReflect.Descriptor instead. +func (*SecretResponse) Descriptor() ([]byte, []int) { + return file_examples_auth_v1_service_proto_rawDescGZIP(), []int{3} +} + +func (x *SecretResponse) GetCaller() string { + if x != nil { + return x.Caller + } + return "" +} + +func (x *SecretResponse) GetSecret() string { + if x != nil { + return x.Secret + } + return "" +} + +var File_examples_auth_v1_service_proto protoreflect.FileDescriptor + +const file_examples_auth_v1_service_proto_rawDesc = "" + + "\n" + + "\x1eexamples/auth/v1/service.proto\x12\x10examples.auth.v1\"\"\n" + + "\fGreetRequest\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\")\n" + + "\rGreetResponse\x12\x18\n" + + "\amessage\x18\x01 \x01(\tR\amessage\"\x0f\n" + + "\rSecretRequest\"@\n" + + "\x0eSecretResponse\x12\x16\n" + + "\x06caller\x18\x01 \x01(\tR\x06caller\x12\x16\n" + + "\x06secret\x18\x02 \x01(\tR\x06secret2\xaf\x01\n" + + "\x12AuthExampleService\x12J\n" + + "\x05Greet\x12\x1e.examples.auth.v1.GreetRequest\x1a\x1f.examples.auth.v1.GreetResponse\"\x00\x12M\n" + + "\x06Secret\x12\x1f.examples.auth.v1.SecretRequest\x1a .examples.auth.v1.SecretResponse\"\x00B4Z2github.com/steady-bytes/draft/api/examples/auth/v1b\x06proto3" + +var ( + file_examples_auth_v1_service_proto_rawDescOnce sync.Once + file_examples_auth_v1_service_proto_rawDescData []byte +) + +func file_examples_auth_v1_service_proto_rawDescGZIP() []byte { + file_examples_auth_v1_service_proto_rawDescOnce.Do(func() { + file_examples_auth_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_examples_auth_v1_service_proto_rawDesc), len(file_examples_auth_v1_service_proto_rawDesc))) + }) + return file_examples_auth_v1_service_proto_rawDescData +} + +var file_examples_auth_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_examples_auth_v1_service_proto_goTypes = []any{ + (*GreetRequest)(nil), // 0: examples.auth.v1.GreetRequest + (*GreetResponse)(nil), // 1: examples.auth.v1.GreetResponse + (*SecretRequest)(nil), // 2: examples.auth.v1.SecretRequest + (*SecretResponse)(nil), // 3: examples.auth.v1.SecretResponse +} +var file_examples_auth_v1_service_proto_depIdxs = []int32{ + 0, // 0: examples.auth.v1.AuthExampleService.Greet:input_type -> examples.auth.v1.GreetRequest + 2, // 1: examples.auth.v1.AuthExampleService.Secret:input_type -> examples.auth.v1.SecretRequest + 1, // 2: examples.auth.v1.AuthExampleService.Greet:output_type -> examples.auth.v1.GreetResponse + 3, // 3: examples.auth.v1.AuthExampleService.Secret:output_type -> examples.auth.v1.SecretResponse + 2, // [2:4] is the sub-list for method output_type + 0, // [0:2] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_examples_auth_v1_service_proto_init() } +func file_examples_auth_v1_service_proto_init() { + if File_examples_auth_v1_service_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_examples_auth_v1_service_proto_rawDesc), len(file_examples_auth_v1_service_proto_rawDesc)), + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_examples_auth_v1_service_proto_goTypes, + DependencyIndexes: file_examples_auth_v1_service_proto_depIdxs, + MessageInfos: file_examples_auth_v1_service_proto_msgTypes, + }.Build() + File_examples_auth_v1_service_proto = out.File + file_examples_auth_v1_service_proto_goTypes = nil + file_examples_auth_v1_service_proto_depIdxs = nil +} diff --git a/api/examples/auth/v1/service.pb.validate.go b/api/examples/auth/v1/service.pb.validate.go new file mode 100644 index 00000000..a1c66642 --- /dev/null +++ b/api/examples/auth/v1/service.pb.validate.go @@ -0,0 +1,443 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: examples/auth/v1/service.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on GreetRequest with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *GreetRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GreetRequest with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in GreetRequestMultiError, or +// nil if none found. +func (m *GreetRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GreetRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Name + + if len(errors) > 0 { + return GreetRequestMultiError(errors) + } + + return nil +} + +// GreetRequestMultiError is an error wrapping multiple validation errors +// returned by GreetRequest.ValidateAll() if the designated constraints aren't met. +type GreetRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GreetRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GreetRequestMultiError) AllErrors() []error { return m } + +// GreetRequestValidationError is the validation error returned by +// GreetRequest.Validate if the designated constraints aren't met. +type GreetRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GreetRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GreetRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GreetRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GreetRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GreetRequestValidationError) ErrorName() string { return "GreetRequestValidationError" } + +// Error satisfies the builtin error interface +func (e GreetRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGreetRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GreetRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GreetRequestValidationError{} + +// Validate checks the field values on GreetResponse with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *GreetResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GreetResponse with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in GreetResponseMultiError, or +// nil if none found. +func (m *GreetResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GreetResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Message + + if len(errors) > 0 { + return GreetResponseMultiError(errors) + } + + return nil +} + +// GreetResponseMultiError is an error wrapping multiple validation errors +// returned by GreetResponse.ValidateAll() if the designated constraints +// aren't met. +type GreetResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GreetResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GreetResponseMultiError) AllErrors() []error { return m } + +// GreetResponseValidationError is the validation error returned by +// GreetResponse.Validate if the designated constraints aren't met. +type GreetResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GreetResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GreetResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GreetResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GreetResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GreetResponseValidationError) ErrorName() string { return "GreetResponseValidationError" } + +// Error satisfies the builtin error interface +func (e GreetResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGreetResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GreetResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GreetResponseValidationError{} + +// Validate checks the field values on SecretRequest with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *SecretRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on SecretRequest with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in SecretRequestMultiError, or +// nil if none found. +func (m *SecretRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *SecretRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return SecretRequestMultiError(errors) + } + + return nil +} + +// SecretRequestMultiError is an error wrapping multiple validation errors +// returned by SecretRequest.ValidateAll() if the designated constraints +// aren't met. +type SecretRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m SecretRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m SecretRequestMultiError) AllErrors() []error { return m } + +// SecretRequestValidationError is the validation error returned by +// SecretRequest.Validate if the designated constraints aren't met. +type SecretRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e SecretRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e SecretRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e SecretRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e SecretRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e SecretRequestValidationError) ErrorName() string { return "SecretRequestValidationError" } + +// Error satisfies the builtin error interface +func (e SecretRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSecretRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = SecretRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = SecretRequestValidationError{} + +// Validate checks the field values on SecretResponse with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *SecretResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on SecretResponse with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in SecretResponseMultiError, +// or nil if none found. +func (m *SecretResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *SecretResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Caller + + // no validation rules for Secret + + if len(errors) > 0 { + return SecretResponseMultiError(errors) + } + + return nil +} + +// SecretResponseMultiError is an error wrapping multiple validation errors +// returned by SecretResponse.ValidateAll() if the designated constraints +// aren't met. +type SecretResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m SecretResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m SecretResponseMultiError) AllErrors() []error { return m } + +// SecretResponseValidationError is the validation error returned by +// SecretResponse.Validate if the designated constraints aren't met. +type SecretResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e SecretResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e SecretResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e SecretResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e SecretResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e SecretResponseValidationError) ErrorName() string { return "SecretResponseValidationError" } + +// Error satisfies the builtin error interface +func (e SecretResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSecretResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = SecretResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = SecretResponseValidationError{} diff --git a/api/examples/auth/v1/service.proto b/api/examples/auth/v1/service.proto new file mode 100644 index 00000000..804ce1a0 --- /dev/null +++ b/api/examples/auth/v1/service.proto @@ -0,0 +1,31 @@ +syntax = "proto3"; + +package examples.auth.v1; + +option go_package = "github.com/steady-bytes/draft/api/examples/auth/v1"; + +// AuthExampleService demonstrates per-method auth policies. +// Greet is public; Secret requires a valid token. +service AuthExampleService { + // Greet is publicly accessible — no auth check. + rpc Greet(GreetRequest) returns (GreetResponse) {} + // Secret requires a valid bearer token (AUTH_POLICY_AUTHENTICATED). + rpc Secret(SecretRequest) returns (SecretResponse) {} +} + +message GreetRequest { + string name = 1; +} + +message GreetResponse { + string message = 1; +} + +message SecretRequest {} + +message SecretResponse { + // The caller's identity as read from the X-Authentik-Username header set by + // the auth service on a successful check. In bypass mode this will be empty. + string caller = 1; + string secret = 2; +} diff --git a/api/examples/auth/v1/v1connect/service.connect.go b/api/examples/auth/v1/v1connect/service.connect.go new file mode 100644 index 00000000..c7add3cd --- /dev/null +++ b/api/examples/auth/v1/v1connect/service.connect.go @@ -0,0 +1,143 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: examples/auth/v1/service.proto + +package v1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "github.com/steady-bytes/draft/api/examples/auth/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // AuthExampleServiceName is the fully-qualified name of the AuthExampleService service. + AuthExampleServiceName = "examples.auth.v1.AuthExampleService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // AuthExampleServiceGreetProcedure is the fully-qualified name of the AuthExampleService's Greet + // RPC. + AuthExampleServiceGreetProcedure = "/examples.auth.v1.AuthExampleService/Greet" + // AuthExampleServiceSecretProcedure is the fully-qualified name of the AuthExampleService's Secret + // RPC. + AuthExampleServiceSecretProcedure = "/examples.auth.v1.AuthExampleService/Secret" +) + +// AuthExampleServiceClient is a client for the examples.auth.v1.AuthExampleService service. +type AuthExampleServiceClient interface { + // Greet is publicly accessible — no auth check. + Greet(context.Context, *connect.Request[v1.GreetRequest]) (*connect.Response[v1.GreetResponse], error) + // Secret requires a valid bearer token (AUTH_POLICY_AUTHENTICATED). + Secret(context.Context, *connect.Request[v1.SecretRequest]) (*connect.Response[v1.SecretResponse], error) +} + +// NewAuthExampleServiceClient constructs a client for the examples.auth.v1.AuthExampleService +// service. By default, it uses the Connect protocol with the binary Protobuf Codec, asks for +// gzipped responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply +// the connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewAuthExampleServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) AuthExampleServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + authExampleServiceMethods := v1.File_examples_auth_v1_service_proto.Services().ByName("AuthExampleService").Methods() + return &authExampleServiceClient{ + greet: connect.NewClient[v1.GreetRequest, v1.GreetResponse]( + httpClient, + baseURL+AuthExampleServiceGreetProcedure, + connect.WithSchema(authExampleServiceMethods.ByName("Greet")), + connect.WithClientOptions(opts...), + ), + secret: connect.NewClient[v1.SecretRequest, v1.SecretResponse]( + httpClient, + baseURL+AuthExampleServiceSecretProcedure, + connect.WithSchema(authExampleServiceMethods.ByName("Secret")), + connect.WithClientOptions(opts...), + ), + } +} + +// authExampleServiceClient implements AuthExampleServiceClient. +type authExampleServiceClient struct { + greet *connect.Client[v1.GreetRequest, v1.GreetResponse] + secret *connect.Client[v1.SecretRequest, v1.SecretResponse] +} + +// Greet calls examples.auth.v1.AuthExampleService.Greet. +func (c *authExampleServiceClient) Greet(ctx context.Context, req *connect.Request[v1.GreetRequest]) (*connect.Response[v1.GreetResponse], error) { + return c.greet.CallUnary(ctx, req) +} + +// Secret calls examples.auth.v1.AuthExampleService.Secret. +func (c *authExampleServiceClient) Secret(ctx context.Context, req *connect.Request[v1.SecretRequest]) (*connect.Response[v1.SecretResponse], error) { + return c.secret.CallUnary(ctx, req) +} + +// AuthExampleServiceHandler is an implementation of the examples.auth.v1.AuthExampleService +// service. +type AuthExampleServiceHandler interface { + // Greet is publicly accessible — no auth check. + Greet(context.Context, *connect.Request[v1.GreetRequest]) (*connect.Response[v1.GreetResponse], error) + // Secret requires a valid bearer token (AUTH_POLICY_AUTHENTICATED). + Secret(context.Context, *connect.Request[v1.SecretRequest]) (*connect.Response[v1.SecretResponse], error) +} + +// NewAuthExampleServiceHandler builds an HTTP handler from the service implementation. It returns +// the path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewAuthExampleServiceHandler(svc AuthExampleServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + authExampleServiceMethods := v1.File_examples_auth_v1_service_proto.Services().ByName("AuthExampleService").Methods() + authExampleServiceGreetHandler := connect.NewUnaryHandler( + AuthExampleServiceGreetProcedure, + svc.Greet, + connect.WithSchema(authExampleServiceMethods.ByName("Greet")), + connect.WithHandlerOptions(opts...), + ) + authExampleServiceSecretHandler := connect.NewUnaryHandler( + AuthExampleServiceSecretProcedure, + svc.Secret, + connect.WithSchema(authExampleServiceMethods.ByName("Secret")), + connect.WithHandlerOptions(opts...), + ) + return "/examples.auth.v1.AuthExampleService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case AuthExampleServiceGreetProcedure: + authExampleServiceGreetHandler.ServeHTTP(w, r) + case AuthExampleServiceSecretProcedure: + authExampleServiceSecretHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedAuthExampleServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedAuthExampleServiceHandler struct{} + +func (UnimplementedAuthExampleServiceHandler) Greet(context.Context, *connect.Request[v1.GreetRequest]) (*connect.Response[v1.GreetResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("examples.auth.v1.AuthExampleService.Greet is not implemented")) +} + +func (UnimplementedAuthExampleServiceHandler) Secret(context.Context, *connect.Request[v1.SecretRequest]) (*connect.Response[v1.SecretResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("examples.auth.v1.AuthExampleService.Secret is not implemented")) +} diff --git a/api/examples/crud/v1/events.pb.go b/api/examples/crud/v1/events.pb.go new file mode 100644 index 00000000..c04a330b --- /dev/null +++ b/api/examples/crud/v1/events.pb.go @@ -0,0 +1,202 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: examples/crud/v1/events.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Operation int32 + +const ( + Operation_OPERATION_UNSPECIFIED Operation = 0 + Operation_OPERATION_CREATE Operation = 1 + Operation_OPERATION_UPDATE Operation = 2 + Operation_OPERATION_DELETE Operation = 3 +) + +// Enum value maps for Operation. +var ( + Operation_name = map[int32]string{ + 0: "OPERATION_UNSPECIFIED", + 1: "OPERATION_CREATE", + 2: "OPERATION_UPDATE", + 3: "OPERATION_DELETE", + } + Operation_value = map[string]int32{ + "OPERATION_UNSPECIFIED": 0, + "OPERATION_CREATE": 1, + "OPERATION_UPDATE": 2, + "OPERATION_DELETE": 3, + } +) + +func (x Operation) Enum() *Operation { + p := new(Operation) + *p = x + return p +} + +func (x Operation) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Operation) Descriptor() protoreflect.EnumDescriptor { + return file_examples_crud_v1_events_proto_enumTypes[0].Descriptor() +} + +func (Operation) Type() protoreflect.EnumType { + return &file_examples_crud_v1_events_proto_enumTypes[0] +} + +func (x Operation) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Operation.Descriptor instead. +func (Operation) EnumDescriptor() ([]byte, []int) { + return file_examples_crud_v1_events_proto_rawDescGZIP(), []int{0} +} + +type DatabaseModelSaved struct { + state protoimpl.MessageState `protogen:"open.v1"` + ModelId string `protobuf:"bytes,1,opt,name=model_id,json=modelId,proto3" json:"model_id,omitempty"` + ModelName string `protobuf:"bytes,2,opt,name=model_name,json=modelName,proto3" json:"model_name,omitempty"` + Operation Operation `protobuf:"varint,3,opt,name=operation,proto3,enum=examples.crud.v1.Operation" json:"operation,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DatabaseModelSaved) Reset() { + *x = DatabaseModelSaved{} + mi := &file_examples_crud_v1_events_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DatabaseModelSaved) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DatabaseModelSaved) ProtoMessage() {} + +func (x *DatabaseModelSaved) ProtoReflect() protoreflect.Message { + mi := &file_examples_crud_v1_events_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DatabaseModelSaved.ProtoReflect.Descriptor instead. +func (*DatabaseModelSaved) Descriptor() ([]byte, []int) { + return file_examples_crud_v1_events_proto_rawDescGZIP(), []int{0} +} + +func (x *DatabaseModelSaved) GetModelId() string { + if x != nil { + return x.ModelId + } + return "" +} + +func (x *DatabaseModelSaved) GetModelName() string { + if x != nil { + return x.ModelName + } + return "" +} + +func (x *DatabaseModelSaved) GetOperation() Operation { + if x != nil { + return x.Operation + } + return Operation_OPERATION_UNSPECIFIED +} + +var File_examples_crud_v1_events_proto protoreflect.FileDescriptor + +const file_examples_crud_v1_events_proto_rawDesc = "" + + "\n" + + "\x1dexamples/crud/v1/events.proto\x12\x10examples.crud.v1\"\x89\x01\n" + + "\x12DatabaseModelSaved\x12\x19\n" + + "\bmodel_id\x18\x01 \x01(\tR\amodelId\x12\x1d\n" + + "\n" + + "model_name\x18\x02 \x01(\tR\tmodelName\x129\n" + + "\toperation\x18\x03 \x01(\x0e2\x1b.examples.crud.v1.OperationR\toperation*h\n" + + "\tOperation\x12\x19\n" + + "\x15OPERATION_UNSPECIFIED\x10\x00\x12\x14\n" + + "\x10OPERATION_CREATE\x10\x01\x12\x14\n" + + "\x10OPERATION_UPDATE\x10\x02\x12\x14\n" + + "\x10OPERATION_DELETE\x10\x03B4Z2github.com/steady-bytes/draft/api/examples/crud/v1b\x06proto3" + +var ( + file_examples_crud_v1_events_proto_rawDescOnce sync.Once + file_examples_crud_v1_events_proto_rawDescData []byte +) + +func file_examples_crud_v1_events_proto_rawDescGZIP() []byte { + file_examples_crud_v1_events_proto_rawDescOnce.Do(func() { + file_examples_crud_v1_events_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_examples_crud_v1_events_proto_rawDesc), len(file_examples_crud_v1_events_proto_rawDesc))) + }) + return file_examples_crud_v1_events_proto_rawDescData +} + +var file_examples_crud_v1_events_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_examples_crud_v1_events_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_examples_crud_v1_events_proto_goTypes = []any{ + (Operation)(0), // 0: examples.crud.v1.Operation + (*DatabaseModelSaved)(nil), // 1: examples.crud.v1.DatabaseModelSaved +} +var file_examples_crud_v1_events_proto_depIdxs = []int32{ + 0, // 0: examples.crud.v1.DatabaseModelSaved.operation:type_name -> examples.crud.v1.Operation + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_examples_crud_v1_events_proto_init() } +func file_examples_crud_v1_events_proto_init() { + if File_examples_crud_v1_events_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_examples_crud_v1_events_proto_rawDesc), len(file_examples_crud_v1_events_proto_rawDesc)), + NumEnums: 1, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_examples_crud_v1_events_proto_goTypes, + DependencyIndexes: file_examples_crud_v1_events_proto_depIdxs, + EnumInfos: file_examples_crud_v1_events_proto_enumTypes, + MessageInfos: file_examples_crud_v1_events_proto_msgTypes, + }.Build() + File_examples_crud_v1_events_proto = out.File + file_examples_crud_v1_events_proto_goTypes = nil + file_examples_crud_v1_events_proto_depIdxs = nil +} diff --git a/api/examples/crud/v1/events.pb.validate.go b/api/examples/crud/v1/events.pb.validate.go new file mode 100644 index 00000000..b8ac6fa7 --- /dev/null +++ b/api/examples/crud/v1/events.pb.validate.go @@ -0,0 +1,144 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: examples/crud/v1/events.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on DatabaseModelSaved with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *DatabaseModelSaved) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on DatabaseModelSaved with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// DatabaseModelSavedMultiError, or nil if none found. +func (m *DatabaseModelSaved) ValidateAll() error { + return m.validate(true) +} + +func (m *DatabaseModelSaved) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for ModelId + + // no validation rules for ModelName + + // no validation rules for Operation + + if len(errors) > 0 { + return DatabaseModelSavedMultiError(errors) + } + + return nil +} + +// DatabaseModelSavedMultiError is an error wrapping multiple validation errors +// returned by DatabaseModelSaved.ValidateAll() if the designated constraints +// aren't met. +type DatabaseModelSavedMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m DatabaseModelSavedMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m DatabaseModelSavedMultiError) AllErrors() []error { return m } + +// DatabaseModelSavedValidationError is the validation error returned by +// DatabaseModelSaved.Validate if the designated constraints aren't met. +type DatabaseModelSavedValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e DatabaseModelSavedValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e DatabaseModelSavedValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e DatabaseModelSavedValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e DatabaseModelSavedValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e DatabaseModelSavedValidationError) ErrorName() string { + return "DatabaseModelSavedValidationError" +} + +// Error satisfies the builtin error interface +func (e DatabaseModelSavedValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDatabaseModelSaved.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = DatabaseModelSavedValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = DatabaseModelSavedValidationError{} diff --git a/api/examples/crud/v1/events.proto b/api/examples/crud/v1/events.proto new file mode 100644 index 00000000..e4234864 --- /dev/null +++ b/api/examples/crud/v1/events.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package examples.crud.v1; + +option go_package = "github.com/steady-bytes/draft/api/examples/crud/v1"; + +enum Operation { + OPERATION_UNSPECIFIED = 0; + OPERATION_CREATE = 1; + OPERATION_UPDATE = 2; + OPERATION_DELETE = 3; +} + +message DatabaseModelSaved { + string model_id = 1; + string model_name = 2; + Operation operation = 3; +} diff --git a/api/examples/crud/v1/models.pb.go b/api/examples/crud/v1/models.pb.go index 0b718e04..1aa474e7 100644 --- a/api/examples/crud/v1/models.pb.go +++ b/api/examples/crud/v1/models.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: examples/crud/v1/models.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -21,22 +22,19 @@ const ( ) type Name struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + FirstName string `protobuf:"bytes,2,opt,name=first_name,json=firstName,proto3" json:"first_name,omitempty"` + LastName string `protobuf:"bytes,3,opt,name=last_name,json=lastName,proto3" json:"last_name,omitempty"` unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id" bun:"id" csv:"id" pg:"id" yaml:"id"` - FirstName string `protobuf:"bytes,2,opt,name=first_name,json=firstName,proto3" json:"first_name" bun:"first_name" csv:"first_name" pg:"first_name" yaml:"first_name"` - LastName string `protobuf:"bytes,3,opt,name=last_name,json=lastName,proto3" json:"last_name" bun:"last_name" csv:"last_name" pg:"last_name" yaml:"last_name"` + sizeCache protoimpl.SizeCache } func (x *Name) Reset() { *x = Name{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_crud_v1_models_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_crud_v1_models_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Name) String() string { @@ -47,7 +45,7 @@ func (*Name) ProtoMessage() {} func (x *Name) ProtoReflect() protoreflect.Message { mi := &file_examples_crud_v1_models_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -85,30 +83,23 @@ func (x *Name) GetLastName() string { var File_examples_crud_v1_models_proto protoreflect.FileDescriptor -var file_examples_crud_v1_models_proto_rawDesc = []byte{ - 0x0a, 0x1d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x72, 0x75, 0x64, 0x2f, - 0x76, 0x31, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x10, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, 0x2e, 0x76, - 0x31, 0x22, 0x52, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x72, - 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, - 0x69, 0x72, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x73, - 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, - 0x2f, 0x64, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, - 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x72, 0x75, 0x64, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, -} +const file_examples_crud_v1_models_proto_rawDesc = "" + + "\n" + + "\x1dexamples/crud/v1/models.proto\x12\x10examples.crud.v1\"R\n" + + "\x04Name\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x1d\n" + + "\n" + + "first_name\x18\x02 \x01(\tR\tfirstName\x12\x1b\n" + + "\tlast_name\x18\x03 \x01(\tR\blastNameB4Z2github.com/steady-bytes/draft/api/examples/crud/v1b\x06proto3" var ( file_examples_crud_v1_models_proto_rawDescOnce sync.Once - file_examples_crud_v1_models_proto_rawDescData = file_examples_crud_v1_models_proto_rawDesc + file_examples_crud_v1_models_proto_rawDescData []byte ) func file_examples_crud_v1_models_proto_rawDescGZIP() []byte { file_examples_crud_v1_models_proto_rawDescOnce.Do(func() { - file_examples_crud_v1_models_proto_rawDescData = protoimpl.X.CompressGZIP(file_examples_crud_v1_models_proto_rawDescData) + file_examples_crud_v1_models_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_examples_crud_v1_models_proto_rawDesc), len(file_examples_crud_v1_models_proto_rawDesc))) }) return file_examples_crud_v1_models_proto_rawDescData } @@ -130,25 +121,11 @@ func file_examples_crud_v1_models_proto_init() { if File_examples_crud_v1_models_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_examples_crud_v1_models_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*Name); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_examples_crud_v1_models_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_examples_crud_v1_models_proto_rawDesc), len(file_examples_crud_v1_models_proto_rawDesc)), NumEnums: 0, NumMessages: 1, NumExtensions: 0, @@ -159,7 +136,6 @@ func file_examples_crud_v1_models_proto_init() { MessageInfos: file_examples_crud_v1_models_proto_msgTypes, }.Build() File_examples_crud_v1_models_proto = out.File - file_examples_crud_v1_models_proto_rawDesc = nil file_examples_crud_v1_models_proto_goTypes = nil file_examples_crud_v1_models_proto_depIdxs = nil } diff --git a/api/examples/crud/v1/models.pb.validate.go b/api/examples/crud/v1/models.pb.validate.go index 3c5a4198..47d9b468 100644 --- a/api/examples/crud/v1/models.pb.validate.go +++ b/api/examples/crud/v1/models.pb.validate.go @@ -75,7 +75,7 @@ type NameMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m NameMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/examples/crud/v1/service.pb.go b/api/examples/crud/v1/service.pb.go index da49e76c..7d417d1e 100644 --- a/api/examples/crud/v1/service.pb.go +++ b/api/examples/crud/v1/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: examples/crud/v1/service.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -21,20 +22,17 @@ const ( ) type CreateRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Name *Name `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` unknownFields protoimpl.UnknownFields - - Name *Name `protobuf:"bytes,1,opt,name=name,proto3" json:"name" bun:"name" csv:"name" pg:"name" yaml:"name"` + sizeCache protoimpl.SizeCache } func (x *CreateRequest) Reset() { *x = CreateRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_crud_v1_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_crud_v1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CreateRequest) String() string { @@ -45,7 +43,7 @@ func (*CreateRequest) ProtoMessage() {} func (x *CreateRequest) ProtoReflect() protoreflect.Message { mi := &file_examples_crud_v1_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -68,20 +66,17 @@ func (x *CreateRequest) GetName() *Name { } type CreateResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id" bun:"id" csv:"id" pg:"id" yaml:"id"` + sizeCache protoimpl.SizeCache } func (x *CreateResponse) Reset() { *x = CreateResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_crud_v1_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_crud_v1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CreateResponse) String() string { @@ -92,7 +87,7 @@ func (*CreateResponse) ProtoMessage() {} func (x *CreateResponse) ProtoReflect() protoreflect.Message { mi := &file_examples_crud_v1_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -115,20 +110,17 @@ func (x *CreateResponse) GetId() string { } type ReadRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id" bun:"id" csv:"id" pg:"id" yaml:"id"` + sizeCache protoimpl.SizeCache } func (x *ReadRequest) Reset() { *x = ReadRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_crud_v1_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_crud_v1_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ReadRequest) String() string { @@ -139,7 +131,7 @@ func (*ReadRequest) ProtoMessage() {} func (x *ReadRequest) ProtoReflect() protoreflect.Message { mi := &file_examples_crud_v1_service_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -162,20 +154,17 @@ func (x *ReadRequest) GetId() string { } type ReadResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Name *Name `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` unknownFields protoimpl.UnknownFields - - Name *Name `protobuf:"bytes,1,opt,name=name,proto3" json:"name" bun:"name" csv:"name" pg:"name" yaml:"name"` + sizeCache protoimpl.SizeCache } func (x *ReadResponse) Reset() { *x = ReadResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_crud_v1_service_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_crud_v1_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ReadResponse) String() string { @@ -186,7 +175,7 @@ func (*ReadResponse) ProtoMessage() {} func (x *ReadResponse) ProtoReflect() protoreflect.Message { mi := &file_examples_crud_v1_service_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -209,20 +198,17 @@ func (x *ReadResponse) GetName() *Name { } type UpdateRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Name *Name `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` unknownFields protoimpl.UnknownFields - - Name *Name `protobuf:"bytes,1,opt,name=name,proto3" json:"name" bun:"name" csv:"name" pg:"name" yaml:"name"` + sizeCache protoimpl.SizeCache } func (x *UpdateRequest) Reset() { *x = UpdateRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_crud_v1_service_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_crud_v1_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *UpdateRequest) String() string { @@ -233,7 +219,7 @@ func (*UpdateRequest) ProtoMessage() {} func (x *UpdateRequest) ProtoReflect() protoreflect.Message { mi := &file_examples_crud_v1_service_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -256,20 +242,17 @@ func (x *UpdateRequest) GetName() *Name { } type UpdateResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id" bun:"id" csv:"id" pg:"id" yaml:"id"` + sizeCache protoimpl.SizeCache } func (x *UpdateResponse) Reset() { *x = UpdateResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_crud_v1_service_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_crud_v1_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *UpdateResponse) String() string { @@ -280,7 +263,7 @@ func (*UpdateResponse) ProtoMessage() {} func (x *UpdateResponse) ProtoReflect() protoreflect.Message { mi := &file_examples_crud_v1_service_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -303,20 +286,17 @@ func (x *UpdateResponse) GetId() string { } type DeleteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id" bun:"id" csv:"id" pg:"id" yaml:"id"` + sizeCache protoimpl.SizeCache } func (x *DeleteRequest) Reset() { *x = DeleteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_crud_v1_service_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_crud_v1_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DeleteRequest) String() string { @@ -327,7 +307,7 @@ func (*DeleteRequest) ProtoMessage() {} func (x *DeleteRequest) ProtoReflect() protoreflect.Message { mi := &file_examples_crud_v1_service_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -350,20 +330,17 @@ func (x *DeleteRequest) GetId() string { } type DeleteResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id" bun:"id" csv:"id" pg:"id" yaml:"id"` + sizeCache protoimpl.SizeCache } func (x *DeleteResponse) Reset() { *x = DeleteResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_crud_v1_service_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_crud_v1_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DeleteResponse) String() string { @@ -374,7 +351,7 @@ func (*DeleteResponse) ProtoMessage() {} func (x *DeleteResponse) ProtoReflect() protoreflect.Message { mi := &file_examples_crud_v1_service_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -398,69 +375,39 @@ func (x *DeleteResponse) GetId() string { var File_examples_crud_v1_service_proto protoreflect.FileDescriptor -var file_examples_crud_v1_service_proto_rawDesc = []byte{ - 0x0a, 0x1e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x72, 0x75, 0x64, 0x2f, - 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x10, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, 0x2e, - 0x76, 0x31, 0x1a, 0x1d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x63, 0x72, 0x75, - 0x64, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0x3b, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, - 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x20, - 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x22, 0x1d, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, - 0x3a, 0x0a, 0x0c, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3b, 0x0a, 0x0d, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x65, 0x78, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, - 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x20, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1f, 0x0a, 0x0d, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x20, 0x0a, 0x0e, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x32, 0xc3, 0x02, - 0x0a, 0x0b, 0x43, 0x72, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4d, 0x0a, - 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, - 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x04, - 0x52, 0x65, 0x61, 0x64, 0x12, 0x1d, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, - 0x63, 0x72, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x63, - 0x72, 0x75, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, - 0x1f, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1f, - 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x75, 0x64, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, - 0x72, 0x61, 0x66, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, - 0x73, 0x2f, 0x63, 0x72, 0x75, 0x64, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} +const file_examples_crud_v1_service_proto_rawDesc = "" + + "\n" + + "\x1eexamples/crud/v1/service.proto\x12\x10examples.crud.v1\x1a\x1dexamples/crud/v1/models.proto\";\n" + + "\rCreateRequest\x12*\n" + + "\x04name\x18\x01 \x01(\v2\x16.examples.crud.v1.NameR\x04name\" \n" + + "\x0eCreateResponse\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\"\x1d\n" + + "\vReadRequest\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\":\n" + + "\fReadResponse\x12*\n" + + "\x04name\x18\x01 \x01(\v2\x16.examples.crud.v1.NameR\x04name\";\n" + + "\rUpdateRequest\x12*\n" + + "\x04name\x18\x01 \x01(\v2\x16.examples.crud.v1.NameR\x04name\" \n" + + "\x0eUpdateResponse\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\"\x1f\n" + + "\rDeleteRequest\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\" \n" + + "\x0eDeleteResponse\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id2\xc3\x02\n" + + "\vCrudService\x12M\n" + + "\x06Create\x12\x1f.examples.crud.v1.CreateRequest\x1a .examples.crud.v1.CreateResponse\"\x00\x12G\n" + + "\x04Read\x12\x1d.examples.crud.v1.ReadRequest\x1a\x1e.examples.crud.v1.ReadResponse\"\x00\x12M\n" + + "\x06Update\x12\x1f.examples.crud.v1.UpdateRequest\x1a .examples.crud.v1.UpdateResponse\"\x00\x12M\n" + + "\x06Delete\x12\x1f.examples.crud.v1.DeleteRequest\x1a .examples.crud.v1.DeleteResponse\"\x00B4Z2github.com/steady-bytes/draft/api/examples/crud/v1b\x06proto3" var ( file_examples_crud_v1_service_proto_rawDescOnce sync.Once - file_examples_crud_v1_service_proto_rawDescData = file_examples_crud_v1_service_proto_rawDesc + file_examples_crud_v1_service_proto_rawDescData []byte ) func file_examples_crud_v1_service_proto_rawDescGZIP() []byte { file_examples_crud_v1_service_proto_rawDescOnce.Do(func() { - file_examples_crud_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_examples_crud_v1_service_proto_rawDescData) + file_examples_crud_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_examples_crud_v1_service_proto_rawDesc), len(file_examples_crud_v1_service_proto_rawDesc))) }) return file_examples_crud_v1_service_proto_rawDescData } @@ -502,109 +449,11 @@ func file_examples_crud_v1_service_proto_init() { return } file_examples_crud_v1_models_proto_init() - if !protoimpl.UnsafeEnabled { - file_examples_crud_v1_service_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*CreateRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_examples_crud_v1_service_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*CreateResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_examples_crud_v1_service_proto_msgTypes[2].Exporter = func(v any, i int) any { - switch v := v.(*ReadRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_examples_crud_v1_service_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*ReadResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_examples_crud_v1_service_proto_msgTypes[4].Exporter = func(v any, i int) any { - switch v := v.(*UpdateRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_examples_crud_v1_service_proto_msgTypes[5].Exporter = func(v any, i int) any { - switch v := v.(*UpdateResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_examples_crud_v1_service_proto_msgTypes[6].Exporter = func(v any, i int) any { - switch v := v.(*DeleteRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_examples_crud_v1_service_proto_msgTypes[7].Exporter = func(v any, i int) any { - switch v := v.(*DeleteResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_examples_crud_v1_service_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_examples_crud_v1_service_proto_rawDesc), len(file_examples_crud_v1_service_proto_rawDesc)), NumEnums: 0, NumMessages: 8, NumExtensions: 0, @@ -615,7 +464,6 @@ func file_examples_crud_v1_service_proto_init() { MessageInfos: file_examples_crud_v1_service_proto_msgTypes, }.Build() File_examples_crud_v1_service_proto = out.File - file_examples_crud_v1_service_proto_rawDesc = nil file_examples_crud_v1_service_proto_goTypes = nil file_examples_crud_v1_service_proto_depIdxs = nil } diff --git a/api/examples/crud/v1/service.pb.validate.go b/api/examples/crud/v1/service.pb.validate.go index b68769f9..cc940d03 100644 --- a/api/examples/crud/v1/service.pb.validate.go +++ b/api/examples/crud/v1/service.pb.validate.go @@ -100,7 +100,7 @@ type CreateRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m CreateRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -202,7 +202,7 @@ type CreateResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m CreateResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -303,7 +303,7 @@ type ReadRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ReadRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -431,7 +431,7 @@ type ReadResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m ReadResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -560,7 +560,7 @@ type UpdateRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m UpdateRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -662,7 +662,7 @@ type UpdateResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m UpdateResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -764,7 +764,7 @@ type DeleteRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m DeleteRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -866,7 +866,7 @@ type DeleteResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m DeleteResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/examples/crud/v1/v1connect/service.connect.go b/api/examples/crud/v1/v1connect/service.connect.go index 57dbcb2e..3500fcd7 100644 --- a/api/examples/crud/v1/v1connect/service.connect.go +++ b/api/examples/crud/v1/v1connect/service.connect.go @@ -43,15 +43,6 @@ const ( CrudServiceDeleteProcedure = "/examples.crud.v1.CrudService/Delete" ) -// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. -var ( - crudServiceServiceDescriptor = v1.File_examples_crud_v1_service_proto.Services().ByName("CrudService") - crudServiceCreateMethodDescriptor = crudServiceServiceDescriptor.Methods().ByName("Create") - crudServiceReadMethodDescriptor = crudServiceServiceDescriptor.Methods().ByName("Read") - crudServiceUpdateMethodDescriptor = crudServiceServiceDescriptor.Methods().ByName("Update") - crudServiceDeleteMethodDescriptor = crudServiceServiceDescriptor.Methods().ByName("Delete") -) - // CrudServiceClient is a client for the examples.crud.v1.CrudService service. type CrudServiceClient interface { Create(context.Context, *connect.Request[v1.CreateRequest]) (*connect.Response[v1.CreateResponse], error) @@ -69,29 +60,30 @@ type CrudServiceClient interface { // http://api.acme.com or https://acme.com/grpc). func NewCrudServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) CrudServiceClient { baseURL = strings.TrimRight(baseURL, "/") + crudServiceMethods := v1.File_examples_crud_v1_service_proto.Services().ByName("CrudService").Methods() return &crudServiceClient{ create: connect.NewClient[v1.CreateRequest, v1.CreateResponse]( httpClient, baseURL+CrudServiceCreateProcedure, - connect.WithSchema(crudServiceCreateMethodDescriptor), + connect.WithSchema(crudServiceMethods.ByName("Create")), connect.WithClientOptions(opts...), ), read: connect.NewClient[v1.ReadRequest, v1.ReadResponse]( httpClient, baseURL+CrudServiceReadProcedure, - connect.WithSchema(crudServiceReadMethodDescriptor), + connect.WithSchema(crudServiceMethods.ByName("Read")), connect.WithClientOptions(opts...), ), update: connect.NewClient[v1.UpdateRequest, v1.UpdateResponse]( httpClient, baseURL+CrudServiceUpdateProcedure, - connect.WithSchema(crudServiceUpdateMethodDescriptor), + connect.WithSchema(crudServiceMethods.ByName("Update")), connect.WithClientOptions(opts...), ), delete: connect.NewClient[v1.DeleteRequest, v1.DeleteResponse]( httpClient, baseURL+CrudServiceDeleteProcedure, - connect.WithSchema(crudServiceDeleteMethodDescriptor), + connect.WithSchema(crudServiceMethods.ByName("Delete")), connect.WithClientOptions(opts...), ), } @@ -139,28 +131,29 @@ type CrudServiceHandler interface { // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. func NewCrudServiceHandler(svc CrudServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + crudServiceMethods := v1.File_examples_crud_v1_service_proto.Services().ByName("CrudService").Methods() crudServiceCreateHandler := connect.NewUnaryHandler( CrudServiceCreateProcedure, svc.Create, - connect.WithSchema(crudServiceCreateMethodDescriptor), + connect.WithSchema(crudServiceMethods.ByName("Create")), connect.WithHandlerOptions(opts...), ) crudServiceReadHandler := connect.NewUnaryHandler( CrudServiceReadProcedure, svc.Read, - connect.WithSchema(crudServiceReadMethodDescriptor), + connect.WithSchema(crudServiceMethods.ByName("Read")), connect.WithHandlerOptions(opts...), ) crudServiceUpdateHandler := connect.NewUnaryHandler( CrudServiceUpdateProcedure, svc.Update, - connect.WithSchema(crudServiceUpdateMethodDescriptor), + connect.WithSchema(crudServiceMethods.ByName("Update")), connect.WithHandlerOptions(opts...), ) crudServiceDeleteHandler := connect.NewUnaryHandler( CrudServiceDeleteProcedure, svc.Delete, - connect.WithSchema(crudServiceDeleteMethodDescriptor), + connect.WithSchema(crudServiceMethods.ByName("Delete")), connect.WithHandlerOptions(opts...), ) return "/examples.crud.v1.CrudService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/api/examples/echo/v1/events.pb.go b/api/examples/echo/v1/events.pb.go new file mode 100644 index 00000000..300e4f67 --- /dev/null +++ b/api/examples/echo/v1/events.pb.go @@ -0,0 +1,244 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: examples/echo/v1/events.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type HelloWorld struct { + state protoimpl.MessageState `protogen:"open.v1"` + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HelloWorld) Reset() { + *x = HelloWorld{} + mi := &file_examples_echo_v1_events_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HelloWorld) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloWorld) ProtoMessage() {} + +func (x *HelloWorld) ProtoReflect() protoreflect.Message { + mi := &file_examples_echo_v1_events_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HelloWorld.ProtoReflect.Descriptor instead. +func (*HelloWorld) Descriptor() ([]byte, []int) { + return file_examples_echo_v1_events_proto_rawDescGZIP(), []int{0} +} + +func (x *HelloWorld) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *HelloWorld) GetSender() string { + if x != nil { + return x.Sender + } + return "" +} + +type Ping struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Ping) Reset() { + *x = Ping{} + mi := &file_examples_echo_v1_events_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Ping) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ping) ProtoMessage() {} + +func (x *Ping) ProtoReflect() protoreflect.Message { + mi := &file_examples_echo_v1_events_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Ping.ProtoReflect.Descriptor instead. +func (*Ping) Descriptor() ([]byte, []int) { + return file_examples_echo_v1_events_proto_rawDescGZIP(), []int{1} +} + +func (x *Ping) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Ping) GetSender() string { + if x != nil { + return x.Sender + } + return "" +} + +type Pong struct { + state protoimpl.MessageState `protogen:"open.v1"` + PingId string `protobuf:"bytes,1,opt,name=ping_id,json=pingId,proto3" json:"ping_id,omitempty"` + Responder string `protobuf:"bytes,2,opt,name=responder,proto3" json:"responder,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Pong) Reset() { + *x = Pong{} + mi := &file_examples_echo_v1_events_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Pong) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Pong) ProtoMessage() {} + +func (x *Pong) ProtoReflect() protoreflect.Message { + mi := &file_examples_echo_v1_events_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Pong.ProtoReflect.Descriptor instead. +func (*Pong) Descriptor() ([]byte, []int) { + return file_examples_echo_v1_events_proto_rawDescGZIP(), []int{2} +} + +func (x *Pong) GetPingId() string { + if x != nil { + return x.PingId + } + return "" +} + +func (x *Pong) GetResponder() string { + if x != nil { + return x.Responder + } + return "" +} + +var File_examples_echo_v1_events_proto protoreflect.FileDescriptor + +const file_examples_echo_v1_events_proto_rawDesc = "" + + "\n" + + "\x1dexamples/echo/v1/events.proto\x12\x10examples.echo.v1\">\n" + + "\n" + + "HelloWorld\x12\x18\n" + + "\amessage\x18\x01 \x01(\tR\amessage\x12\x16\n" + + "\x06sender\x18\x02 \x01(\tR\x06sender\".\n" + + "\x04Ping\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x16\n" + + "\x06sender\x18\x02 \x01(\tR\x06sender\"=\n" + + "\x04Pong\x12\x17\n" + + "\aping_id\x18\x01 \x01(\tR\x06pingId\x12\x1c\n" + + "\tresponder\x18\x02 \x01(\tR\tresponderB4Z2github.com/steady-bytes/draft/api/examples/echo/v1b\x06proto3" + +var ( + file_examples_echo_v1_events_proto_rawDescOnce sync.Once + file_examples_echo_v1_events_proto_rawDescData []byte +) + +func file_examples_echo_v1_events_proto_rawDescGZIP() []byte { + file_examples_echo_v1_events_proto_rawDescOnce.Do(func() { + file_examples_echo_v1_events_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_examples_echo_v1_events_proto_rawDesc), len(file_examples_echo_v1_events_proto_rawDesc))) + }) + return file_examples_echo_v1_events_proto_rawDescData +} + +var file_examples_echo_v1_events_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_examples_echo_v1_events_proto_goTypes = []any{ + (*HelloWorld)(nil), // 0: examples.echo.v1.HelloWorld + (*Ping)(nil), // 1: examples.echo.v1.Ping + (*Pong)(nil), // 2: examples.echo.v1.Pong +} +var file_examples_echo_v1_events_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_examples_echo_v1_events_proto_init() } +func file_examples_echo_v1_events_proto_init() { + if File_examples_echo_v1_events_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_examples_echo_v1_events_proto_rawDesc), len(file_examples_echo_v1_events_proto_rawDesc)), + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_examples_echo_v1_events_proto_goTypes, + DependencyIndexes: file_examples_echo_v1_events_proto_depIdxs, + MessageInfos: file_examples_echo_v1_events_proto_msgTypes, + }.Build() + File_examples_echo_v1_events_proto = out.File + file_examples_echo_v1_events_proto_goTypes = nil + file_examples_echo_v1_events_proto_depIdxs = nil +} diff --git a/api/examples/echo/v1/events.pb.validate.go b/api/examples/echo/v1/events.pb.validate.go new file mode 100644 index 00000000..b93f23aa --- /dev/null +++ b/api/examples/echo/v1/events.pb.validate.go @@ -0,0 +1,343 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: examples/echo/v1/events.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on HelloWorld with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *HelloWorld) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on HelloWorld with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in HelloWorldMultiError, or +// nil if none found. +func (m *HelloWorld) ValidateAll() error { + return m.validate(true) +} + +func (m *HelloWorld) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Message + + // no validation rules for Sender + + if len(errors) > 0 { + return HelloWorldMultiError(errors) + } + + return nil +} + +// HelloWorldMultiError is an error wrapping multiple validation errors +// returned by HelloWorld.ValidateAll() if the designated constraints aren't met. +type HelloWorldMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m HelloWorldMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m HelloWorldMultiError) AllErrors() []error { return m } + +// HelloWorldValidationError is the validation error returned by +// HelloWorld.Validate if the designated constraints aren't met. +type HelloWorldValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e HelloWorldValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e HelloWorldValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e HelloWorldValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e HelloWorldValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e HelloWorldValidationError) ErrorName() string { return "HelloWorldValidationError" } + +// Error satisfies the builtin error interface +func (e HelloWorldValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHelloWorld.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = HelloWorldValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = HelloWorldValidationError{} + +// Validate checks the field values on Ping with the rules defined in the proto +// definition for this message. If any rules are violated, the first error +// encountered is returned, or nil if there are no violations. +func (m *Ping) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on Ping with the rules defined in the +// proto definition for this message. If any rules are violated, the result is +// a list of violation errors wrapped in PingMultiError, or nil if none found. +func (m *Ping) ValidateAll() error { + return m.validate(true) +} + +func (m *Ping) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Id + + // no validation rules for Sender + + if len(errors) > 0 { + return PingMultiError(errors) + } + + return nil +} + +// PingMultiError is an error wrapping multiple validation errors returned by +// Ping.ValidateAll() if the designated constraints aren't met. +type PingMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m PingMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m PingMultiError) AllErrors() []error { return m } + +// PingValidationError is the validation error returned by Ping.Validate if the +// designated constraints aren't met. +type PingValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e PingValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e PingValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e PingValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e PingValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e PingValidationError) ErrorName() string { return "PingValidationError" } + +// Error satisfies the builtin error interface +func (e PingValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sPing.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = PingValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = PingValidationError{} + +// Validate checks the field values on Pong with the rules defined in the proto +// definition for this message. If any rules are violated, the first error +// encountered is returned, or nil if there are no violations. +func (m *Pong) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on Pong with the rules defined in the +// proto definition for this message. If any rules are violated, the result is +// a list of violation errors wrapped in PongMultiError, or nil if none found. +func (m *Pong) ValidateAll() error { + return m.validate(true) +} + +func (m *Pong) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for PingId + + // no validation rules for Responder + + if len(errors) > 0 { + return PongMultiError(errors) + } + + return nil +} + +// PongMultiError is an error wrapping multiple validation errors returned by +// Pong.ValidateAll() if the designated constraints aren't met. +type PongMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m PongMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m PongMultiError) AllErrors() []error { return m } + +// PongValidationError is the validation error returned by Pong.Validate if the +// designated constraints aren't met. +type PongValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e PongValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e PongValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e PongValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e PongValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e PongValidationError) ErrorName() string { return "PongValidationError" } + +// Error satisfies the builtin error interface +func (e PongValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sPong.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = PongValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = PongValidationError{} diff --git a/api/examples/echo/v1/events.proto b/api/examples/echo/v1/events.proto new file mode 100644 index 00000000..e68bfe1f --- /dev/null +++ b/api/examples/echo/v1/events.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +package examples.echo.v1; + +option go_package = "github.com/steady-bytes/draft/api/examples/echo/v1"; + +message HelloWorld { + string message = 1; + string sender = 2; +} + +message Ping { + string id = 1; + string sender = 2; +} + +message Pong { + string ping_id = 1; + string responder = 2; +} diff --git a/api/examples/echo/v1/service.pb.go b/api/examples/echo/v1/service.pb.go index 8d22231e..949e3ef3 100644 --- a/api/examples/echo/v1/service.pb.go +++ b/api/examples/echo/v1/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 +// protoc-gen-go v1.36.11 // protoc (unknown) // source: examples/echo/v1/service.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -21,20 +22,17 @@ const ( ) type SpeakRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Input string `protobuf:"bytes,1,opt,name=input,proto3" json:"input,omitempty"` unknownFields protoimpl.UnknownFields - - Input string `protobuf:"bytes,1,opt,name=input,proto3" json:"input" bun:"input" csv:"input" pg:"input" yaml:"input"` + sizeCache protoimpl.SizeCache } func (x *SpeakRequest) Reset() { *x = SpeakRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_echo_v1_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_echo_v1_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SpeakRequest) String() string { @@ -45,7 +43,7 @@ func (*SpeakRequest) ProtoMessage() {} func (x *SpeakRequest) ProtoReflect() protoreflect.Message { mi := &file_examples_echo_v1_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -68,20 +66,17 @@ func (x *SpeakRequest) GetInput() string { } type SpeakResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Output string `protobuf:"bytes,2,opt,name=output,proto3" json:"output,omitempty"` unknownFields protoimpl.UnknownFields - - Output string `protobuf:"bytes,2,opt,name=output,proto3" json:"output" bun:"output" csv:"output" pg:"output" yaml:"output"` + sizeCache protoimpl.SizeCache } func (x *SpeakResponse) Reset() { *x = SpeakResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_examples_echo_v1_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_examples_echo_v1_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SpeakResponse) String() string { @@ -92,7 +87,7 @@ func (*SpeakResponse) ProtoMessage() {} func (x *SpeakResponse) ProtoReflect() protoreflect.Message { mi := &file_examples_echo_v1_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -116,35 +111,24 @@ func (x *SpeakResponse) GetOutput() string { var File_examples_echo_v1_service_proto protoreflect.FileDescriptor -var file_examples_echo_v1_service_proto_rawDesc = []byte{ - 0x0a, 0x1e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2f, - 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x10, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x65, 0x63, 0x68, 0x6f, 0x2e, - 0x76, 0x31, 0x22, 0x24, 0x0a, 0x0c, 0x53, 0x70, 0x65, 0x61, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x27, 0x0a, 0x0d, 0x53, 0x70, 0x65, 0x61, - 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x32, 0x59, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x4a, 0x0a, 0x05, 0x53, 0x70, 0x65, 0x61, 0x6b, 0x12, 0x1e, 0x2e, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x65, 0x63, 0x68, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x65, - 0x61, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x65, 0x63, 0x68, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x65, - 0x61, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x34, 0x5a, 0x32, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x65, 0x61, 0x64, - 0x79, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2f, 0x64, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2f, - 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_examples_echo_v1_service_proto_rawDesc = "" + + "\n" + + "\x1eexamples/echo/v1/service.proto\x12\x10examples.echo.v1\"$\n" + + "\fSpeakRequest\x12\x14\n" + + "\x05input\x18\x01 \x01(\tR\x05input\"'\n" + + "\rSpeakResponse\x12\x16\n" + + "\x06output\x18\x02 \x01(\tR\x06output2Y\n" + + "\vEchoService\x12J\n" + + "\x05Speak\x12\x1e.examples.echo.v1.SpeakRequest\x1a\x1f.examples.echo.v1.SpeakResponse\"\x00B4Z2github.com/steady-bytes/draft/api/examples/echo/v1b\x06proto3" var ( file_examples_echo_v1_service_proto_rawDescOnce sync.Once - file_examples_echo_v1_service_proto_rawDescData = file_examples_echo_v1_service_proto_rawDesc + file_examples_echo_v1_service_proto_rawDescData []byte ) func file_examples_echo_v1_service_proto_rawDescGZIP() []byte { file_examples_echo_v1_service_proto_rawDescOnce.Do(func() { - file_examples_echo_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_examples_echo_v1_service_proto_rawDescData) + file_examples_echo_v1_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_examples_echo_v1_service_proto_rawDesc), len(file_examples_echo_v1_service_proto_rawDesc))) }) return file_examples_echo_v1_service_proto_rawDescData } @@ -169,37 +153,11 @@ func file_examples_echo_v1_service_proto_init() { if File_examples_echo_v1_service_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_examples_echo_v1_service_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*SpeakRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_examples_echo_v1_service_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*SpeakResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_examples_echo_v1_service_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_examples_echo_v1_service_proto_rawDesc), len(file_examples_echo_v1_service_proto_rawDesc)), NumEnums: 0, NumMessages: 2, NumExtensions: 0, @@ -210,7 +168,6 @@ func file_examples_echo_v1_service_proto_init() { MessageInfos: file_examples_echo_v1_service_proto_msgTypes, }.Build() File_examples_echo_v1_service_proto = out.File - file_examples_echo_v1_service_proto_rawDesc = nil file_examples_echo_v1_service_proto_goTypes = nil file_examples_echo_v1_service_proto_depIdxs = nil } diff --git a/api/examples/echo/v1/service.pb.validate.go b/api/examples/echo/v1/service.pb.validate.go index 2cb84a2e..1dd6cbe9 100644 --- a/api/examples/echo/v1/service.pb.validate.go +++ b/api/examples/echo/v1/service.pb.validate.go @@ -72,7 +72,7 @@ type SpeakRequestMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m SpeakRequestMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } @@ -174,7 +174,7 @@ type SpeakResponseMultiError []error // Error returns a concatenation of all the error messages it wraps. func (m SpeakResponseMultiError) Error() string { - var msgs []string + msgs := make([]string, 0, len(m)) for _, err := range m { msgs = append(msgs, err.Error()) } diff --git a/api/examples/echo/v1/v1connect/service.connect.go b/api/examples/echo/v1/v1connect/service.connect.go index 65ea3ed2..e8daf941 100644 --- a/api/examples/echo/v1/v1connect/service.connect.go +++ b/api/examples/echo/v1/v1connect/service.connect.go @@ -37,12 +37,6 @@ const ( EchoServiceSpeakProcedure = "/examples.echo.v1.EchoService/Speak" ) -// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. -var ( - echoServiceServiceDescriptor = v1.File_examples_echo_v1_service_proto.Services().ByName("EchoService") - echoServiceSpeakMethodDescriptor = echoServiceServiceDescriptor.Methods().ByName("Speak") -) - // EchoServiceClient is a client for the examples.echo.v1.EchoService service. type EchoServiceClient interface { Speak(context.Context, *connect.Request[v1.SpeakRequest]) (*connect.Response[v1.SpeakResponse], error) @@ -57,11 +51,12 @@ type EchoServiceClient interface { // http://api.acme.com or https://acme.com/grpc). func NewEchoServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) EchoServiceClient { baseURL = strings.TrimRight(baseURL, "/") + echoServiceMethods := v1.File_examples_echo_v1_service_proto.Services().ByName("EchoService").Methods() return &echoServiceClient{ speak: connect.NewClient[v1.SpeakRequest, v1.SpeakResponse]( httpClient, baseURL+EchoServiceSpeakProcedure, - connect.WithSchema(echoServiceSpeakMethodDescriptor), + connect.WithSchema(echoServiceMethods.ByName("Speak")), connect.WithClientOptions(opts...), ), } @@ -88,10 +83,11 @@ type EchoServiceHandler interface { // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. func NewEchoServiceHandler(svc EchoServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + echoServiceMethods := v1.File_examples_echo_v1_service_proto.Services().ByName("EchoService").Methods() echoServiceSpeakHandler := connect.NewUnaryHandler( EchoServiceSpeakProcedure, svc.Speak, - connect.WithSchema(echoServiceSpeakMethodDescriptor), + connect.WithSchema(echoServiceMethods.ByName("Speak")), connect.WithHandlerOptions(opts...), ) return "/examples.echo.v1.EchoService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/api/examples/user/v1/events.pb.go b/api/examples/user/v1/events.pb.go new file mode 100644 index 00000000..2ad17490 --- /dev/null +++ b/api/examples/user/v1/events.pb.go @@ -0,0 +1,208 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: examples/user/v1/events.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type UserCreated struct { + state protoimpl.MessageState `protogen:"open.v1"` + UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UserCreated) Reset() { + *x = UserCreated{} + mi := &file_examples_user_v1_events_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UserCreated) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserCreated) ProtoMessage() {} + +func (x *UserCreated) ProtoReflect() protoreflect.Message { + mi := &file_examples_user_v1_events_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserCreated.ProtoReflect.Descriptor instead. +func (*UserCreated) Descriptor() ([]byte, []int) { + return file_examples_user_v1_events_proto_rawDescGZIP(), []int{0} +} + +func (x *UserCreated) GetUserId() string { + if x != nil { + return x.UserId + } + return "" +} + +func (x *UserCreated) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +func (x *UserCreated) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type UserLoggedIn struct { + state protoimpl.MessageState `protogen:"open.v1"` + UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` + LoginAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=login_at,json=loginAt,proto3" json:"login_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UserLoggedIn) Reset() { + *x = UserLoggedIn{} + mi := &file_examples_user_v1_events_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UserLoggedIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserLoggedIn) ProtoMessage() {} + +func (x *UserLoggedIn) ProtoReflect() protoreflect.Message { + mi := &file_examples_user_v1_events_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserLoggedIn.ProtoReflect.Descriptor instead. +func (*UserLoggedIn) Descriptor() ([]byte, []int) { + return file_examples_user_v1_events_proto_rawDescGZIP(), []int{1} +} + +func (x *UserLoggedIn) GetUserId() string { + if x != nil { + return x.UserId + } + return "" +} + +func (x *UserLoggedIn) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +func (x *UserLoggedIn) GetLoginAt() *timestamppb.Timestamp { + if x != nil { + return x.LoginAt + } + return nil +} + +var File_examples_user_v1_events_proto protoreflect.FileDescriptor + +const file_examples_user_v1_events_proto_rawDesc = "" + + "\n" + + "\x1dexamples/user/v1/events.proto\x12\x10examples.user.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"P\n" + + "\vUserCreated\x12\x17\n" + + "\auser_id\x18\x01 \x01(\tR\x06userId\x12\x14\n" + + "\x05email\x18\x02 \x01(\tR\x05email\x12\x12\n" + + "\x04name\x18\x03 \x01(\tR\x04name\"t\n" + + "\fUserLoggedIn\x12\x17\n" + + "\auser_id\x18\x01 \x01(\tR\x06userId\x12\x14\n" + + "\x05email\x18\x02 \x01(\tR\x05email\x125\n" + + "\blogin_at\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\aloginAtB4Z2github.com/steady-bytes/draft/api/examples/user/v1b\x06proto3" + +var ( + file_examples_user_v1_events_proto_rawDescOnce sync.Once + file_examples_user_v1_events_proto_rawDescData []byte +) + +func file_examples_user_v1_events_proto_rawDescGZIP() []byte { + file_examples_user_v1_events_proto_rawDescOnce.Do(func() { + file_examples_user_v1_events_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_examples_user_v1_events_proto_rawDesc), len(file_examples_user_v1_events_proto_rawDesc))) + }) + return file_examples_user_v1_events_proto_rawDescData +} + +var file_examples_user_v1_events_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_examples_user_v1_events_proto_goTypes = []any{ + (*UserCreated)(nil), // 0: examples.user.v1.UserCreated + (*UserLoggedIn)(nil), // 1: examples.user.v1.UserLoggedIn + (*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp +} +var file_examples_user_v1_events_proto_depIdxs = []int32{ + 2, // 0: examples.user.v1.UserLoggedIn.login_at:type_name -> google.protobuf.Timestamp + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_examples_user_v1_events_proto_init() } +func file_examples_user_v1_events_proto_init() { + if File_examples_user_v1_events_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_examples_user_v1_events_proto_rawDesc), len(file_examples_user_v1_events_proto_rawDesc)), + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_examples_user_v1_events_proto_goTypes, + DependencyIndexes: file_examples_user_v1_events_proto_depIdxs, + MessageInfos: file_examples_user_v1_events_proto_msgTypes, + }.Build() + File_examples_user_v1_events_proto = out.File + file_examples_user_v1_events_proto_goTypes = nil + file_examples_user_v1_events_proto_depIdxs = nil +} diff --git a/api/examples/user/v1/events.pb.validate.go b/api/examples/user/v1/events.pb.validate.go new file mode 100644 index 00000000..82402160 --- /dev/null +++ b/api/examples/user/v1/events.pb.validate.go @@ -0,0 +1,273 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: examples/user/v1/events.proto + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on UserCreated with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *UserCreated) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on UserCreated with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in UserCreatedMultiError, or +// nil if none found. +func (m *UserCreated) ValidateAll() error { + return m.validate(true) +} + +func (m *UserCreated) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for UserId + + // no validation rules for Email + + // no validation rules for Name + + if len(errors) > 0 { + return UserCreatedMultiError(errors) + } + + return nil +} + +// UserCreatedMultiError is an error wrapping multiple validation errors +// returned by UserCreated.ValidateAll() if the designated constraints aren't met. +type UserCreatedMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m UserCreatedMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m UserCreatedMultiError) AllErrors() []error { return m } + +// UserCreatedValidationError is the validation error returned by +// UserCreated.Validate if the designated constraints aren't met. +type UserCreatedValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e UserCreatedValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e UserCreatedValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e UserCreatedValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e UserCreatedValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e UserCreatedValidationError) ErrorName() string { return "UserCreatedValidationError" } + +// Error satisfies the builtin error interface +func (e UserCreatedValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sUserCreated.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = UserCreatedValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = UserCreatedValidationError{} + +// Validate checks the field values on UserLoggedIn with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *UserLoggedIn) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on UserLoggedIn with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in UserLoggedInMultiError, or +// nil if none found. +func (m *UserLoggedIn) ValidateAll() error { + return m.validate(true) +} + +func (m *UserLoggedIn) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for UserId + + // no validation rules for Email + + if all { + switch v := interface{}(m.GetLoginAt()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, UserLoggedInValidationError{ + field: "LoginAt", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, UserLoggedInValidationError{ + field: "LoginAt", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetLoginAt()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return UserLoggedInValidationError{ + field: "LoginAt", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return UserLoggedInMultiError(errors) + } + + return nil +} + +// UserLoggedInMultiError is an error wrapping multiple validation errors +// returned by UserLoggedIn.ValidateAll() if the designated constraints aren't met. +type UserLoggedInMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m UserLoggedInMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m UserLoggedInMultiError) AllErrors() []error { return m } + +// UserLoggedInValidationError is the validation error returned by +// UserLoggedIn.Validate if the designated constraints aren't met. +type UserLoggedInValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e UserLoggedInValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e UserLoggedInValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e UserLoggedInValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e UserLoggedInValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e UserLoggedInValidationError) ErrorName() string { return "UserLoggedInValidationError" } + +// Error satisfies the builtin error interface +func (e UserLoggedInValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sUserLoggedIn.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = UserLoggedInValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = UserLoggedInValidationError{} diff --git a/api/examples/user/v1/events.proto b/api/examples/user/v1/events.proto new file mode 100644 index 00000000..1326716d --- /dev/null +++ b/api/examples/user/v1/events.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package examples.user.v1; + +option go_package = "github.com/steady-bytes/draft/api/examples/user/v1"; + +import "google/protobuf/timestamp.proto"; + +message UserCreated { + string user_id = 1; + string email = 2; + string name = 3; +} + +message UserLoggedIn { + string user_id = 1; + string email = 2; + google.protobuf.Timestamp login_at = 3; +} diff --git a/api/src/basic.rs b/api/src/basic.rs new file mode 100644 index 00000000..85d89c53 --- /dev/null +++ b/api/src/basic.rs @@ -0,0 +1,335 @@ +#[cfg(feature = "web")] +pub mod proto; +#[cfg(feature = "web")] +pub mod hook; + +#[cfg(feature = "web")] +use dioxus::prelude::*; +#[cfg(feature = "web")] +use prost::Message as _; + +fn main() { + #[cfg(feature = "web")] + launch(app); +} + +#[cfg(feature = "web")] +const VALUE_TYPE_URL: &str = "type.googleapis.com/core.registry.key_value.v1.Value"; + +#[cfg(feature = "web")] +fn strip_type_prefix(key: &str) -> &str { + key.strip_prefix(VALUE_TYPE_URL) + .and_then(|s| s.strip_prefix('-')) + .unwrap_or(key) +} + +#[cfg(feature = "web")] +fn app() -> Element { + use hook::core_registry_key_value_v1::{ + use_key_value_service_service, GetRequest, SetRequest, Value, + }; + + let mut key = use_signal(|| String::from("my-key")); + let mut value_input = use_signal(|| String::from("my-value")); + + let mut set_req = use_signal(|| SetRequest { + key: String::new(), + value: None, + }); + + let mut get_req = use_signal(|| GetRequest { + key: String::new(), + value: None, + }); + + // Initialized with the Value type URL so Blueprint knows which type to scan. + // Written again on each List click to re-trigger the resource. + let mut list_req = use_signal(|| list_request()); + + let kv = use_key_value_service_service(); + let set_result = kv.set(set_req); + let get_result = kv.get(get_req); + let list_result = kv.list(list_req); + + rsx! { + style { " + * {{ box-sizing: border-box; margin: 0; padding: 0; }} + + body {{ + background: #0f1117; + color: #d0d0e0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + min-height: 100vh; + padding: 2.5rem; + }} + + h1 {{ + font-size: 1.5rem; + font-weight: 600; + color: #a0b4d6; + margin-bottom: 1.75rem; + }} + + .controls {{ + display: flex; + align-items: center; + gap: 0.6rem; + flex-wrap: wrap; + }} + + .controls label {{ + font-size: 0.8rem; + color: #7878a0; + text-transform: uppercase; + letter-spacing: 0.04em; + }} + + .controls input {{ + background: #1c1f2e; + border: 1px solid #2e3250; + border-radius: 6px; + color: #d0d0e0; + font-size: 0.9rem; + padding: 0.4rem 0.7rem; + outline: none; + transition: border-color 0.15s; + }} + + .controls input:focus {{ border-color: #5060a0; }} + + .controls button {{ + background: #2a3580; + border: none; + border-radius: 6px; + color: #c8d4f0; + cursor: pointer; + font-size: 0.85rem; + padding: 0.4rem 0.9rem; + transition: background 0.15s; + }} + + .controls button:hover {{ background: #3a45a0; }} + + table {{ + border-collapse: collapse; + margin-top: 1.5rem; + width: 100%; + max-width: 640px; + background: #1c1f2e; + border-radius: 8px; + overflow: hidden; + }} + + th {{ + background: #161929; + color: #6878a8; + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.06em; + padding: 0.65rem 1rem; + text-align: left; + text-transform: uppercase; + border-bottom: 1px solid #2e3250; + }} + + td {{ + font-size: 0.9rem; + padding: 0.55rem 1rem; + border-bottom: 1px solid #22263a; + }} + + tbody tr:last-child td {{ border-bottom: none; }} + tbody tr:hover {{ background: #22263a; }} + + .get-result {{ + margin-top: 1rem; + padding: 0.6rem 1rem; + background: #1c1f2e; + border: 1px solid #2e3250; + border-left: 3px solid #5060a0; + border-radius: 6px; + font-size: 0.9rem; + color: #a0b4d6; + max-width: 640px; + }} + + .get-result .get-label {{ + font-size: 0.72rem; + text-transform: uppercase; + letter-spacing: 0.05em; + color: #5868a0; + margin-bottom: 0.2rem; + }} + + .toast-stack {{ + position: fixed; + top: 1.25rem; + right: 1.25rem; + display: flex; + flex-direction: column; + gap: 0.5rem; + z-index: 100; + pointer-events: none; + }} + + .toast {{ + background: #162016; + border: 1px solid #2a3e2a; + border-left: 3px solid #4a8a4a; + border-radius: 6px; + color: #88cc88; + font-size: 0.85rem; + padding: 0.6rem 1rem; + min-width: 220px; + animation: slide-in 0.22s cubic-bezier(0.16, 1, 0.3, 1); + }} + + .toast.error {{ + background: #201616; + border-color: #3e2a2a; + border-left-color: #8a4a4a; + color: #cc8888; + }} + + @keyframes slide-in {{ + from {{ transform: translateX(calc(100% + 1.25rem)); opacity: 0; }} + to {{ transform: translateX(0); opacity: 1; }} + }} + " } + + div { + h1 { "Blueprint Key/Value Explorer" } + + div { class: "controls", + label { "Key" } + input { + value: "{key}", + oninput: move |e| key.set(e.value()), + } + label { "Value" } + input { + value: "{value_input}", + oninput: move |e| value_input.set(e.value()), + } + button { + onclick: move |_| { + let v = Value { data: value_input() }; + set_req.set(SetRequest { + key: key(), + value: Some(prost_types::Any { + type_url: VALUE_TYPE_URL + .to_string(), + value: v.encode_to_vec(), + }), + }); + // Refresh the table after each set. + list_req.set(list_request()); + }, + "Set" + } + button { + onclick: move |_| { + get_req.set(GetRequest { + key: key(), + value: Some(prost_types::Any { + type_url: VALUE_TYPE_URL + .to_string(), + value: vec![], + }), + }); + }, + "Get" + } + button { + onclick: move |_| list_req.set(list_request()), + "List" + } + } + + // Inline get result + match &*get_result.read() { + Some(Ok(resp)) => match &resp.value { + Some(any) => { + let v = Value::decode(any.value.as_slice()) + .map(|v| v.data) + .unwrap_or_else(|_| "(binary)".to_string()); + rsx! { + div { class: "get-result", + div { class: "get-label", "Value" } + "{v}" + } + } + } + None => rsx! {}, + }, + _ => rsx! {}, + } + + // Results table + match &*list_result.read() { + None => rsx! { p { "Loading…" } }, + Some(Err(e)) => rsx! { div { class: "toast error", "List error: {e}" } }, + Some(Ok(resp)) => { + let mut rows: Vec<(String, String)> = resp.values + .iter() + .map(|(k, any)| { + let v = Value::decode(any.value.as_slice()) + .map(|v| v.data) + .unwrap_or_else(|_| "(binary)".to_string()); + (strip_type_prefix(k).to_string(), v) + }) + .collect(); + rows.sort_by(|a, b| a.0.cmp(&b.0)); + + rsx! { + table { + thead { + tr { + th { "Key" } + th { "Value" } + } + } + tbody { + if rows.is_empty() { + tr { + td { colspan: "2", "No entries found." } + } + } + for (k, v) in rows { + tr { + key: "{k}", + td { "{k}" } + td { "{v}" } + } + } + } + } + } + } + } + } + + // Toast notifications (fixed, top-right) + div { class: "toast-stack", + match &*set_result.read() { + Some(Ok(resp)) => rsx! { div { class: "toast", "Stored \"{strip_type_prefix(&resp.key)}\"" } }, + Some(Err(e)) => rsx! { div { class: "toast error", "Set error: {e}" } }, + None => rsx! {}, + } + match &*get_result.read() { + Some(Err(e)) => rsx! { div { class: "toast error", "Get error: {e}" } }, + _ => rsx! {}, + } + } + } +} + +#[cfg(feature = "web")] +fn list_request() -> hook::core_registry_key_value_v1::ListRequest { + hook::core_registry_key_value_v1::ListRequest { + value: Some(prost_types::Any { + type_url: VALUE_TYPE_URL.to_string(), + value: vec![], + }), + } +} diff --git a/api/src/hook/core.control_plane.networking.v1.dx.rs b/api/src/hook/core.control_plane.networking.v1.dx.rs new file mode 100644 index 00000000..c496a16d --- /dev/null +++ b/api/src/hook/core.control_plane.networking.v1.dx.rs @@ -0,0 +1,35 @@ +mod proto { + pub use crate::proto::core_control_plane_networking_v1::*; +} +pub use proto::*; +use ::dioxus::prelude::*; + +pub struct NetworkingServiceServiceHook(proto::networking_service_client::NetworkingServiceClient<::tonic_web_wasm_client::Client>); + +pub fn use_networking_service_service() -> NetworkingServiceServiceHook { + NetworkingServiceServiceHook({ let config = use_context::<::dioxus_grpc::GrpcConfig>(); proto::networking_service_client::NetworkingServiceClient::new(::tonic_web_wasm_client::Client::new(config.host.clone())) }) +} + +impl NetworkingServiceServiceHook { + pub fn add_route(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.add_route(req()).await.map(|resp| resp.into_inner()) } + }) + } + pub fn list_routes(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.list_routes(req()).await.map(|resp| resp.into_inner()) } + }) + } + pub fn delete_route(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.delete_route(req()).await.map(|resp| resp.into_inner()) } + }) + } +} \ No newline at end of file diff --git a/api/src/hook/core.message_broker.actors.v1.dx.rs b/api/src/hook/core.message_broker.actors.v1.dx.rs new file mode 100644 index 00000000..a311db5f --- /dev/null +++ b/api/src/hook/core.message_broker.actors.v1.dx.rs @@ -0,0 +1,14 @@ +mod proto { + pub use crate::proto::core_message_broker_actors_v1::*; +} +pub use proto::*; +use ::dioxus::prelude::*; + +pub struct ProducerServiceHook(proto::producer_client::ProducerClient<::tonic_web_wasm_client::Client>); + +pub fn use_producer_service() -> ProducerServiceHook { + ProducerServiceHook({ let config = use_context::<::dioxus_grpc::GrpcConfig>(); proto::producer_client::ProducerClient::new(::tonic_web_wasm_client::Client::new(config.host.clone())) }) +} + +impl ProducerServiceHook { +} \ No newline at end of file diff --git a/api/src/hook/core.registry.key_value.v1.dx.rs b/api/src/hook/core.registry.key_value.v1.dx.rs new file mode 100644 index 00000000..fe69b575 --- /dev/null +++ b/api/src/hook/core.registry.key_value.v1.dx.rs @@ -0,0 +1,42 @@ +mod proto { + pub use crate::proto::core_registry_key_value_v1::*; +} +pub use proto::*; +use ::dioxus::prelude::*; + +pub struct KeyValueServiceServiceHook(proto::key_value_service_client::KeyValueServiceClient<::tonic_web_wasm_client::Client>); + +pub fn use_key_value_service_service() -> KeyValueServiceServiceHook { + KeyValueServiceServiceHook({ let config = use_context::<::dioxus_grpc::GrpcConfig>(); proto::key_value_service_client::KeyValueServiceClient::new(::tonic_web_wasm_client::Client::new(config.host.clone())) }) +} + +impl KeyValueServiceServiceHook { + pub fn set(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.set(req()).await.map(|resp| resp.into_inner()) } + }) + } + pub fn get(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.get(req()).await.map(|resp| resp.into_inner()) } + }) + } + pub fn delete(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.delete(req()).await.map(|resp| resp.into_inner()) } + }) + } + pub fn list(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.list(req()).await.map(|resp| resp.into_inner()) } + }) + } +} \ No newline at end of file diff --git a/api/src/hook/core.registry.service_discovery.v1.dx.rs b/api/src/hook/core.registry.service_discovery.v1.dx.rs new file mode 100644 index 00000000..cb12e31d --- /dev/null +++ b/api/src/hook/core.registry.service_discovery.v1.dx.rs @@ -0,0 +1,42 @@ +mod proto { + pub use crate::proto::core_registry_service_discovery_v1::*; +} +pub use proto::*; +use ::dioxus::prelude::*; + +pub struct ServiceDiscoveryServiceServiceHook(proto::service_discovery_service_client::ServiceDiscoveryServiceClient<::tonic_web_wasm_client::Client>); + +pub fn use_service_discovery_service_service() -> ServiceDiscoveryServiceServiceHook { + ServiceDiscoveryServiceServiceHook({ let config = use_context::<::dioxus_grpc::GrpcConfig>(); proto::service_discovery_service_client::ServiceDiscoveryServiceClient::new(::tonic_web_wasm_client::Client::new(config.host.clone())) }) +} + +impl ServiceDiscoveryServiceServiceHook { + pub fn initialize(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.initialize(req()).await.map(|resp| resp.into_inner()) } + }) + } + pub fn finalize(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.finalize(req()).await.map(|resp| resp.into_inner()) } + }) + } + pub fn report_health(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.report_health(req()).await.map(|resp| resp.into_inner()) } + }) + } + pub fn query(&self, req: Signal) -> Resource> { + let client = self.0.to_owned(); + use_resource(move || { + let mut client = client.clone(); + async move { client.query(req()).await.map(|resp| resp.into_inner()) } + }) + } +} \ No newline at end of file diff --git a/api/src/hook/mod.rs b/api/src/hook/mod.rs new file mode 100644 index 00000000..ad4f4f4d --- /dev/null +++ b/api/src/hook/mod.rs @@ -0,0 +1,8 @@ +#[path = "./core.registry.key_value.v1.dx.rs"] +pub mod core_registry_key_value_v1; +#[path = "./core.registry.service_discovery.v1.dx.rs"] +pub mod core_registry_service_discovery_v1; +#[path = "./core.message_broker.actors.v1.dx.rs"] +pub mod core_message_broker_actors_v1; +#[path = "./core.control_plane.networking.v1.dx.rs"] +pub mod core_control_plane_networking_v1; diff --git a/api/src/lib.rs b/api/src/lib.rs new file mode 100644 index 00000000..2d2ed957 --- /dev/null +++ b/api/src/lib.rs @@ -0,0 +1,4 @@ +#[cfg(feature = "web")] +pub mod proto; +#[cfg(feature = "web")] +pub mod hook; diff --git a/api/src/proto/core.control_plane.networking.v1.rs b/api/src/proto/core.control_plane.networking.v1.rs new file mode 100644 index 00000000..a69fc5eb --- /dev/null +++ b/api/src/proto/core.control_plane.networking.v1.rs @@ -0,0 +1,413 @@ +// This file is @generated by prost-build. +/// AddRouteRequest - Add a route to the networking configuration +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AddRouteRequest { + /// should this be the route type from envoy config. So that I can use the same proto + /// or should I make an internal proto and convert them back and forth + /// An advantage of using the envoy `Route` proto is that it's already ubuqitous in the + /// wild. A disadvantage is that it's a bit more complex than what I need. + #[prost(message, optional, tag = "1")] + pub route: ::core::option::Option, +} +/// AddRouteResponse - Response to adding a route to the networking configuration. Just because a message +/// was received doesn't mean it was successful. The `code` field is used to determine the success of the +/// route entry. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AddRouteResponse { + #[prost(enumeration = "AddRouteResponseCode", tag = "1")] + pub code: i32, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ListRoutesRequest {} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListRoutesResponse { + #[prost(message, repeated, tag = "1")] + pub routes: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct DeleteRouteRequest { + /// route names must be unique making name the primary identifier of a route + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct DeleteRouteResponse { + #[prost(enumeration = "DeleteRouteCode", tag = "1")] + pub code: i32, +} +/// RouteAuth declares the authentication policy for a single route. When absent or +/// enabled=false the route is public and no ext_authz check is performed. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RouteAuth { + #[prost(bool, tag = "1")] + pub enabled: bool, + #[prost(enumeration = "AuthPolicy", tag = "2")] + pub policy: i32, + /// Groups the caller must belong to (AUTH_POLICY_GROUPS). + #[prost(string, repeated, tag = "3")] + pub required_groups: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// OAuth2 scopes required on the token (AUTH_POLICY_SCOPES). + #[prost(string, repeated, tag = "4")] + pub required_scopes: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +/// Route - Close match to the `Route` proto in envoy. Anything that can't be inferred by the draft +/// framework needs to be added by the `process` adding the route configuration. +/// +/// The process will register individual routes, while cluster and virtual host configuration will be handled by the framework. +/// current integration is `process` -> `fuse` -> `envoy` +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Route { + /// Name for the route + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, + /// Route matching parameters + #[prost(message, optional, tag = "2")] + pub r#match: ::core::option::Option, + /// Endpoint parameters + #[prost(message, optional, tag = "3")] + pub endpoint: ::core::option::Option, + /// EnableHTTP2 enables HTTP2 support + #[prost(bool, tag = "4")] + pub enable_http2: bool, + /// Auth declares the authentication policy for this route. Optional; defaults to bypass. + #[prost(message, optional, tag = "5")] + pub auth: ::core::option::Option, +} +/// parameters for the endpoint a route will map to +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Endpoint { + /// host represents the address of the endpoint (upstream). can be either a hostname or an ip address + #[prost(string, tag = "1")] + pub host: ::prost::alloc::string::String, + /// port represents the port on the host of the endpoint (upstream) + #[prost(uint32, tag = "2")] + pub port: u32, +} +/// parameters for matching a route +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RouteMatch { + /// domains for the url a configured in `fuse` but the path to be matched of a route is configured by the `process` + /// (ie. api.draft.com/health -> /health) + #[prost(string, tag = "1")] + pub prefix: ::prost::alloc::string::String, + /// option to match headers of a request + /// TODO -> implement pre 1.0 relase of `fuse` + #[prost(message, optional, tag = "2")] + pub headers: ::core::option::Option, + /// options to simplify the matching of a route for grpc. Most request will be grpc and this configuration + /// makes that integration easier. + /// TODO -> implement pre 1.0 relase of `fuse` + #[prost(message, optional, tag = "3")] + pub grpc_match_options: ::core::option::Option, + /// REF: Envoy + /// Specifies a set of dynamic metadata that a route must match. + /// The router will check the dynamic metadata against all the specified dynamic metadata matchers. + /// If the number of specified dynamic metadata matchers is nonzero, they all must match the + /// dynamic metadata for a match to occur. + /// TODO -> implement pre 2.0 relase of `fuse` + #[prost(message, optional, tag = "4")] + pub dynamic_metadata: ::core::option::Option, + /// Host address for the route + #[prost(string, tag = "5")] + pub host: ::prost::alloc::string::String, +} +/// consider using the `key/value` from `blueprint` key/value store +/// TODO -> implement pre 1.0 relase of `fuse` +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct HeaderMatchOptions { + #[prost(string, tag = "1")] + pub key: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub value: ::prost::alloc::string::String, +} +/// GrpcMatchOptions - Options to simplify the matching of a route for grpc. Most request will be grpc and this configuration +/// should make the integration easier. +/// TODO -> implement pre 1.0 relase of `fuse` +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GrpcMatchOptions {} +/// DynamicMetadata - Specifies a set of dynamic metadata that a route must match. Dynamic metadata can be used in a variety of ways +/// and is a powerful feature of envoy `fuse` will most likely use this feature to add additional information to the route. +/// TODO -> implement pre 2.0 relase of `fuse` +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct DynamicMetadata {} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum AddRouteResponseCode { + InvalidAddRouteResponseCode = 0, + Ok = 1, + Error = 2, + InvalidRequest = 3, +} +impl AddRouteResponseCode { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::InvalidAddRouteResponseCode => "INVALID_ADD_ROUTE_RESPONSE_CODE", + Self::Ok => "OK", + Self::Error => "ERROR", + Self::InvalidRequest => "INVALID_REQUEST", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "INVALID_ADD_ROUTE_RESPONSE_CODE" => Some(Self::InvalidAddRouteResponseCode), + "OK" => Some(Self::Ok), + "ERROR" => Some(Self::Error), + "INVALID_REQUEST" => Some(Self::InvalidRequest), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum DeleteRouteCode { + InvalidDeleteRouteResponseCode = 0, + DeleteRouteOk = 1, + DeleteRouteError = 2, +} +impl DeleteRouteCode { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::InvalidDeleteRouteResponseCode => "INVALID_DELETE_ROUTE_RESPONSE_CODE", + Self::DeleteRouteOk => "DELETE_ROUTE_OK", + Self::DeleteRouteError => "DELETE_ROUTE_ERROR", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "INVALID_DELETE_ROUTE_RESPONSE_CODE" => { + Some(Self::InvalidDeleteRouteResponseCode) + } + "DELETE_ROUTE_OK" => Some(Self::DeleteRouteOk), + "DELETE_ROUTE_ERROR" => Some(Self::DeleteRouteError), + _ => None, + } + } +} +/// AuthPolicy controls how Fuse configures the Envoy ext_authz filter for a route. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum AuthPolicy { + /// No auth check — route is public. + Bypass = 0, + /// Any valid token is accepted. + Authenticated = 1, + /// Token must belong to one of the required_groups. + Groups = 2, + /// Token must carry all of the required_scopes. + Scopes = 3, +} +impl AuthPolicy { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Bypass => "AUTH_POLICY_BYPASS", + Self::Authenticated => "AUTH_POLICY_AUTHENTICATED", + Self::Groups => "AUTH_POLICY_GROUPS", + Self::Scopes => "AUTH_POLICY_SCOPES", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "AUTH_POLICY_BYPASS" => Some(Self::Bypass), + "AUTH_POLICY_AUTHENTICATED" => Some(Self::Authenticated), + "AUTH_POLICY_GROUPS" => Some(Self::Groups), + "AUTH_POLICY_SCOPES" => Some(Self::Scopes), + _ => None, + } + } +} +/// Generated client implementations. +pub mod networking_service_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// An interface to modify the networking configuration of the system. The networking configuration is primarly used to + /// make endpoints available outside of the system (public, or private). To efficiently route traffic to the correct process, the + /// networking configuration is used to configure the `Envoy` proxy. The `Envoy` proxy is used to route traffic to the correct process + /// based on the provided `Route` configuration when the process registers to the system in this case `fuse`. + /// + /// 1. The `NetworkingService` is a `core` service implemented in `fuse` + /// 1. Alot of the networking configuration is specific for `Envoy`. The `Route` proto is an example of this. It's basically a one to one mapping + /// of all fields that can't already be inferred by the `draft` framework. + #[derive(Debug, Clone)] + pub struct NetworkingServiceClient { + inner: tonic::client::Grpc, + } + impl NetworkingServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> NetworkingServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + NetworkingServiceClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Add route exposing an endpoint on the gateway and routing traffic to the correct process + pub async fn add_route( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.control_plane.networking.v1.NetworkingService/AddRoute", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.control_plane.networking.v1.NetworkingService", + "AddRoute", + ), + ); + self.inner.unary(req, path, codec).await + } + /// List all routes in the networking configuration + pub async fn list_routes( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.control_plane.networking.v1.NetworkingService/ListRoutes", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.control_plane.networking.v1.NetworkingService", + "ListRoutes", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Delete a route from the networking configuration, requires the name of the route + /// and returns a response code to indicate the success of the operation + pub async fn delete_route( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.control_plane.networking.v1.NetworkingService/DeleteRoute", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.control_plane.networking.v1.NetworkingService", + "DeleteRoute", + ), + ); + self.inner.unary(req, path, codec).await + } + } +} diff --git a/api/src/proto/core.message_broker.actors.v1.rs b/api/src/proto/core.message_broker.actors.v1.rs new file mode 100644 index 00000000..691ecd5c --- /dev/null +++ b/api/src/proto/core.message_broker.actors.v1.rs @@ -0,0 +1,1343 @@ +// This file is @generated by prost-build. +/// * +/// +/// CloudEvent Protobuf Format +/// +/// * Required context attributes are explicity represented. +/// * Optional and Extension context attributes are carried in a map structure. +/// * Data may be represented as binary, text, or protobuf messages. +/// +/// REF: \[ +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CloudEvent { + /// Required Attributes + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// URI-reference + #[prost(string, tag = "2")] + pub source: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub spec_version: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub r#type: ::prost::alloc::string::String, + /// Optional & Extension Attributes + #[prost(map = "string, message", tag = "5")] + pub attributes: ::std::collections::HashMap< + ::prost::alloc::string::String, + cloud_event::CloudEventAttributeValue, + >, + /// -- CloudEvent Data (Bytes, Text, or Proto) + #[prost(oneof = "cloud_event::Data", tags = "6, 7, 8")] + pub data: ::core::option::Option, +} +/// Nested message and enum types in `CloudEvent`. +pub mod cloud_event { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] + pub struct CloudEventAttributeValue { + #[prost( + oneof = "cloud_event_attribute_value::Attr", + tags = "1, 2, 3, 4, 5, 6, 7" + )] + pub attr: ::core::option::Option, + } + /// Nested message and enum types in `CloudEventAttributeValue`. + pub mod cloud_event_attribute_value { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Attr { + #[prost(bool, tag = "1")] + CeBoolean(bool), + #[prost(int32, tag = "2")] + CeInteger(i32), + #[prost(string, tag = "3")] + CeString(::prost::alloc::string::String), + #[prost(bytes, tag = "4")] + CeBytes(::prost::alloc::vec::Vec), + #[prost(string, tag = "5")] + CeUri(::prost::alloc::string::String), + #[prost(string, tag = "6")] + CeUriRef(::prost::alloc::string::String), + #[prost(message, tag = "7")] + CeTimestamp(::prost_types::Timestamp), + } + } + /// -- CloudEvent Data (Bytes, Text, or Proto) + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Data { + #[prost(bytes, tag = "6")] + BinaryData(::prost::alloc::vec::Vec), + #[prost(string, tag = "7")] + TextData(::prost::alloc::string::String), + #[prost(message, tag = "8")] + ProtoData(::prost_types::Any), + } +} +/// * +/// +/// CloudEvent Protobuf Batch Format +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CloudEventBatch { + #[prost(message, repeated, tag = "1")] + pub events: ::prost::alloc::vec::Vec, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetTopologyRequest {} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetTopologyResponse { + #[prost(message, repeated, tag = "1")] + pub producers: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "2")] + pub consumers: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "3")] + pub edges: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct TopologyNode { + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub name: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct TopologyEdge { + #[prost(string, tag = "1")] + pub producer_source: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub consumer_source: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub event_type: ::prost::alloc::string::String, + #[prost(uint32, tag = "4")] + pub vol: u32, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct WatchTopologyRequest {} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct WatchTopologyResponse { + #[prost(oneof = "watch_topology_response::Event", tags = "1, 2, 3")] + pub event: ::core::option::Option, +} +/// Nested message and enum types in `WatchTopologyResponse`. +pub mod watch_topology_response { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Event { + #[prost(message, tag = "1")] + ConsumerConnected(super::TopologyNode), + #[prost(message, tag = "2")] + ConsumerDisconnected(super::TopologyNode), + #[prost(message, tag = "3")] + ProducerAppeared(super::TopologyNode), + } +} +/// Generated client implementations. +pub mod topology_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct TopologyClient { + inner: tonic::client::Grpc, + } + impl TopologyClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> TopologyClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + TopologyClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// GetTopology returns a snapshot of the current event topology: producers + /// derived from ClickHouse distinct sources, consumers and edges derived from + /// live ConsumeRequest registrations tracked in the broker's atomicMap. + pub async fn get_topology( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.message_broker.actors.v1.Topology/GetTopology", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.message_broker.actors.v1.Topology", + "GetTopology", + ), + ); + self.inner.unary(req, path, codec).await + } + /// WatchTopology streams incremental topology deltas as consumers connect or + /// disconnect and as new producer sources appear in the event store. + pub async fn watch_topology( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.message_broker.actors.v1.Topology/WatchTopology", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.message_broker.actors.v1.Topology", + "WatchTopology", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetTopicSeriesRequest { + #[prost(string, tag = "1")] + pub event_type: ::prost::alloc::string::String, + #[prost(int32, tag = "2")] + pub window_seconds: i32, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SeriesPoint { + #[prost(int64, tag = "1")] + pub timestamp_ms: i64, + #[prost(uint32, tag = "2")] + pub count: u32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetTopicSeriesResponse { + #[prost(message, repeated, tag = "1")] + pub points: ::prost::alloc::vec::Vec, + #[prost(int32, tag = "2")] + pub bucket_secs: i32, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetMetricsRequest { + /// window_seconds is the lookback window for all metrics. 0 defaults to 300 (5 min). + #[prost(int32, tag = "1")] + pub window_seconds: i32, +} +/// EdgeVolume reports the event count for one (source, event_type) pair. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct EdgeVolume { + #[prost(string, tag = "1")] + pub source: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub event_type: ::prost::alloc::string::String, + #[prost(uint32, tag = "3")] + pub count: u32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetMetricsResponse { + #[prost(message, repeated, tag = "1")] + pub edge_volumes: ::prost::alloc::vec::Vec, + #[prost(double, tag = "2")] + pub median_latency_ms: f64, + #[prost(double, tag = "3")] + pub p95_latency_ms: f64, + #[prost(uint32, tag = "4")] + pub total_messages_per_min: u32, +} +/// Generated client implementations. +pub mod metrics_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct MetricsClient { + inner: tonic::client::Grpc, + } + impl MetricsClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> MetricsClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + MetricsClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// GetMetrics returns pre-computed throughput and latency metrics derived from + /// ClickHouse aggregates over the requested time window. + pub async fn get_metrics( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.message_broker.actors.v1.Metrics/GetMetrics", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.message_broker.actors.v1.Metrics", + "GetMetrics", + ), + ); + self.inner.unary(req, path, codec).await + } + /// GetTopicSeries returns a time-bucketed message count for one event_type, + /// suitable for rendering a line chart over the requested window. + pub async fn get_topic_series( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.message_broker.actors.v1.Metrics/GetTopicSeries", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.message_broker.actors.v1.Metrics", + "GetTopicSeries", + ), + ); + self.inner.unary(req, path, codec).await + } + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryRequest { + #[prost(message, optional, tag = "1")] + pub expression: ::core::option::Option, + /// 0 = server default; caps historical replay for QueryStream + #[prost(int32, tag = "2")] + pub limit: i32, + /// ISO 8601 timestamp — replay events after this point before going live + #[prost(string, tag = "3")] + pub after: ::prost::alloc::string::String, + #[prost(enumeration = "OrderDirection", tag = "4")] + pub order_by: i32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryResponse { + #[prost(message, repeated, tag = "1")] + pub events: ::prost::alloc::vec::Vec, +} +/// One event per stream message so the web-client can render each event as it +/// arrives rather than waiting for a batch. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryStreamResponse { + #[prost(message, optional, tag = "1")] + pub event: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Expression { + #[prost(oneof = "expression::Expr", tags = "1, 2, 3, 4, 5, 6, 7, 8")] + pub expr: ::core::option::Option, +} +/// Nested message and enum types in `Expression`. +pub mod expression { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Expr { + #[prost(message, tag = "1")] + Literal(super::Literal), + #[prost(message, tag = "2")] + Attribute(super::AttributeRef), + #[prost(message, tag = "3")] + Unary(::prost::alloc::boxed::Box), + #[prost(message, tag = "4")] + Binary(::prost::alloc::boxed::Box), + #[prost(message, tag = "5")] + Like(::prost::alloc::boxed::Box), + #[prost(message, tag = "6")] + Exists(super::ExistsExpr), + #[prost(message, tag = "7")] + In(::prost::alloc::boxed::Box), + #[prost(message, tag = "8")] + FunctionCall(super::FunctionCall), + } +} +/// The three primitive types defined by the CESQL type system. +/// URI, URI-Reference, and Timestamp are represented as string_value. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Literal { + #[prost(oneof = "literal::Value", tags = "1, 2, 3")] + pub value: ::core::option::Option, +} +/// Nested message and enum types in `Literal`. +pub mod literal { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Value { + #[prost(int32, tag = "1")] + IntegerValue(i32), + #[prost(bool, tag = "2")] + BoolValue(bool), + #[prost(string, tag = "3")] + StringValue(::prost::alloc::string::String), + } +} +/// References a CloudEvent context attribute or extension by name. +/// +/// Required attributes (always present): id, source, specversion, type +/// Optional attributes: datacontenttype, dataschema, subject, time +/// Extensions: any custom attribute added by the event producer +/// +/// A missing optional or extension attribute evaluates to the zero value of the +/// subexpression return type and raises MissingAttributeError per the spec. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AttributeRef { + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UnaryExpr { + #[prost(enumeration = "UnaryOp", tag = "1")] + pub op: i32, + #[prost(message, optional, boxed, tag = "2")] + pub operand: ::core::option::Option<::prost::alloc::boxed::Box>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BinaryExpr { + #[prost(message, optional, boxed, tag = "1")] + pub left: ::core::option::Option<::prost::alloc::boxed::Box>, + #[prost(enumeration = "BinaryOp", tag = "2")] + pub op: i32, + #[prost(message, optional, boxed, tag = "3")] + pub right: ::core::option::Option<::prost::alloc::boxed::Box>, +} +/// String × String → Boolean +/// Pattern syntax: % matches any sequence of characters, +/// \_ matches exactly one character, +/// \\ escapes a literal % or \_. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LikeExpr { + #[prost(message, optional, boxed, tag = "1")] + pub operand: ::core::option::Option<::prost::alloc::boxed::Box>, + /// string literal containing the LIKE pattern + #[prost(string, tag = "2")] + pub pattern: ::prost::alloc::string::String, + /// true → NOT LIKE + #[prost(bool, tag = "3")] + pub negated: bool, +} +/// Returns true if the named attribute is present on the CloudEvent. +/// Always evaluates true for the four required attributes. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ExistsExpr { + #[prost(string, tag = "1")] + pub attribute: ::prost::alloc::string::String, +} +/// expression IN (e1, e2, ...) → Boolean +/// The values set must contain at least one element. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct InExpr { + #[prost(message, optional, boxed, tag = "1")] + pub operand: ::core::option::Option<::prost::alloc::boxed::Box>, + #[prost(message, repeated, tag = "2")] + pub values: ::prost::alloc::vec::Vec, + /// true → NOT IN + #[prost(bool, tag = "3")] + pub negated: bool, +} +/// All built-in CESQL functions are enumerated here. The argument count and +/// types for each function are documented below and enforced at evaluation time. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FunctionCall { + #[prost(enumeration = "BuiltinFunction", tag = "1")] + pub function: i32, + #[prost(message, repeated, tag = "2")] + pub args: ::prost::alloc::vec::Vec, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum OrderDirection { + /// treated as ASC + Unspecified = 0, + Asc = 1, + Desc = 2, +} +impl OrderDirection { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "ORDER_DIRECTION_UNSPECIFIED", + Self::Asc => "ORDER_DIRECTION_ASC", + Self::Desc => "ORDER_DIRECTION_DESC", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ORDER_DIRECTION_UNSPECIFIED" => Some(Self::Unspecified), + "ORDER_DIRECTION_ASC" => Some(Self::Asc), + "ORDER_DIRECTION_DESC" => Some(Self::Desc), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum UnaryOp { + Unspecified = 0, + /// Boolean → Boolean + Not = 1, + /// Integer → Integer (unary minus) + Negate = 2, +} +impl UnaryOp { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "UNARY_OP_UNSPECIFIED", + Self::Not => "UNARY_OP_NOT", + Self::Negate => "UNARY_OP_NEGATE", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "UNARY_OP_UNSPECIFIED" => Some(Self::Unspecified), + "UNARY_OP_NOT" => Some(Self::Not), + "UNARY_OP_NEGATE" => Some(Self::Negate), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum BinaryOp { + Unspecified = 0, + /// Logical — Boolean × Boolean → Boolean + /// AND and OR short-circuit per the spec. + And = 1, + Or = 2, + Xor = 3, + /// Equality — Boolean | Integer | String × same → Boolean + /// + /// = + Eq = 4, + /// != or \<\> (both map to this variant) + Neq = 5, + /// Ordered comparison — Integer × Integer → Boolean + /// + /// \< + Lt = 6, + /// \<= + Lte = 7, + /// + /// > + Gt = 8, + /// + /// > + /// > = + Gte = 9, + /// Arithmetic — Integer × Integer → Integer + /// Division and modulo by zero return 0 and raise MathError per the spec. + /// + /// * + Add = 10, + /// * + Sub = 11, + /// * + Mul = 12, + /// / + Div = 13, + /// % + Mod = 14, +} +impl BinaryOp { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "BINARY_OP_UNSPECIFIED", + Self::And => "BINARY_OP_AND", + Self::Or => "BINARY_OP_OR", + Self::Xor => "BINARY_OP_XOR", + Self::Eq => "BINARY_OP_EQ", + Self::Neq => "BINARY_OP_NEQ", + Self::Lt => "BINARY_OP_LT", + Self::Lte => "BINARY_OP_LTE", + Self::Gt => "BINARY_OP_GT", + Self::Gte => "BINARY_OP_GTE", + Self::Add => "BINARY_OP_ADD", + Self::Sub => "BINARY_OP_SUB", + Self::Mul => "BINARY_OP_MUL", + Self::Div => "BINARY_OP_DIV", + Self::Mod => "BINARY_OP_MOD", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "BINARY_OP_UNSPECIFIED" => Some(Self::Unspecified), + "BINARY_OP_AND" => Some(Self::And), + "BINARY_OP_OR" => Some(Self::Or), + "BINARY_OP_XOR" => Some(Self::Xor), + "BINARY_OP_EQ" => Some(Self::Eq), + "BINARY_OP_NEQ" => Some(Self::Neq), + "BINARY_OP_LT" => Some(Self::Lt), + "BINARY_OP_LTE" => Some(Self::Lte), + "BINARY_OP_GT" => Some(Self::Gt), + "BINARY_OP_GTE" => Some(Self::Gte), + "BINARY_OP_ADD" => Some(Self::Add), + "BINARY_OP_SUB" => Some(Self::Sub), + "BINARY_OP_MUL" => Some(Self::Mul), + "BINARY_OP_DIV" => Some(Self::Div), + "BINARY_OP_MOD" => Some(Self::Mod), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum BuiltinFunction { + FunctionUnspecified = 0, + /// LENGTH(x: String) → Integer + /// Returns the number of characters in x. + FunctionLength = 1, + /// CONCAT(x1, x2, ...: String) → String + /// Returns the concatenation of all arguments. Zero args returns "". + FunctionConcat = 2, + /// CONCAT_WS(delimiter: String, x1, x2, ...: String) → String + /// Returns arguments joined by delimiter. Zero value args returns "". + FunctionConcatWs = 3, + /// LOWER(x: String) → String + FunctionLower = 4, + /// UPPER(x: String) → String + FunctionUpper = 5, + /// TRIM(x: String) → String + /// Removes leading and trailing Unicode whitespace. + FunctionTrim = 6, + /// LEFT(x: String, n: Integer) → String + /// Returns the first n characters. Returns x when LENGTH(x) \<= n. + /// Returns x + FunctionEvaluationError when n \< 0. + FunctionLeft = 7, + /// RIGHT(x: String, n: Integer) → String + /// Returns the last n characters. Returns x when LENGTH(x) \<= n. + /// Returns x + FunctionEvaluationError when n \< 0. + FunctionRight = 8, + /// SUBSTRING(x: String, pos: Integer) → String + /// SUBSTRING(x: String, pos: Integer, len: Integer) → String + /// 1-indexed. Negative pos counts from the end. pos=0 returns "". + /// Returns "" + FunctionEvaluationError when |pos| > LENGTH(x) or len \< 0. + FunctionSubstring = 9, + /// ABS(x: Integer) → Integer + /// Returns the absolute value of x. + /// ABS(-2147483648) returns 2147483647 + MathError per the spec. + FunctionAbs = 10, +} +impl BuiltinFunction { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::FunctionUnspecified => "FUNCTION_UNSPECIFIED", + Self::FunctionLength => "FUNCTION_LENGTH", + Self::FunctionConcat => "FUNCTION_CONCAT", + Self::FunctionConcatWs => "FUNCTION_CONCAT_WS", + Self::FunctionLower => "FUNCTION_LOWER", + Self::FunctionUpper => "FUNCTION_UPPER", + Self::FunctionTrim => "FUNCTION_TRIM", + Self::FunctionLeft => "FUNCTION_LEFT", + Self::FunctionRight => "FUNCTION_RIGHT", + Self::FunctionSubstring => "FUNCTION_SUBSTRING", + Self::FunctionAbs => "FUNCTION_ABS", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "FUNCTION_UNSPECIFIED" => Some(Self::FunctionUnspecified), + "FUNCTION_LENGTH" => Some(Self::FunctionLength), + "FUNCTION_CONCAT" => Some(Self::FunctionConcat), + "FUNCTION_CONCAT_WS" => Some(Self::FunctionConcatWs), + "FUNCTION_LOWER" => Some(Self::FunctionLower), + "FUNCTION_UPPER" => Some(Self::FunctionUpper), + "FUNCTION_TRIM" => Some(Self::FunctionTrim), + "FUNCTION_LEFT" => Some(Self::FunctionLeft), + "FUNCTION_RIGHT" => Some(Self::FunctionRight), + "FUNCTION_SUBSTRING" => Some(Self::FunctionSubstring), + "FUNCTION_ABS" => Some(Self::FunctionAbs), + _ => None, + } + } +} +/// Generated client implementations. +pub mod query_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct QueryClient { + inner: tonic::client::Grpc, + } + impl QueryClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> QueryClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + QueryClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Query executes a CESQL expression against stored events and returns all + /// matching results in a single response. + pub async fn query( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.message_broker.actors.v1.Query/Query", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("core.message_broker.actors.v1.Query", "Query")); + self.inner.unary(req, path, codec).await + } + /// QueryStream opens a persistent server-sent stream. The server first + /// replays any stored events that match the expression (subject to `limit` + /// and `after`), then continues streaming live events as they flow through + /// catalyst in real time. The stream stays open until the client closes it. + pub async fn query_stream( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.message_broker.actors.v1.Query/QueryStream", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("core.message_broker.actors.v1.Query", "QueryStream"), + ); + self.inner.server_streaming(req, path, codec).await + } + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ConsumeRequest { + #[prost(message, optional, tag = "1")] + pub message: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ConsumeResponse { + #[prost(message, optional, tag = "1")] + pub message: ::core::option::Option, +} +/// Generated client implementations. +pub mod consumer_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct ConsumerClient { + inner: tonic::client::Grpc, + } + impl ConsumerClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> ConsumerClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + ConsumerClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn consume( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.message_broker.actors.v1.Consumer/Consume", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("core.message_broker.actors.v1.Consumer", "Consume"), + ); + self.inner.server_streaming(req, path, codec).await + } + } +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetResourceMetricsRequest {} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct GetResourceMetricsResponse { + /// Throughput counters — cumulative since process start. + #[prost(uint64, tag = "1")] + pub messages_published_total: u64, + #[prost(uint64, tag = "2")] + pub messages_dropped_total: u64, + /// Ingest buffer — current depth vs max capacity of the store channel. + #[prost(uint32, tag = "3")] + pub queue_depth: u32, + #[prost(uint32, tag = "4")] + pub queue_capacity: u32, + /// Live connection counts. + #[prost(uint32, tag = "5")] + pub active_consumers: u32, + #[prost(uint32, tag = "6")] + pub active_producers: u32, + /// Store flush performance. + #[prost(double, tag = "7")] + pub store_flush_p95_ms: f64, + #[prost(uint32, tag = "8")] + pub store_flush_count: u32, +} +/// Generated client implementations. +pub mod resource_metrics_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct ResourceMetricsClient { + inner: tonic::client::Grpc, + } + impl ResourceMetricsClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> ResourceMetricsClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + ResourceMetricsClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn get_resource_metrics( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.message_broker.actors.v1.ResourceMetrics/GetResourceMetrics", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.message_broker.actors.v1.ResourceMetrics", + "GetResourceMetrics", + ), + ); + self.inner.unary(req, path, codec).await + } + } +} +/// Send this `Message` to the other `Actors` in the system that are subscribed to this `Message` +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ProduceRequest { + #[prost(message, optional, tag = "1")] + pub message: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ProduceResponse { + /// The message id is returned as a way to acknowledge the message as been committed + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, +} +/// Generated client implementations. +pub mod producer_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct ProducerClient { + inner: tonic::client::Grpc, + } + impl ProducerClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> ProducerClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + ProducerClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn produce( + &mut self, + request: impl tonic::IntoStreamingRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.message_broker.actors.v1.Producer/Produce", + ); + let mut req = request.into_streaming_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("core.message_broker.actors.v1.Producer", "Produce"), + ); + self.inner.streaming(req, path, codec).await + } + } +} diff --git a/api/src/proto/core.registry.key_value.v1.rs b/api/src/proto/core.registry.key_value.v1.rs new file mode 100644 index 00000000..e4b4570c --- /dev/null +++ b/api/src/proto/core.registry.key_value.v1.rs @@ -0,0 +1,371 @@ +// This file is @generated by prost-build. +/// Value - The message that is used to save a value in the `key_value` store. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Value { + #[prost(string, tag = "1")] + pub data: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct NodePosition { + #[prost(float, tag = "1")] + pub x: f32, + #[prost(float, tag = "2")] + pub y: f32, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClusterLayout { + /// Node label → canvas position. Keyed by label so layout is resilient + /// to nodes being added or removed from the graph. + #[prost(map = "string, message", tag = "1")] + pub positions: ::std::collections::HashMap< + ::prost::alloc::string::String, + NodePosition, + >, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SetRequest { + #[prost(string, tag = "1")] + pub key: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub value: ::core::option::Option<::prost_types::Any>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SetResponse { + #[prost(string, tag = "1")] + pub key: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetRequest { + #[prost(string, tag = "1")] + pub key: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub value: ::core::option::Option<::prost_types::Any>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetResponse { + #[prost(message, optional, tag = "1")] + pub value: ::core::option::Option<::prost_types::Any>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct DeleteRequest { + #[prost(string, tag = "1")] + pub key: ::prost::alloc::string::String, + /// value is only used to determine the underlying type, the content within the type does not matter + #[prost(message, optional, tag = "2")] + pub value: ::core::option::Option<::prost_types::Any>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct DeleteResponse { + #[prost(string, tag = "1")] + pub key: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ListRequest { + #[prost(message, optional, tag = "1")] + pub value: ::core::option::Option<::prost_types::Any>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListResponse { + #[prost(map = "string, message", tag = "2")] + pub values: ::std::collections::HashMap< + ::prost::alloc::string::String, + ::prost_types::Any, + >, +} +/// Generated client implementations. +pub mod key_value_service_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct KeyValueServiceClient { + inner: tonic::client::Grpc, + } + impl KeyValueServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> KeyValueServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + KeyValueServiceClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// SET - A key/val pair + pub async fn set( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.registry.key_value.v1.KeyValueService/Set", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("core.registry.key_value.v1.KeyValueService", "Set"), + ); + self.inner.unary(req, path, codec).await + } + /// GET - A key/val pair + pub async fn get( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.registry.key_value.v1.KeyValueService/Get", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("core.registry.key_value.v1.KeyValueService", "Get"), + ); + self.inner.unary(req, path, codec).await + } + /// DELETE - remove a key, and it's associated value + pub async fn delete( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.registry.key_value.v1.KeyValueService/Delete", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.registry.key_value.v1.KeyValueService", + "Delete", + ), + ); + self.inner.unary(req, path, codec).await + } + /// List accepts a type to search the key_value store for all keys + /// matching that type, if any are found they will all be returned + /// as a map. + pub async fn list( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.registry.key_value.v1.KeyValueService/List", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("core.registry.key_value.v1.KeyValueService", "List"), + ); + self.inner.unary(req, path, codec).await + } + } +} +/// Standard ID to be used in the whole system +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Id { + /// generated system uuid + #[prost(string, tag = "1")] + pub uuid: ::prost::alloc::string::String, +} +/// Statement is the root node of the query. It's the entry point to the query system. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Statement { + /// select * from `kind` + #[prost(message, optional, tag = "1")] + pub kind: ::core::option::Option<::prost_types::Any>, + /// The operation to perform on the `kind` object + #[prost(enumeration = "Operation", tag = "2")] + pub operation: i32, + /// The `where` clause is used to filter the results of the query. + #[prost(oneof = "statement::Where", tags = "3, 4, 5")] + pub r#where: ::core::option::Option, +} +/// Nested message and enum types in `Statement`. +pub mod statement { + /// The `where` clause is used to filter the results of the query. + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Where { + /// return all `kinds` - `select * from `courses\` + #[prost(bool, tag = "3")] + IsAll(bool), + /// return a `kind` that matches the `ID` - \`select * from courses where id = "123" + #[prost(message, tag = "4")] + Id(super::Id), + /// return all `kind`'s that equal the key/value pairs fields + /// `select * from courses where name = "Payne Stewart"` + #[prost(message, tag = "5")] + KeyVal(super::Equal), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Equal { + /// of the `Kind` being queried return the values that match the key/value pairs below + #[prost(map = "string, string", tag = "1")] + pub r#match: ::std::collections::HashMap< + ::prost::alloc::string::String, + ::prost::alloc::string::String, + >, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum Operation { + /// No operation is specified, this is the default value. + None = 0, + /// Select is a query that can be used to search for specific objects in `blueprint`. + /// A kind is supplied to the query and it can be used to return all objects of that kind. + /// A singular `Where` clause is used to filter the results. + /// + /// `select * from `kind` where id = "123"` + Select = 1, + /// `delete from `kind` where id = "123"` + Delete = 2, + /// `update `kind` set name = "new name" where id = "123"` + Update = 3, + /// `insert into `kind` (name, description) values ("new name", "new description")` + Insert = 4, +} +impl Operation { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::None => "NONE", + Self::Select => "SELECT", + Self::Delete => "DELETE", + Self::Update => "UPDATE", + Self::Insert => "INSERT", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "NONE" => Some(Self::None), + "SELECT" => Some(Self::Select), + "DELETE" => Some(Self::Delete), + "UPDATE" => Some(Self::Update), + "INSERT" => Some(Self::Insert), + _ => None, + } + } +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct NavigationItem { + #[prost(string, tag = "1")] + pub label: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub path: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NavigationSection { + #[prost(string, tag = "1")] + pub label: ::prost::alloc::string::String, + #[prost(message, repeated, tag = "2")] + pub items: ::prost::alloc::vec::Vec, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NavigationConfig { + #[prost(message, repeated, tag = "1")] + pub sections: ::prost::alloc::vec::Vec, +} diff --git a/api/src/proto/core.registry.service_discovery.v1.rs b/api/src/proto/core.registry.service_discovery.v1.rs new file mode 100644 index 00000000..34aaff5d --- /dev/null +++ b/api/src/proto/core.registry.service_discovery.v1.rs @@ -0,0 +1,605 @@ +// This file is @generated by prost-build. +/// Entities +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Zone {} +/// ProcessIdentity - +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ProcessIdentity { + /// the process_id is assigned when the join request is successful + /// however it does not mean that the process registered, running + /// and in a stage ready to receive traffic + #[prost(string, tag = "1")] + pub pid: ::prost::alloc::string::String, + /// the address the registering process must stream it's health, and status messages to + #[prost(string, tag = "2")] + pub registry_address: ::prost::alloc::string::String, + /// authentication credentials that must be added to each request to the registry + /// + /// The `nonce` is not added to this message b/c it's added to the service environment + /// the and the chassis is responsible for reading at startup. + /// `nonce` maybe replaced with `cert` + #[prost(message, optional, tag = "3")] + pub token: ::core::option::Option, +} +/// configuration the registry is giving to the process to run +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct StartupConfiguration { + #[prost(uint32, tag = "1")] + pub assigned_port: u32, +} +/// A process is a running program on a computer. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Process { + /// pid - is a uuid to identify each process of the system normally + /// this would follow the normal `id` naming convention. But given + /// a `pid` in most systems is very specific, that tradition will be + /// carried on. + #[prost(string, tag = "1")] + pub pid: ::prost::alloc::string::String, + /// name is not required to be unique between other processes. The `pid` + /// is the specific identifier used to lookup a single process.s + #[prost(string, tag = "2")] + pub name: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub group: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub local: ::prost::alloc::string::String, + /// port? + #[prost(string, tag = "5")] + pub ip_address: ::prost::alloc::string::String, + #[prost(enumeration = "ProcessKind", tag = "6")] + pub process_kind: i32, + #[prost(message, repeated, tag = "7")] + pub metadata: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "8")] + pub location: ::core::option::Option, + #[prost(message, optional, tag = "9")] + pub joined_time: ::core::option::Option<::prost_types::Timestamp>, + #[prost(message, optional, tag = "10")] + pub left_time: ::core::option::Option<::prost_types::Timestamp>, + #[prost(message, optional, tag = "11")] + pub last_status_time: ::core::option::Option<::prost_types::Timestamp>, + #[prost(enumeration = "ProcessRunningState", tag = "12")] + pub running_state: i32, + #[prost(enumeration = "ProcessHealthState", tag = "13")] + pub health_state: i32, + #[prost(message, optional, tag = "14")] + pub token: ::core::option::Option, +} +/// Associated data that can be used to lookup the process +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Metadata { + #[prost(string, tag = "1")] + pub pid: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub key: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub value: ::prost::alloc::string::String, +} +/// GeoPoint - Is the location of something using standard lat/lng notion. +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct GeoPoint { + #[prost(float, tag = "1")] + pub lat: f32, + #[prost(float, tag = "2")] + pub lng: f32, +} +/// Token that is generated when the `Init` function is called with the correct `nonce` +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Token { + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub jwt: ::prost::alloc::string::String, +} +/// Server currently falls into a category that is consuming requests from the outside world +/// the `Job` is something that is private and not serving any external requests. I could however +/// be pulling messages from a message queue, and or doing some batch processing. I.e. some sort of +/// training. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ProcessKind { + InvalidProcessKind = 0, + ServerProcess = 1, + JobProcess = 2, +} +impl ProcessKind { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::InvalidProcessKind => "INVALID_PROCESS_KIND", + Self::ServerProcess => "SERVER_PROCESS", + Self::JobProcess => "JOB_PROCESS", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "INVALID_PROCESS_KIND" => Some(Self::InvalidProcessKind), + "SERVER_PROCESS" => Some(Self::ServerProcess), + "JOB_PROCESS" => Some(Self::JobProcess), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ProcessRunningState { + InvalidProcessRunningState = 0, + ProcessStarting = 1, + ProcessTesting = 2, + ProcessRunning = 3, + ProcessDiconnected = 4, +} +impl ProcessRunningState { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::InvalidProcessRunningState => "INVALID_PROCESS_RUNNING_STATE", + Self::ProcessStarting => "PROCESS_STARTING", + Self::ProcessTesting => "PROCESS_TESTING", + Self::ProcessRunning => "PROCESS_RUNNING", + Self::ProcessDiconnected => "PROCESS_DICONNECTED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "INVALID_PROCESS_RUNNING_STATE" => Some(Self::InvalidProcessRunningState), + "PROCESS_STARTING" => Some(Self::ProcessStarting), + "PROCESS_TESTING" => Some(Self::ProcessTesting), + "PROCESS_RUNNING" => Some(Self::ProcessRunning), + "PROCESS_DICONNECTED" => Some(Self::ProcessDiconnected), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ProcessHealthState { + InvalidProcessHealthState = 0, + ProcessHealthy = 1, + ProcessUnhealthy = 2, +} +impl ProcessHealthState { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::InvalidProcessHealthState => "INVALID_PROCESS_HEALTH_STATE", + Self::ProcessHealthy => "PROCESS_HEALTHY", + Self::ProcessUnhealthy => "PROCESS_UNHEALTHY", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "INVALID_PROCESS_HEALTH_STATE" => Some(Self::InvalidProcessHealthState), + "PROCESS_HEALTHY" => Some(Self::ProcessHealthy), + "PROCESS_UNHEALTHY" => Some(Self::ProcessUnhealthy), + _ => None, + } + } +} +/// ProcessDetails - Messages that are sent from the `Process` to the registry. +/// These details are basic operating messages +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClientDetails { + #[prost(string, tag = "1")] + pub pid: ::prost::alloc::string::String, + /// Ops details + #[prost(enumeration = "ProcessRunningState", tag = "2")] + pub running_state: i32, + #[prost(enumeration = "ProcessHealthState", tag = "3")] + pub health_state: i32, + #[prost(enumeration = "ProcessKind", tag = "4")] + pub process_kind: i32, + /// only check the token when a `ProcessDetails` message is received. + #[prost(string, tag = "5")] + pub token: ::prost::alloc::string::String, + #[prost(message, optional, tag = "7")] + pub location: ::core::option::Option, + #[prost(message, repeated, tag = "8")] + pub metadata: ::prost::alloc::vec::Vec, + #[prost(string, tag = "9")] + pub advertise_address: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClusterDetails { + #[prost(message, repeated, tag = "1")] + pub nodes: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Node { + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub address: ::prost::alloc::string::String, + #[prost(enumeration = "LeadershipStatus", tag = "3")] + pub leadership_status: i32, +} +/// InitRequest - Begin the service registry registration flow. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct InitializeRequest { + /// Name of the process to be registered. This field is not required to be unique with the other processes in the registry + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, + /// A token will not be issued, and a process will not be able to connect to the `SystemJournal` if the `nonce` is not signed with the correct public key + #[prost(string, tag = "2")] + pub nonce: ::prost::alloc::string::String, +} +/// InitResponse - Details used by the client to provided to complete the connection +/// If the token is lost and the registry has not received a `ProcessDetails` message within a 2 mintues +/// of the token being forged then the client will have to reinit to connect to the registry/system. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct InitializeResponse { + /// If the init request was succesful then an identity will be given to the process so that it + /// can stream it's operational details to the registry + #[prost(message, optional, tag = "1")] + pub process_identity: ::core::option::Option, + /// Startup configuration + #[prost(message, optional, tag = "2")] + pub configuration: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct QueryRequest { + #[prost(message, optional, tag = "1")] + pub filter: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Filter { + #[prost(oneof = "filter::Attribute", tags = "1, 2, 3")] + pub attribute: ::core::option::Option, +} +/// Nested message and enum types in `Filter`. +pub mod filter { + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Attribute { + #[prost(string, tag = "1")] + Id(::prost::alloc::string::String), + #[prost(string, tag = "2")] + Group(::prost::alloc::string::String), + #[prost(string, tag = "3")] + All(::prost::alloc::string::String), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryResponse { + #[prost(map = "string, message", tag = "1")] + pub data: ::std::collections::HashMap<::prost::alloc::string::String, Process>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct FinalizeRequest { + #[prost(string, tag = "1")] + pub pid: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct FinalizeResponse { + #[prost(string, tag = "1")] + pub pid: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ReportHealthRequest {} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ReportHealthResponse {} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct WatchRequest {} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct WatchResponse { + #[prost(message, optional, tag = "1")] + pub process: ::core::option::Option, + #[prost(bool, tag = "2")] + pub removed: bool, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum LeadershipStatus { + Unspecified = 0, + Leader = 1, + Follower = 2, +} +impl LeadershipStatus { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "LEADERSHIP_STATUS_UNSPECIFIED", + Self::Leader => "LEADERSHIP_STATUS_LEADER", + Self::Follower => "LEADERSHIP_STATUS_FOLLOWER", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "LEADERSHIP_STATUS_UNSPECIFIED" => Some(Self::Unspecified), + "LEADERSHIP_STATUS_LEADER" => Some(Self::Leader), + "LEADERSHIP_STATUS_FOLLOWER" => Some(Self::Follower), + _ => None, + } + } +} +/// Generated client implementations. +pub mod service_discovery_service_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// An interface to connect a process to the registry. The registry is `Geographically` + /// aware of process location, and uses `client-side` service discovery to push details + /// to the registry/system to provide operational details to the remaining system. + /// + /// **ServiceDiscoveryService** - The interface used for a `process` to register with `blueprint`. The interface is organized in + /// the order of the typical lifecycle of a process. + /// + /// 1. **Initialize**: Called first by the process so `blueprint` can issue and identity to the process. + /// 1. **Synchronize**: A unidirectional streaming connection between `blueprints` leader and a registered process. Allowing for the process to make + /// configuration changes with the `blueprint` leader. + /// 1. **Finalize**: The deregister function to remove a process from the registery. + /// + /// **ReportHealth**: Method is used by blueprint's follower nodes. Each blueprint node is delegated a set of processes to poll + /// the health check interface. + #[derive(Debug, Clone)] + pub struct ServiceDiscoveryServiceClient { + inner: tonic::client::Grpc, + } + impl ServiceDiscoveryServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> ServiceDiscoveryServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + ServiceDiscoveryServiceClient::new( + InterceptedService::new(inner, interceptor), + ) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Initialize the registeration of the process to the registry + pub async fn initialize( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.registry.service_discovery.v1.ServiceDiscoveryService/Initialize", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.registry.service_discovery.v1.ServiceDiscoveryService", + "Initialize", + ), + ); + self.inner.unary(req, path, codec).await + } + /// synchronize the client state with the registry + pub async fn synchronize( + &mut self, + request: impl tonic::IntoStreamingRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.registry.service_discovery.v1.ServiceDiscoveryService/Synchronize", + ); + let mut req = request.into_streaming_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.registry.service_discovery.v1.ServiceDiscoveryService", + "Synchronize", + ), + ); + self.inner.streaming(req, path, codec).await + } + /// Gracefully shutdown and `Finalize` the connection of the process to the registry + pub async fn finalize( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.registry.service_discovery.v1.ServiceDiscoveryService/Finalize", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.registry.service_discovery.v1.ServiceDiscoveryService", + "Finalize", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Let a follower draft node report health information on the processes it's responsible for checking the health status of + pub async fn report_health( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.registry.service_discovery.v1.ServiceDiscoveryService/ReportHealth", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.registry.service_discovery.v1.ServiceDiscoveryService", + "ReportHealth", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Query the registry + pub async fn query( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.registry.service_discovery.v1.ServiceDiscoveryService/Query", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.registry.service_discovery.v1.ServiceDiscoveryService", + "Query", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Watch the registry for process state changes + pub async fn watch( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/core.registry.service_discovery.v1.ServiceDiscoveryService/Watch", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "core.registry.service_discovery.v1.ServiceDiscoveryService", + "Watch", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + } +} diff --git a/api/src/proto/mod.rs b/api/src/proto/mod.rs new file mode 100644 index 00000000..b9b16c44 --- /dev/null +++ b/api/src/proto/mod.rs @@ -0,0 +1,8 @@ +#[path = "./core.message_broker.actors.v1.rs"] +pub mod core_message_broker_actors_v1; +#[path = "./core.registry.service_discovery.v1.rs"] +pub mod core_registry_service_discovery_v1; +#[path = "./core.control_plane.networking.v1.rs"] +pub mod core_control_plane_networking_v1; +#[path = "./core.registry.key_value.v1.rs"] +pub mod core_registry_key_value_v1; diff --git a/deployments/compose/.env b/deployments/compose/.env new file mode 100644 index 00000000..f63ba57b --- /dev/null +++ b/deployments/compose/.env @@ -0,0 +1,2 @@ +AUTHENTIK_SECRET_KEY=RtiZcYfAlgbVtur2oB7rJRsgjuP7uG6M51FrVUwmUdbwrOdXaWX3ZetfOBI67aHz +AUTHENTIK_BOOTSTRAP_TOKEN=223e6dc958c1c9dccdf8993f71722cb3f928d5bdab7888e062b8b477e0f05ed8 \ No newline at end of file diff --git a/deployments/compose/auth.yaml b/deployments/compose/auth.yaml new file mode 100644 index 00000000..ee43af68 --- /dev/null +++ b/deployments/compose/auth.yaml @@ -0,0 +1,19 @@ +service: + name: auth + domain: core + entrypoint: http://blueprint:2221 + + logging: + level: info + + network: + bind_address: 0.0.0.0 + bind_port: 9095 + internal: + host: auth + port: 9095 + +auth: + mode: authentik + authentik: + url: http://authentik-server:9000 diff --git a/deployments/compose/authentik-blueprint.yaml b/deployments/compose/authentik-blueprint.yaml new file mode 100644 index 00000000..eb043f88 --- /dev/null +++ b/deployments/compose/authentik-blueprint.yaml @@ -0,0 +1,45 @@ +version: 1 +metadata: + name: draft-framework + labels: + blueprints.goauthentik.io/description: "Draft framework forward auth — proxy provider, application, and embedded outpost assignment" + +entries: + # Proxy Provider: forward auth mode — Authentik validates the session and injects + # X-Authentik-* headers. ext_authz in Envoy calls the outpost check endpoint; + # unauthenticated browser users are redirected to the Authentik login flow. + - model: authentik_providers_proxy.proxyprovider + state: present + identifiers: + name: draft-forward-auth + attrs: + name: draft-forward-auth + authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]] + mode: forward_single + # external_host is where Authentik redirects browsers after login — the public Envoy URL. + # Change this for non-local environments. + external_host: http://localhost:10000 + + # Application: the logical unit users/groups are granted access to. + - model: authentik_core.application + state: present + identifiers: + slug: draft + attrs: + name: Draft + slug: draft + provider: !KeyOf draft-forward-auth + + # Assign the proxy provider to the embedded outpost so it handles auth checks. + - model: authentik_outposts.outpost + state: present + identifiers: + name: authentik Embedded Outpost + attrs: + name: authentik Embedded Outpost + type: proxy + providers: + - !KeyOf draft-forward-auth + config: + authentik_host: http://authentik-server:9000 + authentik_host_insecure: true diff --git a/deployments/compose/docker-compose.auth.yaml b/deployments/compose/docker-compose.auth.yaml new file mode 100644 index 00000000..9c2fee94 --- /dev/null +++ b/deployments/compose/docker-compose.auth.yaml @@ -0,0 +1,80 @@ +name: draft-auth + +services: + postgres: + image: docker.io/library/postgres:16-alpine + restart: unless-stopped + environment: + POSTGRES_PASSWORD: authentik + POSTGRES_USER: authentik + POSTGRES_DB: authentik + ports: + - "5433:5432" + volumes: + - postgres:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U authentik"] + interval: 5s + timeout: 5s + retries: 10 + + redis: + image: docker.io/library/redis:7-alpine + restart: unless-stopped + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 10 + + authentik-server: + image: ghcr.io/goauthentik/server:2024.12.3 + restart: unless-stopped + command: server + environment: + AUTHENTIK_REDIS__HOST: redis + AUTHENTIK_POSTGRESQL__HOST: postgres + AUTHENTIK_POSTGRESQL__USER: authentik + AUTHENTIK_POSTGRESQL__PASSWORD: authentik + AUTHENTIK_POSTGRESQL__NAME: authentik + AUTHENTIK_SECRET_KEY: "${AUTHENTIK_SECRET_KEY:?AUTHENTIK_SECRET_KEY must be set. Run: export AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60)}" + AUTHENTIK_ERROR_REPORTING__ENABLED: "false" + # Seeds an API token for the akadmin user on first startup. + # The auth service uses this same value to call the Authentik management API. + # Generate once and keep alongside AUTHENTIK_SECRET_KEY: + # export AUTHENTIK_BOOTSTRAP_TOKEN=$(openssl rand -hex 32) + AUTHENTIK_BOOTSTRAP_TOKEN: "${AUTHENTIK_BOOTSTRAP_TOKEN:?AUTHENTIK_BOOTSTRAP_TOKEN must be set}" + ports: + - "9050:9000" + - "9443:9443" + volumes: + - ./authentik-blueprint.yaml:/blueprints/custom/draft.yaml:ro + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + + authentik-worker: + image: ghcr.io/goauthentik/server:2024.12.3 + restart: unless-stopped + command: worker + environment: + AUTHENTIK_REDIS__HOST: redis + AUTHENTIK_POSTGRESQL__HOST: postgres + AUTHENTIK_POSTGRESQL__USER: authentik + AUTHENTIK_POSTGRESQL__PASSWORD: authentik + AUTHENTIK_POSTGRESQL__NAME: authentik + AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} + AUTHENTIK_BOOTSTRAP_TOKEN: ${AUTHENTIK_BOOTSTRAP_TOKEN} + AUTHENTIK_ERROR_REPORTING__ENABLED: "false" + volumes: + - ./authentik-blueprint.yaml:/blueprints/custom/draft.yaml:ro + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + +volumes: + postgres: diff --git a/docs/website/assets/jsconfig.json b/docs/website/assets/jsconfig.json index 6cc906c9..3e0f881d 100644 --- a/docs/website/assets/jsconfig.json +++ b/docs/website/assets/jsconfig.json @@ -3,8 +3,8 @@ "baseUrl": ".", "paths": { "*": [ - "../../../../../../.cache/hugo_cache/modules/filecache/modules/pkg/mod/github.com/gohugoio/hugo-mod-jslibs-dist/popperjs/v2@v2.21100.20000/package/dist/cjs/*", - "../../../../../../.cache/hugo_cache/modules/filecache/modules/pkg/mod/github.com/twbs/bootstrap@v5.3.2+incompatible/js/*" + "../../../../../../../Library/Caches/hugo_cache/modules/filecache/modules/pkg/mod/github.com/gohugoio/hugo-mod-jslibs-dist/popperjs/v2@v2.21100.20000/package/dist/cjs/*", + "../../../../../../../Library/Caches/hugo_cache/modules/filecache/modules/pkg/mod/github.com/twbs/bootstrap@v5.3.2+incompatible/js/*" ] } } diff --git a/docs/website/content/docs/architecture/agents-implementation-plan.md b/docs/website/content/docs/architecture/agents-implementation-plan.md new file mode 100644 index 00000000..799da576 --- /dev/null +++ b/docs/website/content/docs/architecture/agents-implementation-plan.md @@ -0,0 +1,339 @@ +--- +weight: 11 +title: Agent Service — Implementation Plan +description: Phased implementation plan for the Orchestrator and Operator services +icon: checklist +draft: false +toc: true +--- + +This document describes the implementation plan for the Agent Service in the order work should be done. Each phase produces a runnable, testable artifact that unblocks the next. + +--- + +## Phase 1 — Proto Definitions + +All service contracts are defined before any Go code is written. This ensures Orchestrator, Operator, and Executor can be developed in parallel against a stable API surface. + +### 1.1 Rename `run` → `objective` in existing protos + +- `api/agent/v1/run.proto` → `api/agent/v1/objective.proto` + - `RunStatus` → `ObjectiveStatus` + - `RunConfig` → `ObjectiveConfig` + - `RunSnapshot` → `ObjectiveSnapshot` + - `OrchestratorService.CreateRun` → `OrchestratorService.CreateObjective` + - `OrchestratorService.GetRun` → `OrchestratorService.GetObjective` + - All `run_id` fields → `objective_id` +- `api/agent/v1/events.proto` + - Rename all `AGENT_EVENT_TYPE_RUN_*` → `AGENT_EVENT_TYPE_OBJECTIVE_*` + - Replace `AGENT_EVENT_TYPE_SUBAGENT_*` with `AGENT_EVENT_TYPE_TASK_*` + - Add `AGENT_EVENT_TYPE_TASK_GRAPH_*` + - Renumber all groups per the scheme in `agents.md` + - Update `AgentEvent.run_id` → `AgentEvent.objective_id`, add `AgentEvent.task_id` + +### 1.2 Add `task_graph.proto` + +Define the task graph data model and the `OperatorService` RPC: + +```protobuf +// api/agent/v1/task_graph.proto + +enum TaskStatus { + TASK_STATUS_UNSPECIFIED = 0; + TASK_STATUS_PENDING = 1; + TASK_STATUS_BLOCKED = 2; + TASK_STATUS_READY = 3; + TASK_STATUS_ASSIGNED = 4; + TASK_STATUS_RUNNING = 5; + TASK_STATUS_COMPLETED = 6; + TASK_STATUS_FAILED = 7; + TASK_STATUS_CANCELLED = 8; +} + +message Task { + string id = 1; + string objective_id = 2; + string description = 3; + TaskStatus status = 4; + repeated string depends_on = 5; // task IDs that must complete first + string result = 6; // populated on completion + google.protobuf.Timestamp created_at = 7; + google.protobuf.Timestamp completed_at = 8; +} + +message TaskGraph { + string objective_id = 1; + repeated Task tasks = 2; +} + +service OperatorService { + rpc GetTaskGraph(GetTaskGraphRequest) returns (TaskGraph); +} +``` + +### 1.3 Run `dctl api build` + +Regenerate Go, Rust, and TypeScript bindings. Verify no compile errors before proceeding. + +--- + +## Phase 2 — Orchestrator Service + +The Orchestrator is a standard Draft service using Chassis. It exposes the external RPC API and manages objective lifecycle state. + +### 2.1 Storage schema + +Create the PostgreSQL schema under `services/agent/orchestrator/migrations/`: + +```sql +-- objectives: one row per objective, updated on every event +CREATE TABLE objectives ( + id TEXT PRIMARY KEY, + status TEXT NOT NULL, + description TEXT NOT NULL, + task_graph_id TEXT, + last_event_sequence BIGINT NOT NULL DEFAULT 0, + created_at TIMESTAMPTZ NOT NULL, + updated_at TIMESTAMPTZ NOT NULL, + completed_at TIMESTAMPTZ, + budget_tokens BIGINT, + tokens_used BIGINT NOT NULL DEFAULT 0 +); + +-- task_graphs: DAG structure for each objective +CREATE TABLE task_graphs ( + id TEXT PRIMARY KEY, + objective_id TEXT NOT NULL REFERENCES objectives(id), + created_at TIMESTAMPTZ NOT NULL +); + +-- tasks: one row per task node +CREATE TABLE tasks ( + id TEXT PRIMARY KEY, + objective_id TEXT NOT NULL REFERENCES objectives(id), + graph_id TEXT NOT NULL REFERENCES task_graphs(id), + description TEXT NOT NULL, + status TEXT NOT NULL, + depends_on TEXT[] NOT NULL DEFAULT '{}', + result TEXT, + created_at TIMESTAMPTZ NOT NULL, + updated_at TIMESTAMPTZ NOT NULL, + completed_at TIMESTAMPTZ +); + +-- steps: one row per LLM iteration within a task +CREATE TABLE steps ( + id TEXT PRIMARY KEY, + task_id TEXT NOT NULL REFERENCES tasks(id), + objective_id TEXT NOT NULL, + index INT NOT NULL, + status TEXT NOT NULL, + tokens_used BIGINT NOT NULL DEFAULT 0, + output TEXT, + started_at TIMESTAMPTZ NOT NULL, + completed_at TIMESTAMPTZ +); + +-- working_memory: agent scratchpad per task +CREATE TABLE working_memory ( + task_id TEXT PRIMARY KEY REFERENCES tasks(id), + messages JSONB NOT NULL DEFAULT '[]', + scratchpad TEXT NOT NULL DEFAULT '', + updated_at TIMESTAMPTZ NOT NULL +); + +-- task_queue: ready tasks pending dispatch, claimed with SELECT FOR UPDATE SKIP LOCKED +CREATE TABLE task_queue ( + task_id TEXT PRIMARY KEY REFERENCES tasks(id), + objective_id TEXT NOT NULL, + queued_at TIMESTAMPTZ NOT NULL +); +``` + +### 2.2 `OrchestratorService` RPC implementation + +Implement in `services/agent/orchestrator/`: + +| RPC | Behavior | +|---|---| +| `CreateObjective` | Validate input, persist objective row, emit `OBJECTIVE_CREATED` + `OBJECTIVE_STARTED` | +| `GetObjective` | Read objective snapshot from `objectives` table | +| `ListObjectives` | Paginated query of `objectives` table | +| `CancelObjective` | Validate state transition, emit `OBJECTIVE_CANCELLED` | +| `ApproveTask` | Validate objective is `paused`, emit `APPROVAL_RECEIVED` | + +### 2.3 Catalyst subscriptions + +The Orchestrator subscribes to the following events to keep the objective snapshot current: + +| Event | Handler | +|---|---| +| `TASK_GRAPH_CREATED` | Record `graph_id` in objective row | +| `TASK_COMPLETED` | Increment completed task count in snapshot | +| `TASK_FAILED` | Record failure in snapshot | +| `OBJECTIVE_COMPLETED` | Transition objective to `completed`, set `completed_at` | +| `OBJECTIVE_FAILED` | Transition objective to `failed` | +| `APPROVAL_REQUESTED` | Transition objective to `paused` | + +### 2.4 State machine enforcement + +All status transitions must be validated before any event is emitted. Illegal transitions return a gRPC `FailedPrecondition` error. Use a transition table: + +```go +var allowedTransitions = map[ObjectiveStatus][]ObjectiveStatus{ + StatusCreated: {StatusPending}, + StatusPending: {StatusRunning}, + StatusRunning: {StatusPaused, StatusCompleted, StatusFailed, StatusCancelled}, + StatusPaused: {StatusRunning, StatusCancelled}, +} +``` + +### 2.5 Budget tracking + +On every `STEP_COMPLETED` event the Orchestrator increments `tokens_used` in the objective snapshot. When `tokens_used` crosses the configured threshold it emits `BUDGET_WARNING`; when it exceeds the limit it emits `BUDGET_EXCEEDED` and transitions the objective to `failed`. + +--- + +## Phase 3 — Operator Service + +The Operator is a new Draft service. It has no external RPC — it communicates exclusively through Catalyst events. + +### 3.1 Objective subscription and planning + +Subscribe to `OBJECTIVE_STARTED` events. On receipt: + +1. Call the planner (initially a direct LLM call using the objective description as the prompt) +2. Parse the planner's response into a `TaskGraph` — a list of tasks with `depends_on` fields +3. Persist the `TaskGraph` and all `Task` rows to PostgreSQL +4. Emit `TASK_GRAPH_CREATED` followed by one `TASK_CREATED` per task +5. Insert all tasks with in-degree zero into `task_queue` +6. Emit `TASK_ASSIGNED` for each queued task + +The planner prompt should instruct the LLM to return a structured JSON task list. Use structured output or tool use to enforce the schema from `task_graph.proto`. + +### 3.2 DAG dispatch loop + +The dispatch loop is event-driven, not a polling loop: + +```go +// On TASK_COMPLETED +func (o *Operator) onTaskCompleted(event AgentEvent) { + task := o.loadTask(event.TaskId) + o.markCompleted(task, event.Payload.Result) + + for _, dependent := range o.dependents(task.Id) { + o.decrementInDegree(dependent) + if o.inDegree(dependent) == 0 { + o.enqueue(dependent) + o.emit(TASK_ASSIGNED, dependent) + } + } + + if o.allTasksDone(event.ObjectiveId) { + o.emit(OBJECTIVE_COMPLETED, event.ObjectiveId) + } +} +``` + +Use `SELECT ... FOR UPDATE SKIP LOCKED` on `task_queue` so multiple Operator instances can run without double-dispatching a task. + +### 3.3 Failure policy + +On `TASK_FAILED`, apply the policy configured on the `TaskGraph`: + +| Policy | Behavior | +|---|---| +| `retry` | Re-enqueue the task up to the configured retry limit, emit `TASK_RETRYING` | +| `skip` | Mark the task skipped; treat dependents as if it completed with an empty result | +| `fail` | Emit `OBJECTIVE_FAILED` and stop processing the graph | + +### 3.4 Human-in-the-loop + +When a task requires approval before execution (flagged in the `Task` definition), the Operator emits `APPROVAL_REQUESTED` instead of `TASK_ASSIGNED` and marks the task `blocked`. On receiving `APPROVAL_RECEIVED` it enqueues the task and emits `TASK_ASSIGNED`. + +### 3.5 Crash recovery + +On startup, the Operator queries the `task_queue` table for any tasks that are in state `ready` but have no active assignment. These are tasks that were enqueued before a crash and never dispatched or claimed. The Operator re-emits `TASK_ASSIGNED` for each one. + +--- + +## Phase 4 — Executor Updates + +The Executor already exists but must be updated to align with the new event naming and the task/step distinction. + +### 4.1 Subscription change + +Change the Catalyst subscription from `STEP_STARTED` (Orchestrator-driven, old model) to `TASK_ASSIGNED` (Operator-driven, new model). The consumer group name stays `"agent-executors"`. + +### 4.2 Task execution loop + +A single task assignment may require multiple LLM steps before producing a final result. The Executor manages this loop internally: + +``` +TASK_ASSIGNED received + │ + Load working memory for task + │ + loop: + Emit STEP_STARTED + Construct prompt from working memory + task description + Call LLM + For each tool call in response: + Emit TOOL_CALLED + Execute tool + Emit TOOL_RETURNED + Emit STEP_COMPLETED + Update working memory + If LLM signals done → break + │ + Emit TASK_COMPLETED with final result +``` + +### 4.3 Event field updates + +All events emitted by the Executor must include both `objective_id` and `task_id` in the `AgentEvent` envelope. Update event construction accordingly. + +--- + +## Phase 5 — Integration and Testing + +### 5.1 Local integration test + +Write an end-to-end test that: + +1. Calls `CreateObjective` with a simple two-task objective (e.g., "summarize document A and document B") +2. Asserts `TASK_GRAPH_CREATED` is emitted with two tasks and no dependencies +3. Asserts both `TASK_ASSIGNED` events are emitted (parallel dispatch) +4. Stubs Executor responses for both tasks +5. Asserts `OBJECTIVE_COMPLETED` is emitted +6. Calls `GetObjective` and asserts status is `completed` + +### 5.2 Sequential dependency test + +Write a test for a two-task graph where task B depends on task A: + +1. Assert only task A receives `TASK_ASSIGNED` initially +2. Complete task A +3. Assert task B receives `TASK_ASSIGNED` with task A's result available in working memory +4. Complete task B +5. Assert `OBJECTIVE_COMPLETED` + +### 5.3 Crash recovery test + +1. Start Operator, receive `OBJECTIVE_STARTED`, emit `TASK_GRAPH_CREATED` +2. Kill Operator before emitting `TASK_ASSIGNED` +3. Restart Operator +4. Assert Operator re-emits `TASK_ASSIGNED` for all ready tasks +5. Complete objective normally + +--- + +## Milestone Summary + +| Phase | Deliverable | Unblocks | +|---|---|---| +| 1 | Updated protos, `task_graph.proto` | Phases 2, 3, 4 in parallel | +| 2 | Orchestrator service with storage and RPC | Integration testing | +| 3 | Operator service with DAG execution | Integration testing | +| 4 | Updated Executor | Integration testing | +| 5 | End-to-end tests passing | Ship | diff --git a/docs/website/content/docs/architecture/agents.md b/docs/website/content/docs/architecture/agents.md new file mode 100644 index 00000000..c9b6807e --- /dev/null +++ b/docs/website/content/docs/architecture/agents.md @@ -0,0 +1,400 @@ +--- +weight: 10 +title: Agent Service +description: An overview of the agent orchestration service and its integration with the Draft cluster +icon: smart_toy +draft: false +toc: true +--- + +The Agent Service is a Draft domain that provides infrastructure for orchestrating AI agents at scale. It is composed of three cooperating processes — an **Orchestrator**, an **Operator**, and one or more **Executors** — that communicate exclusively through [Catalyst](/docs/architecture/core-services#catalyst) using a typed event system built on top of CloudEvents. + +The Agent Service is designed around four principles: + +- **Event sourcing** — every meaningful state change is recorded as an immutable event, giving a full audit trail and the ability to replay or resume any objective +- **Separation of concerns** — the Orchestrator manages state and the external API; the Operator manages task graph planning and DAG execution; the Executor manages LLM calls and tool use; none does another's job +- **Draft-native** — all three processes are standard Draft processes registered with Blueprint, routing through Fuse, and communicating through Catalyst +- **Durable by default** — objectives survive crashes and can resume from their last checkpoint without replaying from the beginning + +See below for an overview of the agent service within a Draft cluster. + +``` +┌──────────────────────────────────────────────────────────────────────┐ +│ Draft Cluster │ +│ │ +│ ┌───────────┐ ┌──────────┐ ┌──────────────────────────┐ │ +│ │ Blueprint │ │ Fuse │ │ Catalyst │ │ +│ │ (registry)│ │ (routing)│ │ (events) │ │ +│ └───────────┘ └──────────┘ └────────────┬─────────────┘ │ +│ │ │ +│ ┌───────────────────────────────────────────┤ │ +│ │ │ │ │ +│ ┌──────▼───────┐ ┌────────▼──────┐ ┌─────▼────────────┐ │ +│ │ Orchestrator │ │ Operator │ │ Executor(s) │ │ +│ │ │ │ │ │ │ │ +│ │ - Objective │ │ - Task graph │ │ - LLM calls │ │ +│ │ state │ │ - DAG routing │ │ - Tool execution │ │ +│ │ - API layer │ │ - Planning │ │ - Working memory │ │ +│ │ - Snapshots │ │ - Dispatch │ │ │ │ +│ │ - Event log │ │ │ │ │ │ +│ └──────────────┘ └───────────────┘ └──────────────────┘ │ +└──────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Orchestrator + +[#orchestrator](#orchestrator) + +The Orchestrator is the control plane of the agent service. It owns the lifecycle of every objective and is the single source of truth for objective state. It does not plan task graphs, call LLMs, or execute tools — it accepts objectives from callers, records all events, and keeps queryable state current. + +Its responsibilities are: + +- Accepting new objectives via its `OrchestratorService` RPC +- Maintaining an **objective snapshot** — a materialized view of the current objective state, queryable without replaying the full event log +- Maintaining the **event log** — the append-only record of every `AgentEvent` emitted during an objective, backed by Catalyst's ClickHouse store +- Enforcing the **state machine** — only legal objective status transitions are permitted; illegal transitions are rejected before any event is emitted +- Surfacing **human-in-the-loop** decisions — when a task requires approval the Orchestrator transitions the objective to `paused` and exposes an `ApproveTask` RPC for external actors + +### State Machine + +An objective moves through the following states. Terminal states (`completed`, `failed`, `cancelled`) accept no further transitions. + +``` +created ──▶ pending ──▶ running ──▶ completed + │ + ├──▶ paused ──▶ running + ├──▶ failed + └──▶ cancelled +``` + +### Objective Snapshot + +The Orchestrator maintains a flat, queryable snapshot of each objective updated after every event is processed. This allows the current state of any objective to be read instantly without replaying the event log. The snapshot tracks identity, status, task graph progress, budget consumption, and timestamps. + +When an objective must be resumed after a crash, the Orchestrator loads the saved snapshot, then replays only the events that occurred after the snapshot's `last_event_sequence` cursor — not the full history. + +--- + +## Operator + +[#operator](#operator) + +The Operator is the planning and execution engine of the agent service. It receives an objective from Catalyst, decomposes it into a `TaskGraph`, and drives that graph to completion by dispatching tasks to Executors and reacting to their results. + +Its responsibilities are: + +- Subscribing to `AGENT_EVENT_TYPE_OBJECTIVE_STARTED` events on Catalyst +- Calling the planner (LLM or rule-based) to decompose the objective into a `TaskGraph` — a directed acyclic graph of `Task` nodes with explicit dependency edges +- Emitting `AGENT_EVENT_TYPE_TASK_GRAPH_CREATED` and one `AGENT_EVENT_TYPE_TASK_CREATED` event per task +- Identifying all tasks with no unmet dependencies (in-degree zero) and dispatching them in parallel via `AGENT_EVENT_TYPE_TASK_ASSIGNED` +- Subscribing to `AGENT_EVENT_TYPE_TASK_COMPLETED` and `AGENT_EVENT_TYPE_TASK_FAILED` events +- On each `TASK_COMPLETED`: decrement the in-degree of dependent tasks; dispatch any task whose in-degree reaches zero +- On `TASK_FAILED`: apply the configured failure policy (retry, skip, or fail the objective) +- Emitting `AGENT_EVENT_TYPE_OBJECTIVE_COMPLETED` or `AGENT_EVENT_TYPE_OBJECTIVE_FAILED` when the graph reaches a terminal state + +### DAG Execution Loop + +``` +OBJECTIVE_STARTED received + │ + Build TaskGraph via planner + │ + Emit TASK_GRAPH_CREATED + TASK_CREATED (×N) + │ + Find all tasks with in-degree = 0 + │ + Emit TASK_ASSIGNED in parallel ──────────────────┐ + │ + TASK_COMPLETED received │ + │ │ + Mark task done, store result │ + Decrement in-degree of dependents │ + Any dependent reaches 0? → emit TASK_ASSIGNED ───┘ + │ + No tasks remaining → emit OBJECTIVE_COMPLETED +``` + +The Operator is stateless between events. All durable task graph state is persisted in PostgreSQL so any Operator instance can pick up after a crash by reading the stored graph and finding tasks that are ready but unassigned. + +--- + +## Executor + +[#executor](#executor) + +The Executor is the data plane of the agent service. It receives task assignments from Catalyst, runs the agent logic (LLM calls, tool use, scratchpad updates), and publishes results back as `AgentEvent`s. + +Its responsibilities are: + +- Subscribing to `AGENT_EVENT_TYPE_TASK_ASSIGNED` events on Catalyst, load-balanced across all running Executor instances via a consumer group +- Loading working memory for the task at the start of execution +- Executing the agent: constructing the prompt, calling the LLM, parsing tool calls, and running tools across one or more internal steps +- Emitting `AGENT_EVENT_TYPE_STEP_STARTED`, `AGENT_EVENT_TYPE_STEP_COMPLETED`, `AGENT_EVENT_TYPE_TOOL_CALLED`, and `AGENT_EVENT_TYPE_TOOL_RETURNED` for each iteration +- Publishing `AGENT_EVENT_TYPE_TASK_COMPLETED` or `AGENT_EVENT_TYPE_TASK_FAILED` when the task finishes +- Committing updated working memory after each step + +Executors are stateless between tasks. All durable state lives in the Orchestrator and Operator. Multiple Executor instances can run simultaneously, each picking up tasks from the Catalyst consumer group, giving horizontal scalability at the execution layer. + +--- + +## Agent Events + +[#agent-events](#agent-events) + +All communication between the three services flows through `AgentEvent` messages published on Catalyst. An `AgentEvent` is a typed, versioned proto message carried inside a standard Catalyst `CloudEvent`. + +### Envelope + +Every `AgentEvent` shares a common envelope defined in `api/agent/v1/events.proto`: + +```protobuf +message AgentEvent { + string id = 1; // unique event ID + AgentEventType type = 2; // typed enum, see below + string objective_id = 3; // which objective this event belongs to + string task_id = 4; // which task, if applicable + int64 sequence = 5; // monotonic per-objective ordering + google.protobuf.Timestamp occurred_at = 6; + + oneof payload { ... } // typed payload, one per event type +} +``` + +The `sequence` field provides a monotonic per-objective cursor used by the snapshot to know which events have already been applied, enabling safe incremental replay. + +### CloudEvent Mapping + +`AgentEvent`s are packed into Catalyst `CloudEvent`s using the following field mapping: + +| CloudEvent field | Value | Purpose | +|---|---|---| +| `id` | `AgentEvent.id` | Unique event identity | +| `source` | `agent.AgentEvent/{objective_id}` | Enables per-objective subscription and prefix filtering | +| `type` | `AgentEventType` enum name | Enables event-type routing without deserializing payload | +| `binary_data` | proto-marshaled `AgentEvent` bytes | Full typed event, deserialized by consumers | + +The `source` format `agent.AgentEvent/{objective_id}` is intentional. Catalyst consumers can filter at two levels: prefix-match on `agent.AgentEvent/` to receive all agent events across all objectives, or exact-match on `agent.AgentEvent/{objective_id}` to receive events for a specific objective only. + +```go +// Subscribe to all events for a specific objective +broker.Subscribe(ctx, chassis.SubscribeOptions{ + Event: &acv1.CloudEvent{ + Type: agentv1.AgentEventType_AGENT_EVENT_TYPE_OBJECTIVE_STARTED.String(), + Source: "agent.AgentEvent/" + objectiveID, + }, + Consumer: orchestrator, +}) + +// Subscribe to task assignments across all objectives, load-balanced +broker.Subscribe(ctx, chassis.SubscribeOptions{ + Event: &acv1.CloudEvent{Type: agentv1.AgentEventType_AGENT_EVENT_TYPE_TASK_ASSIGNED.String()}, + Group: "agent-executors", + Consumer: executor, +}) +``` + +### Event Types + +`AgentEventType` is a proto enum. Adding a new event type requires a recompile, which is intentional — it ensures all consumers are aware of new event types at compile time. + +```protobuf +enum AgentEventType { + AGENT_EVENT_TYPE_UNSPECIFIED = 0; + + // Objective lifecycle (10–19) + AGENT_EVENT_TYPE_OBJECTIVE_CREATED = 10; + AGENT_EVENT_TYPE_OBJECTIVE_STARTED = 11; + AGENT_EVENT_TYPE_OBJECTIVE_PAUSED = 12; + AGENT_EVENT_TYPE_OBJECTIVE_RESUMED = 13; + AGENT_EVENT_TYPE_OBJECTIVE_CANCELLED = 14; + AGENT_EVENT_TYPE_OBJECTIVE_COMPLETED = 15; + AGENT_EVENT_TYPE_OBJECTIVE_FAILED = 16; + + // Task graph (20–29) + AGENT_EVENT_TYPE_TASK_GRAPH_CREATED = 20; + AGENT_EVENT_TYPE_TASK_GRAPH_UPDATED = 21; // replanning + + // Task lifecycle (30–39) + AGENT_EVENT_TYPE_TASK_CREATED = 30; + AGENT_EVENT_TYPE_TASK_ASSIGNED = 31; + AGENT_EVENT_TYPE_TASK_STARTED = 32; + AGENT_EVENT_TYPE_TASK_COMPLETED = 33; + AGENT_EVENT_TYPE_TASK_FAILED = 34; + AGENT_EVENT_TYPE_TASK_RETRYING = 35; + AGENT_EVENT_TYPE_TASK_BLOCKED = 36; + AGENT_EVENT_TYPE_TASK_UNBLOCKED = 37; + + // Step lifecycle (40–49) + AGENT_EVENT_TYPE_STEP_STARTED = 40; + AGENT_EVENT_TYPE_STEP_COMPLETED = 41; + AGENT_EVENT_TYPE_STEP_FAILED = 42; + AGENT_EVENT_TYPE_STEP_RETRYING = 43; + + // Tool calls (50–59) + AGENT_EVENT_TYPE_TOOL_CALLED = 50; + AGENT_EVENT_TYPE_TOOL_RETURNED = 51; + AGENT_EVENT_TYPE_TOOL_FAILED = 52; + + // Human-in-the-loop (60–69) + AGENT_EVENT_TYPE_APPROVAL_REQUESTED = 60; + AGENT_EVENT_TYPE_APPROVAL_RECEIVED = 61; + + // Budget / safety (70–79) + AGENT_EVENT_TYPE_BUDGET_WARNING = 70; + AGENT_EVENT_TYPE_BUDGET_EXCEEDED = 71; +} +``` + +Event type numbers are grouped by category with gaps between groups, leaving room to add new types within a category without breaking ordering. + +### Event Groups + +**Objective lifecycle** events mark top-level transitions through the state machine. `OBJECTIVE_CREATED` is always the first event for any objective. `OBJECTIVE_COMPLETED`, `OBJECTIVE_FAILED`, and `OBJECTIVE_CANCELLED` are terminal — no further events are emitted after them. + +**Task graph** events are emitted by the Operator when it plans or replans the work for an objective. `TASK_GRAPH_CREATED` carries the full DAG structure. `TASK_GRAPH_UPDATED` is emitted if the Operator revises the plan mid-execution based on task results. + +**Task lifecycle** events track each node in the task graph from creation through assignment, execution, and completion. `TASK_BLOCKED` is emitted when a task cannot start because a dependency has not yet completed. `TASK_UNBLOCKED` is emitted by the Operator when the last blocking dependency resolves and the task becomes eligible for dispatch. + +**Step lifecycle** events mark individual LLM iterations within a single task execution. A task may require multiple steps if the agent needs to reason across several LLM calls before producing a final result. `STEP_RETRYING` is emitted between retry attempts and carries the attempt number and backoff duration for observability. + +**Tool call** events are emitted by the Executor during step execution for every external tool interaction. They provide a complete record of what the agent called, with what arguments, and what was returned — essential for debugging and cost attribution. + +**Human-in-the-loop** events pause an objective at a task boundary and surface a decision to an external actor. The objective transitions to `paused` status on `APPROVAL_REQUESTED` and resumes on `APPROVAL_RECEIVED`. + +**Budget and safety** events are emitted by the Orchestrator when an objective approaches or exceeds a configured limit (token count, cost, or step count). `BUDGET_EXCEEDED` causes the objective to transition to `failed`. + +--- + +## Service Interaction + +[#service-interaction](#service-interaction) + +Each service has a defined set of events it emits and subscribes to. No service calls another directly — all coordination flows through Catalyst. + +### Orchestrator + +| Direction | Event | Trigger | +|---|---|---| +| Emits | `OBJECTIVE_CREATED` | Client calls `CreateObjective` RPC | +| Emits | `OBJECTIVE_STARTED` | Immediately after `OBJECTIVE_CREATED` | +| Emits | `OBJECTIVE_PAUSED` | `APPROVAL_REQUESTED` received; transitions state | +| Emits | `OBJECTIVE_RESUMED` | Client calls `ApproveTask` RPC | +| Emits | `OBJECTIVE_CANCELLED` | Client calls `CancelObjective` RPC | +| Emits | `BUDGET_WARNING` | Budget threshold crossed | +| Emits | `BUDGET_EXCEEDED` | Budget limit exceeded | +| Subscribes | `TASK_GRAPH_CREATED` | Records graph structure in snapshot | +| Subscribes | `TASK_COMPLETED` | Updates per-task progress in snapshot | +| Subscribes | `TASK_FAILED` | Updates failure state in snapshot | +| Subscribes | `OBJECTIVE_COMPLETED` | Transitions objective to terminal state | +| Subscribes | `OBJECTIVE_FAILED` | Transitions objective to terminal state | +| Subscribes | `APPROVAL_REQUESTED` | Transitions objective to `paused` | + +### Operator + +| Direction | Event | Trigger | +|---|---|---| +| Subscribes | `OBJECTIVE_STARTED` | Begins planning: calls the planner, builds TaskGraph | +| Subscribes | `TASK_COMPLETED` | Decrements dependent in-degrees; dispatches newly ready tasks | +| Subscribes | `TASK_FAILED` | Applies failure policy: retry, skip, or fail the objective | +| Subscribes | `APPROVAL_RECEIVED` | Resumes the task that was waiting on approval | +| Subscribes | `OBJECTIVE_CANCELLED` | Stops processing; marks in-flight tasks cancelled | +| Emits | `TASK_GRAPH_CREATED` | Planning complete; carries full DAG | +| Emits | `TASK_GRAPH_UPDATED` | Replanning triggered by a task result | +| Emits | `TASK_CREATED` | One per task node in the graph | +| Emits | `TASK_ASSIGNED` | Task is ready and dispatched to an Executor | +| Emits | `TASK_BLOCKED` | Task is waiting on an unresolved dependency | +| Emits | `TASK_UNBLOCKED` | Last dependency resolved; task is now ready | +| Emits | `APPROVAL_REQUESTED` | Task requires human approval before proceeding | +| Emits | `OBJECTIVE_COMPLETED` | All tasks in the graph have completed successfully | +| Emits | `OBJECTIVE_FAILED` | An unrecoverable task failure has terminated the objective | + +### Executor + +| Direction | Event | Trigger | +|---|---|---| +| Subscribes | `TASK_ASSIGNED` | Picks up a task from the consumer group | +| Emits | `TASK_STARTED` | Task execution begins | +| Emits | `STEP_STARTED` | Each LLM iteration begins | +| Emits | `STEP_COMPLETED` | LLM iteration produces a result | +| Emits | `STEP_FAILED` | LLM iteration fails | +| Emits | `STEP_RETRYING` | Step is being retried after failure | +| Emits | `TOOL_CALLED` | Agent invokes an external tool | +| Emits | `TOOL_RETURNED` | Tool call returns a result | +| Emits | `TOOL_FAILED` | Tool call fails | +| Emits | `TASK_COMPLETED` | Task execution finishes successfully | +| Emits | `TASK_FAILED` | Task execution fails after all retries | +| Emits | `TASK_RETRYING` | Task is being retried at the task level | + +--- + +## Event Flow + +[#event-flow](#event-flow) + +Below is the sequence of events for a two-task objective where the tasks have no dependency between them and execute in parallel: + +``` +Client Orchestrator Catalyst Operator Executor + │ │ │ │ │ + │─ CreateObjective▶│ │ │ │ + │ │─ OBJ_CREATED ───▶│ │ │ + │ │─ OBJ_STARTED ───▶│────────────────▶│ │ + │ │ │ │─ [plan tasks] │ + │ │ │◀─ TASK_GRAPH_CREATED ──────────────│ + │ │◀─ TASK_GRAPH_CREATED ──────────────│ │ + │ │ │◀─ TASK_CREATED (×2) ───────────────│ + │ │ │◀─ TASK_ASSIGNED ───────────────────│──────────────▶│ + │ │ │◀─ TASK_ASSIGNED ───────────────────│──────────────▶│ + │ │ │ │ │─ TASK_STARTED │ + │ │ │ │ │─ STEP_STARTED │ + │ │ │◀─ TOOL_CALLED ─────────────────────────────────────│ + │ │ │◀─ TOOL_RETURNED ───────────────────────────────────│ + │ │ │◀─ STEP_COMPLETED ──────────────────────────────────│ + │ │ │◀─ TASK_COMPLETED ──────────────────│◀──────────────│ + │ │◀─ TASK_COMPLETED ─│ │ │ │ + │ │ │◀─ TASK_COMPLETED ──────────────────│◀──────────────│ + │ │◀─ TASK_COMPLETED ─│ │ │ │ + │ │ │ │─ [all done] │ │ + │ │ │◀─ OBJ_COMPLETED ──────────────────── │ + │ │◀─ OBJ_COMPLETED ──│ │ │ + │ │ [update snapshot] │ │ │ + │◀─ GetObjective ──│ │ │ │ +``` + +--- + +## Storage + +[#storage](#storage) + +The Orchestrator uses PostgreSQL as its storage layer with the following logical tables: + +- **`objectives`** — the objective snapshot, one row per objective, updated after each event +- **`task_graphs`** — the DAG structure for each objective: task nodes and dependency edges +- **`tasks`** — individual task records with status, assignment, and result +- **`steps`** — individual step records within a task, with timing and token usage +- **`working_memory`** — a JSON blob per task holding the agent's message history and scratchpad +- **`task_queue`** — pending work claimed by the Operator using `SELECT ... FOR UPDATE SKIP LOCKED`, ensuring each ready task is dispatched exactly once even under concurrent Operator instances + +The **event log** is backed by Catalyst's ClickHouse store. `AgentEvent`s are stored with `source = agent.AgentEvent/{objective_id}` and ordered by `(source, sequence)`, making per-objective replay efficient. The Orchestrator's snapshot tracks a `last_event_sequence` cursor so it can replay only new events after a crash rather than the full history. + +--- + +## Proto Definitions + +[#proto-definitions](#proto-definitions) + +All agent service types are defined under `api/agent/v1/`. + +| File | Contents | +|---|---| +| `events.proto` | `AgentEvent`, `AgentEventType` enum, all payload message types | +| `objective.proto` | `ObjectiveStatus`, `ObjectiveConfig`, `ObjectiveSnapshot`, `OrchestratorService` RPC | +| `task_graph.proto` | `TaskGraph`, `Task`, `TaskStatus`, `OperatorService` RPC | +| `step.proto` | `StepStatus`, `Step`, `AgentExecutorService` RPC | +| `memory.proto` | `WorkingMemory`, `Scratchpad`, `Message` | +| `queue.proto` | `QueuedTask` | + +{{< alert context="info" text="The AgentEvent envelope is packed into a Catalyst CloudEvent using binary_data. The CloudEvent type and source fields are populated from the AgentEvent directly, so Catalyst can route by event type and objective ID without deserializing the payload." />}} diff --git a/docs/website/content/docs/architecture/authentication-setup.md b/docs/website/content/docs/architecture/authentication-setup.md new file mode 100644 index 00000000..6442818c --- /dev/null +++ b/docs/website/content/docs/architecture/authentication-setup.md @@ -0,0 +1,280 @@ +--- +weight: 25 +title: 'Authentication Setup' +description: 'How to start, configure, and manage Authentik authentication in a Draft cluster' +icon: 'settings' +draft: false +toc: true +--- + +This guide covers the practical steps to get authentication running in a Draft cluster. It assumes you have already read the [Authentication & Authorization](/docs/architecture/authentication) architecture overview and understand the role of the auth core service and Envoy ext_authz. + +There are two complementary approaches to configuring Authentik: + +| Approach | When to use | +|---|---| +| **Blueprint YAML** | Declarative, commit-once setup applied automatically on `docker compose up`. Best for the foundational configuration — the proxy provider, application, and embedded outpost — that never changes across environments. | +| **Auth Service API** | Runtime management via ConnectRPC. Best for configuration that changes while the system is live — new groups for `AUTH_POLICY_GROUPS` routes, new scopes for `AUTH_POLICY_SCOPES` routes, new service providers as services are added. | + +Both approaches work together: the Blueprint YAML lays the foundation on first boot, and the Auth Service API keeps Authentik in sync with the cluster's evolving route policies. + +--- + +## Prerequisites + +- Docker and Docker Compose installed +- The Draft monorepo checked out and the core services built (see [Getting Started](/docs/getting-started)) +- Two secrets generated and exported in your shell (or stored in `deployments/compose/.env`): + +```shell +# Generate once and store securely — do not commit these values +export AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60) +export AUTHENTIK_BOOTSTRAP_TOKEN=$(openssl rand -hex 32) +``` + +`AUTHENTIK_SECRET_KEY` is Authentik's internal signing secret. `AUTHENTIK_BOOTSTRAP_TOKEN` seeds an API key for the `akadmin` user on first startup; the auth core service uses this same token to call Authentik's management API. + +{{< alert context="info" text="Store these values in deployments/compose/.env — Docker Compose loads it automatically. Add .env to your .gitignore. Both values only need to be generated once; changing AUTHENTIK_SECRET_KEY after first startup will invalidate all existing sessions." />}} + +--- + +## Option 1 — Blueprint YAML (declarative, startup) + +Authentik ships a built-in **Blueprint** system: YAML files describing providers, applications, flows, and outpost assignments that Authentik applies idempotently on startup. Mounting a blueprint into the container means `docker compose up` produces a fully configured Authentik with no manual steps. + +### What the Draft blueprint creates + +The file `deployments/compose/authentik-blueprint.yaml` is mounted into the Authentik server at `/blueprints/custom/draft.yaml`. On startup, Authentik applies it and creates: + +1. **Proxy Provider** (`draft-forward-auth`) — forward auth mode. Authentik validates every check request from the Envoy ext_authz filter and injects identity headers (`X-Authentik-Username`, `X-Authentik-Groups`) on allow. +2. **Application** (`Draft`) — the logical identity unit in Authentik. Users and groups are granted access to this application. +3. **Embedded Outpost assignment** — the proxy provider is attached to Authentik's built-in embedded outpost so it handles ext_authz check requests immediately, without deploying a separate outpost process. + +### Starting the stack + +```shell +# From the root of the draft repository +docker compose -f deployments/compose/docker-compose.auth.yaml up +``` + +The first time you run this, Authentik will apply the blueprint after its database migrations complete. Watch for a log line like: + +``` +authentik-server | ... Successfully applied blueprint 'Draft Framework' +``` + +### First-time admin setup + +After the server starts, open the initial setup wizard in your browser: + +``` +http://localhost:9050/if/flow/initial-setup/ +``` + +Create the admin account (`akadmin`). Once saved, the `AUTHENTIK_BOOTSTRAP_TOKEN` you set is already active as an API key for this account — no further action is needed. + +### Customising the external host + +The Proxy Provider's `external_host` is the URL Authentik redirects browsers to after login — the publicly accessible address of your Envoy gateway. It defaults to `http://localhost:10000` (Envoy's default local port). Override it before starting the stack: + +```shell +export AUTHENTIK_DRAFT_EXTERNAL_HOST=https://api.example.com +docker compose -f deployments/compose/docker-compose.auth.yaml up +``` + +### Viewing applied blueprints + +In the Authentik UI: **System → Blueprints**. The `draft-framework` entry shows its last apply time and any errors. You can re-trigger a manual apply from this screen. + +### PostgreSQL access + +The Authentik Postgres instance is exposed on host port `5433` for inspection via DBeaver or `psql`: + +``` +Host: localhost +Port: 5433 +Database: authentik +User: authentik +Password: authentik +``` + +```shell +# Via psql in the container (no port exposure needed) +docker exec -it draft-auth-postgres-1 psql -U authentik -d authentik +``` + +--- + +## Option 2 — Auth Service API (dynamic, runtime) + +The Blueprint YAML handles static configuration. But as services are added to the cluster — each potentially declaring new group or scope requirements — someone needs to ensure those groups and scopes exist in Authentik before the first request arrives. + +The auth core service (`services/core/auth`) is the runtime bridge. In `authentik` mode it: + +1. On startup: reads all registered routes from Blueprint KV, reconciles required groups and scopes against Authentik's API, and blocks serving traffic until reconciliation succeeds. +2. In the background: watches Blueprint KV for route changes and reconciles automatically on a configurable interval. +3. Exposes a `AuthManagementService` ConnectRPC API so admin tooling can trigger reconciliation or inspect state on demand. + +```mermaid +flowchart TD + Service["Application Service\nregisters routes with auth policies"] + Blueprint["Blueprint KV\nroute config store"] + AuthSvc["Auth Core Service\nroute watcher + management API"] + AuthentikAPI["Authentik REST API v3"] + AuthentikOutpost["Authentik Embedded Outpost\next_authz check endpoint"] + Envoy["Envoy\next_authz filter"] + + Service -->|"WithRoute() → Fuse"| Blueprint + AuthSvc -->|"poll on sync_interval"| Blueprint + AuthSvc -->|"EnsureGroup / EnsureScope"| AuthentikAPI + Envoy -->|"check request"| AuthSvc + AuthSvc -->|"forward to outpost"| AuthentikOutpost + AuthentikOutpost -->|"200 OK + headers or 401/403"| AuthSvc + AuthSvc -->|"relay response"| Envoy +``` + +### Configuration + +Enable management mode in the auth service config (`services/core/auth/config.yaml` for local development): + +```yaml +service: + name: auth + domain: core + entrypoint: http://localhost:2221 + + network: + bind_address: localhost + bind_port: 9095 + internal: + host: host.docker.internal + port: 9095 + +auth: + mode: authentik + authentik: + url: http://localhost:9050 + api_token: "${AUTHENTIK_BOOTSTRAP_TOKEN}" # same token seeded by compose + external_host: http://localhost:10000 # Envoy public URL for proxy provider + management: + enabled: true + sync_interval: 30s +``` + +`api_token` is the same `AUTHENTIK_BOOTSTRAP_TOKEN` value you generated in the prerequisites — the auth service reads it from this config (or its environment) and presents it as a Bearer token on every Authentik API call. + +### Auth Management API + +The auth service exposes a `AuthManagementService` alongside the ext_authz check endpoint. These RPCs are usable from `dctl` or any ConnectRPC client: + +| RPC | Purpose | +|---|---| +| `SyncRoutes` | Trigger an immediate full reconcile of all Blueprint routes against Authentik. Returns a report of what was created, updated, or was already present. | +| `EnsureGroup(name)` | Idempotent: create a group in Authentik if it does not exist. Returns the group's Authentik UUID. | +| `EnsureScope(name)` | Idempotent: create an OAuth2 scope mapping if it does not exist. | +| `GetStatus` | Returns Authentik connectivity state and a summary of the last reconcile pass (group count, scope count, last sync time). | + +#### Triggering a manual sync + +```shell +# Via dctl (once dctl auth subcommand is added) +dctl auth sync + +# Or directly via grpcurl +grpcurl -plaintext localhost:9095 \ + core.auth.v1.AuthManagementService/SyncRoutes +``` + +### Route watcher behaviour + +The watcher runs as a background goroutine inside the auth service. Every `sync_interval` (default 30s) it: + +1. Lists all service registrations from Blueprint KV +2. For each route with `AUTH_POLICY_GROUPS`: calls `EnsureGroup` for each entry in `required_groups` +3. For each route with `AUTH_POLICY_SCOPES`: calls `EnsureScope` for each entry in `required_scopes` +4. Logs a summary of any changes made + +If Authentik is temporarily unavailable, the watcher logs the error and retries on the next interval. The check server continues serving from its last known state — it does not stop accepting ext_authz requests during a failed sync. + +### Startup reconciliation + +In `authentik` mode the auth service blocks the check server from serving traffic until: + +1. Authentik's `/api/v3/root/config/` returns healthy +2. One full reconcile pass completes successfully + +This ensures that by the time Envoy's first check request arrives, every group and scope declared in the current route config already exists in Authentik. + +--- + +## Workflow: combining both options + +The typical lifecycle for a Draft cluster looks like this: + +```mermaid +sequenceDiagram + participant Dev as Developer + participant Compose as docker compose up + participant Blueprint as Blueprint YAML + participant AuthSvc as Auth Service + participant Authentik as Authentik + + Dev->>Compose: docker compose -f docker-compose.auth.yaml up + Compose->>Authentik: start postgres, redis, server, worker + Authentik->>Blueprint: apply /blueprints/custom/draft.yaml + Blueprint-->>Authentik: proxy provider + application + outpost ✓ + + Dev->>Compose: start auth service (VS Code or dctl run) + AuthSvc->>Authentik: GET /api/v3/root/config/ (health check) + AuthSvc->>Authentik: EnsureGroup("admins") for each route policy + AuthSvc->>Authentik: EnsureScope("read:data") for each scope policy + AuthSvc-->>Dev: reconcile complete, check server ready + + Dev->>Dev: add new service with AUTH_POLICY_GROUPS: ["editors"] + AuthSvc->>Authentik: EnsureGroup("editors") [next sync interval] + Dev->>Authentik: assign users to "editors" group via UI +``` + +**Day 1**: Run `docker compose up` → Blueprint YAML creates provider, application, outpost. Visit `http://localhost:9050/if/flow/initial-setup/` to create the admin account. + +**Ongoing**: Auth service watcher keeps groups and scopes in sync as services declare new policies. No manual Authentik UI work is needed for group/scope creation — only for assigning users to groups. + +--- + +## Local development without Authentik + +For development where you want auth policy enforced in route config but don't want to run the full Authentik stack, set bypass mode: + +```yaml +# services/core/auth/config.yaml +auth: + mode: bypass +``` + +In bypass mode the auth service returns `200 OK` for every check request and writes `X-Authentik-Username: bypass-user` as a passthrough header. Fuse still enables the ext_authz filter (the auth service is still registered with Blueprint), but no Postgres, Redis, or Authentik process is required. + +Switch back to `mode: authentik` and start the compose stack when you need to test real auth flows. + +--- + +## Environment variable reference + +| Variable | Required | Description | +|---|---|---| +| `AUTHENTIK_SECRET_KEY` | Yes | Authentik's internal signing secret. Generate with `openssl rand -base64 60`. | +| `AUTHENTIK_BOOTSTRAP_TOKEN` | Yes | Seeds an API key for `akadmin` on first startup. The auth service uses this same value. Generate with `openssl rand -hex 32`. | +| `AUTHENTIK_DRAFT_EXTERNAL_HOST` | No | The public URL of the Envoy gateway. Used in the Proxy Provider as the post-login redirect target. Defaults to `http://localhost:10000`. | + +--- + +## VS Code launch configurations + +The `.vscode/launch.json` in the root of the repository includes ready-to-use launch configurations: + +| Configuration | What it starts | +|---|---| +| `Auth` | The auth core service (`services/core/auth/main.go`) using `services/core/auth/config.yaml` | +| `Auth Example` | The example auth service (`services/examples/auth/main.go`) for testing BYPASS and GROUPS policies locally | +| `Auth (core + example)` | Compound: starts both `Auth` and `Auth Example` together | + +Start Blueprint and Fuse first, then use the `Auth (core + example)` compound to bring up the auth layer. diff --git a/docs/website/content/docs/architecture/authentication.md b/docs/website/content/docs/architecture/authentication.md new file mode 100644 index 00000000..4b9a0d82 --- /dev/null +++ b/docs/website/content/docs/architecture/authentication.md @@ -0,0 +1,583 @@ +--- +weight: 20 +title: 'Authentication & Authorization' +description: 'How authentication and per-route authorization work within a Draft cluster' +icon: 'lock' +draft: false +toc: true +--- + +Authentication and authorization in a Draft cluster are handled at the proxy layer by [Envoy](https://www.envoyproxy.io/), controlled dynamically through [Fuse](/docs/architecture/core-services#fuse). Every inbound request — whether from an end-user browser, a mobile client, or another service within the cluster — passes through Envoy before reaching its destination. This gives Draft a single, consistent enforcement point for auth policy regardless of which service or RPC method is being called. + +The identity provider is [Authentik](https://goauthentik.io/), an open-source identity platform that handles both human user authentication (SSO, OIDC) and machine-to-machine (M2M) service authentication (OAuth2 `client_credentials` grant, JWT bearer tokens). Authentik is deployed alongside the Draft core services and is itself a registered Draft process. + +```mermaid +flowchart LR + Client(["Client\nbrowser · service · mobile"]) + + subgraph cluster["Draft Cluster"] + Envoy["Envoy\next_authz filter"] + App["Application Service"] + Outpost["Authentik Outpost\nauth sidecar"] + AuthServer["Authentik Server\nOIDC / policies"] + Fuse["Fuse\ncontrol plane"] + end + + Client -- "request" --> Envoy + Envoy -- "① check request" --> Outpost + Outpost <-- "policy sync\nWebSocket" --> AuthServer + Outpost -- "② 200 OK + identity headers" --> Envoy + Envoy -- "③ forward on allow" --> App + Fuse -. "xDS config" .-> Envoy +``` + +--- + +## Why Authentik + +[#why-authentik](#why-authentik) + +Two identity providers were evaluated: [Authelia](https://www.authelia.com/) and [Authentik](https://goauthentik.io/). Both support Envoy's `ext_authz` HTTP filter, which is the integration point used by Draft. The decision criteria centered on how well each handled the service-to-machine (M2M) use case, because Draft services call each other's RPCs directly and need a first-class way to issue and validate service identities. + +| Criteria | Authelia | Authentik | +|---|---|---| +| Envoy ext_authz | Yes (HTTP) | Yes (HTTP, via outpost) | +| Per-route policies | Path/group regex rules | Flows + Expression Policies | +| M2M `client_credentials` | Workaround (username/password) | First-class (`client_id` + `client_secret`) | +| JWT bearer / JWKS federation | Limited | Yes | +| Service account lifecycle | Manual | Auto-provisioned per provider | +| Kubernetes-native deployment | Standalone binary | Outpost model (K8s Deployment) | + +Authentik's **outpost model** is the key differentiator. The outpost is a lightweight proxy process deployed as a Kubernetes Deployment that connects to the Authentik server via WebSocket for live policy updates. Envoy routes its auth check requests to the outpost — not the Authentik server directly — which keeps the critical auth check path low-latency and available even if the Authentik server is temporarily unreachable. + +Authelia is a reasonable choice for clusters that only need to protect human-facing UIs, but its M2M support is bolted on. Authentik was designed for both human and service identity from the start. + +--- + +## How ext_authz Works + +[#how-ext_authz-works](#how-ext_authz-works) + +Envoy's [External Authorization filter](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/ext_authz_filter) (`ext_authz`) intercepts every inbound HTTP request before it is forwarded to the upstream service. For each request, Envoy forwards a **check request** to the Authentik outpost containing the original request headers, method, path, and any per-route context extensions configured by Fuse. The outpost responds with one of: + +- **200 OK** — request is allowed; the outpost adds user identity headers (e.g. `X-Authentik-Username`, `X-Authentik-Groups`) that are forwarded to the upstream service +- **401 / 403** — request is denied; Envoy returns the denial response to the caller without contacting the upstream + +This check happens at the HTTP layer, which means it works uniformly for browser requests, REST calls, and ConnectRPC/gRPC calls. ConnectRPC method paths follow the pattern `/package.service.v1.ServiceName/MethodName`, which are plain HTTP paths from Envoy's perspective, so path-based routing and auth policies apply without any special handling. + +```mermaid +sequenceDiagram + participant C as Client + participant E as Envoy (ext_authz) + participant O as Authentik Outpost + participant U as Upstream Service + + C->>E: inbound request + E->>O: check request (headers, path, method, context extensions) + alt request allowed + O-->>E: 200 OK + identity headers + E->>U: forward request + identity headers + U-->>E: response + E-->>C: response + else request denied + O-->>E: 401 / 403 denial + E-->>C: 401 / 403 denial + end +``` + +The `ext_authz` filter is configured on the Envoy **listener** (applied globally to all routes), while each individual route can override the filter behavior via Envoy's `typed_per_filter_config` mechanism. This allows Fuse to declare some routes as public (auth bypassed) and others as protected with specific group or scope requirements — all driven from the same Route configuration that services already register. + +--- + +## Route Auth Configuration + +[#route-auth-configuration](#route-auth-configuration) + +Authentication policy is declared per-route when a service registers its routes with Fuse. The `Route` proto message in `api/core/control_plane/networking/v1/service.proto` is extended with an optional `RouteAuth` block: + +```protobuf +enum AuthPolicy { + AUTH_POLICY_BYPASS = 0; // public — no check + AUTH_POLICY_AUTHENTICATED = 1; // any valid token accepted + AUTH_POLICY_GROUPS = 2; // token must carry required_groups + AUTH_POLICY_SCOPES = 3; // token must carry required_scopes +} + +message RouteAuth { + bool enabled = 1; + AuthPolicy policy = 2; + repeated string required_groups = 3; // e.g. ["admins", "internal-services"] + repeated string required_scopes = 4; // OAuth2 scopes required on the token +} + +message Route { + string name = 1; + RouteMatch match = 2; + Endpoint endpoint = 3; + bool enable_http2 = 4; + RouteAuth auth = 5; // optional; defaults to bypass if absent +} +``` + +`RouteAuth` is optional. If absent (or `enabled = false`), Fuse generates an `ExtAuthzPerRoute { disabled: true }` Envoy config for that route — no check request is made and the route is treated as public. + +--- + +## Fuse Control Plane Changes + +[#fuse-control-plane-changes](#fuse-control-plane-changes) + +Fuse's `apply()` function in `services/core/fuse/control_plane/controller.go` already rebuilds and pushes a full Envoy xDS snapshot whenever a route is added. The auth extension adds two new responsibilities to `apply()`: + +**1. Global ext_authz cluster and filter** + +When Fuse starts, it reads the Authentik outpost address from Blueprint KV (key: `auth_service_address`). This address is added as a cluster to the Envoy snapshot and as an `HttpFilter` on the listener's `HttpConnectionManager`, placed before the router filter: + +```mermaid +flowchart LR + F0["[0] ext_authz filter"] -->|"check request"| AO["Authentik Outpost cluster"] + F0 --> F1["[1] router filter"] + F1 --> US["Upstream Service"] +``` + +If no `auth_service_address` is found in Blueprint KV, Fuse omits the ext_authz filter entirely and all routes are effectively public. This preserves backward compatibility for clusters that have not yet deployed Authentik. + +**2. Per-route typed_per_filter_config** + +When building the route table inside `makeRouterConfig()`, Fuse inspects each route's `RouteAuth` and attaches the appropriate per-route override: + +| `RouteAuth` state | Envoy per-route config | +|---|---| +| `auth` absent or `enabled = false` | `ExtAuthzPerRoute { disabled: true }` | +| `AUTH_POLICY_BYPASS` | `ExtAuthzPerRoute { disabled: true }` | +| `AUTH_POLICY_AUTHENTICATED` | `ExtAuthzPerRoute { check_settings: {} }` | +| `AUTH_POLICY_GROUPS` | `ExtAuthzPerRoute { check_settings: { context_extensions: { "required_groups": "admin,ops" } } }` | +| `AUTH_POLICY_SCOPES` | `ExtAuthzPerRoute { check_settings: { context_extensions: { "required_scopes": "read:courses write:scores" } } }` | + +Context extensions are forwarded by Envoy to the Authentik outpost inside the check request. Authentik Expression Policies read these extensions and enforce the declared requirements before issuing an allow or deny response. + +--- + +## Chassis API + +[#chassis-api](#chassis-api) + +Services declare their auth requirements through the existing `WithRoute()` builder on the chassis, extended to accept the new `RouteAuth` field: + +```go +chassis.New(logger). + Register(chassis.RegistrationOptions{ + Namespace: "golf", + }). + WithRPCHandler(ctrl). + // Public read — no auth check + WithRoute(&ntv1.Route{ + Name: "list-courses", + Match: &ntv1.RouteMatch{ + Prefix: "/golf.v1.CourseCreator/ListCourses", + }, + Auth: &ntv1.RouteAuth{ + Policy: ntv1.AuthPolicy_AUTH_POLICY_BYPASS, + }, + }). + // Mutating methods require a valid token from an internal service group + WithRoute(&ntv1.Route{ + Name: "create-course", + Match: &ntv1.RouteMatch{ + Prefix: "/golf.v1.CourseCreator/CreateCourse", + }, + Auth: &ntv1.RouteAuth{ + Enabled: true, + Policy: ntv1.AuthPolicy_AUTH_POLICY_GROUPS, + RequiredGroups: []string{"internal-services", "admins"}, + }, + }). + Start() +``` + +The `WithRoute()` implementation in `pkg/chassis/builder.go` already calls `AddRoute` on the Fuse control plane. No changes are needed to the call site — Fuse reads the `auth` field from the proto and handles the rest. + +### Per-Method Granularity + +Because ConnectRPC paths are `/package.service.v1.ServiceName/MethodName`, registering separate routes for each method gives method-level access control. Envoy selects routes by longest prefix match, so a route for `/golf.v1.CourseCreator/CreateCourse` takes priority over a more general prefix for `/golf.v1.CourseCreator/`. There is no limit to how fine-grained this can be: + +```go +// Allow everyone to list +WithRoute(&ntv1.Route{ + Match: &ntv1.RouteMatch{Prefix: "/golf.v1.ShotTracker/ListShots"}, + Auth: &ntv1.RouteAuth{Policy: ntv1.AuthPolicy_AUTH_POLICY_BYPASS}, +}) + +// Only the owning player or admins can record shots +WithRoute(&ntv1.Route{ + Match: &ntv1.RouteMatch{Prefix: "/golf.v1.ShotTracker/RecordShot"}, + Auth: &ntv1.RouteAuth{ + Enabled: true, + Policy: ntv1.AuthPolicy_AUTH_POLICY_GROUPS, + RequiredGroups: []string{"players", "admins"}, + }, +}) +``` + +--- + +## Machine-to-Machine Authentication + +[#machine-to-machine-authentication](#machine-to-machine-authentication) + +Draft services that call other services' RPCs authenticate using Authentik's OAuth2 `client_credentials` grant. Each service is provisioned with a `client_id` and `client_secret` at startup (stored in Blueprint KV or a secret vault plugin), and exchanges them for a short-lived JWT access token: + +```mermaid +sequenceDiagram + participant A as Service A + participant Auth as Authentik Server + participant E as Envoy + participant O as Authentik Outpost + participant B as Service B + + A->>Auth: POST /o/token/ (grant_type=client_credentials, client_id, client_secret) + Auth-->>A: JWT access token + + A->>E: RPC call (Authorization: Bearer token) + E->>O: ext_authz check request + O->>O: validate token, check group membership + O-->>E: 200 OK + identity headers + E->>B: forward RPC + identity headers + B-->>E: RPC response + E-->>A: RPC response +``` + +The chassis will provide a helper in `pkg/chassis` for managing this token lifecycle — fetching a token on first use, caching it for the duration of its `expires_in`, and refreshing before expiry. Services that use this helper need only configure their `client_id` and `client_secret`; token management is transparent. + +### Token Forwarding to Upstream Services + +When the Authentik outpost allows a request, it adds identity headers that the upstream service can read to learn who the caller is: + +| Header | Value | +|---|---| +| `X-Authentik-Username` | The service account name (M2M) or user's username | +| `X-Authentik-Groups` | Comma-separated list of groups the caller belongs to | +| `X-Authentik-Email` | The caller's email (human users) | +| `X-Authentik-Uid` | The caller's unique ID in Authentik | + +These headers are set by the outpost and forwarded by Envoy. Services can trust them because they are always stripped by Envoy before the check (callers cannot inject them) and only re-added by the outpost after a successful validation. + +--- + +## Auth Core Service + +[#auth-core-service](#auth-core-service) + +Authentik is a third-party binary — it has no knowledge of Blueprint and cannot use the Draft chassis to register itself. This creates a gap: Fuse needs to discover the auth endpoint via Blueprint KV (the same pattern used for `fuse_address`), but nothing in the Authentik stack can write that key. + +The solution is a new thin Draft core service, `services/core/auth`, that bridges the two worlds: + +1. It registers with Blueprint via the standard chassis registration flow, giving it a tracked process identity with health and running state. +2. It serves the Envoy ext_authz HTTP check endpoint on its own port. +3. At startup it writes its own address to Blueprint KV under `auth_service_address`, which Fuse reads to enable the ext_authz filter. +4. It forwards incoming check requests to the configured Authentik endpoint and relays the response back to Envoy. + +```mermaid +sequenceDiagram + participant F as Fuse + participant B as Blueprint KV + participant A as Auth Service + participant K as Authentik Server + + A->>B: Register (chassis) + A->>B: Set auth_service_address = http://auth:9090 + F->>B: Read auth_service_address + B-->>F: http://auth:9090 + F->>F: Rebuild xDS snapshot with ext_authz cluster + + note over F,K: Per-request check flow + F->>A: ext_authz check request (headers, path, context extensions) + A->>K: Forward to /outpost.goauthentik.io/auth/envoy + K-->>A: 200 OK + identity headers (or 401/403) + A-->>F: Relay response +``` + +The auth service supports a **bypass mode** (`auth.mode: bypass`) that returns 200 for every check request without contacting Authentik. This lets developers run a full Draft cluster locally without standing up Authentik's PostgreSQL and Redis dependencies. + +### Auth Service Config + +```yaml +service: + name: auth + domain: core + entrypoint: http://blueprint:2221 + network: + bind_address: 0.0.0.0 + bind_port: 9090 + internal: + host: auth + port: 9090 + +auth: + mode: authentik # or "bypass" for local dev without Authentik + authentik: + url: http://authentik-server:9000 +``` + +Fuse watches for `auth_service_address` in Blueprint KV. When the auth service starts and writes the key, Fuse regenerates the Envoy snapshot to include the ext_authz filter. When the auth service stops and Blueprint marks it unhealthy, Fuse detects the absence on the next poll and falls back to a public-access snapshot. + +This means auth is **opt-in at the cluster level**: a Draft cluster without the auth service behaves exactly as it does today — no auth checks, no changes needed to existing services. + +--- + +## Deployment + +[#deployment](#deployment) + +Within a Kubernetes cluster, the recommended topology is: + +```mermaid +graph TB + subgraph k8s["Kubernetes Cluster"] + subgraph core["Draft Core Namespace"] + Blueprint["Blueprint Pod"] + Fuse["Fuse Pod"] + Catalyst["Catalyst Pod"] + Auth["Auth Pod\ndraft-core-auth"] + AuthentikServer["Authentik Server Pod\n+ embedded outpost"] + AuthentikWorker["Authentik Worker Pod"] + Postgres["PostgreSQL Pod"] + Redis["Redis Pod"] + end + + subgraph apps["Application Namespace"] + GolfApp["Golf App Pod"] + OtherServices["Other Service Pods"] + end + end + + Auth --> Blueprint + Auth --> AuthentikServer + AuthentikServer --> Postgres + AuthentikServer --> Redis + AuthentikWorker --> Postgres + AuthentikWorker --> Redis +``` + +The **Auth Service** (`draft-core-auth`) is the only component that registers with Blueprint. It is the ext_authz endpoint that Envoy talks to, and it delegates policy decisions to Authentik. + +The **Authentik Server** is the identity backend — it holds users, groups, flows, and policies, and issues tokens. It bundles an embedded outpost (the component the auth service proxies to) so no separate outpost deployment is required. It requires a PostgreSQL database and Redis. + +The **Authentik Worker** runs background tasks (policy evaluation caching, token cleanup, flow execution) and must share the same database and Redis as the server. + +--- + +## Implementation Plan + +[#implementation-plan](#implementation-plan) + +The work is divided into five phases, each independently deployable. + +### Phase 1 — Proto Extension + +Extend `api/core/control_plane/networking/v1/service.proto` with the `RouteAuth` message and the `auth` field on `Route`. Run `dctl api build` to regenerate Go, Rust, and TypeScript clients. No behavioral changes — existing routes with no `auth` field continue to work as before. + +### Phase 2 — Fuse ext_authz Support + +Update `services/core/fuse/control_plane/controller.go`: + +1. Read `auth_service_address` from Blueprint KV at startup and on change +2. When the address is present, add the auth service as a cluster in the xDS snapshot +3. Add the ext_authz `HttpFilter` to the listener's `HttpConnectionManager` (before the router filter) +4. In `makeRouterConfig()`, generate `typed_per_filter_config` per route based on the `RouteAuth` field + +If `auth_service_address` is absent from Blueprint KV, Fuse omits the ext_authz filter entirely and all routes remain public. This means Phase 2 can be deployed before Phase 3 without breaking anything. + +### Phase 3 — Auth Core Service + +Create `services/core/auth` — a new Draft core service that bridges Blueprint and Authentik. + +**Directory layout:** +``` +services/core/auth/ + main.go # chassis registration, writes auth_service_address to Blueprint KV + handler.go # ext_authz HTTP check endpoint + forwarder.go # proxies check requests to Authentik (or bypass) + config.go # typed config struct +``` + +**Startup sequence:** +1. Register with Blueprint via `chassis.Register()` (same as every other core service) +2. Read `auth.mode` from config — either `authentik` or `bypass` +3. Write own address to Blueprint KV under `auth_service_address` +4. Start serving the ext_authz HTTP endpoint + +**Bypass mode** — for local development without Authentik: + +```yaml +auth: + mode: bypass +``` + +In bypass mode the handler returns `200 OK` for every check request. This lets the full Draft stack run locally with auth enforcement enabled in the route config, but without requiring Postgres, Redis, or Authentik. + +**Authentik mode** — for staging and production: + +```yaml +auth: + mode: authentik + authentik: + url: http://authentik-server:9000 +``` + +The handler forwards the original request headers to `{authentik.url}/outpost.goauthentik.io/auth/envoy` and relays the response (status code + headers) back to Envoy unchanged. + +#### Local Docker Compose + +A new `deployments/compose/docker-compose.auth.yaml` layers on top of the existing `docker-compose.yaml` to add Authentik and the auth service: + +```yaml +name: draft-auth + +services: + postgres: + image: docker.io/library/postgres:16-alpine + restart: unless-stopped + environment: + POSTGRES_PASSWORD: authentik + POSTGRES_USER: authentik + POSTGRES_DB: authentik + volumes: + - postgres:/var/lib/postgresql/data + + redis: + image: docker.io/library/redis:alpine + restart: unless-stopped + + authentik-server: + image: ghcr.io/goauthentik/server:2024.12.3 + restart: unless-stopped + command: server + environment: + AUTHENTIK_REDIS__HOST: redis + AUTHENTIK_POSTGRESQL__HOST: postgres + AUTHENTIK_POSTGRESQL__USER: authentik + AUTHENTIK_POSTGRESQL__PASSWORD: authentik + AUTHENTIK_POSTGRESQL__NAME: authentik + AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} + ports: + - 9000:9000 + depends_on: + - postgres + - redis + + authentik-worker: + image: ghcr.io/goauthentik/server:2024.12.3 + restart: unless-stopped + command: worker + environment: + AUTHENTIK_REDIS__HOST: redis + AUTHENTIK_POSTGRESQL__HOST: postgres + AUTHENTIK_POSTGRESQL__USER: authentik + AUTHENTIK_POSTGRESQL__PASSWORD: authentik + AUTHENTIK_POSTGRESQL__NAME: authentik + AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} + depends_on: + - postgres + - redis + + auth: + image: ghcr.io/steady-bytes/draft-core-auth:latest + restart: unless-stopped + ports: + - 9090:9090 + volumes: + - ./auth.yaml:/etc/config.yaml + depends_on: + authentik-server: + condition: service_started + blueprint: + condition: service_started + +volumes: + postgres: +``` + +With a corresponding `deployments/compose/auth.yaml` config: + +```yaml +service: + name: auth + domain: core + entrypoint: http://blueprint:2221 + network: + bind_address: 0.0.0.0 + bind_port: 9090 + internal: + host: auth + port: 9090 + +auth: + mode: authentik + authentik: + url: http://authentik-server:9000 +``` + +**Starting the full stack locally:** + +```shell +# Core Draft services only (no auth) +docker compose -f deployments/compose/docker-compose.yaml up + +# Core Draft services + Authentik +AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60) \ + docker compose \ + -f deployments/compose/docker-compose.yaml \ + -f deployments/compose/docker-compose.auth.yaml \ + up +``` + +Authentik's first-run setup wizard is available at `http://localhost:9000/if/flow/initial-setup/` after the server starts. + +{{< alert context="info" text="Generate a stable AUTHENTIK_SECRET_KEY once and store it in a local .env file at deployments/compose/.env. Docker Compose loads .env automatically. Never commit this file." />}} + +### Phase 4 — Authentik Configuration + +With Authentik running, configure the identity policies through its UI or Terraform provider: + +- An **OIDC provider** for human user SSO (browser login flows) +- An **OAuth2 provider** for M2M `client_credentials` flows, with service accounts for each core Draft service (Blueprint, Catalyst, Fuse, Auth) +- **Expression policies** that read the `required_groups` and `required_scopes` context extensions forwarded by Envoy and enforce group membership or scope requirements before issuing an allow response + +Once the auth service is running and `auth_service_address` is written to Blueprint KV, Fuse will automatically enable the ext_authz filter on the next snapshot push. + +### Phase 5 — Chassis M2M Helper + +Add a token manager to `pkg/chassis` that: + +1. Reads `client_id` and `client_secret` from the service's config (or secret vault plugin) +2. Fetches a JWT from Authentik on first outbound RPC call +3. Caches the token until `expires_in - 30s` +4. Injects `Authorization: Bearer ` into outbound ConnectRPC requests + +Services opt in by calling a new builder method: + +```go +chassis.New(logger). + Register(...). + WithM2MAuth(chassis.M2MAuthOptions{ + TokenURL: "http://authentik-server:9000/application/o/token/", + ClientID: cfg.ClientID, + ClientSecret: cfg.ClientSecret, + }). + Start() +``` + +--- + +## Open Questions + +[#open-questions](#open-questions) + +The following items require further investigation before or during implementation: + +- **Outpost and HTTP/2 trailers**: ConnectRPC error responses use HTTP trailers. Verify that the Authentik outpost correctly handles the HTTP/2 framing used by Envoy when proxying ConnectRPC denials (4xx responses with gRPC status trailers). +- **Core service auth**: Blueprint, Catalyst, and Fuse call each other during startup, before Authentik is available. The startup order and whether core-to-core calls need auth at all must be decided. The simplest approach is to exempt the internal cluster network CIDR from ext_authz checks using Envoy's `peer_is_trusted_cluster` configuration. +- **Token propagation across service hops**: If Service A calls Service B which calls Service C, does Service B forward the original token or present its own service identity to C? A consistent policy needs to be defined. +- **Secret storage for client credentials**: `client_id` and `client_secret` should not be in plaintext config. The chassis secret vault plugin (if available) or Kubernetes Secrets should be used. +- **Auth service HA**: In a multi-node Draft cluster, determine the recommended number of auth service replicas and how Fuse's Envoy cluster config should reference them (single Service VIP vs. strict DNS EDS). Authentik itself is stateless between requests (policy state lives in its PostgreSQL + Redis), so the auth service can be replicated freely once those dependencies are HA. diff --git a/docs/website/content/docs/architecture/blueprint-web-client-components.md b/docs/website/content/docs/architecture/blueprint-web-client-components.md new file mode 100644 index 00000000..cba5a676 --- /dev/null +++ b/docs/website/content/docs/architecture/blueprint-web-client-components.md @@ -0,0 +1,255 @@ +--- +weight: 4 +title: 'Blueprint Web Client Components' +description: 'A reference guide to the reusable Dioxus components that make up the Blueprint web client UI.' +icon: 'dashboard' +draft: false +toc: true +--- + +The Blueprint web client is a Dioxus (Rust/WASM) single-page application that provides a control panel for Draft clusters. Its UI is built from a set of reusable components living in `services/core/blueprint/web-client/src/components/`. This page documents each component, its inputs, and its purpose. + +--- + +## WaveLoader + +**File:** `wave_loader.rs` + +An animated sound-wave loading indicator made of seven thin white SVG bars. Each bar pulses at a slightly different speed and delay to produce a random, organic wave effect. The animation keyframes are embedded directly in the SVG so the component has no external CSS dependency. + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `width` | `u32` | `80` | Width of the SVG in pixels. | +| `height` | `u32` | `30` | Height of the SVG in pixels. Bars scale to fill the full height. | + +```rust +WaveLoader {} // 80 × 30 default +WaveLoader { width: 120, height: 40 } // larger variant +``` + +--- + +## CesqlBar + +**File:** `cesql_bar.rs` + +A single-row input bar for entering and running [CESQL](https://github.com/cloudevents/spec/blob/main/cesql/spec.md) filter expressions. Renders a text field, a clear (`✕`) button, and a **run** button joined into a single DaisyUI `join` group. Pressing Enter in the field also triggers `on_run`. + +| Prop | Type | Description | +|------|------|-------------| +| `expression` | `Signal` | Two-way binding for the current expression string. | +| `on_run` | `EventHandler<()>` | Called when the user clicks **run** or presses Enter. | +| `on_clear` | `EventHandler<()>` | Called when the user clicks the clear button. | + +```rust +CesqlBar { + expression, + on_run: move |_| run_query.call(()), + on_clear: move |_| expression.set(String::new()), +} +``` + +--- + +## FilterChips + +**File:** `filter_chips.rs` + +A horizontal row of clickable badge chips, each representing a common preset CESQL expression (e.g. `type = 'order.created'`, `source LIKE '%shop%'`). Clicking a chip calls `on_select` with the full CESQL string, which the parent can append to the expression bar. + +| Prop | Type | Description | +|------|------|-------------| +| `on_select` | `EventHandler` | Called with the preset CESQL expression string when a chip is clicked. | + +```rust +FilterChips { + on_select: move |expr: String| expression.set(expr), +} +``` + +--- + +## TypeBadge + +**File:** `type_badge.rs` + +A small colored badge that displays a CloudEvent `type` string. The badge color is deterministically derived from the event type name via a hash, so the same type always renders in the same color across the UI. + +| Prop | Type | Description | +|------|------|-------------| +| `event_type` | `String` | The CloudEvent type string to display (e.g. `"com.shop.order.created"`). | + +```rust +TypeBadge { event_type: event.r#type.clone() } +``` + +--- + +## QueryBuilder + +**File:** `query_builder.rs` + +A collapsible form that guides the user through building a CESQL filter expression without writing it by hand. The user picks a field (`type`, `source`, `id`, `subject`, or `body.*`), an operator (`=` or `LIKE`), and a value. A live preview shows the resulting fragment before it is added. Also contains an ORDER BY toggle for controlling query sort direction. + +When `has_expression` is true an AND/OR connector toggle appears so the new fragment can be joined to an existing expression. + +| Prop | Type | Description | +|------|------|-------------| +| `has_expression` | `bool` | Whether an expression already exists. Controls whether the AND/OR connector is shown. | +| `on_add` | `EventHandler` | Called with the generated CESQL fragment (prefixed with `"OR "` or `"AND "` when joining). | +| `sort_dir` | `SortDir` | Current sort direction (`SortDir::Asc` or `SortDir::Desc`). | +| `on_sort_change` | `EventHandler` | Called when the user changes the ORDER BY direction. | + +```rust +QueryBuilder { + has_expression: !expression.read().is_empty(), + sort_dir: sort_dir(), + on_sort_change: move |dir: SortDir| { sort_dir.set(dir); run_query.call(()); }, + on_add: move |fragment: String| { + let current = expression.read().clone(); + expression.set(if current.trim().is_empty() { fragment } + else { format!("{current} {fragment}") }); + }, +} +``` + +--- + +## MetricCard + +**File:** `metric_card.rs` + +A dashboard-style card that displays a single metric value with a label, optional unit, trend indicator, and a small sparkline chart. The trend arrow and color respond to `trend_up` and `trend_good` so the card can express both direction and health independently. + +| Prop | Type | Description | +|------|------|-------------| +| `icon` | `MetricIcon` | Icon displayed in the card header. One of: `Messages`, `Clock`, `Warning`, `Users`, `Server`, `ArrowUp`. | +| `label` | `String` | Uppercase label shown above the value (e.g. `"MESSAGES / MIN"`). | +| `value` | `String` | The primary value displayed in large text. Pass `"—"` when data is unavailable. | +| `unit` | `Option` | Optional unit suffix rendered smaller next to the value (e.g. `Some("ms")`). | +| `trend_up` | `bool` | `true` renders an upward arrow `↑`, `false` renders a downward arrow `↓`. | +| `trend_good` | `bool` | `true` colors the trend green, `false` colors it red. | +| `trend_delta` | `String` | Label shown next to the trend arrow (e.g. `"live"`, `"since start"`). | +| `sparkline_data` | `Vec` | Series of data points rendered as a polyline sparkline. Needs at least 2 points. | +| `sparkline_color` | `String` | CSS color string for the sparkline stroke (e.g. `"#4ade80"`). | + +```rust +MetricCard { + icon: MetricIcon::Messages, + label: "MESSAGES / MIN".to_string(), + value: m.msgs_per_min.to_string(), + unit: None, + trend_up: true, + trend_good: true, + trend_delta: "live".to_string(), + sparkline_data: vec![280.0, 295.0, 310.0, 290.0, 305.0], + sparkline_color: "#4ade80".to_string(), +} +``` + +--- + +## Hero + +**File:** `hero.rs` + +A full-screen DaisyUI hero section shown on the Blueprint landing page. Displays the application name and a link to the Draft documentation. Takes no props — the application name is read from a global signal. + +```rust +Hero {} +``` + +--- + +## ArcSpine + +**File:** `arc_spine.rs` + +An SVG visualization that renders the event topology as a two-column arc diagram. Producers appear on the left, consumers on the right, and edges between them are drawn as cubic Bézier curves colored by event type. Nodes are interactive — clicking one highlights its connected edges and dims the rest. Bundled edges between the same producer/consumer pair are fanned out with a small offset. + +| Prop | Type | Description | +|------|------|-------------| +| `data` | `TopologyData` | The full topology snapshot: producers, consumers, and edges with event types. | + +See [Topology Data Types](#topology-data-types) below for the shape of `TopologyData`. + +```rust +ArcSpine { data: topology_data } +``` + +--- + +## FullCircle + +**File:** `full_circle.rs` + +An SVG visualization that arranges all topology nodes (producers and consumers) evenly around a single circle. Edges are drawn as Bézier curves through the center, with stroke weight and opacity scaled by message volume. Clicking a node opens a side panel listing its event connections and volumes. + +| Prop | Type | Description | +|------|------|-------------| +| `data` | `TopologyData` | The full topology snapshot: producers, consumers, and edges with volume counts. | + +```rust +FullCircle { data: topology_data } +``` + +--- + +## Navbar Helpers + +**File:** `navbar.rs` + +Three zero-argument helper functions used to compose the application navbar. They are free functions rather than components — call them with `{navbar_icon()}` syntax inside RSX. + +| Function | Description | +|----------|-------------| +| `navbar_icon()` | Renders the application name as a link back to the Key Value view. | +| `navbar_menu_button()` | Renders a hamburger icon button that opens the DaisyUI drawer sidebar. | +| `navbar_secondary_menu_button()` | Renders a three-dot overflow button for secondary navigation actions. | + +--- + +## Topology Data Types + +**File:** `topology.rs` + +Shared data structures passed to `ArcSpine` and `FullCircle`, plus a color-mapping helper used across topology and event table views. + +### `TopologyData` + +| Field | Type | Description | +|-------|------|-------------| +| `producers` | `Vec` | Services that publish CloudEvents. | +| `consumers` | `Vec` | Services that subscribe to CloudEvents. | +| `edges` | `Vec` | Directed flows from a producer to a consumer for a given event type. | + +### `TopologyNode` + +| Field | Type | Description | +|-------|------|-------------| +| `id` | `String` | Unique identifier for the node (matches the CloudEvent `source` field). | +| `name` | `String` | Human-readable display name. Falls back to `id` when empty. | + +### `TopologyEdge` + +| Field | Type | Description | +|-------|------|-------------| +| `producer_id` | `String` | `id` of the producing node. | +| `consumer_id` | `String` | `id` of the consuming node. | +| `event_type` | `String` | CloudEvent type string flowing along this edge. | +| `vol` | `u32` | Message volume count, used to scale visual weight in topology charts. | + +### `event_color(event_type: &str) -> &'static str` + +Maps well-known event type strings to hex color codes for consistent coloring across the UI. Falls back to `#6b7280` (gray) for unrecognized types. + +| Event type | Color | +|------------|-------| +| `"created"` | `#3b82f6` (blue) | +| `"cancelled"` | `#ef4444` (red) | +| `"ok"` | `#22c55e` (green) | +| `"failed"` | `#f97316` (orange) | +| `"reserved"` | `#a855f7` (purple) | +| `"updated"` | `#14b8a6` (teal) | +| `"registered"` | `#eab308` (yellow) | +| _other_ | `#6b7280` (gray) | diff --git a/docs/website/content/docs/architecture/cluster-graph-persistence.md b/docs/website/content/docs/architecture/cluster-graph-persistence.md new file mode 100644 index 00000000..f98181c4 --- /dev/null +++ b/docs/website/content/docs/architecture/cluster-graph-persistence.md @@ -0,0 +1,217 @@ +--- +weight: 5 +title: Cluster Graph — Persistence Implementation Plan +description: How the Blueprint web client renders the cluster graph with egui and persists layout state to localStorage and Blueprint KV. +icon: account_tree +draft: false +toc: true +--- + +The cluster page of the Blueprint web client renders a live graph of Draft core services using [egui](https://github.com/emilk/egui) embedded inside a Dioxus component. This document describes how the graph is built, how node layout is persisted to the browser's `localStorage`, and how that same layout will later be synced to Blueprint's key-value store so it survives across browsers and sessions. + +--- + +## Background — egui inside Dioxus + +Dioxus manages the page as a standard WASM single-page application. egui/eframe is a completely separate immediate-mode GUI framework that renders into an HTML `` element using WebGL (via `glow`). The two frameworks coexist by having Dioxus own the canvas DOM element and hand it off to eframe on mount. + +### Canvas lifecycle + +The `Cluster` Dioxus component renders a single ``. A `use_effect` hook fires on every mount: + +1. Destroys any previous `WebRunner` (the eframe instance handle) stored in a `thread_local` +2. Looks up the canvas element from the DOM by ID +3. Calls `WebRunner::start()` with the `HtmlCanvasElement`, initialising a fresh eframe app against the new canvas + +This destroy-and-recreate pattern is required because Dioxus unmounts and remounts components on route navigation. Each mount produces a new canvas DOM element — eframe must be reinitialised against it, not the previous one. + +```rust +thread_local! { + static RUNNER: RefCell> = const { RefCell::new(None) }; +} + +#[component] +pub fn Cluster() -> Element { + use_effect(move || { + RUNNER.with(|r| { + if let Some(old) = r.borrow_mut().take() { + old.destroy(); + } + }); + spawn(async move { + let canvas = web_sys::window() + .and_then(|w| w.document()) + .and_then(|d| d.get_element_by_id("cluster-egui-canvas")) + .and_then(|e| e.dyn_into::().ok()); + // ... start WebRunner + }); + }); + rsx! { + canvas { id: "cluster-egui-canvas", style: "width: 100%; height: 100%; display: block;" } + } +} +``` + +### Graph rendering + +The graph is rendered using [egui_graphs](https://github.com/blitzarx1/egui_graphs), which wraps a `petgraph::StableGraph` and provides an interactive `GraphView` widget. Nodes use a custom `SquareNodeShape` that implements the `DisplayNode` trait: + +- **Shape**: `RectShape` with `CornerRadius::ZERO` and a semi-transparent fill (`alpha = 20`) to give a "ghost square" appearance +- **Border**: 0.75px stroke, thickening to 1.5px when selected +- **Label**: rendered above each node using egui's font system; always visible +- **Edges**: 0.75px lines via `SettingsStyle::with_edge_stroke_hook` +- **Navigation**: zoom and pan enabled; initial fit-to-screen disabled so saved positions are respected + +Node positions are set at construction time using `add_node_with_label_and_location`, giving each core service (Blueprint, Catalyst, Fuse, Service A/B/C) a fixed starting position that the user can then drag. + +--- + +## Persistence — Phase 1: localStorage + +eframe includes a built-in persistence layer that reads and writes `localStorage` on the web. Implementing it requires three things: a serializable layout type, two helper functions, and two `App` lifecycle hooks. + +### Step 1 — Define `ClusterLayout` as a Protocol Buffer + +Rather than defining the layout type by hand in Rust, it is defined as a Protocol Buffer in the shared API layer. This ensures the Go server and Rust client share the same type definition from the start, with no translation required when Blueprint KV persistence is added later. + +**New file**: `api/core/registry/key_value/v1/cluster_layout.proto` + +```protobuf +syntax = "proto3"; + +package core.registry.key_value.v1; + +option go_package = "github.com/steady-bytes/draft/api/core/registry/key_value/v1"; + +message NodePosition { + float x = 1; + float y = 2; +} + +message ClusterLayout { + map positions = 1; // node label → position +} +``` + +Positions are keyed by node label string (e.g. `"Blueprint"`, `"Catalyst"`) rather than by petgraph node index. This means: + +- Adding or removing nodes in the future does not invalidate saved state for existing nodes +- The key maps directly to a Blueprint KV key (`cluster/layout`) without any transformation + +After creating the file, run: + +```shell +dctl api build +``` + +This generates: +- **Go**: a `ClusterLayout` struct in `github.com/steady-bytes/draft/api/core/registry/key_value/v1` +- **Rust**: a `ClusterLayout` struct via `prost`, available through the existing `draft-api` crate + +No new Cargo dependencies are needed — the web client already has `prost` and `draft-api`. + +Because `eframe::set_value` / `get_value` use serde JSON internally, the generated `ClusterLayout` and `NodePosition` types need `serde::Serialize` and `serde::Deserialize`. If `prost-build` is not configured to derive these, add a thin newtype wrapper or enable serde support in the build script. + +### Step 2 — Add extract / apply helpers + +Two pure functions in `cluster.rs` move data between the live graph and the proto layout type. These functions are the only place that knows about both representations, and they are shared by the localStorage and Blueprint KV paths. + +```rust +fn extract_layout(graph: &ClusterGraph) -> ClusterLayout { + // Iterate graph nodes, read SquareNodeShape.label_text and .pos, + // populate ClusterLayout.positions map +} + +fn apply_layout(graph: &mut ClusterGraph, layout: &ClusterLayout) { + // Iterate graph nodes, look up label_text in layout.positions, + // write pos if found — unknown labels are silently ignored +} +``` + +`apply_layout` ignoring unknown labels is the key invariant: it means a layout saved with six nodes will apply cleanly to a graph that now has seven, leaving the new node at its default position. + +### Step 3 — Hook into eframe's save / load cycle + +eframe calls `App::save` automatically on a ~30-second interval and whenever the app is about to close. No manual timer is needed. + +**Saving:** + +```rust +impl eframe::App for ClusterApp { + fn save(&mut self, storage: &mut dyn eframe::Storage) { + let layout = extract_layout(&self.graph); + eframe::set_value(storage, "cluster_layout", &layout); + } +} +``` + +**Loading:** + +```rust +impl ClusterApp { + fn new(cc: &eframe::CreationContext<'_>) -> Self { + let mut app = Self { graph: build_graph() }; + if let Some(layout) = cc.storage + .and_then(|s| eframe::get_value::(s, "cluster_layout")) + { + apply_layout(&mut app.graph, &layout); + } + app + } +} +``` + +`build_graph` constructs the graph with default node positions. The saved layout is then applied on top, overwriting positions for any node whose label appears in the saved data. + +### Step 4 — Verify persistence in `WebOptions` + +`WebOptions::default()` enables eframe's persistence layer on web. Confirm during implementation that `cc.storage` is `Some` on the first load after a save — if it is `None`, check that `WebOptions::persist_window` or equivalent is not disabled. + +--- + +## Persistence — Phase 2: Blueprint KV (future) + +Once localStorage persistence is in place, Blueprint KV is additive — the `ClusterLayout` proto type and the extract/apply helpers do not change. + +### Save path + +`App::save` gains a second branch after the localStorage write: + +```rust +fn save(&mut self, storage: &mut dyn eframe::Storage) { + let layout = extract_layout(&self.graph); + eframe::set_value(storage, "cluster_layout", &layout); + + // Encode to proto bytes and fire a gRPC Set call to Blueprint KV + // key: "cluster/layout", value: prost::Message::encode(layout) + // (fire-and-forget via spawn — save must not block the render loop) +} +``` + +The gRPC call is fire-and-forget: `spawn` it so it does not block the eframe render loop. + +### Load path + +`ClusterApp::new` gains a remote-first fallback: + +1. Attempt a gRPC `Get` on key `cluster/layout` from Blueprint KV +2. If successful, decode the `ClusterLayout` proto and call `apply_layout` +3. If the call fails or returns nothing, fall back to the value in `cc.storage` + +Because `ClusterApp::new` is called inside an `async` block (within the `WebRunner::start` closure), the gRPC call can be awaited without needing an additional spawn. + +### Why this ordering matters + +localStorage is always written first. If the Blueprint KV call fails (Blueprint is down, network error), the last known layout is still preserved locally. The KV store is the source of truth for cross-browser/cross-session sharing; localStorage is the fast-path cache. + +--- + +## Summary + +| Step | File(s) changed | What it does | +|---|---|---| +| 1 | `api/core/registry/key_value/v1/cluster_layout.proto` | Defines the shared layout type for both Rust and Go | +| 2 | `services/core/blueprint/web-client/src/views/cluster.rs` | Adds `extract_layout` and `apply_layout` helpers | +| 3 | `services/core/blueprint/web-client/src/views/cluster.rs` | Implements `App::save` and loads layout in `ClusterApp::new` | +| 4 | — | Verify `WebOptions` wires `cc.storage` correctly | +| Future | `cluster.rs` + Blueprint KV gRPC client | Adds remote save/load with localStorage fallback | diff --git a/docs/website/content/docs/architecture/operations-telemetry.md b/docs/website/content/docs/architecture/operations-telemetry.md new file mode 100644 index 00000000..c1f97f52 --- /dev/null +++ b/docs/website/content/docs/architecture/operations-telemetry.md @@ -0,0 +1,473 @@ +--- +weight: 10 +title: "Operations & Telemetry" +description: "Design options for surfacing live event topology, service mesh topology, and runtime metrics in a Draft system" +icon: "monitoring" +draft: false +toc: true +--- + +## Overview + +This document describes design options for making the operational state of a Draft cluster observable at runtime. It covers three related concerns: + +- **Event topology** — which services are producing and consuming which event types through Catalyst +- **Service mesh topology** — which processes are registered in the cluster and how they are connected +- **Event metrics** — latency, throughput, and error rate derived from the event store + +These concerns are addressed through a combination of existing APIs (Blueprint's `ServiceDiscoveryService`, Catalyst's `Query`), proposed new RPCs, and optional integration with the OpenTelemetry stack. + +--- + +## Event Topology + +### Current state + +Catalyst stores every event in ClickHouse with `source` (the publishing service), `type` (the event kind), and a `forwarded_at` timestamp captured after the event is dispatched to consumers. The `Query` and `QueryStream` RPCs expose this history. + +Routing in the broker uses `atomicMap`, keyed by the proto message descriptor name. Because every CloudEvent shares the same descriptor, **all active consumers receive all events** — routing is a pure broadcast at the broker level, with consumer-side filtering left to each service. + +This means: +- **Producers** are fully derivable today: query ClickHouse for `DISTINCT source`. +- **Event types** are fully derivable today: query ClickHouse for `DISTINCT type`. +- **Consumers and their edge relationships are not currently queryable.** The `atomicMap` stores live gRPC stream handles only — no service identity. + +### Option 1 — Query-only (producers and event types only) + +Use the existing `Query` RPC with no filter expression and a high limit, then deduplicate `source` and `type` values client-side. This gives a partial topology — producers and the event types they emit — but cannot draw the consumer half of the graph. + +**Suitable for**: a read-only producer view backed entirely by stored event history. + +**What is needed today**: nothing — the API already supports this. + +### Option 2 — Consumer identity convention + `GetTopology` RPC + +This is the recommended path for a complete bidirectional topology. + +#### Step 1: Consumers declare identity at subscription time + +The `ConsumeRequest.message` is a full `CloudEvent` that is currently unused for routing. Adopt a convention: services populate it with their own identity and declared interest when they call `Consume`: + +``` +source = "notify-svc" // the consumer's own service name +type = "orders.created" // the event type it intends to process +``` + +This is non-breaking — existing consumers continue to work unchanged and can adopt the convention incrementally. + +#### Step 2: Track registrations in the broker + +Add a `registrations` field to `atomicMap` populated from the subscription CloudEvent when a consumer connects: + +```go +// maps event_type → []consumer_source_names +registrations map[string][]string +``` + +This gives the broker a live, in-memory view of which consumers are subscribed and what they care about. + +#### Step 3: Add a `GetTopology` RPC to Catalyst + +Add to the query proto (or a new `topology.proto`): + +```protobuf +service Topology { + rpc GetTopology(GetTopologyRequest) returns (GetTopologyResponse) {} +} + +message GetTopologyRequest {} + +message TopologyNode { + string id = 1; + string name = 2; +} + +message TopologyEdge { + string producer_source = 1; + string consumer_source = 2; + string event_type = 3; +} + +message GetTopologyResponse { + repeated TopologyNode producers = 1; + repeated TopologyNode consumers = 2; + repeated TopologyEdge edges = 3; +} +``` + +The handler derives: +- **Producers**: `SELECT DISTINCT source FROM events LIMIT 200` run directly against ClickHouse +- **Consumers and edges**: read live from `atomicMap.registrations` + +The response shape maps directly to the `TopologyData` type in the web client, allowing the `ArcSpine` (producers view) and `FullCircle` (consumers view) components to be fed real data with no structural change. + +**Suitable for**: the primary production implementation of both topology views. + +**Trade-off**: consumers that do not yet adopt the identity convention will not appear in the graph until they do. + +--- + +## Service Mesh Topology + +### Current state + +Blueprint's `ServiceDiscoveryService` already provides a complete registry of every process in the cluster. The `Query` RPC returns all registered `Process` records with `name`, `group`, `ip_address`, `running_state`, `health_state`, `last_status_time`, and a `repeated Metadata` key-value bag. The `Watch` RPC streams process state changes in real time as services start, disconnect, or change health. + +This means **every node in the service mesh is already enumerable at zero cost**. What is missing is the edge set: which service communicates with or depends on which other service. + +### Option A — Metadata-declared dependencies (works today) + +The `Process.metadata` field is already sent from every service via `ClientDetails.Metadata` on each `Synchronize` heartbeat. Services can declare their dependencies there using a convention: + +```go +Metadata: []*sdv1.Metadata{ + {Key: "dep", Value: "blueprint"}, + {Key: "dep", Value: "catalyst"}, + {Key: "dep", Value: "fuse"}, +} +``` + +The web client calls `ServiceDiscoveryService.Query`, receives all processes, reads `dep` metadata entries, and derives the edge list without any new server-side code. The `Watch` RPC keeps node health state live. + +**Suitable for**: an immediate, lightweight service map that is accurate as long as services maintain their declarations. + +**Trade-off**: declared intent, not observed behavior. Stale or missing declarations produce an inaccurate graph. + +### Option B — OpenTelemetry service graph (observed behavior) + +The Draft repository ships a local observability stack (`docker-otel-lgtm`) that includes [Grafana Tempo](https://grafana.com/oss/tempo/). Any service instrumented with the OpenTelemetry SDK emits distributed traces that carry the caller and callee service name on every RPC or HTTP call. Tempo's API can return this as a **service graph** — a live, automatically-derived adjacency list built from observed traffic. + +The web client would query Tempo's HTTP API directly, or Blueprint could proxy the query and return it alongside `Process` data in an enriched response. + +**Suitable for**: accurate, automatically maintained topology that requires no manual declaration and reflects actual traffic patterns. + +**Trade-off**: requires OTel instrumentation in each service and a running Tempo instance. More infrastructure than Option A but more reliable long-term. + +### Combining both sources + +The two options are complementary. Blueprint's `Query` + `Watch` gives authoritative node identity and health state. The edge set comes from either metadata declarations (Option A) or OTel traces (Option B). A `GetServiceTopology` RPC on Blueprint could merge both: query all processes from the KV store, then enrich edges from whichever source is available. + +--- + +## Event Metrics + +### `forwarded_at` timestamp + +The Catalyst broker captures a `forwarded_at` timestamp immediately after dispatching each event to consumers via `state.Broadcast()`. This timestamp is: + +- Injected into the CloudEvent's `attributes` map before broadcasting, so live `QueryStream` subscribers receive it alongside the event payload +- Written to a dedicated `forwarded_at DateTime64(9)` column in the ClickHouse `events` table as part of the batch insert +- Back-filled dynamically for rows stored before this column existed: the `Query` handler reads both `raw` and `forwarded_at` from ClickHouse and injects the column value into the proto for any row where the attribute is absent and the column value is after epoch zero + +### Derivable metrics + +With `inserted_at` (event arrival time) and `forwarded_at` (dispatch time) both stored in ClickHouse, the following metrics can be computed purely from SQL: + +| Metric | Query pattern | +|---|---| +| Throughput (messages/min) | `COUNT(*) / minutes` over a time window | +| Median dispatch latency | `quantile(0.5)(forwarded_at - inserted_at)` | +| P95 dispatch latency | `quantile(0.95)(forwarded_at - inserted_at)` | +| Error rate | Requires an `error` attribute convention on events | +| Producer volume by source | `COUNT(*) GROUP BY source` | +| Consumer load by type | `COUNT(*) GROUP BY type` | + +### Surfacing metrics from the web client + +The `Query` RPC accepts a CESQL expression and returns matching events. Aggregate metrics require either: + +1. **Client-side aggregation** — `QueryStream` with a time-window filter and client-side bucketing. Simple to implement, suitable for small windows (< 10k events). + +2. **A dedicated `GetMetrics` RPC** — a new endpoint on Catalyst that runs parameterised ClickHouse aggregate queries and returns pre-computed metric values. This is the correct path for production dashboards at any scale. + +The current web client `Metrics` view uses placeholder sparkline data and is wired to accept real values once either approach above is implemented. + +--- + +## Implementation Roadmap + +The options above are ordered by implementation cost and dependency. + +| Phase | What | Unlocks | +|---|---|---| +| 1 | Call `ServiceDiscoveryService.Query` + `Watch` in the web client | Live service node list with health state, no edges | +| 2 | Add `dep` metadata convention to core services | Service mesh edges appear in the topology view | +| 3 | Consumers set `source`/`type` on `ConsumeRequest.message` | Consumer identity is declared at the broker | +| 4 | Add `registrations` tracking to `atomicMap` | Broker holds live consumer-to-event-type mapping | +| 5 | Add `GetTopology` RPC to Catalyst | Full event topology (producers, consumers, edges) queryable over gRPC | +| 6 | Add `GetMetrics` RPC to Catalyst | Pre-computed throughput and latency from ClickHouse | +| 7 | Instrument services with OTel SDK | Observed service graph replaces or validates metadata declarations | + +Phases 1–2 require no server-side changes and can be shipped from the web client alone. Phases 3–6 are additive server changes with no breaking impact on existing consumers. Phase 7 is an operational investment that pays off at scale. + +--- + +## Implementation Plan + +The phases below describe a concrete, ordered implementation path that takes the `FullCircle` and `ArcSpine` topology views from mock data to live operational telemetry. Each phase is independently shippable. + +--- + +### Phase 1 — Query-only producers `[web client only]` + +**Goal:** Replace mock data in the `Consumers` view with real producer topology derived from Catalyst's event history. + +**Files changed:** +- `services/core/blueprint/web-client/src/views/consumers.rs` + +**How it works:** +Call `QueryClient.query()` on mount with no expression filter. Walk the returned `CloudEvent` list, collect unique `source` field values, and build a `TopologyData` with producers only. Show mock data as a placeholder until the query returns. If the query fails (Catalyst unreachable), keep the mock data visible. + +```rust +fn topology_from_events(events: &[CloudEvent]) -> TopologyData { + let mut producers: Vec = Vec::new(); + for ev in events { + if !ev.source.is_empty() && !producers.iter().any(|p| p.id == ev.source) { + producers.push(TopologyNode { id: ev.source.clone(), name: ev.source.clone() }); + } + } + producers.sort_by(|a, b| a.id.cmp(&b.id)); + TopologyData { producers, consumers: vec![], edges: vec![] } +} +``` + +**Limitations:** The lower arc (consumers) and all bezier threads remain empty until Phase 5. + +**How to test:** Open `/consumers` in a running cluster — the upper arc should show real service names from the event store. Open the route with Catalyst unreachable — mock data stays visible. + +**Status:** ✅ Complete — `consumers.rs` calls `QueryClient.query()` on mount; `topology_from_events()` derives producers from unique `source` fields; mock data shown as initial placeholder while loading. + +--- + +### Phase 2 — Live volume via QueryStream `[web client only]` + +**Goal:** Keep the topology view's thread weights live by counting events from an open `QueryStream`. + +**Files changed:** +- `services/core/blueprint/web-client/src/views/consumers.rs` + +**How it works:** +After the initial snapshot query, open a `QueryStream` with no filter. For each arriving event, increment a `Signal>` keyed by `(source, event_type)`. When edges are present (Phase 5), merge the live counts into `TopologyData.edges[].vol` before each render so bezier thread weights update in real time. + +**How to test:** Produce events through Catalyst while the consumers view is open. Thread widths should change in response to traffic. + +**Status:** ✅ Complete — `consumers.rs` opens a `QueryStream` on mount alongside the Phase 1 snapshot query; each arriving event increments `vol_map: Signal>` keyed by `(source, event_type)`; `merge_vol()` splices the live counts into edge `vol` fields before each render. The `stream_task` handle is stored so the stream can be cancelled if the effect re-runs. Phase 5 edges will make the vol weights visually active; the counts are already flowing. + +--- + +### Phase 3 — Consumer identity convention `[no server changes]` + +**Goal:** Establish the convention that consumers set `source` and `type` on `ConsumeRequest.message` at subscription time so the broker can observe consumer identity. + +**Files changed:** +- Any service that calls `Consume` (adopt the convention in each subscriber) + +**Convention:** +``` +ConsumeRequest.message.source = "" // the consumer's own name +ConsumeRequest.message.type = "" // the event type(s) it processes +``` + +Multiple `Consume` calls per service are fine — each maps to one `(consumer, event_type)` edge. The broker ignores `ConsumeRequest.message` today, so existing consumers continue to work unchanged; adopting the convention is opt-in. + +**How to test:** No automated test at this phase — verify by reading `atomicMap.registrations` after Phase 4 is deployed. + +**Status:** ✅ Complete — `services/examples/consumer/main.go` refactored to open one `Consume` stream per declared event type (`examples.crud.v1.DatabaseModelSaved`, `examples.user.v1.UserCreated`, `examples.user.v1.UserLoggedIn`), each setting `Message.Source = "examples-consumer"` and `Message.Type = `; each goroutine filters to its own declared type so no event is double-processed. `tools/dctl/cmd/broker/consume.go` updated to set `Source = "dctl"` and `Type = ""` (subscribes to all events, appropriate for a debug CLI). + +--- + +### Phase 4 — Registration tracking in broker `[Go server]` + +**Goal:** Make the Catalyst broker track which consumers are subscribed and which event types they declared interest in, using the identity set in Phase 3. + +**Files changed:** +- `services/core/catalyst/broker/atomicMap.go` +- `services/core/catalyst/broker/controller.go` +- `services/core/catalyst/broker/rpc.go` + +**`atomicMap.go`** — add a `registrations` map with thread-safe accessors: +```go +type atomicMap struct { + mu sync.RWMutex + m map[string][]*connect.ServerStream[acv1.CloudEvent] + n map[string]chan *acv1.CloudEvent + registrations map[string][]string // event_type → []consumer_source_names +} + +func (a *atomicMap) AddRegistration(eventType, source string) { ... } +func (a *atomicMap) RemoveRegistration(eventType, source string) { ... } +func (a *atomicMap) Registrations() map[string][]string { ... } +``` + +**`controller.go`** — extend `register` struct with context for disconnect detection: +```go +type register struct { + ctx context.Context // carries the client disconnect signal + message *acv1.CloudEvent + stream *connect.ServerStream[acv1.CloudEvent] +} + +// In consume() goroutine, after state.Broker(key, stream): +src := reg.message.GetSource() +typ := reg.message.GetType() +if src != "" && typ != "" { + state.AddRegistration(typ, src) + go func(ctx context.Context, src, typ string) { + <-ctx.Done() + state.RemoveRegistration(typ, src) + }(reg.ctx, src, typ) +} +``` + +**`rpc.go`** — pass context through: +```go +// In Consume(): +controller.Consume(ctx, ®ister{ctx: ctx, message: req.Msg.Message, stream: stream}) +``` + +**How to test:** Start a consumer that sets `source`/`type` on its subscription CloudEvent. Inspect `GetTopology` (Phase 5). Disconnect the consumer — its entry should be removed within one connection timeout. + +**Status:** ✅ Complete — `atomicMap` gains a `registrations map[string][]string` field with `AddRegistration`, `RemoveRegistration`, and `Registrations` (snapshot copy) methods, all guarded by the existing `mu` mutex. The `register` struct in `controller.go` gains a `ctx context.Context` field. `consumer.go` populates it from the RPC context passed into `Consume`. In `controller.consume`, after wiring the stream, `src`/`typ` are read from the CloudEvent; if both are non-empty, `AddRegistration` is called and a cleanup goroutine waits on `ctx.Done()` to call `RemoveRegistration`. `rpc.go` required no changes — `ctx` was already threaded through. + +--- + +### Phase 5 — `GetTopology` and `WatchTopology` RPCs `[Go server + Rust client]` ✅ + +**Goal:** Add a `Topology` service to Catalyst so the web client can query and stream the full event topology (producers, consumers, edges) in real time. + +**Files changed:** +- `api/core/message_broker/actors/v1/topology.proto` (new) +- `services/core/catalyst/broker/topology.go` (new) +- `services/core/catalyst/broker/rpc.go` +- `services/core/blueprint/web-client/src/views/consumers.rs` + +**`topology.proto`:** +```protobuf +syntax = "proto3"; +package core.message_broker.actors.v1; + +service Topology { + rpc GetTopology(GetTopologyRequest) returns (GetTopologyResponse) {} + rpc WatchTopology(WatchTopologyRequest) returns (stream WatchTopologyResponse) {} +} + +message GetTopologyRequest {} +message GetTopologyResponse { + repeated TopologyNode producers = 1; + repeated TopologyNode consumers = 2; + repeated TopologyEdge edges = 3; +} +message TopologyNode { string id = 1; string name = 2; } +message TopologyEdge { + string producer_source = 1; + string consumer_source = 2; + string event_type = 3; + uint32 vol = 4; // events in the last 5-min window +} + +message WatchTopologyRequest {} +message WatchTopologyResponse { + oneof event { + TopologyNode consumer_connected = 1; + TopologyNode consumer_disconnected = 2; + TopologyNode producer_appeared = 3; + } +} +``` + +After editing the proto, run `dctl api build` to regenerate Go and Rust bindings. + +**`topology.go`** — broker-side observer registry (mirrors `observerRegistry` pattern): +```go +type topologyObserver struct { + stream *connect.ServerStream[acv1.WatchTopologyResponse] +} +type topologyRegistry struct { + mu sync.RWMutex + observers []*topologyObserver +} +func (r *topologyRegistry) Add(obs *topologyObserver) { ... } +func (r *topologyRegistry) Remove(obs *topologyObserver) { ... } +func (r *topologyRegistry) Broadcast(resp *acv1.WatchTopologyResponse) { ... } +``` + +Call `Broadcast` from `AddRegistration` / `RemoveRegistration` in `atomicMap.go` after Phase 4. + +**`rpc.go`** additions: +```go +func (r *Rpc) GetTopology(ctx context.Context, ...) (*connect.Response[acv1.GetTopologyResponse], error) { + // producers: SELECT DISTINCT source FROM events via store.QueryDistinctSources() + // consumers + edges: atomicMap.Registrations() +} +func (r *Rpc) WatchTopology(ctx context.Context, ..., stream *connect.ServerStream[acv1.WatchTopologyResponse]) error { + // register observer, block on ctx.Done(), remove on disconnect +} +``` + +**`consumers.rs`** — three concurrent tasks: +```rust +// Task 1: TopologyClient.get_topology() snapshot on mount — populate full arc +// Task 2: TopologyClient.watch_topology() stream — apply_topology_delta() for live updates +// Task 3: QueryStream — update edge vol counts from live event traffic +``` + +**How to test:** Run Catalyst locally. Open `/consumers` — full arc (producers + consumers) and bezier threads should appear with real data. Start or stop a consumer service — the node should appear or disappear within seconds via the `WatchTopology` stream. + +**Status:** ✅ Complete — `GetTopology` and `WatchTopology` implemented in `broker/rpc.go`, `broker/controller.go`, `broker/store.go` (via `QueryDistinctSources`), and `broker/topology.go`; proto generated in `api/core/message_broker/actors/v1/topology.proto`; `consumers.rs` uses all three tasks (snapshot, watch, query stream). + +--- + +### Phase 6 — `GetMetrics` RPC `[Go server + Rust client]` + +**Goal:** Replace client-side event counting with pre-computed per-edge volume from ClickHouse aggregates, and surface latency metrics. + +**Files changed:** +- `api/core/message_broker/actors/v1/metrics.proto` (new) +- `services/core/catalyst/broker/store.go` — add `QueryVolumes()` +- `services/core/catalyst/broker/rpc.go` — add `MetricsHandler` +- `services/core/blueprint/web-client/src/views/consumers.rs` — replace sliding-window counter with `GetMetrics` call + +**`metrics.proto`:** +```protobuf +service Metrics { + rpc GetMetrics(GetMetricsRequest) returns (GetMetricsResponse) {} +} +message GetMetricsRequest { int32 window_seconds = 1; } +message EdgeVolume { string source = 1; string event_type = 2; uint32 count = 3; } +message GetMetricsResponse { + repeated EdgeVolume edge_volumes = 1; + double median_latency_ms = 2; + double p95_latency_ms = 3; +} +``` + +**ClickHouse query in `store.go`:** +```sql +SELECT source, type, COUNT(*) AS cnt +FROM events +WHERE inserted_at >= now() - INTERVAL ? SECOND +GROUP BY source, type +ORDER BY cnt DESC +``` + +**How to test:** Send a burst of events via Catalyst. Call `GetMetrics`. Thread widths in the web client should reflect the burst with accurate ClickHouse-derived counts. + +**Status:** ✅ Complete — `metrics.proto` added and Go/Rust bindings regenerated; `store.go` gains `QueryVolumes` (COUNT GROUP BY source, type) and `QueryLatency` (quantile aggregates on `forwarded_at - inserted_at`); `controller.go` exposes `GetMetrics`; `rpc.go` registers the `MetricsHandler`; `metrics.rs` calls `MetricsClient.get_metrics()` on mount and on time-range change, displaying real msgs/min, median latency, and P95 latency. Sparklines remain placeholder pending a time-series endpoint (Phase 7+). + +--- + +### Phase 7 — OTel / Tempo service graph `[infrastructure + web client]` + +**Goal:** Populate the `Cluster` view with the observed service graph from Grafana Tempo distributed traces, replacing or augmenting metadata-declared dependencies. + +**Files changed:** +- `services/core/blueprint/web-client/src/views/cluster.rs` + +**How it works:** +Query Tempo's HTTP API (service graph endpoint) from the web client. Map the returned `(caller, callee)` edge list to a node graph. `ServiceDiscoveryService.Query` + `Watch` from Blueprint provides node identity and health state; Tempo provides the observed edges. + +**Prerequisites:** OTel SDK instrumentation in each service; Grafana Tempo running (the `docker-otel-lgtm` stack already ships it). + +**How to test:** Run the full `docker-otel-lgtm` stack. Make RPCs between services. Open the Cluster view — nodes should appear connected by observed traffic edges. + +**Status:** ⏳ Pending diff --git a/pkg/chassis/builder.go b/pkg/chassis/builder.go index 85357df7..a1fba52c 100644 --- a/pkg/chassis/builder.go +++ b/pkg/chassis/builder.go @@ -418,6 +418,7 @@ func (c *Runtime) buildCors() *cors.Cors { "X-User-Agent", // Used for gRPC-web }, ExposedHeaders: []string{ + "Content-Type", // Required for gRPC-web: application/grpc-web+proto is not a CORS-safelisted MIME type "Content-Encoding", // Unused in web browsers, but added for future-proofing "Connect-Content-Encoding", // Unused in web browsers, but added for future-proofing "Grpc-Status", // Required for gRPC-web diff --git a/pkg/chassis/error.go b/pkg/chassis/error.go index 4b9dfe6e..aac734d7 100644 --- a/pkg/chassis/error.go +++ b/pkg/chassis/error.go @@ -51,17 +51,21 @@ func (r Error) Fields() Fields { // add first call to stack calls = append(calls, fmt.Sprintf("%s:%d", r.file, r.line)) // start with fields of first error in wrapping chain - fields := r.fields + src := r.fields // add all other calls to stack (ignoring standard Go errors) for e := errors.Unwrap(r); e != nil; e = errors.Unwrap(e) { if e, ok := e.(Error); ok { calls = append(calls, fmt.Sprintf("%s:%d", e.file, e.line)) - fields = e.fields + src = e.fields } } - // add calls to fields - fields["call_stack"] = calls - return fields + // return a copy so callers cannot mutate the error's internal fields map + out := make(Fields, len(src)+1) + for k, v := range src { + out[k] = v + } + out["call_stack"] = calls + return out } // Wrap creates a customError from a given standard Go error and logger fields. It pulls out the diff --git a/pkg/repositories/go.mod b/pkg/repositories/go.mod index 8059544b..0938496a 100644 --- a/pkg/repositories/go.mod +++ b/pkg/repositories/go.mod @@ -43,6 +43,7 @@ require ( github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/raft v1.6.0 // indirect github.com/hashicorp/raft-boltdb/v2 v2.3.0 // indirect @@ -57,10 +58,12 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/montanaflynn/stats v0.6.6 // indirect + github.com/ncruces/go-strftime v0.1.9 // indirect github.com/paulmach/orb v0.11.1 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rs/cors v1.10.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -75,6 +78,7 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect + github.com/uptrace/bun/dialect/sqlitedialect v1.1.16 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect @@ -86,13 +90,20 @@ require ( go.opentelemetry.io/otel/trace v1.22.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.21.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect golang.org/x/net v0.23.0 // indirect golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect mellium.im/sasl v0.3.1 // indirect + modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect + modernc.org/libc v1.55.3 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.8.0 // indirect + modernc.org/sqlite v1.34.4 // indirect + modernc.org/strutil v1.2.0 // indirect + modernc.org/token v1.1.0 // indirect ) diff --git a/pkg/repositories/go.sum b/pkg/repositories/go.sum index 2ef70d55..2f3b9b55 100644 --- a/pkg/repositories/go.sum +++ b/pkg/repositories/go.sum @@ -104,6 +104,8 @@ github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/raft v1.6.0 h1:tkIAORZy2GbJ2Trp5eUSggLXDPOJLXC+JJLNMMqtgtM= @@ -166,6 +168,8 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ github.com/montanaflynn/stats v0.6.6 h1:Duep6KMIDpY4Yo11iFsvyqJDyfzLF9+sndUKT+v64GQ= github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU= @@ -194,6 +198,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= @@ -259,6 +265,8 @@ github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= github.com/uptrace/bun/dialect/pgdialect v1.1.16 h1:eUPZ+YCJ69BA+W1X1ZmpOJSkv1oYtinr0zCXf7zCo5g= github.com/uptrace/bun/dialect/pgdialect v1.1.16/go.mod h1:KQjfx/r6JM0OXfbv0rFrxAbdkPD7idK8VitnjIV9fZI= +github.com/uptrace/bun/dialect/sqlitedialect v1.1.16 h1:gbc9BP/e4sNOB9VBj+Si46dpOz2oktmZPidkda92GYY= +github.com/uptrace/bun/dialect/sqlitedialect v1.1.16/go.mod h1:YNezpK7fIn5Wa2WGmTCZ/nEyiswcXmuT4iNWADeL1x4= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= @@ -302,6 +310,7 @@ golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -348,6 +357,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -392,3 +403,17 @@ gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= mellium.im/sasl v0.3.1 h1:wE0LW6g7U83vhvxjC1IY8DnXM+EU095yeo8XClvCdfo= mellium.im/sasl v0.3.1/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= +modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= +modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= +modernc.org/sqlite v1.34.4 h1:sjdARozcL5KJBvYQvLlZEmctRgW9xqIZc2ncN7PU0P8= +modernc.org/sqlite v1.34.4/go.mod h1:3QQFCG2SEMtc2nv+Wq4cQCH7Hjcg+p/RMlS1XK+zwbk= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/pkg/repositories/sqlite/sqlite.go b/pkg/repositories/sqlite/sqlite.go new file mode 100644 index 00000000..7f4f62a1 --- /dev/null +++ b/pkg/repositories/sqlite/sqlite.go @@ -0,0 +1,81 @@ +package sqlite + +import ( + "context" + "database/sql" + "fmt" + + "github.com/steady-bytes/draft/pkg/chassis" + + "github.com/uptrace/bun" + "github.com/uptrace/bun/dialect/sqlitedialect" + + // Pure-Go driver, registers itself under the "sqlite" driver name — no + // CGO, so cross-compilation for desktop/mobile client targets stays + // simple. This was Architecture's resolved call over both mattn's CGO + // driver and the existing badger plugin: Block's access pattern (ordered + // by position, filtered by document_id, parent-child) is natively + // relational, and a .sqlite file stays independently user-inspectable + // and exportable in a way a KV store's blob isn't. + _ "modernc.org/sqlite" +) + +type ( + Repository interface { + chassis.Repository + Client() *bun.DB + } + repository struct { + client *bun.DB + configKey string + } +) + +// New instantiates a new repository. A call to Open is required before use. +// The configKey parameter dictates which key in the configuration will be read during +// initialization. Default: "repositories.sqlite" +func New(configKey string) Repository { + if configKey == "" { + configKey = "repositories.sqlite" + } + return &repository{ + configKey: configKey, + } +} + +func (r *repository) Client() *bun.DB { + return r.client +} + +func (r *repository) Open(ctx context.Context, config chassis.Config) error { + path := config.GetString(fmt.Sprintf("%s.path", r.configKey)) + if path == "" { + path = config.NodeID() + ".sqlite" + } + sqldb, err := sql.Open("sqlite", path) + if err != nil { + return fmt.Errorf("failed to open sqlite db at %s: %w", path, err) + } + // SQLite allows only one writer at a time; a single pooled connection + // avoids "database is locked" errors surfacing as flaky query failures + // under concurrent access, rather than masking them with retry logic. + sqldb.SetMaxOpenConns(1) + r.client = bun.NewDB(sqldb, sqlitedialect.New()) + return r.Ping(ctx) +} + +func (r *repository) Close(ctx context.Context) error { + err := r.client.Close() + if err != nil { + return fmt.Errorf("failed to close the db connection for disconnect") + } + return nil +} + +func (r *repository) Ping(ctx context.Context) error { + err := r.client.PingContext(ctx) + if err != nil { + return fmt.Errorf("failed to ping the db") + } + return nil +} diff --git a/services/core/auth/auth b/services/core/auth/auth new file mode 100755 index 00000000..ab38eeed Binary files /dev/null and b/services/core/auth/auth differ diff --git a/services/core/auth/config.go b/services/core/auth/config.go new file mode 100644 index 00000000..cc1a02f3 --- /dev/null +++ b/services/core/auth/config.go @@ -0,0 +1,30 @@ +package main + +import "github.com/steady-bytes/draft/pkg/chassis" + +const ( + // ModeBypass accepts every check request without contacting an identity provider. + // Safe for local development when Authentik is not running. + ModeBypass = "bypass" + ModeAuthentik = "authentik" + + configModeKey = "auth.mode" + configAuthentikURL = "auth.authentik.url" +) + +type authConfig struct { + mode string + authentikURL string +} + +func loadAuthConfig() authConfig { + cfg := chassis.GetConfig() + mode := cfg.GetString(configModeKey) + if mode == "" { + mode = ModeBypass + } + return authConfig{ + mode: mode, + authentikURL: cfg.GetString(configAuthentikURL), + } +} diff --git a/services/core/auth/config.yaml b/services/core/auth/config.yaml new file mode 100644 index 00000000..a8c7eee9 --- /dev/null +++ b/services/core/auth/config.yaml @@ -0,0 +1,21 @@ +service: + name: auth + domain: core + entrypoint: http://localhost:2221 + + logging: + level: debug + + network: + bind_address: localhost + bind_port: 9095 + internal: + host: host.docker.internal + port: 9095 + +# auth.mode controls whether the service validates tokens (authentik) or allows +# all requests through (bypass). Use bypass for local development without Authentik. +auth: + mode: bypass + authentik: + url: http://localhost:9050 diff --git a/services/core/auth/forwarder.go b/services/core/auth/forwarder.go new file mode 100644 index 00000000..f2facee9 --- /dev/null +++ b/services/core/auth/forwarder.go @@ -0,0 +1,53 @@ +package main + +import ( + "io" + "net/http" +) + +// forwarder proxies an ext_authz check request to the Authentik embedded outpost. +// Envoy sends the original request headers to this service; we relay them to Authentik +// and return its decision (200 allow, 4xx deny) with any identity headers intact. +type forwarder struct { + authentikCheckURL string + client *http.Client +} + +func newForwarder(authentikBaseURL string) *forwarder { + return &forwarder{ + // Authentik's embedded outpost ext_authz endpoint + authentikCheckURL: authentikBaseURL + "/outpost.goauthentik.io/auth/envoy", + client: &http.Client{}, + } +} + +func (f *forwarder) check(w http.ResponseWriter, r *http.Request) { + outReq, err := http.NewRequestWithContext(r.Context(), http.MethodGet, f.authentikCheckURL, nil) + if err != nil { + http.Error(w, "failed to build auth request", http.StatusInternalServerError) + return + } + + // Copy original request headers so Authentik can read cookies, Authorization, etc. + for key, vals := range r.Header { + for _, v := range vals { + outReq.Header.Add(key, v) + } + } + + resp, err := f.client.Do(outReq) + if err != nil { + http.Error(w, "auth service unreachable", http.StatusServiceUnavailable) + return + } + defer resp.Body.Close() + + // Relay identity headers (X-Authentik-*) so the upstream service can read them. + for key, vals := range resp.Header { + for _, v := range vals { + w.Header().Add(key, v) + } + } + w.WriteHeader(resp.StatusCode) + io.Copy(w, resp.Body) //nolint:errcheck +} diff --git a/services/core/auth/go.mod b/services/core/auth/go.mod new file mode 100644 index 00000000..4042bbae --- /dev/null +++ b/services/core/auth/go.mod @@ -0,0 +1,56 @@ +module github.com/steady-bytes/draft/services/core/auth + +go 1.23.2 + +replace github.com/steady-bytes/draft/api => ../../../api + +require ( + connectrpc.com/connect v1.16.2 + github.com/steady-bytes/draft/api v1.0.0 + github.com/steady-bytes/draft/pkg/chassis v0.4.5 + github.com/steady-bytes/draft/pkg/loggers v0.2.4 + golang.org/x/net v0.34.0 + google.golang.org/protobuf v1.36.3 +) + +require ( + connectrpc.com/grpcreflect v1.2.0 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/boltdb/bolt v1.3.1 // indirect + github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 // indirect + github.com/envoyproxy/go-control-plane v0.12.0 // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/raft v1.6.0 // indirect + github.com/hashicorp/raft-boltdb/v2 v2.3.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/rs/cors v1.10.1 // indirect + github.com/rs/zerolog v1.32.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.etcd.io/bbolt v1.3.7 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/grpc v1.65.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/services/core/auth/go.sum b/services/core/auth/go.sum new file mode 100644 index 00000000..1c79e83a --- /dev/null +++ b/services/core/auth/go.sum @@ -0,0 +1,226 @@ +connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= +connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= +connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= +connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 h1:VIG8z8W5EDy5cIbv2mH5TufcdZm7p/Nn73GZ6nJaXcQ= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0/go.mod h1:rMOW7HwKadbOR8W4sxYCaHS5TwK0mbpysmDINEfr5SE= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= +github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/raft v1.6.0 h1:tkIAORZy2GbJ2Trp5eUSggLXDPOJLXC+JJLNMMqtgtM= +github.com/hashicorp/raft v1.6.0/go.mod h1:Xil5pDgeGwRWuX4uPUmwa+7Vagg4N804dz6mhNi6S7o= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245 h1:NyeelmxyaUHfDdmhzlEVlrRk+1T9EnlCjvHenrusrfU= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0= +github.com/hashicorp/raft-boltdb/v2 v2.3.0 h1:fPpQR1iGEVYjZ2OELvUHX600VAK5qmdnDEv3eXOwZUA= +github.com/hashicorp/raft-boltdb/v2 v2.3.0/go.mod h1:YHukhB04ChJsLHLJEUD6vjFyLX2L3dsX3wPBZcX4tmc= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/steady-bytes/draft/pkg/chassis v0.4.5 h1:UQ2+2vsy/lsOkGk904SCthkwZcqD8ZBnLpHn2Cgts0Y= +github.com/steady-bytes/draft/pkg/chassis v0.4.5/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM= +github.com/steady-bytes/draft/pkg/loggers v0.2.4 h1:cRzJaqnJ2VSekiJpYBAl64yaKoaTOhdp42F/CSKNWsc= +github.com/steady-bytes/draft/pkg/loggers v0.2.4/go.mod h1:nXeOQ6lXhsVWHzRqVcJz0JIeSW75ORVN+0izJwwnH+Y= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/services/core/auth/handler.go b/services/core/auth/handler.go new file mode 100644 index 00000000..da71c616 --- /dev/null +++ b/services/core/auth/handler.go @@ -0,0 +1,38 @@ +package main + +import ( + "net/http" + + "github.com/steady-bytes/draft/pkg/chassis" +) + +// checkHandler implements the Envoy ext_authz HTTP check endpoint. +// Envoy sends every inbound request through here before forwarding it upstream. +// The handler either bypasses (always allow) or delegates to Authentik. +type checkHandler struct { + cfg authConfig + fwd *forwarder + logger chassis.Logger +} + +func newCheckHandler(cfg authConfig, logger chassis.Logger) *checkHandler { + var fwd *forwarder + if cfg.mode == ModeAuthentik { + fwd = newForwarder(cfg.authentikURL) + } + return &checkHandler{cfg: cfg, fwd: fwd, logger: logger} +} + +// ServeHTTP handles all paths — Envoy sends the original request path as-is. +func (h *checkHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + switch h.cfg.mode { + case ModeBypass: + // No identity provider; allow everything. Useful for local dev. + w.WriteHeader(http.StatusOK) + case ModeAuthentik: + h.fwd.check(w, r) + default: + h.logger.WithField("mode", h.cfg.mode).Error("unknown auth mode — denying request") + http.Error(w, "misconfigured auth service", http.StatusInternalServerError) + } +} diff --git a/services/core/auth/main.go b/services/core/auth/main.go new file mode 100644 index 00000000..466a6ecd --- /dev/null +++ b/services/core/auth/main.go @@ -0,0 +1,77 @@ +package main + +import ( + "context" + "fmt" + "net/http" + + kvv1 "github.com/steady-bytes/draft/api/core/registry/key_value/v1" + kvv1Connect "github.com/steady-bytes/draft/api/core/registry/key_value/v1/v1connect" + "github.com/steady-bytes/draft/pkg/chassis" + "github.com/steady-bytes/draft/pkg/loggers/zerolog" + + "connectrpc.com/connect" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + "google.golang.org/protobuf/types/known/anypb" +) + +// authServiceBlueprintKey is the Blueprint KV key Fuse reads to discover this service. +// Must match AuthServiceBlueprintKey in services/core/fuse/control_plane/controller.go. +const authServiceBlueprintKey = "auth_service_address" + +func main() { + logger := zerolog.New() + cfg := loadAuthConfig() + + handler := newCheckHandler(cfg, logger) + + defer chassis.New(logger). + Register(chassis.RegistrationOptions{ + Namespace: "core", + }). + WithRunner(func() { + writeAuthAddress(logger) + serveCheckEndpoint(handler, logger) + }). + Start() +} + +// writeAuthAddress publishes this service's address to Blueprint KV so Fuse can +// discover it and enable the ext_authz filter on the Envoy listener. +func writeAuthAddress(logger chassis.Logger) { + config := chassis.GetConfig() + host := config.GetString("service.network.internal.host") + port := config.GetInt("service.network.internal.port") + addr := fmt.Sprintf("http://%s:%d", host, port) + + val, err := anypb.New(&kvv1.Value{Data: addr}) + if err != nil { + logger.WithError(err).Error("failed to marshal auth_service_address") + return + } + + client := kvv1Connect.NewKeyValueServiceClient(http.DefaultClient, config.Entrypoint()) + _, err = client.Set(context.Background(), connect.NewRequest(&kvv1.SetRequest{ + Key: authServiceBlueprintKey, + Value: val, + })) + if err != nil { + logger.WithError(err).Error("failed to write auth_service_address to blueprint") + return + } + logger.WithField("address", addr).Info("registered auth_service_address with blueprint") +} + +// serveCheckEndpoint starts the HTTP server that handles Envoy ext_authz check requests. +func serveCheckEndpoint(handler http.Handler, logger chassis.Logger) { + config := chassis.GetConfig() + addr := fmt.Sprintf("%s:%d", + config.GetString("service.network.bind_address"), + config.GetInt("service.network.bind_port"), + ) + logger.WithField("addr", addr).Info("auth check server listening") + if err := http.ListenAndServe(addr, h2c.NewHandler(handler, &http2.Server{})); err != nil { + logger.WithError(err).Error("auth check server stopped") + } +} diff --git a/services/core/blueprint/README.md b/services/core/blueprint/README.md index c3e99c82..67ff6ccd 100644 --- a/services/core/blueprint/README.md +++ b/services/core/blueprint/README.md @@ -1 +1,11 @@ # blueprint + +A central long term replicated durable storage solution that acts as the central control panel for a system using the draft framework. + +## Features +- Reliable key/val storage +- Service discovery +- Storage interface for fuse, and catalyst +- Central UI + +## Architecture diff --git a/services/core/blueprint/go.mod b/services/core/blueprint/go.mod index 7b8e8bdf..c04e8110 100644 --- a/services/core/blueprint/go.mod +++ b/services/core/blueprint/go.mod @@ -2,6 +2,8 @@ module github.com/steady-bytes/draft/services/core/blueprint go 1.23.2 +replace github.com/steady-bytes/draft/api => ../../../api + require ( connectrpc.com/connect v1.16.2 github.com/dgraph-io/badger/v2 v2.2007.4 @@ -11,7 +13,7 @@ require ( github.com/steady-bytes/draft/pkg/chassis v0.5.0 github.com/steady-bytes/draft/pkg/loggers v0.2.3 github.com/steady-bytes/draft/pkg/repositories v0.0.3 - google.golang.org/protobuf v1.34.2 + google.golang.org/protobuf v1.36.3 ) require ( diff --git a/services/core/blueprint/go.sum b/services/core/blueprint/go.sum index f2d0e818..19773cc6 100644 --- a/services/core/blueprint/go.sum +++ b/services/core/blueprint/go.sum @@ -196,8 +196,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= -github.com/steady-bytes/draft/api v1.0.0 h1:QIvboAJgU0fBOV6BKChLMhHYIjBTR53+LJaR3w3g0NY= -github.com/steady-bytes/draft/api v1.0.0/go.mod h1:mlwxjvRiqvwySGdzVmF8voFhMffWq2F7dyd+xt6kENA= github.com/steady-bytes/draft/pkg/chassis v0.5.0 h1:aSBl7yH54xXHAFUc58yyEYW3U4bOzO3lYO/ojIh7uFQ= github.com/steady-bytes/draft/pkg/chassis v0.5.0/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM= github.com/steady-bytes/draft/pkg/loggers v0.2.3 h1:tZadHH8f9fo+tRHVp3BaJlVYvKlrlX8Hd6LxncUVgAM= @@ -265,8 +263,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/services/core/blueprint/main.go b/services/core/blueprint/main.go index f64adcce..0c26c11d 100644 --- a/services/core/blueprint/main.go +++ b/services/core/blueprint/main.go @@ -1,7 +1,9 @@ package main import ( + "context" "embed" + "time" kv "github.com/steady-bytes/draft/services/core/blueprint/key_value" sd "github.com/steady-bytes/draft/services/core/blueprint/service_discovery" @@ -34,7 +36,14 @@ func main() { c.WithRPCHandler(keyValueRPC). WithRPCHandler(serviceDiscoveryRPC). - WithClientApplication(files, "web-client/target/dx/blueprint-pwa/release/web/public") + WithClientApplication(files, "web-client/target/dx/blueprint-pwa/release/web/public"). + WithRunner(func() { + ticker := time.NewTicker(sd.ReapInterval) + defer ticker.Stop() + for range ticker.C { + serviceDiscoveryController.Reap(context.Background(), logger) + } + }) defer c.Start() } diff --git a/services/core/blueprint/service_discovery/broadcaster.go b/services/core/blueprint/service_discovery/broadcaster.go new file mode 100644 index 00000000..ec2f7f58 --- /dev/null +++ b/services/core/blueprint/service_discovery/broadcaster.go @@ -0,0 +1,62 @@ +package service_discovery + +import ( + "sync" + + sdv1 "github.com/steady-bytes/draft/api/core/registry/service_discovery/v1" + + "github.com/google/uuid" +) + +type ProcessEvent struct { + Process *sdv1.Process + Removed bool +} + +type Broadcaster struct { + mu sync.RWMutex + subscribers map[string]chan *ProcessEvent +} + +func NewBroadcaster() *Broadcaster { + return &Broadcaster{ + subscribers: make(map[string]chan *ProcessEvent), + } +} + +func (b *Broadcaster) Subscribe() (string, <-chan *ProcessEvent) { + id := uuid.NewString() + ch := make(chan *ProcessEvent, 16) + b.mu.Lock() + b.subscribers[id] = ch + b.mu.Unlock() + return id, ch +} + +func (b *Broadcaster) Unsubscribe(id string) { + b.mu.Lock() + if ch, ok := b.subscribers[id]; ok { + delete(b.subscribers, id) + close(ch) + } + b.mu.Unlock() +} + +func (b *Broadcaster) Publish(process *sdv1.Process) { + b.publish(&ProcessEvent{Process: process, Removed: false}) +} + +func (b *Broadcaster) PublishRemoved(pid string) { + b.publish(&ProcessEvent{Process: &sdv1.Process{Pid: pid}, Removed: true}) +} + +func (b *Broadcaster) publish(event *ProcessEvent) { + b.mu.RLock() + defer b.mu.RUnlock() + for _, ch := range b.subscribers { + select { + case ch <- event: + default: + } + } +} diff --git a/services/core/blueprint/service_discovery/controller.go b/services/core/blueprint/service_discovery/controller.go index 515bd51c..6b96d5d9 100644 --- a/services/core/blueprint/service_discovery/controller.go +++ b/services/core/blueprint/service_discovery/controller.go @@ -19,6 +19,13 @@ import ( const ( // TODO: this was removed from the chassis and I'm not sure where it should go tbh GlobalNonceKey = "GLOBAL_NONCE" + + // staleThreshold is how long without a heartbeat before a process is considered dead. + // Set to 3x the chassis sync interval to allow for a couple of missed heartbeats. + staleThreshold = 3 * chassis.SYNC_INTERVAL + + // ReapInterval is how often the reaper loop runs. Exported so main.go can drive the ticker. + ReapInterval = 30 * time.Second ) type ( @@ -32,6 +39,10 @@ type ( Synchronize(ctx context.Context, log chassis.Logger, details *sdv1.ClientDetails) Query(ctx context.Context, log chassis.Logger) (map[string]*sdv1.Process, error) + Reap(ctx context.Context, log chassis.Logger) + + Subscribe() (string, <-chan *ProcessEvent) + Unsubscribe(id string) GetClusterDetails() *sdv1.ClusterDetails GetClusterLeaderAddress(logger chassis.Logger) (string, error) @@ -41,6 +52,7 @@ type ( kvController kv.Controller raftController chassis.RaftController secretStore chassis.SecretStore + broadcaster *Broadcaster } ) @@ -49,9 +61,18 @@ func NewController(kvController kv.Controller, raftController chassis.RaftContro kvController: kvController, raftController: raftController, secretStore: nil, + broadcaster: NewBroadcaster(), } } +func (c *controller) Subscribe() (string, <-chan *ProcessEvent) { + return c.broadcaster.Subscribe() +} + +func (c *controller) Unsubscribe(id string) { + c.broadcaster.Unsubscribe(id) +} + // Accepts a `SecretStore` interface and adds it to the controller func (c *controller) SetSecretStore(s chassis.SecretStore) { c.secretStore = s @@ -73,17 +94,8 @@ const ( func (c *controller) Initialize(ctx context.Context, log chassis.Logger, nonce, name string) (*sdv1.ProcessIdentity, error) { var ( err error - pid = uuid.NewString() - process = &sdv1.Process{ - Pid: pid, - Name: name, - ProcessKind: sdv1.ProcessKind_SERVER_PROCESS, - Metadata: []*sdv1.Metadata{}, - JoinedTime: timestamppb.Now(), - RunningState: sdv1.ProcessRunningState_PROCESS_STARTING, - HealthState: sdv1.ProcessHealthState_PROCESS_HEALTHY, - } - pAny = &anypb.Any{} + process *sdv1.Process + pAny = &anypb.Any{} ) // validate the nonce (this will also require that a nonce is read in by the chassis). @@ -95,7 +107,31 @@ func (c *controller) Initialize(ctx context.Context, log chassis.Logger, nonce, // return nil, errors.New(ErrFailedNonce) // } - // generate the process identity as a signed token token + // reuse the PID of a disconnected process with the same name if one exists + existing, err := c.Query(ctx, log) + if err == nil { + for _, p := range existing { + if p.Name == name && p.RunningState == sdv1.ProcessRunningState_PROCESS_DICONNECTED { + process = p + break + } + } + } + + if process == nil { + process = &sdv1.Process{ + Pid: uuid.NewString(), + Name: name, + ProcessKind: sdv1.ProcessKind_SERVER_PROCESS, + Metadata: []*sdv1.Metadata{}, + JoinedTime: timestamppb.Now(), + } + } + + process.RunningState = sdv1.ProcessRunningState_PROCESS_STARTING + process.HealthState = sdv1.ProcessHealthState_PROCESS_HEALTHY + + // generate a fresh token for this connection process.Token, err = c.forgeIdentityToken() if err != nil { return nil, errors.New(ErrFailedTokenForge) @@ -106,16 +142,17 @@ func (c *controller) Initialize(ctx context.Context, log chassis.Logger, nonce, return nil, errors.New(ErrFailedTypeCast) } - // save details to the systemJournal on the file system - _, err = c.kvController.Set(log, pid, pAny, 500*time.Millisecond) + _, err = c.kvController.Set(log, process.Pid, pAny, 500*time.Millisecond) if err != nil { return nil, errors.New(ErrFailedToSaveProcessDetails) } + c.broadcaster.Publish(process) + // TODO (@andrewsc208): Get the leaders registry address to send synchronize packets to return &sdv1.ProcessIdentity{ - Pid: pid, + Pid: process.Pid, RegistryAddress: "localhost:2221", Token: process.Token, }, nil @@ -174,10 +211,11 @@ func (c *controller) Synchronize(ctx context.Context, log chassis.Logger, detail log.Error(ErrFailedToSaveProcessDetails) return } + + c.broadcaster.Publish(process) } -// Finalize - Gracefully remove the process from the registry. Close the connection if one is still -// open and change the process state to `Finalized` +// Finalize - Mark the process as disconnected and unhealthy in the registry. func (c *controller) Finalize(ctx context.Context, log chassis.Logger, pid string) error { var ( err error @@ -191,14 +229,73 @@ func (c *controller) Finalize(ctx context.Context, log chassis.Logger, pid strin return errors.New(ErrFailedTypeCast) } - if err = c.kvController.Delete(log, pid, pAny); err != nil { + pAny, err = c.kvController.Get(log, pid, pAny) + if err != nil { log.WithError(err) return err } + if err = anypb.UnmarshalTo(pAny, process, proto.UnmarshalOptions{}); err != nil { + log.WithError(err) + return err + } + + process.RunningState = sdv1.ProcessRunningState_PROCESS_DICONNECTED + process.HealthState = sdv1.ProcessHealthState_PROCESS_UNHEALTHY + + pAny, err = anypb.New(process) + if err != nil { + log.WithError(err) + return errors.New(ErrFailedTypeCast) + } + + if _, err = c.kvController.Set(log, pid, pAny, 500*time.Millisecond); err != nil { + log.WithError(err) + return err + } + + c.broadcaster.Publish(process) + return nil } +func (c *controller) Reap(ctx context.Context, log chassis.Logger) { + if c.raftController.Stats(ctx)["state"] != "Leader" { + return + } + + processes, err := c.Query(ctx, log) + if err != nil { + log.WithError(err).Error("reaper: failed to query processes") + return + } + + for _, process := range processes { + if process.LastStatusTime == nil { + continue + } + if time.Since(process.LastStatusTime.AsTime()) > staleThreshold { + log.WithField("pid", process.Pid).WithField("name", process.Name).Warn("reaper: marking stale process as disconnected") + + process.RunningState = sdv1.ProcessRunningState_PROCESS_DICONNECTED + process.HealthState = sdv1.ProcessHealthState_PROCESS_UNHEALTHY + + pAny, err := anypb.New(process) + if err != nil { + log.WithError(err).WithField("pid", process.Pid).Error("reaper: failed to marshal process") + continue + } + + if _, err := c.kvController.Set(log, process.Pid, pAny, 500*time.Millisecond); err != nil { + log.WithError(err).WithField("pid", process.Pid).Error("reaper: failed to update stale process") + continue + } + + c.broadcaster.Publish(process) + } + } +} + func (c *controller) Query(ctx context.Context, log chassis.Logger) (map[string]*sdv1.Process, error) { log.Trace("query") @@ -222,13 +319,13 @@ func (c *controller) Query(ctx context.Context, log chassis.Logger) (map[string] } // convert map from map[string]*anypb.Any to map[string]*sdv1.Process - for k, v := range res { + for _, v := range res { if v.MessageIs(process) { p := &sdv1.Process{} if err := anypb.UnmarshalTo(v, p, proto.UnmarshalOptions{}); err != nil { log.WithError(err) } - systemJournal[k] = p + systemJournal[p.Pid] = p } } diff --git a/services/core/blueprint/service_discovery/rpc.go b/services/core/blueprint/service_discovery/rpc.go index be386d0f..185506ac 100644 --- a/services/core/blueprint/service_discovery/rpc.go +++ b/services/core/blueprint/service_discovery/rpc.go @@ -77,6 +77,7 @@ func (h *rpc) Synchronize(ctx context.Context, stream *connect.BidiStream[sdv1.C } else if err != nil { // TODO: determine how to handle this error log.WithError(err).Error("connection error") + h.controller.Finalize(ctx, log, id) return err } @@ -149,3 +150,22 @@ func (h *rpc) ReportHealth( ) (*connect.Response[sdv1.ReportHealthResponse], error) { return nil, errors.New("implement me") } + +func (h *rpc) Watch(ctx context.Context, req *connect.Request[sdv1.WatchRequest], stream *connect.ServerStream[sdv1.WatchResponse]) error { + id, ch := h.controller.Subscribe() + defer h.controller.Unsubscribe(id) + + for { + select { + case <-ctx.Done(): + return nil + case event, ok := <-ch: + if !ok { + return nil + } + if err := stream.Send(&sdv1.WatchResponse{Process: event.Process, Removed: event.Removed}); err != nil { + return err + } + } + } +} diff --git a/services/core/blueprint/web-client/.cargo/config.toml b/services/core/blueprint/web-client/.cargo/config.toml new file mode 100644 index 00000000..0e465b2d --- /dev/null +++ b/services/core/blueprint/web-client/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.wasm32-unknown-unknown] +rustflags = ["--cfg", "getrandom_backend=\"wasm_js\""] diff --git a/services/core/blueprint/web-client/Cargo.lock b/services/core/blueprint/web-client/Cargo.lock index c9854101..1b3e05d2 100644 --- a/services/core/blueprint/web-client/Cargo.lock +++ b/services/core/blueprint/web-client/Cargo.lock @@ -3,163 +3,201 @@ version = 4 [[package]] -name = "addr2line" -version = "0.24.2" +name = "accesskit" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "5351dcebb14b579ccab05f288596b2ae097005be7ee50a7c3d4ca9d0d5a66f6a" dependencies = [ - "gimli", + "enumn", + "serde", + "uuid", ] [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] -name = "aho-corasick" -version = "1.1.3" +name = "ahash" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ - "memchr", + "cfg-if", + "once_cell", + "serde", + "version_check", + "zerocopy", ] [[package]] -name = "ashpd" -version = "0.8.1" +name = "aho-corasick" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ - "enumflags2", - "futures-channel", - "futures-util", - "rand 0.8.5", - "serde", - "serde_repr", - "tokio", - "url", - "zbus", + "memchr", ] [[package]] -name = "async-broadcast" -version = "0.7.2" +name = "aligned" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", + "as-slice", ] [[package]] -name = "async-channel" -version = "2.3.1" +name = "aligned-vec" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", + "equator", ] [[package]] -name = "async-io" -version = "2.4.0" +name = "android-activity" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" dependencies = [ - "async-lock", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix 0.38.44", - "slab", - "tracing", - "windows-sys 0.59.0", + "android-properties", + "bitflags 2.11.0", + "cc", + "jni 0.22.4", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror 2.0.18", ] [[package]] -name = "async-lock" -version = "3.4.0" +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_system_properties" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", + "libc", ] [[package]] -name = "async-process" -version = "2.3.0" +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arboard" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" dependencies = [ - "async-channel", - "async-io", - "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix 0.38.44", - "tracing", + "clipboard-win", + "image", + "log", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "parking_lot", + "percent-encoding", + "windows-sys 0.60.2", + "x11rb", ] [[package]] -name = "async-recursion" -version = "1.1.1" +name = "arg_enum_proc_macro" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] -name = "async-signal" -version = "0.2.10" +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-slice" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", + "stable_deref_trait", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", "futures-core", - "futures-io", - "rustix 0.38.44", - "signal-hook-registry", - "slab", - "windows-sys 0.59.0", + "pin-project-lite", ] [[package]] -name = "async-task" -version = "4.7.1" +name = "async-stream-impl" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "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]] @@ -193,31 +231,119 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] -name = "backtrace" -version = "0.3.74" +name = "av-scenechange" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.18", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375082f007bd67184fb9c0374614b29f9aaa604ec301635f72338bb65386a53d" +dependencies = [ + "arrayvec", ] +[[package]] +name = "axum" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" +dependencies = [ + "axum-core", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "multer", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[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", +] + +[[package]] +name = "base16" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + [[package]] name = "bitflags" version = "1.3.2" @@ -226,11 +352,20 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" dependencies = [ - "serde", + "serde_core", +] + +[[package]] +name = "bitstream-io" +version = "4.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" +dependencies = [ + "no_std_io2", ] [[package]] @@ -259,44 +394,70 @@ dependencies = [ [[package]] name = "block2" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d59b4c170e16f0405a2e95aff44432a0d41aa97675f3d52623effe95792a037" -dependencies = [ - "objc2 0.6.0", -] - -[[package]] -name = "blocking" -version = "1.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", + "objc2 0.6.4", ] [[package]] name = "blueprint-pwa" version = "0.1.0" dependencies = [ + "chrono", "dioxus", + "dioxus-grpc", "dioxus-logger", "dotenv", + "draft-api", + "eframe", + "egui_graphs", + "getrandom 0.3.4", + "gloo-timers", "once_cell", - "reqwest", + "petgraph 0.8.3", + "prost 0.14.3", + "prost-types 0.14.3", "serde", + "serde_json", + "tonic-web-wasm-client", + "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", ] +[[package]] +name = "built" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" + [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytemuck" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "byteorder" @@ -304,11 +465,20 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "serde", +] [[package]] name = "cairo-rs" @@ -316,7 +486,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "cairo-sys-rs", "glib", "libc", @@ -335,12 +505,54 @@ dependencies = [ "system-deps", ] +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.11.0", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" +dependencies = [ + "bitflags 2.11.0", + "polling", + "rustix 1.1.4", + "slab", + "tracing", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" +dependencies = [ + "calloop 0.14.4", + "rustix 1.1.4", + "wayland-backend", + "wayland-client", +] + [[package]] name = "cc" -version = "1.2.18" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -373,24 +585,62 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] -name = "ciborium" -version = "0.2.2" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] -name = "ciborium-io" -version = "0.2.2" +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + +[[package]] +name = "charset" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f927b07c74ba84c7e5fe4db2baeb3e996ab2688992e39ac68ce3220a677c7e" +dependencies = [ + "base64", + "encoding_rs", +] + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link 0.2.1", +] + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" @@ -405,31 +655,24 @@ dependencies = [ ] [[package]] -name = "cocoa" -version = "0.25.0" +name = "clipboard-win" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" dependencies = [ - "bitflags 1.3.2", - "block", - "cocoa-foundation 0.1.2", - "core-foundation 0.9.4", - "core-graphics 0.23.2", - "foreign-types 0.5.0", - "libc", - "objc", + "error-code", ] [[package]] name = "cocoa" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2" +checksum = "ad36507aeb7e16159dfe68db81ccc27571c3ccd4b76fb2fb72fc59e7a4b1b64c" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "block", - "cocoa-foundation 0.2.0", - "core-foundation 0.10.0", + "cocoa-foundation", + "core-foundation 0.10.1", "core-graphics 0.24.0", "foreign-types 0.5.0", "libc", @@ -438,32 +681,32 @@ dependencies = [ [[package]] name = "cocoa-foundation" -version = "0.1.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +checksum = "81411967c50ee9a1fc11365f8c585f863a22a9697c89239c452292c40ba79b0d" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.11.0", "block", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", - "libc", + "core-foundation 0.10.1", + "core-graphics-types 0.2.0", "objc", ] [[package]] -name = "cocoa-foundation" -version = "0.2.0" +name = "color" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d" +checksum = "2ec7c5eb7a16992b1904d76c517d170ab353b0e0b3d5a0c81a8a0cd1037893cf" dependencies = [ - "bitflags 2.9.0", - "block", - "core-foundation 0.10.0", - "core-graphics-types 0.2.0", - "libc", - "objc", + "bytemuck", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "combine" version = "4.6.7" @@ -484,41 +727,58 @@ dependencies = [ ] [[package]] -name = "console_error_panic_hook" -version = "0.1.7" +name = "const-serialize" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +checksum = "ad7154afa56de2f290e3c82c2c6dc4f5b282b6870903f56ef3509aba95866edc" dependencies = [ - "cfg-if", - "wasm-bindgen", + "const-serialize-macro 0.7.2", ] [[package]] name = "const-serialize" -version = "0.6.2" +version = "0.8.0-alpha.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08259976d62c715c4826cb4a3d64a3a9e5c5f68f964ff6087319857f569f93a6" +checksum = "9e42cd5aabba86f128b3763da1fec1491c0f728ce99245062cd49b6f9e6d235b" dependencies = [ - "const-serialize-macro", + "const-serialize 0.7.2", + "const-serialize-macro 0.8.0-alpha.0", "serde", ] [[package]] name = "const-serialize-macro" -version = "0.6.2" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f160aad86b4343e8d4e261fee9965c3005b2fd6bc117d172ab65948779e4acf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "const-serialize-macro" +version = "0.8.0-alpha.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04382d0d9df7434af6b1b49ea1a026ef39df1b0738b1cc373368cf175354f6eb" +checksum = "42571ed01eb46d2e1adcf99c8ca576f081e46f2623d13500eba70d1d99a4c439" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] +[[package]] +name = "const-str" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0664d2867b4a32697dfe655557f5c3b187e9b605b38612a748e5ec99811d160" + [[package]] name = "const_format" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" dependencies = [ "const_format_proc_macros", ] @@ -534,6 +794,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "content_disposition" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc14a88e1463ddd193906285abe5c360c7e8564e05ccc5d501755f7fbc9ca9c" +dependencies = [ + "charset", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -542,13 +811,51 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "convert_case" -version = "0.6.0" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "convert_case" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ "unicode-segmentation", ] +[[package]] +name = "cookie" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "cookie_store" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" +dependencies = [ + "cookie", + "document-features", + "idna", + "log", + "publicsuffix", + "serde", + "serde_derive", + "serde_json", + "time", + "url", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -561,9 +868,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys", "libc", @@ -594,8 +901,21 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.10.0", + "bitflags 2.11.0", + "core-foundation 0.10.1", + "core-graphics-types 0.2.0", + "foreign-types 0.5.0", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", "core-graphics-types 0.2.0", "foreign-types 0.5.0", "libc", @@ -618,8 +938,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.10.0", + "bitflags 2.11.0", + "core-foundation 0.10.1", "libc", ] @@ -634,18 +954,37 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] @@ -658,15 +997,15 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -674,15 +1013,15 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.27.2" +version = "0.29.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" dependencies = [ "cssparser-macros", "dtoa-short", - "itoa 0.4.8", + "itoa", "matches", - "phf 0.8.0", + "phf 0.10.1", "proc-macro2", "quote", "smallvec", @@ -696,14 +1035,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.100", + "syn 2.0.117", ] +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + [[package]] name = "darling" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ "darling_core", "darling_macro", @@ -711,69 +1056,77 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "darling_macro" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] -name = "dashmap" -version = "5.5.3" +name = "data-encoding" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" [[package]] -name = "data-encoding" -version = "2.8.0" +name = "deranged" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] [[package]] -name = "derivative" -version = "2.2.0" +name = "derive_more" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ + "convert_case 0.4.0", "proc-macro2", "quote", - "syn 1.0.109", + "rustc_version", + "syn 2.0.117", ] [[package]] name = "derive_more" -version = "0.99.19" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "convert_case 0.4.0", + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case 0.10.0", "proc-macro2", "quote", "rustc_version", - "syn 2.0.100", + "syn 2.0.117", + "unicode-xid", ] [[package]] @@ -788,12 +1141,14 @@ dependencies = [ [[package]] name = "dioxus" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a247114500f1a78e87022defa8173de847accfada8e8809dfae23a118a580c" +checksum = "14b5fd24c3d394e5a8cfc15b8319da5f853c9d27471a9f46ace0653761499740" dependencies = [ + "dioxus-asset-resolver", "dioxus-cli-config", "dioxus-config-macro", + "dioxus-config-macros", "dioxus-core", "dioxus-core-macro", "dioxus-desktop", @@ -804,86 +1159,115 @@ dependencies = [ "dioxus-hooks", "dioxus-html", "dioxus-logger", - "dioxus-mobile", "dioxus-router", "dioxus-signals", + "dioxus-stores", "dioxus-web", "manganis", + "subsecond", "warnings", ] +[[package]] +name = "dioxus-asset-resolver" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8b546050ecfc7fcd310be344b2f3a2a79f21554c5a9e8df28e7a07e9b36009b" +dependencies = [ + "dioxus-cli-config", + "http", + "infer", + "jni 0.21.1", + "js-sys", + "ndk", + "ndk-context", + "ndk-sys", + "percent-encoding", + "thiserror 2.0.18", + "tokio", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "dioxus-cli-config" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd16948f1ffdb068dd9a64812158073a4250e2af4e98ea31fdac0312e6bce86" +checksum = "d4ad73f0ff638cd27466d389cd57f0975f909b66130dc1c25d5212d4041e5352" dependencies = [ "wasm-bindgen", ] [[package]] name = "dioxus-config-macro" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cbf582fbb1c32d34a1042ea675469065574109c95154468710a4d73ee98b49" +checksum = "e004bc8b958031117d373db2b5e0ab9d7e763751de129dd36f00ef7e318333cd" dependencies = [ "proc-macro2", "quote", ] +[[package]] +name = "dioxus-config-macros" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808a9994a9a2623e6b6890b6cc68def24bd669177ec4713684447fb46418c256" + [[package]] name = "dioxus-core" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c03f451a119e47433c16e2d8eb5b15bf7d6e6734eb1a4c47574e6711dadff8d" +checksum = "247ed8d679a13232641f1c84ba22246623fae01320b4c22db225c0b4f2fa7398" dependencies = [ + "anyhow", "const_format", "dioxus-core-types", "futures-channel", "futures-util", "generational-box", "longest-increasing-subsequence", - "rustc-hash", + "rustc-hash 2.1.2", "rustversion", "serde", "slab", "slotmap", + "subsecond", "tracing", - "warnings", ] [[package]] name = "dioxus-core-macro" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "105c954caaaedf8cd10f3d1ba576b01e18aa8d33ad435182125eefe488cf0064" +checksum = "75fbe64029b90144041f8521300c7b3508e6c48caea3244de2ff5d1ade15390c" dependencies = [ - "convert_case 0.6.0", + "convert_case 0.8.0", "dioxus-rsx", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "dioxus-core-types" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91a82fccfa48574eb7aa183e297769540904694844598433a9eb55896ad9f93b" -dependencies = [ - "once_cell", -] +checksum = "cbfea5c8946e0745b254b5c33c515d81b3ba638f33c2a532ed06730392394d4d" [[package]] name = "dioxus-desktop" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b0cca3e7a10a4a3df37ea52c4cc7a53e5c9233489e03ee3f2829471fc3099a" +checksum = "00c82f695d1214e41482badc0f8d0057b256c077a2827ade637f925f4097f1f6" dependencies = [ + "anyhow", "async-trait", "base64", - "cocoa 0.25.0", - "core-foundation 0.9.4", + "bytes", + "cocoa", + "core-foundation 0.10.1", + "dioxus-asset-resolver", "dioxus-cli-config", "dioxus-core", "dioxus-devtools", @@ -898,63 +1282,70 @@ dependencies = [ "futures-util", "generational-box", "global-hotkey", + "image", "infer", - "jni", + "jni 0.21.1", "lazy-js-bundle", - "muda 0.11.5", + "libc", + "muda", "ndk", "ndk-context", "ndk-sys", "objc", "objc_id", - "once_cell", + "percent-encoding", + "rand 0.9.4", "rfd", - "rustc-hash", + "rustc-hash 2.1.2", "serde", "serde_json", "signal-hook", "slab", + "subtle", "tao", - "thiserror 1.0.69", + "thiserror 2.0.18", "tokio", "tracing", "tray-icon", - "urlencoding", + "tungstenite 0.28.0", "webbrowser", "wry", ] [[package]] name = "dioxus-devtools" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a7300f1e8181218187b03502044157eef04e0a25b518117c5ef9ae1096880" +checksum = "08d30370fa78266aed3f3d9119dea2de9e92a0348941dbfa777f7a669f2ea375" dependencies = [ + "dioxus-cli-config", "dioxus-core", "dioxus-devtools-types", "dioxus-signals", "serde", "serde_json", + "subsecond", + "thiserror 2.0.18", "tracing", - "tungstenite", - "warnings", + "tungstenite 0.28.0", ] [[package]] name = "dioxus-devtools-types" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f62434973c0c9c5a3bc42e9cd5e7070401c2062a437fb5528f318c3e42ebf4ff" +checksum = "3907a2b61cf56039f047da6a37317a03d9e15411753bc40e5e34a27e405ac320" dependencies = [ "dioxus-core", "serde", + "subsecond-types", ] [[package]] name = "dioxus-document" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "802a2014d1662b6615eec0a275745822ee4fc66aacd9d0f2fb33d6c8da79b8f2" +checksum = "e3b75a1809af7c13546ae4487c8b02ab80cc4d059e7db5a5d090374ceaa71d5b" dependencies = [ "dioxus-core", "dioxus-core-macro", @@ -971,35 +1362,116 @@ dependencies = [ [[package]] name = "dioxus-fullstack" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe99b48a1348eec385b5c4bd3e80fd863b0d3b47257d34e2ddc58754dec5d128" +checksum = "c8ee56dd65fbf1222fa6a2749c3f821df28facf1832854b43d480b547a096f6d" dependencies = [ + "anyhow", + "async-stream", + "async-tungstenite", + "axum", + "axum-core", "base64", "bytes", "ciborium", - "dioxus-desktop", - "dioxus-devtools", - "dioxus-history", - "dioxus-lib", - "dioxus-mobile", - "dioxus-web", - "dioxus_server_macro", + "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", - "generational-box", - "once_cell", - "serde", - "server_fn", - "tracing", - "web-sys", -] - -[[package]] + "gloo-net", + "headers", + "http", + "http-body", + "http-body-util", + "js-sys", + "mime", + "pin-project", + "reqwest", + "rustversion", + "send_wrapper", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "thiserror 2.0.18", + "tokio-util", + "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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40d33a447cb158acdb61787b2ff52dd8a0f9a9f20e95e5c5fe9873f01c2b55b" +dependencies = [ + "anyhow", + "axum-core", + "base64", + "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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c06eb66bce50d5f47b793e6af5fc2e0a511bf2b4fa2423cf86e35023d8f17e6" +dependencies = [ + "const_format", + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", + "xxhash-rust", +] + +[[package]] +name = "dioxus-grpc" +version = "0.1.0" +dependencies = [ + "convert_case 0.8.0", + "tonic-build 0.13.1", +] + +[[package]] name = "dioxus-history" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ae4e22616c698f35b60727313134955d885de2d32e83689258e586ebc9b7909" +checksum = "c1d8024afd482956eadae2c43d0b1e73e584adb724ac09be87f268d52002387b" dependencies = [ "dioxus-core", "tracing", @@ -1007,9 +1479,9 @@ dependencies = [ [[package]] name = "dioxus-hooks" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "948e2b3f20d9d4b2c300aaa60281b1755f3298684448920b27106da5841896d0" +checksum = "233b5e168a7c38c4bf96d0f390221a72a5a28bb31ce2dcf6d2af879dc561ef42" dependencies = [ "dioxus-core", "dioxus-signals", @@ -1019,16 +1491,16 @@ dependencies = [ "rustversion", "slab", "tracing", - "warnings", ] [[package]] name = "dioxus-html" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c9a40e6fee20ce7990095492dedb6a753eebe05e67d28271a249de74dc796d" +checksum = "4abf4ad27eee650d1ab8ebe13591e8b0ee595fa5a5dd236be13a5b7b3fab678d" dependencies = [ "async-trait", + "bytes", "dioxus-core", "dioxus-core-macro", "dioxus-core-types", @@ -1037,6 +1509,7 @@ dependencies = [ "enumset", "euclid", "futures-channel", + "futures-util", "generational-box", "keyboard-types", "lazy-js-bundle", @@ -1049,28 +1522,28 @@ dependencies = [ [[package]] name = "dioxus-html-internal-macro" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ba87b53688a2c9f619ecdf4b3b955bc1f08bd0570a80a0d626c405f6d14a76" +checksum = "025e107e677f790f4ed648a189e36f51ae014e5341902b97313e4eae626cffa2" dependencies = [ - "convert_case 0.6.0", + "convert_case 0.8.0", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "dioxus-interpreter-js" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330707b10ca75cb0eb05f9e5f8d80217cd0d7e62116a8277ae363c1a09b57a22" +checksum = "57caa76427d8ec4105ccca44ff8c511055688af732a094b9fe9ef3547d2a11b2" dependencies = [ "dioxus-core", "dioxus-core-types", "dioxus-html", "js-sys", "lazy-js-bundle", - "rustc-hash", + "rustc-hash 2.1.2", "serde", "sledgehammer_bindgen", "sledgehammer_utils", @@ -1079,116 +1552,112 @@ dependencies = [ "web-sys", ] -[[package]] -name = "dioxus-lib" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5405b71aa9b8b0c3e0d22728f12f34217ca5277792bd315878cc6ecab7301b72" -dependencies = [ - "dioxus-config-macro", - "dioxus-core", - "dioxus-core-macro", - "dioxus-document", - "dioxus-history", - "dioxus-hooks", - "dioxus-html", - "dioxus-rsx", - "dioxus-signals", - "warnings", -] - [[package]] name = "dioxus-logger" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545961e752f6c8bf59c274951b3c8b18a106db6ad2f9e2035b29e1f2a3e899b1" +checksum = "0cbbee192b1b12fccb444a5b04d809710cfce4d27b792129fea6c845fae7f329" dependencies = [ - "console_error_panic_hook", "dioxus-cli-config", "tracing", "tracing-subscriber", "tracing-wasm", ] -[[package]] -name = "dioxus-mobile" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1295388909f427758993f32a571e0f8698d6ce0f125fa0e81b8bfdec3fa952" -dependencies = [ - "dioxus-cli-config", - "dioxus-desktop", - "dioxus-lib", - "jni", - "libc", - "once_cell", -] - [[package]] name = "dioxus-router" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7266a76fc9e4a91f56499d1d1aecfff7168952b6627a6008b4e9748d6bf863e4" +checksum = "ecdb19d7a1489ba252be9b3a07f9db92814020eb4ba8c1306f04242a44d17e66" dependencies = [ "dioxus-cli-config", + "dioxus-core", + "dioxus-core-macro", "dioxus-history", - "dioxus-lib", + "dioxus-hooks", + "dioxus-html", "dioxus-router-macro", + "dioxus-signals", + "percent-encoding", "rustversion", "tracing", "url", - "urlencoding", ] [[package]] name = "dioxus-router-macro" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2743ffb79e9a7d33d779c87d6deea2a6c047d0736012f95d63b909b83f0a6fd2" +checksum = "b525ab775585f1dc4850178de9d0cb6bb37f7b9c1a1a0c121eab7449d7021480" dependencies = [ + "base16", + "digest", "proc-macro2", "quote", + "sha2", "slab", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "dioxus-rsx" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb588e05800b5a7eb90b2f40fca5bbd7626e823fb5e1ba21e011de649b45aa1" +checksum = "37fb07e40e9734946511659668ea3675ed214b60889e7aa7f0a5a85271518475" dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.100", + "rustversion", + "syn 2.0.117", ] [[package]] name = "dioxus-signals" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10e032dbb3a2c0386ec8b8ee59bc20b5aeb67038147c855801237b45b13d72ac" +checksum = "5393fd579f42c6547bf47ec0a2dedf2a366cd541d31deedc1059a096e6c35798" dependencies = [ "dioxus-core", "futures-channel", "futures-util", "generational-box", - "once_cell", "parking_lot", - "rustc-hash", + "rustc-hash 2.1.2", "tracing", "warnings", ] +[[package]] +name = "dioxus-stores" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c59f52e8194439604dd35f8c540456c22b4a4b076930e424d0289f98ea3cb4" +dependencies = [ + "dioxus-core", + "dioxus-signals", + "dioxus-stores-macro", + "generational-box", +] + +[[package]] +name = "dioxus-stores-macro" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "737600865572cecf60ff934f88252bd4144f4ca189e0e570b7a780e8f0e01a1f" +dependencies = [ + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "dioxus-web" -version = "0.6.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7c12475c3d360058b8afe1b68eb6dfc9cbb7dcd760aed37c5f85c561c83ed1" +checksum = "176eb0a5ee8251203a816b413a64fdc014b43e53d4245f769b1b0c2035b88ac3" dependencies = [ - "async-trait", - "ciborium", "dioxus-cli-config", "dioxus-core", "dioxus-core-types", @@ -1201,30 +1670,21 @@ dependencies = [ "futures-channel", "futures-util", "generational-box", + "gloo-timers", "js-sys", "lazy-js-bundle", - "rustc-hash", + "rustc-hash 2.1.2", + "send_wrapper", "serde", "serde-wasm-bindgen", "serde_json", "tracing", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams 0.4.2", "web-sys", ] -[[package]] -name = "dioxus_server_macro" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "371a5b21989a06b53c5092e977b3f75d0e60a65a4c15a2aa1d07014c3b2dda97" -dependencies = [ - "proc-macro2", - "quote", - "server_fn_macro", - "syn 2.0.100", -] - [[package]] name = "dirs" version = "6.0.0" @@ -1243,7 +1703,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1252,6 +1712,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[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 0.6.2", + "libc", + "objc2 0.6.4", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -1260,14 +1732,23 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading 0.8.9", ] [[package]] name = "dlopen2" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" dependencies = [ "dlopen2_derive", "libc", @@ -1277,13 +1758,22 @@ dependencies = [ [[package]] name = "dlopen2_derive" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" +checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "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]] @@ -1292,17 +1782,39 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "dpi" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "draft-api" +version = "0.1.0" +dependencies = [ + "dioxus", + "dioxus-grpc", + "prost 0.14.3", + "prost-types 0.14.3", + "serde", + "tonic", + "tonic-prost", + "tonic-prost-build", + "tonic-web", + "tonic-web-wasm-client", +] [[package]] name = "dtoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" [[package]] name = "dtoa-short" @@ -1320,114 +1832,292 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] -name = "encoding_rs" -version = "0.8.35" +name = "ecolor" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "a05fbfa222ffb51989d5ccf33e5f7aebfcf96c5023413856b0c3618a7f79896e" dependencies = [ - "cfg-if", + "bytemuck", + "emath", + "serde", ] [[package]] -name = "endi" -version = "1.1.0" +name = "eframe" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" +checksum = "f98fe83b2589105b69dd25ca1e0fa2135a6e864d502fd8e08978f937e128cfef" +dependencies = [ + "ahash", + "bytemuck", + "document-features", + "egui", + "egui-winit", + "egui_glow", + "glow", + "glutin", + "glutin-winit", + "image", + "js-sys", + "log", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-foundation 0.3.2", + "parking_lot", + "percent-encoding", + "profiling", + "raw-window-handle 0.6.2", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time", + "windows-sys 0.61.2", + "winit", +] [[package]] -name = "enumflags2" -version = "0.7.11" +name = "egui" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147" +checksum = "42112be0ae157289312b92b3dfaf20e911b5a3c4c65d4aab0e7c47fbc0ce16e3" dependencies = [ - "enumflags2_derive", + "accesskit", + "ahash", + "bitflags 2.11.0", + "emath", + "epaint", + "log", + "nohash-hasher", + "profiling", + "ron", "serde", + "smallvec", + "unicode-segmentation", ] [[package]] -name = "enumflags2_derive" -version = "0.7.11" +name = "egui-winit" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79" +checksum = "967c5b323625d46d46a59b5daba3fef742248d27693cc18972458619858c4239" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", + "arboard", + "bytemuck", + "egui", + "log", + "objc2 0.6.4", + "objc2-foundation 0.3.2", + "objc2-ui-kit 0.3.2", + "profiling", + "raw-window-handle 0.6.2", + "smithay-clipboard", + "web-time", + "webbrowser", + "winit", ] [[package]] -name = "enumset" -version = "1.1.5" +name = "egui_glow" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" +checksum = "62b652957fa7e1ab01e8fecbfbf4e35f6e43a53fa98af8a562b50d5403cd44b9" dependencies = [ - "enumset_derive", + "bytemuck", + "egui", + "glow", + "log", + "memoffset", + "profiling", + "wasm-bindgen", + "web-sys", ] [[package]] -name = "enumset_derive" -version = "0.10.0" +name = "egui_graphs" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" +checksum = "4521b2f9253a5763b199f124d269c563ef76f4698e0d820c961ca4dd50666bcf" dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.100", + "egui", + "getrandom 0.2.17", + "petgraph 0.8.3", + "rand 0.9.4", + "serde", + "web-time", ] [[package]] -name = "equivalent" -version = "1.0.2" +name = "either" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] -name = "errno" -version = "0.3.11" +name = "emath" +version = "0.34.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +checksum = "b53f0d33a479321da6b0caa71366c9f67e8a2c149762d90bdc0d16e601ee8ecb" dependencies = [ - "libc", - "windows-sys 0.59.0", + "bytemuck", + "serde", ] [[package]] -name = "euclid" -version = "0.22.11" +name = "encoding_rs" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "num-traits", - "serde", + "cfg-if", ] [[package]] -name = "event-listener" -version = "5.4.0" +name = "enumn" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "event-listener-strategy" -version = "0.5.4" +name = "enumset" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +checksum = "25b07a8dfbbbfc0064c0a6bdf9edcf966de6b1c33ce344bdeca3b41615452634" dependencies = [ - "event-listener", - "pin-project-lite", + "enumset_derive", ] [[package]] -name = "fastrand" -version = "2.3.0" +name = "enumset_derive" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "epaint" +version = "0.34.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6675898a291ec212fc3df04f537d177fce8496120244590e6359dcaa4c25da79" +dependencies = [ + "ahash", + "bytemuck", + "ecolor", + "emath", + "font-types", + "log", + "nohash-hasher", + "parking_lot", + "profiling", + "self_cell", + "serde", + "skrifa", + "smallvec", + "vello_cpu", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "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 = "error-code" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fastrand" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1f" + +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "fdeflate" @@ -1438,6 +2128,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "fearless_simd" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb2907d1f08b2b316b9223ced5b0e89d87028ba8deae9764741dba8ff7f3903" +dependencies = [ + "bytemuck", +] + [[package]] name = "field-offset" version = "0.3.6" @@ -1448,11 +2147,23 @@ dependencies = [ "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 = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" -version = "1.1.1" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1464,6 +2175,28 @@ 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 = "font-types" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b38ad915f6dadd993ced50848a8291a543bd41ca62bc10740d5e64e2ab4cfd7" +dependencies = [ + "bytemuck", + "serde", +] + [[package]] name = "foreign-types" version = "0.3.2" @@ -1491,7 +2224,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] @@ -1508,9 +2241,9 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1527,9 +2260,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -1542,9 +2275,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -1552,15 +2285,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -1569,51 +2302,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-lite" -version = "2.6.0" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -1623,7 +2343,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -1708,20 +2427,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "gdkx11" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe" -dependencies = [ - "gdk", - "gdkx11-sys", - "gio", - "glib", - "libc", - "x11", -] - [[package]] name = "gdkx11-sys" version = "0.18.2" @@ -1737,9 +2442,9 @@ dependencies = [ [[package]] name = "generational-box" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a673cf4fb0ea6a91aa86c08695756dfe875277a912cdbf33db9a9f62d47ed82b" +checksum = "c68d74be1fbe3bba37604bdfd61403f26af9f6324cf325053abd89d60c22e799" dependencies = [ "parking_lot", "tracing", @@ -1755,6 +2460,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.4", + "windows-link 0.2.1", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -1768,32 +2483,53 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.2" +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 = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "r-efi 6.0.0", + "wasip2", + "wasip3", ] [[package]] -name = "gimli" -version = "0.31.1" +name = "gif" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" +dependencies = [ + "color_quant", + "weezl", +] [[package]] name = "gio" @@ -1827,13 +2563,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + [[package]] name = "glib" version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "futures-channel", "futures-core", "futures-executor", @@ -1861,7 +2608,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] @@ -1876,19 +2623,19 @@ dependencies = [ [[package]] name = "global-hotkey" -version = "0.5.5" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b436093d1598b05e3b7fddc097b2bad32763f53a1beb25ab6f9718c6a60acd09" +checksum = "b9247516746aa8e53411a0db9b62b0e24efbcf6a76e0ba73e5a91b512ddabed7" dependencies = [ - "bitflags 2.9.0", - "cocoa 0.25.0", "crossbeam-channel", "keyboard-types", - "objc", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", "once_cell", - "thiserror 1.0.69", - "windows-sys 0.52.0", - "x11-dl", + "thiserror 2.0.18", + "windows-sys 0.59.0", + "x11rb", + "xkeysym", ] [[package]] @@ -1912,6 +2659,18 @@ dependencies = [ "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" @@ -1925,6 +2684,71 @@ dependencies = [ "web-sys", ] +[[package]] +name = "glow" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" +dependencies = [ + "bitflags 2.11.0", + "cfg_aliases", + "cgl", + "dispatch2", + "glutin_egl_sys", + "glutin_wgl_sys", + "libloading 0.8.9", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "once_cell", + "raw-window-handle 0.6.2", + "windows-sys 0.52.0", +] + +[[package]] +name = "glutin-winit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" +dependencies = [ + "cfg_aliases", + "glutin", + "raw-window-handle 0.6.2", + "winit", +] + +[[package]] +name = "glutin_egl_sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" +dependencies = [ + "gl_generator", + "windows-sys 0.52.0", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + [[package]] name = "gobject-sys" version = "0.18.0" @@ -1985,55 +2809,61 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] -name = "h2" -version = "0.4.8" +name = "half" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap 2.9.0", - "slab", - "tokio", - "tokio-util", - "tracing", + "cfg-if", + "crunchy", + "zerocopy", ] [[package]] -name = "half" -version = "2.5.0" +name = "hashbrown" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "cfg-if", - "crunchy", + "foldhash 0.1.5", ] [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", +] [[package]] -name = "hashbrown" -version = "0.14.5" +name = "headers" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" +dependencies = [ + "base64", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] [[package]] -name = "hashbrown" -version = "0.15.2" +name = "headers-core" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http", +] [[package]] name = "heck" @@ -2049,48 +2879,30 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "home" -version = "0.5.11" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "html5ever" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" dependencies = [ "log", "mac", "markup5ever", - "proc-macro2", - "quote", - "syn 1.0.109", + "match_token", ] [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", - "itoa 1.0.15", + "itoa", ] [[package]] @@ -2122,20 +2934,26 @@ 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.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", - "h2", + "futures-core", "http", "http-body", "httparse", - "itoa 1.0.15", + "itoa", "pin-project-lite", "smallvec", "tokio", @@ -2144,50 +2962,36 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.5" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ - "futures-util", "http", "hyper", "hyper-util", "rustls", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", -] - -[[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", + "webpki-roots", ] [[package]] name = "hyper-util" -version = "0.1.11" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ + "base64", "bytes", "futures-channel", "futures-util", "http", "http-body", "hyper", + "ipnet", "libc", + "percent-encoding", "pin-project-lite", "socket2", "tokio", @@ -2196,122 +3000,116 @@ dependencies = [ ] [[package]] -name = "icu_collections" -version = "1.5.0" +name = "iana-time-zone" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "iana-time-zone-haiku" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", + "cc", ] [[package]] -name = "icu_locid_transform" -version = "1.5.0" +name = "icu_collections" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", "zerovec", ] [[package]] -name = "icu_locid_transform_data" -version = "1.5.1" +name = "icu_locale_core" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", + "icu_locale_core", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] [[package]] -name = "icu_provider_macros" -version = "1.5.0" +name = "id-arena" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "ident_case" @@ -2321,9 +3119,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -2332,69 +3130,125 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", ] [[package]] -name = "indexmap" -version = "1.9.3" +name = "image" +version = "0.25.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ - "autocfg", - "hashbrown 0.12.3", + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png 0.18.1", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", ] +[[package]] +name = "imgref" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" + [[package]] name = "indexmap" -version = "2.9.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] name = "infer" -version = "0.11.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6c16b11a665b26aeeb9b1d7f954cdeb034be38dd00adab4f2ae921a8fee804" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" dependencies = [ "cfb", ] [[package]] -name = "instant" -version = "0.1.13" +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "inventory" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" dependencies = [ - "cfg-if", + "rustversion", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] -name = "itoa" -version = "0.4.8" +name = "iri-string" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "javascriptcore-rs" @@ -2428,25 +3282,89 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys", + "jni-sys 0.3.1", "log", "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link 0.2.1", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", +] + [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "jobserver" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -2457,29 +3375,46 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "serde", "unicode-segmentation", ] +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + [[package]] name = "kuchikiki" -version = "0.8.2" +version = "0.8.8-speedreader" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" dependencies = [ "cssparser", "html5ever", - "indexmap 1.9.3", - "matches", + "indexmap", "selectors", ] +[[package]] +name = "kurbo" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b60dfc32f652b926df6192e55525b16d186c69d47876c3ead4da5cc9f8450e2" +dependencies = [ + "arrayvec", + "euclid", + "polycool", + "smallvec", +] + [[package]] name = "lazy-js-bundle" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e49596223b9d9d4947a14a25c142a6e7d8ab3f27eb3ade269d238bb8b5c267e2" +checksum = "ebbde2c5796719fbd82d6b8ec0be3dacf1f70c2876dee0f2c001632794d6641f" [[package]] name = "lazy_static" @@ -2487,6 +3422,18 @@ 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 = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + [[package]] name = "libappindicator" version = "0.9.0" @@ -2507,15 +3454,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" dependencies = [ "gtk-sys", - "libloading", + "libloading 0.7.4", "once_cell", ] [[package]] name = "libc" -version = "0.2.171" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" +dependencies = [ + "arbitrary", + "cc", +] [[package]] name = "libloading" @@ -2527,14 +3484,26 @@ dependencies = [ "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.3" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "libc", + "plain", + "redox_syscall 0.7.5", ] [[package]] @@ -2556,6 +3525,12 @@ dependencies = [ "x11", ] +[[package]] +name = "linebender_resource_handle" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -2564,31 +3539,36 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "litrs" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "longest-increasing-subsequence" @@ -2596,12 +3576,38 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[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" @@ -2613,65 +3619,127 @@ dependencies = [ [[package]] name = "manganis" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317af44b15e7605b85f04525449a3bb631753040156c9b318e6cba8a3ea4ef73" +checksum = "2e06225f29a781d86afdfafa562de09621f2ace377136ae2ae9ca9e72a29b920" dependencies = [ - "const-serialize", + "const-serialize 0.7.2", + "const-serialize 0.8.0-alpha.0", + "jni 0.21.1", "manganis-core", "manganis-macro", + "ndk-context", + "objc2 0.6.4", + "thiserror 2.0.18", ] [[package]] name = "manganis-core" -version = "0.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c38bee65cc725b2bba23b5dbb290f57c8be8fadbe2043fb7e2ce73022ea06519" +checksum = "774ddc382b4fb30f3fdcf2418131cbac5e6111f00e6c7ddf9e598ef3b2b4cd91" dependencies = [ - "const-serialize", + "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.6.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f4f71310913c40174d9f0cfcbcb127dad0329ecdb3945678a120db22d3d065" +checksum = "731c83c89d831f341fb46eba0aefdfb3433f77a3f78a8b08d9d88746613a8f8b" dependencies = [ "dunce", + "macro-string", "manganis-core", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "markup5ever" -version = "0.11.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" dependencies = [ "log", - "phf 0.10.1", - "phf_codegen 0.10.0", + "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 = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + [[package]] name = "memchr" -version = "2.7.4" +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 1.1.4", +] + +[[package]] +name = "memmap2" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] [[package]] name = "memoffset" @@ -2700,9 +3768,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.7" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", "simd-adler32", @@ -2710,58 +3778,74 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.61.2", ] [[package]] -name = "muda" -version = "0.11.5" +name = "moxcms" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c47e7625990fc1af2226ea4f34fb2412b03c12639fcb91868581eb3a6893453" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" dependencies = [ - "cocoa 0.25.0", - "crossbeam-channel", - "gtk", - "keyboard-types", - "libxdo", - "objc", - "once_cell", - "png", - "thiserror 1.0.69", - "windows-sys 0.52.0", + "num-traits", + "pxfm", ] [[package]] name = "muda" -version = "0.15.3" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdae9c00e61cc0579bcac625e8ad22104c60548a025bfc972dc83868a28e1484" +checksum = "7c9fec5a4e89860383d778d10563a605838f8f0b2f9303868937e5ff32e86177" dependencies = [ "crossbeam-channel", "dpi", "gtk", "keyboard-types", "libxdo", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", "once_cell", - "png", - "thiserror 1.0.69", - "windows-sys 0.59.0", + "png 0.17.16", + "thiserror 2.0.18", + "windows-sys 0.60.2", +] + +[[package]] +name = "multer" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "memchr", + "mime", + "spin", + "version_check", ] +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", @@ -2780,8 +3864,8 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.9.0", - "jni-sys", + "bitflags 2.11.0", + "jni-sys 0.3.1", "log", "ndk-sys", "num_enum", @@ -2801,7 +3885,7 @@ version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ - "jni-sys", + "jni-sys 0.3.1", ] [[package]] @@ -2811,15 +3895,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] -name = "nix" -version = "0.27.1" +name = "no_std_io2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "b51ed7824b6e07d354605f4abb3d9d300350701299da96642ee084f5ce631550" dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "libc", - "memoffset", + "memchr", ] [[package]] @@ -2828,6 +3909,74 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2839,23 +3988,24 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate 2.0.2", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] @@ -2865,18 +4015,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", ] [[package]] @@ -2897,11 +4035,12 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3531f65190d9cff863b77a99857e74c314dd16bf56c538c4b57c7cbc3f3a6e59" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", + "objc2-exception-helper", ] [[package]] @@ -2910,7 +4049,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -2922,14 +4061,40 @@ dependencies = [ [[package]] name = "objc2-app-kit" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5906f93257178e2f7ae069efb89fbd6ee94f0592740b5f8a1512ca498814d0fb" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.9.0", - "objc2 0.6.0", + "bitflags 2.11.0", + "block2 0.6.2", + "objc2 0.6.4", "objc2-core-foundation", - "objc2-foundation 0.3.0", + "objc2-core-graphics", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -2938,7 +4103,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -2946,22 +4111,26 @@ dependencies = [ [[package]] name = "objc2-core-foundation" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.9.0", - "objc2 0.6.0", + "bitflags 2.11.0", + "dispatch2", + "objc2 0.6.4", ] [[package]] name = "objc2-core-graphics" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dca602628b65356b6513290a21a6405b4d4027b8b250f0b98dddbb28b7de02" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", + "dispatch2", + "objc2 0.6.4", "objc2-core-foundation", + "objc2-io-surface", ] [[package]] @@ -2976,43 +4145,88 @@ dependencies = [ "objc2-metal", ] +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + [[package]] name = "objc2-encode" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" +[[package]] +name = "objc2-exception-helper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" +dependencies = [ + "cc", +] + [[package]] name = "objc2-foundation" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "block2 0.5.1", + "dispatch", "libc", "objc2 0.5.2", ] [[package]] name = "objc2-foundation" -version = "0.3.0" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.11.0", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.9.0", - "block2 0.6.0", - "objc2 0.6.0", + "bitflags 2.11.0", + "objc2 0.6.4", "objc2-core-foundation", ] +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + [[package]] name = "objc2-metal" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -3024,7 +4238,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -3032,75 +4246,138 @@ dependencies = [ ] [[package]] -name = "objc_exception" -version = "0.1.2" +name = "objc2-symbols" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" dependencies = [ - "cc", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] -name = "objc_id" -version = "0.1.1" +name = "objc2-ui-kit" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "objc", + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", ] [[package]] -name = "object" -version = "0.36.7" +name = "objc2-ui-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "memchr", + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", ] [[package]] -name = "once_cell" -version = "1.21.3" +name = "objc2-uniform-type-identifiers" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] [[package]] -name = "openssl" -version = "0.10.71" +name = "objc2-user-notifications" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "foreign-types 0.3.2", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", ] [[package]] -name = "openssl-macros" -version = "0.1.1" +name = "objc2-web-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "proc-macro2", + "bitflags 2.11.0", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "openssl" +version = "0.10.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" +dependencies = [ + "bitflags 2.11.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" dependencies = [ "cc", "libc", @@ -3115,13 +4392,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] -name = "ordered-stream" -version = "0.2.0" +name = "orbclient" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747" dependencies = [ - "futures-core", - "pin-project-lite", + "libc", + "libredox", ] [[package]] @@ -3149,17 +4426,11 @@ dependencies = [ "system-deps", ] -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -3167,22 +4438,70 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.18", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + +[[package]] +name = "peniko" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "839c8299360d2e998bdb106dc0a6cd71dcc5f4df51df1b620361bf50e283cca6" +dependencies = [ + "bytemuck", + "color", + "kurbo", + "linebender_resource_handle", "smallvec", - "windows-targets 0.52.6", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap", + "serde", + "serde_derive", +] [[package]] name = "phf" @@ -3190,9 +4509,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", "phf_shared 0.8.0", - "proc-macro-hack", ] [[package]] @@ -3201,7 +4518,18 @@ 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]] @@ -3216,12 +4544,12 @@ dependencies = [ [[package]] name = "phf_codegen" -version = "0.10.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", + "phf_generator 0.11.3", + "phf_shared 0.11.3", ] [[package]] @@ -3256,12 +4584,12 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", + "phf_generator 0.10.0", + "phf_shared 0.10.0", "proc-macro-hack", "proc-macro2", "quote", @@ -3292,51 +4620,34 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher 1.0.1", + "siphasher 1.0.2", ] [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.4" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" @@ -3344,6 +4655,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "png" version = "0.17.16" @@ -3357,127 +4674,433 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.11.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "polling" -version = "3.7.4" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 0.38.44", - "tracing", - "windows-sys 0.59.0", + "rustix 1.1.4", + "windows-sys 0.61.2", ] [[package]] name = "pollster" -version = "0.3.0" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "polycool" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50596ddc09eb5ad5f75cacd40209568e66df71baf86e1499a0e99c4cff12a5a6" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "potential_utf" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +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 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.10+spec-1.1.0", +] + +[[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 = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "version_check", +] + +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive 0.13.5", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive 0.14.3", +] + +[[package]] +name = "prost-build" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +dependencies = [ + "heck 0.5.0", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph 0.7.1", + "prettyplease", + "prost 0.13.5", + "prost-types 0.13.5", + "regex", + "syn 2.0.117", + "tempfile", +] + +[[package]] +name = "prost-build" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" +dependencies = [ + "heck 0.5.0", + "itertools", + "log", + "multimap", + "petgraph 0.8.3", + "prettyplease", + "prost 0.14.3", + "prost-types 0.14.3", + "pulldown-cmark", + "pulldown-cmark-to-cmark", + "regex", + "syn 2.0.117", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost-types" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost 0.13.5", +] + +[[package]] +name = "prost-types" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" +dependencies = [ + "prost 0.14.3", +] + +[[package]] +name = "psl-types" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" + +[[package]] +name = "publicsuffix" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" +dependencies = [ + "idna", + "psl-types", +] + +[[package]] +name = "pulldown-cmark" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" +dependencies = [ + "bitflags 2.11.0", + "memchr", + "unicase", +] [[package]] -name = "ppv-lite86" -version = "0.2.21" +name = "pulldown-cmark-to-cmark" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" dependencies = [ - "zerocopy", + "pulldown-cmark", ] [[package]] -name = "precomputed-hash" -version = "0.1.1" +name = "pxfm" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" [[package]] -name = "proc-macro-crate" -version = "1.3.1" +name = "qoi" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "bytemuck", ] [[package]] -name = "proc-macro-crate" -version = "2.0.2" +name = "quick-error" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" -dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", -] +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "quick-xml" +version = "0.39.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", + "memchr", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "quinn" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ - "proc-macro2", - "quote", - "version_check", + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.2", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", ] [[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.94" +name = "quinn-proto" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ - "unicode-ident", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring", + "rustc-hash 2.1.2", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", ] [[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" +name = "quinn-udp" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "version_check", + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" @@ -3504,6 +5127,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + [[package]] name = "rand_chacha" version = "0.2.2" @@ -3524,6 +5157,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + [[package]] name = "rand_core" version = "0.5.1" @@ -3539,7 +5182,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", ] [[package]] @@ -3560,6 +5212,56 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.4", + "rand_chacha 0.9.0", + "simd_helpers", + "thiserror 2.0.18", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + [[package]] name = "raw-window-handle" version = "0.5.2" @@ -3572,31 +5274,79 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "read-fonts" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" +dependencies = [ + "bytemuck", + "font-types", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", ] [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.17", "libredox", - "thiserror 2.0.12", + "thiserror 2.0.18", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -3606,9 +5356,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -3617,80 +5367,84 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", - "encoding_rs", + "cookie", + "cookie_store", "futures-core", "futures-util", - "h2", "http", "http-body", "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", - "ipnet", "js-sys", "log", - "mime", "mime_guess", - "native-tls", - "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "quinn", + "rustls", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.4.2", "web-sys", - "windows-registry", + "webpki-roots", ] [[package]] name = "rfd" -version = "0.14.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a73a7337fc24366edfca76ec521f51877b114e42dab584008209cca6719251" +checksum = "20dafead71c16a34e1ff357ddefc8afc11e7d51d6d2b9fbd07eaa48e3e540220" dependencies = [ - "ashpd", - "block", - "dispatch", + "block2 0.6.2", + "dispatch2", "js-sys", + "libc", "log", - "objc", - "objc-foundation", - "objc_id", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "percent-encoding", "pollster", "raw-window-handle 0.6.2", - "urlencoding", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" + [[package]] name = "ring" version = "0.17.14" @@ -3699,17 +5453,25 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "ron" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "4147b952f3f819eca0e99527022f7d6a8d05f111aeb0a62960c74eb283bec8fc" +dependencies = [ + "bitflags 2.11.0", + "once_cell", + "serde", + "serde_derive", + "typeid", + "unicode-ident", +] [[package]] name = "rustc-hash" @@ -3717,6 +5479,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + [[package]] name = "rustc_version" version = "0.4.1" @@ -3732,7 +5500,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -3741,24 +5509,25 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.5" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.9.3", - "windows-sys 0.59.0", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.25" +version = "0.23.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +checksum = "7c2c118cb077cca2822033836dfb1b975355dfb784b5e8da48f7b6c5db74e60e" dependencies = [ "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -3766,25 +5535,20 @@ dependencies = [ ] [[package]] -name = "rustls-pemfile" -version = "2.2.0" +name = "rustls-pki-types" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ - "rustls-pki-types", + "web-time", + "zeroize", ] -[[package]] -name = "rustls-pki-types" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" - [[package]] name = "rustls-webpki" -version = "0.103.1" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", @@ -3793,15 +5557,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -3814,13 +5578,19 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -3829,12 +5599,12 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.11.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.9.4", + "bitflags 2.11.0", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -3842,9 +5612,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -3852,29 +5622,33 @@ dependencies = [ [[package]] name = "selectors" -version = "0.22.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" dependencies = [ "bitflags 1.3.2", "cssparser", - "derive_more", + "derive_more 0.99.20", "fxhash", "log", - "matches", "phf 0.8.0", "phf_codegen 0.8.0", "precomputed-hash", "servo_arc", "smallvec", - "thin-slice", ] +[[package]] +name = "self_cell" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" + [[package]] name = "semver" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "send_wrapper" @@ -3887,56 +5661,78 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] [[package]] name = "serde-wasm-bindgen" -version = "0.5.0" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" dependencies = [ "js-sys", "serde", "wasm-bindgen", ] +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "itoa 1.0.15", + "itoa", "memchr", - "ryu", "serde", + "serde_core", + "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.12.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0431a35568651e363364210c91983c1da5eb29404d9f0928b67d4ebcfa7d330c" +checksum = "f3faaf9e727533a19351a43cc5a8de957372163c7d35cc48c90b75cdda13c352" dependencies = [ "percent-encoding", "serde", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] @@ -3947,14 +5743,14 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -3965,70 +5761,17 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "form_urlencoded", - "itoa 1.0.15", - "ryu", - "serde", -] - -[[package]] -name = "server_fn" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fae7a3038a32e5a34ba32c6c45eb4852f8affaf8b794ebfcd4b1099e2d62ebe" -dependencies = [ - "bytes", - "const_format", - "dashmap", - "futures", - "gloo-net", - "http", - "js-sys", - "once_cell", - "reqwest", - "send_wrapper", - "serde", - "serde_json", - "serde_qs", - "server_fn_macro_default", - "thiserror 1.0.69", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "xxhash-rust", -] - -[[package]] -name = "server_fn_macro" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaaf648c6967aef78177c0610478abb5a3455811f401f3c62d10ae9bd3901a1" -dependencies = [ - "const_format", - "convert_case 0.6.0", - "proc-macro2", - "quote", - "syn 2.0.100", - "xxhash-rust", -] - -[[package]] -name = "server_fn_macro_default" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2aa8119b558a17992e0ac1fd07f080099564f24532858811ce04f742542440" -dependencies = [ - "server_fn_macro", - "syn 2.0.100", + "form_urlencoded", + "itoa", + "ryu", + "serde", ] [[package]] name = "servo_arc" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" dependencies = [ "nodrop", "stable_deref_trait", @@ -4047,9 +5790,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -4073,9 +5816,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" dependencies = [ "libc", "signal-hook-registry", @@ -4083,18 +5826,44 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "siphasher" @@ -4104,19 +5873,26 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] -name = "slab" -version = "0.4.9" +name = "skrifa" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" dependencies = [ - "autocfg", + "bytemuck", + "read-fonts", ] +[[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" @@ -4129,12 +5905,12 @@ dependencies = [ [[package]] name = "sledgehammer_bindgen_macro" -version = "0.6.0" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a1b4f13e2bbf2f5b29d09dfebc9de69229ffee245aed80e3b70f9b5fd28c06" +checksum = "bb251b407f50028476a600541542b605bb864d35d9ee1de4f6cab45d88475e6d" dependencies = [ "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] @@ -4143,14 +5919,14 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "debdd4b83524961983cea3c55383b3910fd2f24fd13a188f5b091d2d504a61ae" dependencies = [ - "rustc-hash", + "rustc-hash 1.1.0", ] [[package]] name = "slotmap" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" dependencies = [ "serde", "version_check", @@ -4158,18 +5934,68 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "smithay-client-toolkit" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" +dependencies = [ + "bitflags 2.11.0", + "calloop 0.14.4", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 1.1.4", + "thiserror 2.0.18", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-clipboard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" +dependencies = [ + "libc", + "smithay-client-toolkit", + "wayland-backend", +] + +[[package]] +name = "smol_str" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] [[package]] name = "socket2" -version = "0.5.9" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4198,11 +6024,17 @@ dependencies = [ "system-deps", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -4235,6 +6067,34 @@ dependencies = [ "quote", ] +[[package]] +name = "subsecond" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feae81a4a7ca6d0bcf70c385a43b7dbacbff527f0805cb0a4043ce2c2c559a2c" +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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85256ee192cbdf00473e48e6133863b125dd4f772fddfbc97287ec7a61458c25" +dependencies = [ + "serde", +] + [[package]] name = "subtle" version = "2.6.1" @@ -4254,9 +6114,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.100" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -4274,34 +6134,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.9.4", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", + "syn 2.0.117", ] [[package]] @@ -4319,35 +6158,34 @@ dependencies = [ [[package]] name = "tao" -version = "0.30.8" +version = "0.34.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da" +checksum = "9103edf55f2da3c82aea4c7fab7c4241032bfeea0e71fa557d98e00e7ce7cc20" dependencies = [ - "bitflags 2.9.0", - "cocoa 0.26.0", - "core-foundation 0.10.0", - "core-graphics 0.24.0", + "bitflags 2.11.0", + "block2 0.6.2", + "core-foundation 0.10.1", + "core-graphics 0.25.0", "crossbeam-channel", - "dispatch", + "dispatch2", "dlopen2", "dpi", "gdkwayland-sys", "gdkx11-sys", "gtk", - "instant", - "jni", - "lazy_static", + "jni 0.21.1", "libc", "log", "ndk", "ndk-context", "ndk-sys", - "objc", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-foundation 0.3.2", "once_cell", "parking_lot", "raw-window-handle 0.5.2", "raw-window-handle 0.6.2", - "scopeguard", "tao-macros", "unicode-segmentation", "url", @@ -4365,7 +6203,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] @@ -4376,15 +6214,15 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.19.1" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.2", + "getrandom 0.4.2", "once_cell", - "rustix 1.0.5", - "windows-sys 0.59.0", + "rustix 1.1.4", + "windows-sys 0.61.2", ] [[package]] @@ -4398,12 +6236,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "thin-slice" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" - [[package]] name = "thiserror" version = "1.0.69" @@ -4415,11 +6247,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.18", ] [[package]] @@ -4430,98 +6262,157 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", +] + +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + +[[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.7.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" -version = "1.44.2" +version = "1.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd" dependencies = [ - "backtrace", "bytes", "libc", "mio", "pin-project-lite", - "signal-hook-registry", "socket2", "tokio-macros", - "tracing", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "native-tls", + "rustls", "tokio", ] [[package]] -name = "tokio-rustls" -version = "0.26.2" +name = "tokio-stream" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ - "rustls", + "futures-core", + "pin-project-lite", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.14" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", + "futures-util", "pin-project-lite", "tokio", ] @@ -4534,7 +6425,7 @@ checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.3", "toml_edit 0.20.2", ] @@ -4547,15 +6438,24 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.9.0", - "toml_datetime", - "winnow", + "indexmap", + "toml_datetime 0.6.3", + "winnow 0.5.40", ] [[package]] @@ -4564,18 +6464,156 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.9.0", + "indexmap", "serde", "serde_spanned", - "toml_datetime", - "winnow", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.25.10+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.1", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.1", +] + +[[package]] +name = "tonic" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" +dependencies = [ + "async-trait", + "base64", + "bytes", + "http", + "http-body", + "http-body-util", + "percent-encoding", + "pin-project", + "sync_wrapper", + "tokio-stream", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac6f67be712d12f0b41328db3137e0d0757645d8904b4cb7d51cd9c2279e847" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build 0.13.5", + "prost-types 0.13.5", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tonic-build" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tonic-prost" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" +dependencies = [ + "bytes", + "prost 0.14.3", + "tonic", +] + +[[package]] +name = "tonic-prost-build" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build 0.14.3", + "prost-types 0.14.3", + "quote", + "syn 2.0.117", + "tempfile", + "tonic-build 0.14.5", +] + +[[package]] +name = "tonic-web" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29453d84de05f4f1b573db22e6f9f6c95c189a6089a440c9a098aa9dea009299" +dependencies = [ + "base64", + "bytes", + "http", + "http-body", + "pin-project", + "tokio-stream", + "tonic", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-web-wasm-client" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0469c353de5f665c95f898074b5b004b500c6722214c3249f1dc79c0a2a3f6" +dependencies = [ + "base64", + "byteorder", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "httparse", + "js-sys", + "pin-project", + "thiserror 2.0.18", + "tonic", + "tower-service", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.5.0", + "web-sys", ] [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -4586,6 +6624,24 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags 2.11.0", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -4600,10 +6656,11 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4611,32 +6668,36 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", ] [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ + "matchers", + "once_cell", + "regex-automata", "sharded-slab", "thread_local", + "tracing", "tracing-core", ] @@ -4653,23 +6714,23 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.19.3" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadd75f5002e2513eaa19b2365f533090cc3e93abd38788452d9ea85cff7b48a" +checksum = "a5e85aa143ceb072062fc4d6356c1b520a51d636e7bc8e77ec94be3608e5e80c" dependencies = [ "crossbeam-channel", "dirs", "libappindicator", - "muda 0.15.3", - "objc2 0.6.0", - "objc2-app-kit 0.3.0", + "muda", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.0", + "objc2-foundation 0.3.2", "once_cell", - "png", - "thiserror 2.0.12", - "windows-sys 0.59.0", + "png 0.17.16", + "thiserror 2.0.18", + "windows-sys 0.60.2", ] [[package]] @@ -4680,56 +6741,69 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.23.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" +checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" dependencies = [ - "byteorder", "bytes", "data-encoding", "http", "httparse", "log", - "rand 0.8.5", + "rand 0.9.4", "sha1", - "thiserror 1.0.69", + "thiserror 2.0.18", "utf-8", ] [[package]] -name = "typenum" -version = "1.18.0" +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", + "native-tls", + "rand 0.9.4", + "rustls", + "sha1", + "thiserror 2.0.18", + "utf-8", +] + +[[package]] +name = "typeid" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] -name = "uds_windows" -version = "1.1.0" +name = "typenum" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" -dependencies = [ - "memoffset", - "tempfile", - "winapi", -] +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicase" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-xid" @@ -4745,9 +6819,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -4755,24 +6829,12 @@ dependencies = [ "serde", ] -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "utf-8" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -4781,9 +6843,25 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.16.0" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] [[package]] name = "vcpkg" @@ -4791,11 +6869,37 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vello_common" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd1a4c633ce09e7d713df1a6e036644a125e15e0c169cfb5180ddf5836ca04b" +dependencies = [ + "bytemuck", + "fearless_simd", + "hashbrown 0.16.1", + "log", + "peniko", + "skrifa", + "smallvec", +] + +[[package]] +name = "vello_cpu" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0162bfe48aabf6a9fdcd401b628c7d9f260c2cbabb343c70a65feba6f7849edc" +dependencies = [ + "bytemuck", + "hashbrown 0.16.1", + "vello_common", +] + [[package]] name = "version-compare" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" [[package]] name = "version_check" @@ -4841,7 +6945,7 @@ checksum = "59195a1db0e95b920366d949ba5e0d3fc0e70b67c09be15ce5abb790106b0571" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] @@ -4852,63 +6956,56 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen" -version = "0.2.100" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" +name = "wasm-bindgen" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.100", + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4916,26 +7013,48 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.100", - "wasm-bindgen-backend", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.4.2" @@ -4949,11 +7068,168 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "wayland-backend" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" +dependencies = [ + "bitflags 2.11.0", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.11.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +dependencies = [ + "rustix 1.1.4", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-experimental" +version = "20250721.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -4961,17 +7237,16 @@ dependencies = [ [[package]] name = "webbrowser" -version = "0.8.15" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" +checksum = "0fc95580916af1e68ff6a7be07446fc5db73ebf71cf092de939bbf5f7e189f72" dependencies = [ - "core-foundation 0.9.4", - "home", - "jni", + "core-foundation 0.10.1", + "jni 0.22.4", "log", "ndk-context", - "objc", - "raw-window-handle 0.5.2", + "objc2 0.6.4", + "objc2-foundation 0.3.2", "url", "web-sys", ] @@ -5020,11 +7295,20 @@ dependencies = [ "system-deps", ] +[[package]] +name = "webpki-roots" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webview2-com" -version = "0.33.0" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61ff3d9d0ee4efcb461b14eb3acfda2702d10dc329f339303fc3e57215ae2c" +checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a" dependencies = [ "webview2-com-macros", "webview2-com-sys", @@ -5036,26 +7320,32 @@ dependencies = [ [[package]] name = "webview2-com-macros" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" +checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "webview2-com-sys" -version = "0.33.0" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886" +checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" dependencies = [ - "thiserror 1.0.69", + "thiserror 2.0.18", "windows", "windows-core", ] +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + [[package]] name = "winapi" version = "0.3.9" @@ -5074,11 +7364,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5089,101 +7379,110 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.58.0" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core", + "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", - "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.58.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", + "windows-link 0.1.3", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core", + "windows-link 0.1.3", + "windows-threading", ] [[package]] name = "windows-implement" -version = "0.58.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "windows-interface" -version = "0.58.0" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "windows-link" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" - -[[package]] -name = "windows-registry" -version = "0.4.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" -dependencies = [ - "windows-result 0.3.2", - "windows-strings 0.3.1", - "windows-targets 0.53.0", -] +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] -name = "windows-result" -version = "0.2.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-result" -version = "0.3.2" +name = "windows-numerics" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-link", + "windows-core", + "windows-link 0.1.3", ] [[package]] -name = "windows-strings" -version = "0.1.0" +name = "windows-result" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-result 0.2.0", - "windows-targets 0.52.6", + "windows-link 0.1.3", ] [[package]] name = "windows-strings" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5197,29 +7496,38 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "windows-sys" -version = "0.52.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-sys" -version = "0.59.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -5237,21 +7545,6 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -5270,40 +7563,44 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.0" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] -name = "windows-version" -version = "0.1.4" +name = "windows-threading" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04a5c6627e310a23ad2358483286c7df260c964eb2d003d8efd6d0f4e79265c" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" +name = "windows-version" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" +dependencies = [ + "windows-link 0.2.1", +] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" @@ -5313,9 +7610,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -5323,12 +7620,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -5337,9 +7628,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -5347,12 +7638,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -5361,9 +7646,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -5373,9 +7658,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -5383,12 +7668,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -5397,9 +7676,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -5407,12 +7686,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -5421,9 +7694,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -5431,12 +7704,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -5445,9 +7712,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -5457,21 +7724,55 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" +name = "winit" +version = "0.30.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" +dependencies = [ + "android-activity", + "atomic-waker", + "bitflags 2.11.0", + "block2 0.5.1", + "calloop 0.13.0", + "cfg_aliases", + "concurrent-queue", + "core-foundation 0.9.4", + "core-graphics 0.23.2", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "ndk", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit 0.2.2", + "orbclient", + "pin-project", + "raw-window-handle 0.6.2", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "xkbcommon-dl", +] [[package]] name = "winnow" @@ -5483,64 +7784,158 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "winnow" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ - "bitflags 2.9.0", + "memchr", ] [[package]] -name = "write16" -version = "1.0.0" +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wry" -version = "0.45.0" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac0099a336829fbf54c26b5f620c68980ebbe37196772aeaf6118df4931b5cb0" +checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2" dependencies = [ "base64", - "block", - "cocoa 0.26.0", - "core-graphics 0.24.0", + "block2 0.6.2", + "cookie", "crossbeam-channel", + "dirs", "dpi", "dunce", - "gdkx11", "gtk", "html5ever", "http", "javascriptcore-rs", - "jni", + "jni 0.21.1", "kuchikiki", "libc", "ndk", - "objc", - "objc_id", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-ui-kit 0.3.2", + "objc2-web-kit", "once_cell", "percent-encoding", "raw-window-handle 0.6.2", "sha2", "soup3", "tao-macros", - "thiserror 1.0.69", + "thiserror 2.0.18", + "url", "webkit2gtk", "webkit2gtk-sys", "webview2-com", "windows", "windows-core", "windows-version", - "x11-dl", ] [[package]] @@ -5565,156 +7960,151 @@ dependencies = [ ] [[package]] -name = "xdg-home" -version = "1.3.0" +name = "x11rb" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ - "libc", - "windows-sys 0.59.0", + "gethostname", + "rustix 1.1.4", + "x11rb-protocol", ] [[package]] -name = "xxhash-rust" -version = "0.8.15" +name = "x11rb-protocol" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" [[package]] -name = "yoke" -version = "0.7.5" +name = "xcursor" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" [[package]] -name = "yoke-derive" -version = "0.7.5" +name = "xkbcommon-dl" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "synstructure", + "bitflags 2.11.0", + "dlib", + "log", + "once_cell", + "xkeysym", ] [[package]] -name = "zbus" -version = "4.0.1" +name = "xkeysym" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b8e3d6ae3342792a6cc2340e4394334c7402f3d793b390d2c5494a4032b3030" -dependencies = [ - "async-broadcast", - "async-process", - "async-recursion", - "async-trait", - "derivative", - "enumflags2", - "event-listener", - "futures-core", - "futures-sink", - "futures-util", - "hex", - "nix", - "ordered-stream", - "rand 0.8.5", - "serde", - "serde_repr", - "sha1", - "static_assertions", - "tokio", - "tracing", - "uds_windows", - "windows-sys 0.52.0", - "xdg-home", - "zbus_macros", - "zbus_names", - "zvariant", -] +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] -name = "zbus_macros" -version = "4.0.1" +name = "xml-rs" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a3e850ff1e7217a3b7a07eba90d37fe9bb9e89a310f718afcde5885ca9b6d7" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "regex", - "syn 1.0.109", - "zvariant_utils", + "stable_deref_trait", + "yoke-derive", + "zerofrom", ] [[package]] -name = "zbus_names" -version = "3.0.0" +name = "yoke-derive" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ - "serde", - "static_assertions", - "zvariant", + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.24" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.24" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -5723,49 +8113,41 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.117", ] [[package]] -name = "zvariant" -version = "4.0.0" +name = "zmij" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e09e8be97d44eeab994d752f341e67b3b0d80512a8b315a0671d47232ef1b65" -dependencies = [ - "endi", - "enumflags2", - "serde", - "static_assertions", - "url", - "zvariant_derive", -] +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] -name = "zvariant_derive" -version = "4.0.0" +name = "zune-inflate" +version = "0.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a5857e2856435331636a9fbb415b09243df4521a267c5bedcd5289b4d5799e" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", - "zvariant_utils", + "simd-adler32", ] [[package]] -name = "zvariant_utils" -version = "1.1.0" +name = "zune-jpeg" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "zune-core", ] diff --git a/services/core/blueprint/web-client/Cargo.toml b/services/core/blueprint/web-client/Cargo.toml index c33930e1..300c8c2c 100644 --- a/services/core/blueprint/web-client/Cargo.toml +++ b/services/core/blueprint/web-client/Cargo.toml @@ -8,13 +8,26 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -dioxus = { version = "0.6.0", features = ["web", "router"] } -dioxus-logger = "0.6.2" +dioxus = { version = "0.7.5", features = ["web", "router"] } +dioxus-logger = "0.7.4" dotenv = "0.15.0" once_cell = "1.21.3" -reqwest = { version = "0.12.15", features = ["json"] } serde = { version = "1.0.219", features = ["derive"] } web-sys = "0.3.77" +draft-api = { path = "../../../../api", features = ["web"] } +dioxus-grpc = { path = "../../../../tools/dioxus-grpc", default-features = false } +tonic-web-wasm-client = "0.9.1" +prost = "0.14" +prost-types = "0.14" +chrono = "0.4.44" +serde_json = "1" +gloo-timers = { version = "0.3", features = ["futures"] } +eframe = { version = "0.34", default-features = false, features = ["glow"] } +egui_graphs = "0.30" +petgraph = "0.8" +getrandom = { version = "0.3", features = ["wasm_js"] } +wasm-bindgen = "0.2" +wasm-bindgen-futures = "0.4" [features] default = ["web"] diff --git a/services/core/blueprint/web-client/Dioxus.toml b/services/core/blueprint/web-client/Dioxus.toml index 05e563cf..20ce6b7b 100644 --- a/services/core/blueprint/web-client/Dioxus.toml +++ b/services/core/blueprint/web-client/Dioxus.toml @@ -29,4 +29,10 @@ watch_path = ["src", "public"] [web.resource.dev] [[web.proxy]] -backend = "http://localhost:2221/draft" \ No newline at end of file +backend = "http://localhost:2221/core.registry.key_value.v1.KeyValueService/" + +[[web.proxy]] +backend = "http://localhost:2221/core.registry.service_discovery.v1.ServiceDiscoveryService/" + +[[web.proxy]] +backend = "http://localhost:18000/core.control_plane.networking.v1.NetworkingService/" \ No newline at end of file diff --git a/services/core/blueprint/web-client/src/components/arc_spine.rs b/services/core/blueprint/web-client/src/components/arc_spine.rs new file mode 100644 index 00000000..c9a648ed --- /dev/null +++ b/services/core/blueprint/web-client/src/components/arc_spine.rs @@ -0,0 +1,349 @@ +use dioxus::prelude::*; +use crate::components::topology::{TopologyData, event_color}; + +const SVG_H: f32 = 640.0; +const NODE_W: f32 = 220.0; +const NODE_H: f32 = 40.0; +const NODE_RX: f32 = 6.0; +const PROD_CX: f32 = 200.0; +const CONS_CX: f32 = 760.0; +const VERT_GAP: f32 = 24.0; +const EDGE_X1: f32 = 313.0; +const EDGE_X2: f32 = 647.0; + +fn col_ys(count: usize) -> Vec { + let total_h = count as f32 * NODE_H + (count.saturating_sub(1)) as f32 * VERT_GAP; + let start_y = (SVG_H - total_h) / 2.0; + (0..count) + .map(|i| start_y + i as f32 * (NODE_H + VERT_GAP) + NODE_H / 2.0) + .collect() +} + +fn bezier(x1: f32, y1: f32, x2: f32, y2: f32) -> String { + let cp = (x2 - x1) * 0.35; + format!("M {x1:.1} {y1:.1} C {:.1} {y1:.1} {:.1} {y2:.1} {x2:.1} {y2:.1}", + x1 + cp, x2 - cp) +} + +struct EdgeInfo { + key: String, + pid: String, + cid: String, + etype: String, + path: String, + mid_x: f32, + mid_y: f32, + color: &'static str, +} + +struct NodeInfo { + id: String, + name: String, + cy: f32, + dot_color: &'static str, + glow_color: &'static str, + sel_stroke: &'static str, +} + +#[component] +pub fn ArcSpine(data: TopologyData) -> Element { + let mut selected: Signal> = use_signal(|| None); + + let prod_ys = col_ys(data.producers.len()); + let cons_ys = col_ys(data.consumers.len()); + + let prod_cy: std::collections::HashMap = data.producers.iter().zip(prod_ys.iter()) + .map(|(n, &y)| (n.id.clone(), y)) + .collect(); + let cons_cy: std::collections::HashMap = data.consumers.iter().zip(cons_ys.iter()) + .map(|(n, &y)| (n.id.clone(), y)) + .collect(); + + // Bundle offset: group edges by (pid, cid), assign slot per-edge + let mut group_totals: std::collections::HashMap<(String, String), usize> = Default::default(); + for e in &data.edges { + *group_totals.entry((e.producer_id.clone(), e.consumer_id.clone())).or_insert(0) += 1; + } + let mut group_pos: std::collections::HashMap<(String, String), usize> = Default::default(); + + let edges: Vec = data.edges.iter().map(|e| { + let py = prod_cy.get(&e.producer_id).copied().unwrap_or(SVG_H / 2.0); + let cy = cons_cy.get(&e.consumer_id).copied().unwrap_or(SVG_H / 2.0); + let key = (e.producer_id.clone(), e.consumer_id.clone()); + let n = *group_totals.get(&key).unwrap_or(&1); + let pos = { + let slot = group_pos.entry(key).or_insert(0); + let v = *slot; + *slot += 1; + v + }; + let offset = (pos as f32 - (n as f32 - 1.0) / 2.0) * 13.0; + let y1 = py + offset; + let y2 = cy + offset; + EdgeInfo { + key: format!("{}-{}-{}", e.producer_id, e.consumer_id, e.event_type), + pid: e.producer_id.clone(), + cid: e.consumer_id.clone(), + etype: e.event_type.clone(), + path: bezier(EDGE_X1, y1, EDGE_X2, y2), + mid_x: (EDGE_X1 + EDGE_X2) / 2.0, + mid_y: (y1 + y2) / 2.0, + color: event_color(&e.event_type), + } + }).collect(); + + let prod_nodes: Vec = data.producers.iter().zip(prod_ys.iter()).map(|(n, &y)| { + NodeInfo { + id: n.id.clone(), + name: n.name.clone(), + cy: y, + dot_color: "#3b82f6", + glow_color: "#3b82f666", + sel_stroke: "#3b82f6", + } + }).collect(); + + let cons_nodes: Vec = data.consumers.iter().zip(cons_ys.iter()).map(|(n, &y)| { + NodeInfo { + id: n.id.clone(), + name: n.name.clone(), + cy: y, + dot_color: "#22c55e", + glow_color: "#22c55e66", + sel_stroke: "#22c55e", + } + }).collect(); + + let event_types: Vec<(String, &'static str)> = data.unique_event_types().iter() + .map(|s| (s.to_string(), event_color(s))) + .collect(); + + rsx! { + div { class: "w-full overflow-x-auto", + svg { + view_box: "0 0 960 640", + width: "960", + height: "640", + style: "max-width:100%; display:block; margin:0 auto;", + + rect { x: "0", y: "0", width: "960", height: "640", fill: "var(--color-base-100)" } + + defs { + pattern { + id: "as-grid", + width: "24", height: "24", + pattern_units: "userSpaceOnUse", + circle { cx: "1", cy: "1", r: "1", fill: "#ffffff0d" } + } + } + rect { x: "0", y: "0", width: "960", height: "640", fill: "url(#as-grid)" } + + line { + x1: "480", y1: "48", x2: "480", y2: "592", + stroke: "#1e293b", stroke_width: "1", + } + + text { + x: "200", y: "38", + text_anchor: "middle", + fill: "#475569", + font_size: "10", + font_family: "monospace", + letter_spacing: "2", + "PRODUCERS" + } + text { + x: "760", y: "38", + text_anchor: "middle", + fill: "#475569", + font_size: "10", + font_family: "monospace", + letter_spacing: "2", + "CONSUMERS" + } + + for ed in edges.iter() { + { + let pid = ed.pid.clone(); + let cid = ed.cid.clone(); + let etype = ed.etype.clone(); + let path = ed.path.clone(); + let mid_x = ed.mid_x; + let mid_y = ed.mid_y; + let color = ed.color; + let ekey = ed.key.clone(); + let sel = selected.read().clone(); + let active = sel.as_ref().map(|id| id == &pid || id == &cid).unwrap_or(true); + rsx! { + g { key: "{ekey}", + path { + d: "{path}", + fill: "none", + stroke: "{color}", + stroke_width: "1.5", + opacity: if active { "1" } else { "0.1" }, + } + if active { + rect { + x: "{mid_x - 30.0}", y: "{mid_y - 8.5}", + width: "60", height: "17", + rx: "8.5", + fill: "{color}1a", + stroke: "{color}", + stroke_width: "0.5", + } + text { + x: "{mid_x}", y: "{mid_y + 4.5}", + text_anchor: "middle", + fill: "{color}", + font_size: "8.5", + font_family: "monospace", + "{etype}" + } + } + } + } + } + } + + for node in prod_nodes.iter() { + { + let nid = node.id.clone(); + let nname = node.name.clone(); + let cy = node.cy; + let dot_color = node.dot_color; + let glow_color = node.glow_color; + let sel_stroke = node.sel_stroke; + let nx = PROD_CX - NODE_W / 2.0; + let ny = cy - NODE_H / 2.0; + let sel = selected.read().clone(); + let is_sel = sel.as_deref() == Some(nid.as_str()); + let is_dim = sel.as_ref().map(|s| s != &nid).unwrap_or(false); + let nid_click = nid.clone(); + rsx! { + g { + key: "p-{nid}", + style: if is_sel { + format!("filter:drop-shadow(0 0 8px {glow_color}); cursor:pointer;") + } else { + "cursor:pointer;".to_string() + }, + opacity: if is_dim { "0.2" } else { "1" }, + onclick: move |_| { + if selected.read().as_deref() == Some(nid_click.as_str()) { + selected.set(None); + } else { + selected.set(Some(nid_click.clone())); + } + }, + rect { + x: "{nx}", y: "{ny}", + width: "{NODE_W}", height: "{NODE_H}", + rx: "{NODE_RX}", + fill: "#1e293b", + stroke: if is_sel { sel_stroke } else { "#334155" }, + stroke_width: if is_sel { "2" } else { "1" }, + } + circle { + cx: "{nx + 16.0}", cy: "{cy}", + r: "4", fill: "{dot_color}", + } + text { + x: "{nx + 30.0}", y: "{cy + 5.0}", + fill: "#e2e8f0", + font_size: "13", + font_family: "ui-sans-serif, system-ui, sans-serif", + "{nname}" + } + } + } + } + } + + for node in cons_nodes.iter() { + { + let nid = node.id.clone(); + let nname = node.name.clone(); + let cy = node.cy; + let dot_color = node.dot_color; + let glow_color = node.glow_color; + let sel_stroke = node.sel_stroke; + let nx = CONS_CX - NODE_W / 2.0; + let ny = cy - NODE_H / 2.0; + let sel = selected.read().clone(); + let is_sel = sel.as_deref() == Some(nid.as_str()); + let is_dim = sel.as_ref().map(|s| s != &nid).unwrap_or(false); + let nid_click = nid.clone(); + rsx! { + g { + key: "c-{nid}", + style: if is_sel { + format!("filter:drop-shadow(0 0 8px {glow_color}); cursor:pointer;") + } else { + "cursor:pointer;".to_string() + }, + opacity: if is_dim { "0.2" } else { "1" }, + onclick: move |_| { + if selected.read().as_deref() == Some(nid_click.as_str()) { + selected.set(None); + } else { + selected.set(Some(nid_click.clone())); + } + }, + rect { + x: "{nx}", y: "{ny}", + width: "{NODE_W}", height: "{NODE_H}", + rx: "{NODE_RX}", + fill: "#1e293b", + stroke: if is_sel { sel_stroke } else { "#334155" }, + stroke_width: if is_sel { "2" } else { "1" }, + } + circle { + cx: "{nx + 16.0}", cy: "{cy}", + r: "4", fill: "{dot_color}", + } + text { + x: "{nx + 30.0}", y: "{cy + 5.0}", + fill: "#e2e8f0", + font_size: "13", + font_family: "ui-sans-serif, system-ui, sans-serif", + "{nname}" + } + } + } + } + } + + // Legend row + for (idx, (etype, color)) in event_types.iter().enumerate() { + { + let lx = 48.0 + idx as f32 * 118.0; + let ly = SVG_H - 18.0; + let etype = etype.clone(); + let color = *color; + rsx! { + g { key: "leg-{etype}", + rect { + x: "{lx}", y: "{ly - 8.0}", + width: "108", height: "16", + rx: "8", + fill: "{color}18", + stroke: "{color}", + stroke_width: "0.75", + } + text { + x: "{lx + 54.0}", y: "{ly + 4.5}", + text_anchor: "middle", + fill: "{color}", + font_size: "9", + font_family: "monospace", + "{etype}" + } + } + } + } + } + } + } + } +} diff --git a/services/core/blueprint/web-client/src/components/cesql_bar.rs b/services/core/blueprint/web-client/src/components/cesql_bar.rs new file mode 100644 index 00000000..0611a6ba --- /dev/null +++ b/services/core/blueprint/web-client/src/components/cesql_bar.rs @@ -0,0 +1,30 @@ +use dioxus::prelude::*; + +#[component] +pub fn CesqlBar(expression: Signal, on_run: EventHandler<()>, on_clear: EventHandler<()>) -> Element { + rsx! { + div { class: "join w-full", + input { + class: "input input-bordered input-sm join-item flex-1 font-mono bg-base-200", + placeholder: "e.g. type = 'com.shop.order.created' or source LIKE '%shop%'", + value: "{expression}", + oninput: move |e| expression.set(e.value()), + onkeydown: move |e| { + if e.key() == Key::Enter { + on_run.call(()); + } + }, + } + button { + class: "btn btn-sm btn-ghost join-item text-base-content/50 hover:text-base-content", + onclick: move |_| on_clear.call(()), + "✕" + } + button { + class: "btn btn-sm btn-neutral join-item", + onclick: move |_| on_run.call(()), + "run" + } + } + } +} diff --git a/services/core/blueprint/web-client/src/components/filter_chips.rs b/services/core/blueprint/web-client/src/components/filter_chips.rs new file mode 100644 index 00000000..0138f2f8 --- /dev/null +++ b/services/core/blueprint/web-client/src/components/filter_chips.rs @@ -0,0 +1,32 @@ +use dioxus::prelude::*; + +const PRESETS: &[(&str, &str)] = &[ + ("type = order.created", "type = 'order.created'"), + ("source LIKE %shop%", "source LIKE '%shop%'"), + ("failed OR cancelled", "type = 'failed' OR type = 'cancelled'"), + ("EXISTS correlationid", "EXISTS correlationid"), + ("no correlation", "NOT EXISTS correlationid"), + ("paid or succeeded", "type = 'paid' OR type = 'succeeded'"), + ("inventory events", "source LIKE '%inventory%'"), + ("late events (>2s)", "subject LIKE '%timeout%'"), +]; + +#[component] +pub fn FilterChips(on_select: EventHandler) -> Element { + rsx! { + div { class: "flex flex-wrap gap-2", + for (label, expr) in PRESETS.iter() { + { + let expr_owned = expr.to_string(); + rsx! { + button { + class: "badge badge-outline badge-sm cursor-pointer hover:badge-primary transition-colors", + onclick: move |_| on_select.call(expr_owned.clone()), + "{label}" + } + } + } + } + } + } +} diff --git a/services/core/blueprint/web-client/src/components/full_circle.rs b/services/core/blueprint/web-client/src/components/full_circle.rs new file mode 100644 index 00000000..8bf4f882 --- /dev/null +++ b/services/core/blueprint/web-client/src/components/full_circle.rs @@ -0,0 +1,608 @@ +use std::f32::consts::PI; +use dioxus::prelude::*; +use crate::components::topology::TopologyData; + +const CX0: f32 = 340.0; +const CY0: f32 = 340.0; +const R: f32 = 210.0; +const OR: f32 = 308.0; +const ARC_W: f32 = 7.0; +const ARC_SPAN: f32 = 4.58; // ≈ 0.08 radians +const CP_R: f32 = 55.0; +const LABEL_R: f32 = R + ARC_W + 18.0; + +fn circ(deg: f32, radius: f32) -> (f32, f32) { + let rad = (deg - 90.0) * PI / 180.0; + (CX0 + radius * rad.cos(), CY0 + radius * rad.sin()) +} + +fn evenly_spaced(start: f32, end: f32, n: usize) -> Vec { + match n { + 0 => vec![], + 1 => vec![(start + end) / 2.0], + _ => (0..n).map(|i| start + i as f32 * (end - start) / (n - 1) as f32).collect(), + } +} + +fn node_arc(deg: f32) -> String { + let (x1, y1) = circ(deg - ARC_SPAN, R); + let (x2, y2) = circ(deg + ARC_SPAN, R); + format!("M {x1:.2} {y1:.2} A {R} {R} 0 0 1 {x2:.2} {y2:.2}") +} + +fn bezier(pa: f32, ca: f32) -> String { + let (px, py) = circ(pa, R); + let (ex, ey) = circ(ca, R); + let (c1x, c1y) = circ(pa, CP_R); + let (c2x, c2y) = circ(ca, CP_R); + format!("M {px:.2} {py:.2} C {c1x:.2} {c1y:.2} {c2x:.2} {c2y:.2} {ex:.2} {ey:.2}") +} + +fn thread_lw(vol: u32, max: u32) -> f32 { + 0.5 + (vol as f32 / max as f32) * 7.5 +} + +fn thread_alpha(vol: u32, max: u32) -> f32 { + 0.12 + 0.55 * (vol as f32 / max as f32) +} + +static BG_DOTS: &[(f32, f32)] = &[ + (72.0, 44.0), (145.0, 90.0), (312.0, 28.0), (498.0, 61.0), (620.0, 44.0), + (51.0, 200.0), (190.0, 155.0), (580.0, 130.0), (660.0, 210.0), (30.0, 380.0), + (640.0, 340.0), (85.0, 520.0), (600.0, 490.0), (180.0, 610.0), (480.0, 640.0), + (620.0, 580.0), (350.0, 665.0), (120.0, 660.0), (230.0, 50.0), (560.0, 330.0), +]; + +#[derive(Clone)] +struct Node { + id: String, + label: String, + is_prod: bool, + deg: f32, +} + +#[derive(Clone)] +struct Edge { + pid: String, + cid: String, + ev: String, + vol: u32, + path: String, +} + +#[derive(Clone)] +struct ConnRow { + ev: String, + partner: String, + vol: u32, + bar_w: u32, +} + +fn has_conn(sel_id: &str, nid: &str, edges: &[Edge]) -> bool { + nid == sel_id + || edges.iter().any(|e| { + (e.pid == sel_id || e.cid == sel_id) && (e.pid == nid || e.cid == nid) + }) +} + +#[component] +pub fn FullCircle(data: TopologyData) -> Element { + let mut sel: Signal> = use_signal(|| None); + let mut hovered: Signal> = use_signal(|| None); + let mut hover_pos: Signal<(f64, f64)> = use_signal(|| (0.0, 0.0)); + let mut show_lbl = use_signal(|| true); + let mut show_vol = use_signal(|| true); + + // Producers: upper 160° arc, centred on top (−80° → +80°) + // Consumers: lower 160° arc, centred on bottom (100° → 260°) + // 20° gap on each side keeps producers and consumers fully separated. + let prod_degs = evenly_spaced(-80.0, 80.0, data.producers.len()); + let cons_degs = evenly_spaced(100.0, 260.0, data.consumers.len()); + + let nodes: Vec = data.producers.iter().zip(&prod_degs) + .map(|(n, &d)| Node { id: n.id.clone(), label: n.name.clone(), is_prod: true, deg: d }) + .chain(data.consumers.iter().zip(&cons_degs) + .map(|(n, &d)| Node { id: n.id.clone(), label: n.name.clone(), is_prod: false, deg: d })) + .collect(); + + let max_vol = data.edges.iter().map(|e| e.vol).max().unwrap_or(1); + + let edges: Vec = data.edges.iter().map(|e| { + let pa = nodes.iter().find(|n| n.id == e.producer_id).map(|n| n.deg).unwrap_or(0.0); + let ca = nodes.iter().find(|n| n.id == e.consumer_id).map(|n| n.deg).unwrap_or(180.0); + Edge { + pid: e.producer_id.clone(), + cid: e.consumer_id.clone(), + ev: e.event_type.clone(), + vol: e.vol, + path: bezier(pa, ca), + } + }).collect(); + + let sel_val = sel(); + let hov_val = hovered(); + let (hx, hy) = hover_pos(); + let lbl = show_lbl(); + let vol_mode = show_vol(); + + // 36 evenly-spaced outer-ring tick marks, skipping positions near a node (< 4°) + let ticks: Vec<[f32; 4]> = (0..36u32).filter_map(|i| { + let tick_deg = (i as f32 / 36.0) * 360.0 + 90.0; + let near = nodes.iter().any(|nd| { + let d = ((nd.deg - tick_deg + 540.0) % 360.0) - 180.0; + d.abs() < 4.01 + }); + if near { return None; } + let (x1, y1) = circ(tick_deg, OR - 2.0); + let (x2, y2) = circ(tick_deg, OR + 2.0); + Some([x1, y1, x2, y2]) + }).collect(); + + // Volume-scale bar descriptors: (stroke-width, x-start) + let vol_bars: [(f32, f32); 4] = [(0.5, 128.0), (2.0, 150.0), (5.0, 172.0), (8.0, 194.0)]; + + // Pre-compute tooltip data from hovered node + let tooltip: Option<(String, String, Vec, u32)> = + hov_val.as_ref().and_then(|hid| { + nodes.iter().find(|n| &n.id == hid).map(|nd| { + let mut rows: Vec = edges.iter() + .filter(|e| &e.pid == hid || &e.cid == hid) + .map(|e| { + let partner_id = if &e.pid == hid { &e.cid } else { &e.pid }; + let partner = nodes.iter().find(|n| &n.id == partner_id) + .map(|n| n.label.clone()) + .unwrap_or_else(|| partner_id.clone()); + ConnRow { + ev: e.ev.clone(), + partner, + vol: e.vol, + bar_w: ((e.vol as f32 / max_vol as f32) * 60.0).round() as u32, + } + }) + .collect(); + rows.sort_by(|a, b| b.vol.cmp(&a.vol)); + let total: u32 = rows.iter().map(|r| r.vol).sum(); + let ntype = if nd.is_prod { "producer" } else { "consumer" }; + (nd.label.clone(), ntype.to_string(), rows, total) + }) + }); + + // Pre-compute center-panel data from selected node (or mesh summary) + let (sel_center, n_nodes, n_edges) = { + let nn = nodes.len(); + let ne = edges.len(); + let info = sel_val.as_ref().and_then(|sid| { + nodes.iter().find(|n| &n.id == sid).map(|nd| { + let conns: Vec<_> = edges.iter() + .filter(|e| &e.pid == sid || &e.cid == sid) + .collect(); + let total: u32 = conns.iter().map(|e| e.vol).sum(); + let ntype = if nd.is_prod { "producer" } else { "consumer" }; + (nd.label.clone(), ntype.to_string(), total, conns.len()) + }) + }); + (info, nn, ne) + }; + + // Button pill styles + let pill = |on: bool| -> String { + format!( + "font-size:10px;padding:2px 9px;border-radius:99px;border:0.5px solid {};background:transparent;color:{};cursor:pointer;font-family:inherit;", + if on { "rgba(255,255,255,0.28)" } else { "rgba(255,255,255,0.08)" }, + if on { "rgba(255,255,255,0.65)" } else { "rgba(255,255,255,0.2)" }, + ) + }; + let lbl_pill = pill(lbl); + let vol_pill = pill(vol_mode); + + rsx! { + div { + style: "position:relative;width:100%;height:100%;overflow:hidden;background:#080808;font-family:ui-sans-serif,system-ui,sans-serif;", + + svg { + view_box: "-38 -38 756 756", + width: "100%", + height: "100%", + style: "display:block;", + onmousemove: move |ev| { + let c = ev.element_coordinates(); + hover_pos.set((c.x, c.y)); + }, + onmouseleave: move |_| { hovered.set(None); }, + + // ── Background ────────────────────────────────────────────── + rect { x: "0", y: "0", width: "680", height: "680", fill: "#080808" } + for dot in BG_DOTS { + circle { cx: "{dot.0}", cy: "{dot.1}", r: "0.7", fill: "rgba(255,255,255,0.18)" } + } + + // ── Outer decorative ring ──────────────────────────────────── + circle { + cx: "{CX0}", cy: "{CY0}", r: "{OR}", + fill: "none", stroke: "rgba(255,255,255,0.18)", stroke_width: "0.5" + } + for t in ticks.iter() { + line { + x1: "{t[0]:.2}", y1: "{t[1]:.2}", x2: "{t[2]:.2}", y2: "{t[3]:.2}", + stroke: "rgba(255,255,255,0.09)", stroke_width: "0.5" + } + } + + // ── Base node ring ─────────────────────────────────────────── + circle { + cx: "{CX0}", cy: "{CY0}", r: "{R}", + fill: "none", stroke: "rgba(255,255,255,0.05)", stroke_width: "1" + } + + // ── Dimmed threads ─────────────────────────────────────────── + for e in edges.iter() { + if sel_val.as_ref().map_or(false, |sid| &e.pid != sid && &e.cid != sid) { + path { + d: "{e.path}", + fill: "none", + stroke: "rgba(255,255,255,0.04)", + stroke_width: "0.5" + } + } + } + + // ── Active threads ─────────────────────────────────────────── + for e in edges.iter() { + if sel_val.as_ref().map_or(true, |sid| &e.pid == sid || &e.cid == sid) { + { + let sw = if vol_mode { thread_lw(e.vol, max_vol) } else { 1.5_f32 }; + let alpha = if vol_mode { thread_alpha(e.vol, max_vol) } else { 0.45_f32 }; + let stroke = format!("rgba(255,255,255,{alpha:.3})"); + let path = e.path.clone(); + rsx! { + path { + d: "{path}", + fill: "none", + stroke: "{stroke}", + stroke_width: "{sw:.2}", + stroke_linecap: "round", + stroke_linejoin: "round" + } + } + } + } + } + + // ── Nodes ──────────────────────────────────────────────────── + for nd in nodes.iter() { + { + let nid = nd.id.clone(); + let nid2 = nd.id.clone(); + + let dim = sel_val.as_ref().map_or(false, |s| !has_conn(s, &nd.id, &edges)); + let is_sel = sel_val.as_deref() == Some(nd.id.as_str()); + + // Arc segment + let arc = node_arc(nd.deg); + let arc_stroke = if is_sel { "rgba(255,255,255,0.95)" } + else if nd.is_prod { "rgba(255,200,80,0.65)" } + else { "rgba(80,160,255,0.5)" }; + let arc_sw = if is_sel { ARC_W } else { ARC_W * 0.6 }; + + // Inward tick + let (tx, ty) = circ(nd.deg, R); + let (tick_x, tick_y) = circ(nd.deg, R - 10.0); + let tick_clr = if is_sel { "rgba(255,255,255,0.5)" } else { "rgba(255,255,255,0.18)" }; + + // Outer ring marker + let (ox1, oy1) = circ(nd.deg, OR - 3.0); + let (ox2, oy2) = circ(nd.deg, OR + 3.0); + let outer_clr = if is_sel { "rgba(255,255,255,0.7)" } + else if nd.is_prod { "rgba(255,255,255,0.35)" } + else { "rgba(255,255,255,0.2)" }; + let outer_sw = if is_sel { "1.5" } else { "0.5" }; + + // Label – placed in a local coordinate group so that the + // indicator (line / dot) can be drawn without additional + // trigonometry. `canvas_deg` is the standard SVG rotation + // angle (CW from right); the "flip" condition prevents text + // on the left hemisphere from rendering upside-down. + let (lx, ly) = circ(nd.deg, LABEL_R); + let canvas_deg = nd.deg - 90.0; + let norm = (canvas_deg + 360.0) % 360.0; + let flip = norm > 90.0 && norm < 270.0; + let rot = if flip { canvas_deg + 180.0 } else { canvas_deg }; + let gtransform = format!("translate({lx:.2},{ly:.2}) rotate({rot:.1})"); + let txt_x: f32 = if flip { -4.0 } else { 4.0 }; + let txt_anchor = if flip { "end" } else { "start" }; + let ind_x1: f32 = if flip { -14.0 } else { -4.0 }; + let ind_x2: f32 = if flip { -4.0 } else { 4.0 }; + let dot_cx: f32 = if flip { -9.0 } else { 0.0 }; + let lbl_fill = if is_sel { "rgba(255,255,255,0.95)" } + else if nd.is_prod { "rgba(255,255,255,0.65)" } + else { "rgba(255,255,255,0.4)" }; + let lbl_w = if is_sel { "500" } else { "400" }; + let ind_clr = if is_sel { "rgba(255,255,255,0.35)" } else { "rgba(255,255,255,0.15)" }; + + let opacity = if dim { "0.1" } else { "1" }; + let label = nd.label.clone(); + let is_prod = nd.is_prod; + + rsx! { + g { + opacity: "{opacity}", + style: "cursor:pointer;", + onmouseenter: move |_| hovered.set(Some(nid.clone())), + onmouseleave: move |_| hovered.set(None), + onclick: move |_| { + let cur = sel(); + sel.set( + if cur.as_deref() == Some(nid2.as_str()) { None } + else { Some(nid2.clone()) } + ); + }, + + // Arc segment marker + path { + d: "{arc}", + fill: "none", + stroke: "{arc_stroke}", + stroke_width: "{arc_sw:.1}", + stroke_linecap: "round" + } + // Inward tick + line { + x1: "{tx:.2}", y1: "{ty:.2}", + x2: "{tick_x:.2}", y2: "{tick_y:.2}", + stroke: "{tick_clr}", stroke_width: "0.5" + } + // Outer ring tick + line { + x1: "{ox1:.2}", y1: "{oy1:.2}", + x2: "{ox2:.2}", y2: "{oy2:.2}", + stroke: "{outer_clr}", stroke_width: "{outer_sw}" + } + // Invisible hit-area circle + circle { cx: "{tx:.2}", cy: "{ty:.2}", r: "20", fill: "transparent" } + + // Label + producer-line / consumer-dot indicator + if lbl { + g { transform: "{gtransform}", + text { + x: "{txt_x}", y: "0", + text_anchor: "{txt_anchor}", + dominant_baseline: "middle", + fill: "{lbl_fill}", + font_size: "11", + font_weight: "{lbl_w}", + font_family: "ui-sans-serif,system-ui,sans-serif", + "{label}" + } + if is_prod { + line { + x1: "{ind_x1}", y1: "12", + x2: "{ind_x2}", y2: "12", + stroke: "{ind_clr}", stroke_width: "1" + } + } else { + circle { cx: "{dot_cx}", cy: "12", r: "1.5", fill: "{ind_clr}" } + } + } + } + } + } + } + } + + // ── Legend (producer line · "producer" ● "consumer") ─────── + if lbl { + line { + x1: "{680.0 - 18.0 - 60.0 - 8.0 - 56.0 - 14.0}", + y1: "{680.0 - 20.0}", + x2: "{680.0 - 18.0 - 60.0 - 8.0 - 56.0 - 4.0}", + y2: "{680.0 - 20.0}", + stroke: "rgba(255,200,80,0.5)", stroke_width: "1" + } + text { + x: "{680.0 - 18.0 - 60.0 - 8.0}", y: "{680.0 - 20.0}", + text_anchor: "end", dominant_baseline: "middle", + fill: "rgba(255,255,255,0.2)", font_size: "10", + font_family: "ui-sans-serif,sans-serif", + "producer" + } + circle { + cx: "{680.0 - 18.0 - 60.0}", cy: "{680.0 - 20.0}", + r: "1.5", fill: "rgba(80,160,255,0.5)" + } + text { + x: "{680.0 - 18.0}", y: "{680.0 - 20.0}", + text_anchor: "end", dominant_baseline: "middle", + fill: "rgba(255,255,255,0.2)", font_size: "10", + font_family: "ui-sans-serif,sans-serif", + "consumer" + } + } + + // ── Volume-scale legend ─────────────────────────────────────── + if vol_mode { + text { + x: "16", y: "{680.0 - 20.0}", + dominant_baseline: "middle", + fill: "rgba(255,255,255,0.16)", font_size: "9", + font_family: "ui-sans-serif,sans-serif", + "thread = msgs/min" + } + for bar in vol_bars.iter() { + { + let sw = bar.0; + let bx = bar.1; + let alpha = 0.15 + sw * 0.06; + let s = format!("rgba(255,255,255,{alpha:.3})"); + rsx! { + line { + x1: "{bx}", y1: "{680.0 - 20.0}", + x2: "{bx + 16.0}", y2: "{680.0 - 20.0}", + stroke: "{s}", stroke_width: "{sw}", + stroke_linecap: "round" + } + } + } + } + } + + // ── Center panel ───────────────────────────────────────────── + if let Some((c_lbl, c_type, c_vol, c_conn)) = sel_center { + { + let conn_s = if c_conn != 1 { "s" } else { "" }; + rsx! { + text { + x: "{CX0}", y: "{CY0 - 22.0}", + text_anchor: "middle", dominant_baseline: "middle", + fill: "rgba(255,255,255,0.72)", font_size: "13", + font_weight: "500", font_family: "ui-sans-serif,sans-serif", + "{c_lbl}" + } + text { + x: "{CX0}", y: "{CY0 - 5.0}", + text_anchor: "middle", dominant_baseline: "middle", + fill: "rgba(255,255,255,0.28)", font_size: "10", + font_family: "ui-sans-serif,sans-serif", + "{c_type}" + } + text { + x: "{CX0}", y: "{CY0 + 11.0}", + text_anchor: "middle", dominant_baseline: "middle", + fill: "rgba(255,255,255,0.22)", font_size: "10", + font_family: "ui-sans-serif,sans-serif", + "{c_vol} msgs/min" + } + text { + x: "{CX0}", y: "{CY0 + 26.0}", + text_anchor: "middle", dominant_baseline: "middle", + fill: "rgba(255,255,255,0.14)", font_size: "10", + font_family: "ui-sans-serif,sans-serif", + "{c_conn} connection{conn_s}" + } + } + } + } else { + text { + x: "{CX0}", y: "{CY0 - 8.0}", + text_anchor: "middle", dominant_baseline: "middle", + fill: "rgba(255,255,255,0.08)", font_size: "11", + font_weight: "500", font_family: "ui-sans-serif,sans-serif", + "mesh" + } + text { + x: "{CX0}", y: "{CY0 + 8.0}", + text_anchor: "middle", dominant_baseline: "middle", + fill: "rgba(255,255,255,0.05)", font_size: "10", + font_family: "ui-sans-serif,sans-serif", + "{n_nodes} nodes · {n_edges} edges" + } + } + } + + // ── View-toggle overlay ────────────────────────────────────────── + div { + style: "position:absolute;top:14px;left:16px;display:flex;gap:6px;align-items:center;", + span { + style: "font-size:10px;color:rgba(255,255,255,0.22);letter-spacing:0.08em;text-transform:uppercase;margin-right:2px;", + "view" + } + button { + style: "{lbl_pill}", + onclick: move |_| show_lbl.toggle(), + "labels" + } + button { + style: "{vol_pill}", + onclick: move |_| show_vol.toggle(), + "volume" + } + } + + // ── Hover tooltip ──────────────────────────────────────────────── + if let Some((t_lbl, t_type, t_rows, t_total)) = tooltip { + { + // Container height = viewport minus 4rem navbar. + let container_h = web_sys::window() + .and_then(|w| w.inner_height().ok()) + .and_then(|v| v.as_f64()) + .unwrap_or(800.0) - 64.0; + + // Estimate rendered tooltip height: header block + per-row + footer. + let est_h = 80.0 + t_rows.len() as f64 * 42.0 + 36.0; + + let tip_x = hx + 18.0; + let tip_y_raw = (hy - 10.0).max(4.0); + let tip_y = if tip_y_raw + est_h > container_h { + (container_h - est_h - 4.0).max(4.0) + } else { + tip_y_raw + }; + + // Hard cap: tooltip can never be taller than the space below tip_y. + let max_h = (container_h - tip_y - 4.0).max(80.0); + + rsx! { + div { + style: "position:absolute;pointer-events:none;left:{tip_x}px;top:{tip_y}px;", + div { + style: "background:rgba(8,8,8,0.97);border:0.5px solid rgba(255,255,255,0.1);border-radius:8px;padding:10px 14px;min-width:200px;max-height:{max_h}px;overflow-y:auto;", + div { + style: "font-size:11px;font-weight:500;color:rgba(255,255,255,0.85);margin-bottom:2px;", + "{t_lbl}" + } + div { + style: "font-size:9px;letter-spacing:0.08em;text-transform:uppercase;color:rgba(255,255,255,0.3);margin-bottom:8px;", + "{t_type}" + } + for row in t_rows.iter() { + { + let ev = row.ev.clone(); + let partner = row.partner.clone(); + let vol = row.vol; + let bw = row.bar_w; + rsx! { + div { + style: "padding:3px 0;border-bottom:0.5px solid rgba(255,255,255,0.06);", + div { + style: "display:flex;align-items:center;gap:16px;margin-bottom:3px;", + span { + style: "font-size:10px;color:rgba(255,255,255,0.5);flex:1;min-width:0;", + "{ev}" + } + span { + style: "font-size:10px;color:rgba(255,255,255,0.55);font-family:monospace;flex-shrink:0;", + "{vol}/min" + } + } + div { + style: "display:flex;align-items:center;gap:6px;", + div { + style: "width:{bw}px;height:1.5px;background:rgba(255,255,255,0.35);border-radius:1px;" + } + span { + style: "font-size:10px;color:rgba(255,255,255,0.3);", + "{partner}" + } + } + } + } + } + } + div { + style: "display:flex;justify-content:space-between;padding-top:6px;margin-top:2px;", + span { + style: "font-size:10px;color:rgba(255,255,255,0.25);", + "total" + } + span { + style: "font-size:10px;color:rgba(255,255,255,0.55);font-family:monospace;", + "{t_total}/min" + } + } + } + } + } + } + } + } + } +} diff --git a/services/core/blueprint/web-client/src/components/hero.rs b/services/core/blueprint/web-client/src/components/hero.rs index ce4186f0..0773d24b 100644 --- a/services/core/blueprint/web-client/src/components/hero.rs +++ b/services/core/blueprint/web-client/src/components/hero.rs @@ -1,6 +1,6 @@ use dioxus::prelude::*; -static BLUEPRINT_NAME: GlobalSignal = Signal::global(|| "{blueprint}".to_string()); +static BLUEPRINT_NAME: GlobalSignal = Signal::global(|| "{draft}".to_string()); #[component] pub fn Hero() -> Element { diff --git a/services/core/blueprint/web-client/src/components/metric_card.rs b/services/core/blueprint/web-client/src/components/metric_card.rs new file mode 100644 index 00000000..46541e74 --- /dev/null +++ b/services/core/blueprint/web-client/src/components/metric_card.rs @@ -0,0 +1,181 @@ +use dioxus::prelude::*; + +#[derive(Clone, PartialEq)] +pub enum MetricIcon { + Messages, + Clock, + Warning, + Users, + Server, + ArrowUp, +} + +fn sparkline_points_str(data: &[f32]) -> String { + if data.len() < 2 { + return String::new(); + } + let min = data.iter().cloned().fold(f32::INFINITY, f32::min); + let max = data.iter().cloned().fold(f32::NEG_INFINITY, f32::max); + let range = if (max - min).abs() < 0.01 { 1.0 } else { max - min }; + let last = (data.len() - 1) as f32; + data.iter() + .enumerate() + .map(|(i, &v)| { + let x = i as f32 / last * 80.0; + let y = 26.0 - (v - min) / range * 24.0; + format!("{x:.1},{y:.1}") + }) + .collect::>() + .join(" ") +} + +fn icon_svg(icon: &MetricIcon) -> Element { + match icon { + MetricIcon::Messages => rsx! { + svg { + class: "w-4 h-4 shrink-0", + xmlns: "http://www.w3.org/2000/svg", + fill: "none", + view_box: "0 0 24 24", + stroke: "currentColor", + stroke_width: "1.5", + path { + stroke_linecap: "round", + stroke_linejoin: "round", + d: "M8.625 9.75a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H8.25m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H12m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0h-.375M21 12c0 4.556-4.03 8.25-9 8.25a9.764 9.764 0 0 1-2.555-.337A5.972 5.972 0 0 1 5.41 20.97a5.969 5.969 0 0 1-.474-.065 4.48 4.48 0 0 0 .978-2.025c.09-.457-.133-.901-.467-1.226C3.93 16.178 3 14.189 3 12c0-4.556 4.03-8.25 9-8.25s9 3.694 9 8.25Z", + } + } + }, + MetricIcon::Clock => rsx! { + svg { + class: "w-4 h-4 shrink-0", + xmlns: "http://www.w3.org/2000/svg", + fill: "none", + view_box: "0 0 24 24", + stroke: "currentColor", + stroke_width: "1.5", + path { + stroke_linecap: "round", + stroke_linejoin: "round", + d: "M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z", + } + } + }, + MetricIcon::Warning => rsx! { + svg { + class: "w-4 h-4 shrink-0", + xmlns: "http://www.w3.org/2000/svg", + fill: "none", + view_box: "0 0 24 24", + stroke: "currentColor", + stroke_width: "1.5", + path { + stroke_linecap: "round", + stroke_linejoin: "round", + d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z", + } + } + }, + MetricIcon::Users => rsx! { + svg { + class: "w-4 h-4 shrink-0", + xmlns: "http://www.w3.org/2000/svg", + fill: "none", + view_box: "0 0 24 24", + stroke: "currentColor", + stroke_width: "1.5", + path { + stroke_linecap: "round", + stroke_linejoin: "round", + d: "M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z", + } + } + }, + MetricIcon::Server => rsx! { + svg { + class: "w-4 h-4 shrink-0", + xmlns: "http://www.w3.org/2000/svg", + fill: "none", + view_box: "0 0 24 24", + stroke: "currentColor", + stroke_width: "1.5", + path { + stroke_linecap: "round", + stroke_linejoin: "round", + d: "M5.25 14.25h13.5m-13.5 0a3 3 0 0 1-3-3m3 3a3 3 0 1 0 0 6h13.5a3 3 0 1 0 0-6m-16.5-3a3 3 0 0 1 3-3h13.5a3 3 0 0 1 3 3m-19.5 0a4.5 4.5 0 0 1 .9-2.7L5.737 5.1a3.375 3.375 0 0 1 2.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 0 1 .9 2.7m0 0a3 3 0 0 1-3 3m0 3h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Zm-3 6h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Z", + } + } + }, + MetricIcon::ArrowUp => rsx! { + svg { + class: "w-4 h-4 shrink-0", + xmlns: "http://www.w3.org/2000/svg", + fill: "none", + view_box: "0 0 24 24", + stroke: "currentColor", + stroke_width: "1.5", + path { + stroke_linecap: "round", + stroke_linejoin: "round", + d: "M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5m-13.5-9L12 3m0 0 4.5 4.5M12 3v13.5", + } + } + }, + } +} + +#[component] +pub fn MetricCard( + icon: MetricIcon, + label: String, + value: String, + unit: Option, + trend_up: bool, + trend_good: bool, + trend_delta: String, + sparkline_data: Vec, + sparkline_color: String, +) -> Element { + let points = sparkline_points_str(&sparkline_data); + let trend_color = if trend_good { "#4ade80" } else { "#f87171" }; + let arrow = if trend_up { "↑" } else { "↓" }; + + rsx! { + div { class: "bg-base-200 rounded-xl p-4 flex flex-col gap-3", + div { class: "flex items-center gap-2 text-xs text-base-content/40 uppercase tracking-wider", + {icon_svg(&icon)} + span { "{label}" } + } + div { class: "text-5xl font-bold leading-none tracking-tight", + "{value}" + if let Some(u) = unit { + span { class: "text-2xl font-semibold ml-0.5 text-base-content/70", "{u}" } + } + } + div { class: "flex items-end justify-between gap-2", + span { + class: "text-sm font-medium", + style: "color: {trend_color}", + "{arrow} {trend_delta} vs prev" + } + if !points.is_empty() { + svg { + width: "80", + height: "28", + view_box: "0 0 80 28", + fill: "none", + xmlns: "http://www.w3.org/2000/svg", + polyline { + points: "{points}", + stroke: "{sparkline_color}", + stroke_width: "2", + fill: "none", + stroke_linecap: "round", + stroke_linejoin: "round", + } + } + } + } + } + } +} diff --git a/services/core/blueprint/web-client/src/components/mod.rs b/services/core/blueprint/web-client/src/components/mod.rs index 0ea2f2eb..f8fa915c 100644 --- a/services/core/blueprint/web-client/src/components/mod.rs +++ b/services/core/blueprint/web-client/src/components/mod.rs @@ -2,4 +2,31 @@ mod navbar; pub use navbar::{navbar_menu_button, navbar_icon, navbar_secondary_menu_button}; mod hero; -pub use hero::Hero; \ No newline at end of file +pub use hero::Hero; + +mod cesql_bar; +pub use cesql_bar::CesqlBar; + +mod filter_chips; +pub use filter_chips::FilterChips; + +mod type_badge; +pub use type_badge::TypeBadge; + +mod query_builder; +pub use query_builder::{QueryBuilder, SortDir}; + +mod metric_card; +pub use metric_card::{MetricCard, MetricIcon}; + +mod topology; +pub use topology::{TopologyData, TopologyNode, TopologyEdge, event_color}; + +mod arc_spine; +pub use arc_spine::ArcSpine; + +mod full_circle; +pub use full_circle::FullCircle; + +mod wave_loader; +pub use wave_loader::WaveLoader; \ No newline at end of file diff --git a/services/core/blueprint/web-client/src/components/navbar.rs b/services/core/blueprint/web-client/src/components/navbar.rs index 26cdc242..5b3e13e4 100644 --- a/services/core/blueprint/web-client/src/components/navbar.rs +++ b/services/core/blueprint/web-client/src/components/navbar.rs @@ -2,13 +2,12 @@ use dioxus::prelude::*; use crate::Route; - -static BLUEPRINT_NAME: GlobalSignal = Signal::global(|| "{blueprint}".to_string()); +static BLUEPRINT_NAME: GlobalSignal = Signal::global(|| "{draft}".to_string()); pub fn navbar_icon() -> Element { rsx! { a { class: "btn btn-ghost text-xl", - Link { to: Route::Home {}, "{BLUEPRINT_NAME}"}, + Link { to: Route::KeyValueView {}, "{BLUEPRINT_NAME}"}, } } } diff --git a/services/core/blueprint/web-client/src/components/query_builder.rs b/services/core/blueprint/web-client/src/components/query_builder.rs new file mode 100644 index 00000000..ebf6bda7 --- /dev/null +++ b/services/core/blueprint/web-client/src/components/query_builder.rs @@ -0,0 +1,260 @@ +use dioxus::prelude::*; + +#[derive(Clone, PartialEq, Copy)] +pub enum SortDir { + Asc, + Desc, +} + +#[derive(Clone, PartialEq)] +enum FieldKind { + Type, + Source, + Id, + Subject, + Body, +} + +#[derive(Clone, PartialEq)] +enum Operator { + Eq, + Like, +} + +#[derive(Clone, PartialEq)] +enum Connector { + Or, + And, +} + +fn cesql_name(field: &FieldKind, body_field: &str) -> String { + match field { + FieldKind::Type => "type".to_string(), + FieldKind::Source => "source".to_string(), + FieldKind::Id => "id".to_string(), + FieldKind::Subject => "subject".to_string(), + FieldKind::Body => format!("body.{body_field}"), + } +} + +fn format_fragment(op: &Operator, field_name: &str, value: &str) -> String { + match op { + Operator::Eq => format!("{field_name} = '{value}'"), + Operator::Like => format!("{field_name} LIKE '%{value}%'"), + } +} + +/// Collapsible form that generates a CESQL fragment and appends it to the +/// expression bar. `has_expression` controls whether the AND/OR connector +/// selector is shown. `on_add` is called with the fragment (prefixed with +/// "OR "/"AND " when joining an existing expression). `on_sort_change` is +/// called when the user changes the ORDER BY direction so the parent can +/// update its signal and trigger a re-query explicitly. +#[component] +pub fn QueryBuilder( + has_expression: bool, + on_add: EventHandler, + sort_dir: SortDir, + on_sort_change: EventHandler, +) -> Element { + let mut open = use_signal(|| false); + let mut field = use_signal(|| FieldKind::Type); + let mut body_field = use_signal(String::new); + let mut operator = use_signal(|| Operator::Eq); + let mut value = use_signal(String::new); + let mut connector = use_signal(|| Connector::Or); + + let field_name = cesql_name(&field(), &body_field()); + let preview = format_fragment(&operator(), &field_name, &value()); + + rsx! { + div { class: "border border-base-300 rounded-lg", + + // ── Collapsible header ────────────────────────────────────────── + button { + class: "w-full flex items-center gap-2 px-3 py-2 text-xs text-base-content/50 hover:bg-base-200/50 rounded-lg transition-colors", + onclick: move |_| open.toggle(), + span { + class: if open() { + "transition-transform duration-150 rotate-90 inline-block" + } else { + "transition-transform duration-150 inline-block" + }, + "▶" + } + "Query Builder" + span { class: "ml-auto text-base-content/30 text-[10px] italic", + "build a CESQL expression" + } + } + + // ── Expanded body ─────────────────────────────────────────────── + if open() { + div { class: "px-3 pb-3 flex flex-col gap-2 border-t border-base-300", + + // Row 1 — field / body-field / operator / value + div { class: "pt-2 flex flex-wrap items-end gap-2", + + div { class: "flex flex-col gap-1", + span { class: "text-[10px] text-base-content/40 uppercase tracking-wide", "Field" } + select { + class: "select select-xs select-bordered", + onchange: move |e| { + field.set(match e.value().as_str() { + "source" => FieldKind::Source, + "id" => FieldKind::Id, + "subject" => FieldKind::Subject, + "body" => FieldKind::Body, + _ => FieldKind::Type, + }); + }, + option { value: "type", selected: field() == FieldKind::Type, "type" } + option { value: "source", selected: field() == FieldKind::Source, "source" } + option { value: "id", selected: field() == FieldKind::Id, "id" } + option { value: "subject", selected: field() == FieldKind::Subject, "subject" } + option { value: "body", selected: field() == FieldKind::Body, "body.*" } + } + } + + // Body field name — only shown when body.* is selected + if field() == FieldKind::Body { + div { class: "flex flex-col gap-1", + span { class: "text-[10px] text-base-content/40 uppercase tracking-wide", "Body field" } + input { + class: "input input-xs input-bordered font-mono w-36", + placeholder: "e.g. modelName", + value: "{body_field}", + oninput: move |e| body_field.set(e.value()), + } + } + } + + div { class: "flex flex-col gap-1", + span { class: "text-[10px] text-base-content/40 uppercase tracking-wide", "Operator" } + select { + class: "select select-xs select-bordered", + onchange: move |e| { + operator.set(if e.value() == "like" { Operator::Like } else { Operator::Eq }); + }, + option { value: "eq", selected: operator() == Operator::Eq, "= (equals)" } + option { value: "like", selected: operator() == Operator::Like, "LIKE (contains)" } + } + } + + div { class: "flex flex-col gap-1 flex-1 min-w-28", + span { class: "text-[10px] text-base-content/40 uppercase tracking-wide", "Value" } + input { + class: "input input-xs input-bordered font-mono w-full", + placeholder: "value…", + value: "{value}", + oninput: move |e| value.set(e.value()), + onkeydown: move |e| { + if e.key() != Key::Enter { return; } + let v = value(); + if v.is_empty() { return; } + let fn_ = cesql_name(&field(), &body_field()); + let frag = format_fragment(&operator(), &fn_, &v); + let full = if has_expression { + match connector() { + Connector::Or => format!("OR {frag}"), + Connector::And => format!("AND {frag}"), + } + } else { frag }; + on_add.call(full); + value.set(String::new()); + }, + } + } + } + + // Row 2 — ORDER BY toggle (query-level, not a CESQL clause) + div { class: "flex items-center gap-2 border-t border-base-300/50 pt-2", + span { class: "text-[10px] text-base-content/40 uppercase tracking-wide", "Order" } + div { class: "join", + button { + class: if sort_dir == SortDir::Asc { + "btn btn-xs join-item btn-primary" + } else { + "btn btn-xs join-item btn-ghost" + }, + onclick: move |_| on_sort_change.call(SortDir::Asc), + "↑ Oldest first" + } + button { + class: if sort_dir == SortDir::Desc { + "btn btn-xs join-item btn-primary" + } else { + "btn btn-xs join-item btn-ghost" + }, + onclick: move |_| on_sort_change.call(SortDir::Desc), + "↓ Newest first" + } + } + } + + // Row 3 — live preview + connector toggle + add button + div { class: "flex items-center gap-2 flex-wrap", + + // Preview badge — shows exactly what CESQL will be inserted + div { class: "font-mono text-xs bg-base-300 px-2 py-1 rounded text-base-content/70 flex-1 min-w-0 truncate", + if has_expression { + span { class: "text-primary font-semibold mr-1", + match connector() { + Connector::Or => "OR ", + Connector::And => "AND ", + } + } + } + "{preview}" + } + + // AND / OR toggle — only relevant when joining an existing expression + if has_expression { + div { class: "join", + button { + class: if connector() == Connector::Or { + "btn btn-xs join-item btn-primary" + } else { + "btn btn-xs join-item btn-ghost" + }, + onclick: move |_| connector.set(Connector::Or), + "OR" + } + button { + class: if connector() == Connector::And { + "btn btn-xs join-item btn-primary" + } else { + "btn btn-xs join-item btn-ghost" + }, + onclick: move |_| connector.set(Connector::And), + "AND" + } + } + } + + button { + class: "btn btn-xs btn-neutral", + disabled: value().is_empty() + || (field() == FieldKind::Body && body_field().is_empty()), + onclick: move |_| { + let v = value(); + if v.is_empty() { return; } + let fn_ = cesql_name(&field(), &body_field()); + let frag = format_fragment(&operator(), &fn_, &v); + let full = if has_expression { + match connector() { + Connector::Or => format!("OR {frag}"), + Connector::And => format!("AND {frag}"), + } + } else { frag }; + on_add.call(full); + value.set(String::new()); + }, + "Add to query →" + } + } + } + } + } + } +} diff --git a/services/core/blueprint/web-client/src/components/topology.rs b/services/core/blueprint/web-client/src/components/topology.rs new file mode 100644 index 00000000..38a11400 --- /dev/null +++ b/services/core/blueprint/web-client/src/components/topology.rs @@ -0,0 +1,52 @@ +/// Topology types mirror Catalyst API data shapes: +/// producers — distinct CloudEvent.source values from the Produce stream +/// consumers — services registered via the Consume stream RPC +/// edges — (source × event_type × consumer) flows derived from event history + +#[derive(Clone, PartialEq)] +pub struct TopologyNode { + pub id: String, + pub name: String, +} + +#[derive(Clone, PartialEq)] +pub struct TopologyEdge { + pub producer_id: String, + pub consumer_id: String, + pub event_type: String, + pub vol: u32, +} + +#[derive(Clone, PartialEq, Default)] +pub struct TopologyData { + pub producers: Vec, + pub consumers: Vec, + pub edges: Vec, +} + +impl TopologyData { + pub fn unique_event_types(&self) -> Vec<&str> { + let mut out: Vec<&str> = Vec::new(); + for e in &self.edges { + if !out.contains(&e.event_type.as_str()) { + out.push(e.event_type.as_str()); + } + } + out.sort_unstable(); + out + } +} + +pub fn event_color(event_type: &str) -> &'static str { + match event_type { + "created" => "#3b82f6", + "cancelled" => "#ef4444", + "ok" => "#22c55e", + "failed" => "#f97316", + "reserved" => "#a855f7", + "updated" => "#14b8a6", + "registered" => "#eab308", + _ => "#6b7280", + } +} + diff --git a/services/core/blueprint/web-client/src/components/type_badge.rs b/services/core/blueprint/web-client/src/components/type_badge.rs new file mode 100644 index 00000000..5051adb9 --- /dev/null +++ b/services/core/blueprint/web-client/src/components/type_badge.rs @@ -0,0 +1,27 @@ +use dioxus::prelude::*; + +const COLORS: [&str; 5] = [ + "badge-success", + "badge-warning", + "badge-error", + "badge-info", + "badge-accent", +]; + +fn badge_color(event_type: &str) -> &'static str { + let hash = event_type + .bytes() + .fold(0usize, |acc, b| acc.wrapping_mul(31).wrapping_add(b as usize)); + COLORS[hash % COLORS.len()] +} + +#[component] +pub fn TypeBadge(event_type: String) -> Element { + let color = badge_color(&event_type); + rsx! { + span { class: "flex items-center gap-1.5", + span { class: "badge badge-xs {color}" } + span { class: "text-xs", "{event_type}" } + } + } +} diff --git a/services/core/blueprint/web-client/src/components/wave_loader.rs b/services/core/blueprint/web-client/src/components/wave_loader.rs new file mode 100644 index 00000000..e9cf123b --- /dev/null +++ b/services/core/blueprint/web-client/src/components/wave_loader.rs @@ -0,0 +1,56 @@ +use dioxus::prelude::*; + +const BAR_DURATIONS: [f32; 7] = [0.9, 0.7, 1.1, 0.6, 1.3, 0.8, 1.0]; +const BAR_DELAYS: [f32; 7] = [0.0, 0.15, 0.3, 0.45, 0.2, 0.35, 0.1]; + +// Embedded so the component has no external CSS dependency. +const KEYFRAMES: &str = "@keyframes wave-bar {\ + 0%,100%{transform:scaleY(0.06)}\ + 50%{transform:scaleY(1)}\ +}"; + +#[derive(Props, Clone, PartialEq)] +pub struct WaveLoaderProps { + #[props(default = 80)] + pub width: u32, + #[props(default = 30)] + pub height: u32, +} + +#[component] +pub fn WaveLoader(props: WaveLoaderProps) -> Element { + let w = props.width as f32; + let h = props.height as f32; + let n: usize = 7; + let bar_w = 2.0_f32; + let gap = (w - n as f32 * bar_w) / (n as f32 + 1.0); + + rsx! { + svg { + width: "{props.width}", + height: "{props.height}", + view_box: "0 0 {w:.0} {h:.0}", + xmlns: "http://www.w3.org/2000/svg", + style { "{KEYFRAMES}" } + for i in 0..n { + { + let x = gap + i as f32 * (bar_w + gap); + let dur = BAR_DURATIONS[i]; + let delay = BAR_DELAYS[i]; + rsx! { + rect { + key: "{i}", + x: "{x:.2}", + y: "0", + width: "{bar_w}", + height: "{h}", + fill: "white", + rx: "1", + style: "transform-box:fill-box;transform-origin:center;animation:wave-bar {dur}s ease-in-out {delay}s infinite;", + } + } + } + } + } + } +} diff --git a/services/core/blueprint/web-client/src/main.rs b/services/core/blueprint/web-client/src/main.rs index 0024be8a..46f39c77 100644 --- a/services/core/blueprint/web-client/src/main.rs +++ b/services/core/blueprint/web-client/src/main.rs @@ -1,36 +1,125 @@ use dioxus::prelude::*; use dioxus::logger::tracing::{Level, info}; use once_cell::sync::Lazy; +use std::collections::HashSet; use web_sys::window; +use draft_api::proto::core_registry_key_value_v1::{NavigationConfig, NavigationSection, NavigationItem}; +use draft_api::hook::core_registry_key_value_v1::{ + key_value_service_client::KeyValueServiceClient, + GetRequest, +}; +use prost::Message as _; +use prost_types::Any; +use tonic_web_wasm_client::Client as WasmClient; mod views; mod components; use components::{navbar_menu_button, navbar_icon, navbar_secondary_menu_button}; -use views::{Home, KeyValueView, ServiceRegistry, Metrics, PageNotFound}; +use views::{ + KeyValueView, ServiceRegistry, Gateway, Agents, Mcp, Tools, + Store, Topology, Cluster, Metrics, Settings, PageNotFound, +}; + +pub const NAV_CONFIG_KV_KEY: &str = "ui/navigation"; +pub const NAV_CONFIG_TYPE_URL: &str = + "type.googleapis.com/core.registry.key_value.v1.NavigationConfig"; + +pub const KNOWN_ROUTES: &[(&str, &str)] = &[ + ("/", "Key/Value"), + ("/service-registry", "Service Registry"), + ("/gateway", "Gateway"), + ("/agents", "Agents"), + ("/mcp", "MCP"), + ("/tools", "Tools"), + ("/store", "Store"), + ("/topology", "Topology"), + ("/cluster", "Cluster"), + ("/metrics", "Metrics"), +]; #[derive(Debug, Clone, Routable, PartialEq)] #[rustfmt::skip] enum Route { #[layout(dashboard_layout)] #[route("/")] - Home {}, - #[route("/key-val")] KeyValueView {}, #[route("/service-registry")] ServiceRegistry{}, + #[route("/gateway")] + Gateway{}, + #[route("/agents")] + Agents{}, + #[route("/mcp")] + Mcp{}, + #[route("/tools")] + Tools{}, + #[route("/store")] + Store{}, + #[route("/topology")] + Topology{}, + #[route("/cluster")] + Cluster{}, #[route("/metrics")] Metrics{}, - // end dashboard layout, all routes above will be wrapped in this layout + #[route("/settings")] + Settings{}, #[end_layout] - // PageNotFound is a catch all route that will match any route and placing the matched segments in the route field #[route("/:..route")] PageNotFound { route: Vec, }, } +pub fn path_to_route(path: &str) -> Option { + match path { + "/" => Some(Route::KeyValueView {}), + "/service-registry" => Some(Route::ServiceRegistry {}), + "/gateway" => Some(Route::Gateway {}), + "/agents" => Some(Route::Agents {}), + "/mcp" => Some(Route::Mcp {}), + "/tools" => Some(Route::Tools {}), + "/store" => Some(Route::Store {}), + "/topology" => Some(Route::Topology {}), + "/cluster" => Some(Route::Cluster {}), + "/metrics" => Some(Route::Metrics {}), + _ => None, + } +} + +pub fn default_nav_config() -> NavigationConfig { + NavigationConfig { + sections: vec![ + NavigationSection { + label: "Control Plane".to_string(), + items: vec![ + NavigationItem { label: "Key/Value".to_string(), path: "/".to_string() }, + NavigationItem { label: "Service Registry".to_string(), path: "/service-registry".to_string() }, + NavigationItem { label: "Gateway".to_string(), path: "/gateway".to_string() }, + ], + }, + NavigationSection { + label: "Automations".to_string(), + items: vec![ + NavigationItem { label: "Agents".to_string(), path: "/agents".to_string() }, + NavigationItem { label: "MCP".to_string(), path: "/mcp".to_string() }, + NavigationItem { label: "Tools".to_string(), path: "/tools".to_string() }, + ], + }, + NavigationSection { + label: "Events".to_string(), + items: vec![ + NavigationItem { label: "Store".to_string(), path: "/store".to_string() }, + NavigationItem { label: "Topology".to_string(), path: "/topology".to_string() }, + NavigationItem { label: "Cluster".to_string(), path: "/cluster".to_string() }, + NavigationItem { label: "Metrics".to_string(), path: "/metrics".to_string() }, + ], + }, + ], + } +} + fn get_domain() -> String { let window = window().expect("no global `window` exists"); let location = window.location(); @@ -39,44 +128,95 @@ fn get_domain() -> String { } pub static API_DOMAIN: Lazy = Lazy::new(|| { - // Check if the API_DOMAIN environment variable is set if let Some(api_domain) = option_env!("API_DOMAIN") { info!("API_DOMAIN: {}", api_domain); if api_domain.is_empty() { return get_domain().to_string() } - api_domain.to_string() } else { get_domain().to_string() } }); +pub static CATALYST_DOMAIN: Lazy = Lazy::new(|| { + if let Some(d) = option_env!("CATALYST_DOMAIN") { + if !d.is_empty() { + info!("CATALYST_DOMAIN: {}", d); + return d.to_string(); + } + } + "http://localhost:2220".to_string() +}); + fn main() { dioxus::logger::init(Level::INFO).expect("logger failed to init"); dioxus::launch(|| { - rsx!{ + use_context_provider(|| dioxus_grpc::GrpcConfig { + host: API_DOMAIN.clone(), + }); + rsx! { Router:: {} } }); } fn dashboard_layout() -> Element { + let mut nav_config: Signal> = + use_context_provider(|| Signal::new(None)); + let mut open_sections: Signal> = use_signal(HashSet::new); + + // Fetch nav config from KV once on mount; fall back to hardcoded default. + let _fetch = use_resource(move || async move { + let mut client = KeyValueServiceClient::new(WasmClient::new(crate::API_DOMAIN.clone())); + let config = match client.get(GetRequest { + key: NAV_CONFIG_KV_KEY.to_string(), + value: Some(Any { + type_url: NAV_CONFIG_TYPE_URL.to_string(), + value: vec![], + }), + }).await { + Ok(resp) => resp + .into_inner() + .value + .and_then(|any| NavigationConfig::decode(any.value.as_slice()).ok()) + .unwrap_or_else(default_nav_config), + Err(_) => default_nav_config(), + }; + nav_config.set(Some(config)); + }); + + // Pre-process config for rendering so rsx! sees plain owned data. + let config = nav_config().unwrap_or_else(default_nav_config); + let open = open_sections(); + let sections: Vec<(String, bool, Vec<(String, Option)>)> = config + .sections + .into_iter() + .map(|s| { + let is_open = open.contains(&s.label); + let items = s + .items + .into_iter() + .map(|i| (i.label, path_to_route(&i.path))) + .collect(); + (s.label, is_open, items) + }) + .collect(); + rsx! { div { class: "drawer lg:drawer-open", - input { class: "drawer-toggle", id: "my-drawer", type: "checkbox" } + input { class: "drawer-toggle", id: "my-drawer", r#type: "checkbox" } div { class: "drawer-content flex flex-col", - // navbar div { class: "navbar bg-base-300 shadow-sm w-full", div { class: "flex-none lg:hidden", - navbar_menu_button{} + navbar_menu_button {} } div { class: "flex-1 lg:hidden", - navbar_icon{} + navbar_icon {} } - div{ class: "hidden flex-1 lg:block"} + div { class: "hidden flex-1 lg:block" } div { class: "flex-none", navbar_secondary_menu_button {} } @@ -89,24 +229,56 @@ fn dashboard_layout() -> Element { label { aria_label: "close sidebar", class: "drawer-overlay", - for: "my-drawer", + r#for: "my-drawer", } ul { class: "menu bg-base-200 min-h-full w-80 p-4", - navbar_icon{} - div {class: "divider", "style": "margin: 0px 0px 0px 0px;"} - li { - Link { class: "bg-base-300", - to: Route::KeyValueView {}, "Key/Value" } - } - li { - Link { to: Route::ServiceRegistry {}, "Service Registry" } + navbar_icon {} + div { class: "divider", style: "margin: 0px;" } + + for (label, is_open, items) in sections { + { + let toggle_label = label.clone(); + rsx! { + li { + button { + class: "font-bold", + onclick: move |_| { + let lbl = toggle_label.clone(); + let mut set = open_sections(); + if set.contains(&lbl) { + set.remove(&lbl); + } else { + set.insert(lbl); + } + open_sections.set(set); + }, + "{label}" + } + if is_open { + ul { + for (item_label, route) in items { + { + if let Some(r) = route { + rsx! { li { Link { to: r, "{item_label}" } } } + } else { + rsx! {} + } + } + } + } + } + } + } + } } + + div { class: "divider", style: "margin: 0px;" } li { - Link { to: Route::Metrics {}, "Metrics" } + Link { to: Route::Settings {}, "Settings" } } } } } } -} \ No newline at end of file +} diff --git a/services/core/blueprint/web-client/src/views/agents.rs b/services/core/blueprint/web-client/src/views/agents.rs new file mode 100644 index 00000000..0f3f95c7 --- /dev/null +++ b/services/core/blueprint/web-client/src/views/agents.rs @@ -0,0 +1,11 @@ +use dioxus::prelude::*; + +#[component] +pub fn Agents() -> Element { + rsx! { + div { class: "p-4", + h1 { class: "text-2xl font-bold mb-4", "Agents" } + p { class: "text-base-content/60", "Automation agents will appear here." } + } + } +} diff --git a/services/core/blueprint/web-client/src/views/cluster.rs b/services/core/blueprint/web-client/src/views/cluster.rs new file mode 100644 index 00000000..67d1ac6d --- /dev/null +++ b/services/core/blueprint/web-client/src/views/cluster.rs @@ -0,0 +1,1168 @@ +use dioxus::prelude::*; +use dioxus::html::input_data::MouseButton; +use std::sync::atomic::{AtomicU64, Ordering}; + +// ── ID generator ───────────────────────────────────────────────────────────── + +static UID: AtomicU64 = AtomicU64::new(1); +fn next_id() -> String { format!("n{}", UID.fetch_add(1, Ordering::Relaxed)) } +fn uid_val() -> u64 { UID.load(Ordering::Relaxed) } + +// ── Node kind ───────────────────────────────────────────────────────────────── + +#[derive(Clone, Debug, PartialEq)] +enum NodeKind { Catalyst, Blueprint, Fuse, Service } + +impl NodeKind { + fn sym(&self) -> &'static str { match self { Self::Catalyst=>"Ca", Self::Blueprint=>"Bp", Self::Fuse=>"Fs", Self::Service=>"Sv" } } + fn el(&self) -> &'static str { match self { Self::Catalyst=>"CATALYST", Self::Blueprint=>"BLUEPRINT", Self::Fuse=>"FUSE", Self::Service=>"SERVICE" } } + fn num(&self) -> &'static str { match self { Self::Catalyst=>"01", Self::Blueprint=>"02", Self::Fuse=>"03", Self::Service=>"··" } } + fn role(&self) -> &'static str { match self { Self::Catalyst=>"EVENT BUS", Self::Blueprint=>"SERVICE REGISTRY", Self::Fuse=>"API GATEWAY", Self::Service=>"WORKLOAD" } } + fn color(&self) -> &'static str { match self { Self::Catalyst=>"#58a6ff", Self::Blueprint=>"#b48cff", Self::Fuse=>"#ffb454", Self::Service=>"#9fb3c2" } } +} + +// ── Data model ──────────────────────────────────────────────────────────────── + +#[derive(Clone, Debug, PartialEq)] +struct RoutingRule { method: String, path: String, target: String } + +#[derive(Clone, Debug, PartialEq)] +struct Topic { name: String, retention: String, partitions: u32 } + +#[derive(Clone, Debug, PartialEq)] +struct ClNode { + id: String, + kind: NodeKind, + name: String, + x: f64, + y: f64, + online: bool, + rules: Vec, + topics: Vec, + host: String, + port: u16, + protocol: String, + ttl: String, +} + +impl ClNode { + fn new(kind: NodeKind, name: &str, x: f64, y: f64) -> Self { + let (rules, topics, host, port, ttl) = match &kind { + NodeKind::Fuse => ( + vec![ + RoutingRule { method: "GET".into(), path: "/api/auth/*".into(), target: "auth-svc".into() }, + RoutingRule { method: "POST".into(), path: "/api/billing/*".into(), target: "billing-svc".into() }, + ], + vec![], String::new(), 8080u16, String::new(), + ), + NodeKind::Catalyst => (vec![], vec![ + Topic { name: "agent.events".into(), retention: "72h".into(), partitions: 6 }, + Topic { name: "billing.tx".into(), retention: "30d".into(), partitions: 3 }, + ], String::new(), 8080, String::new()), + NodeKind::Blueprint => (vec![], vec![], String::new(), 8080, "15s".into()), + NodeKind::Service => (vec![], vec![], format!("{name}.cluster.local"), 8080, String::new()), + }; + Self { id: next_id(), kind, name: name.into(), x, y, online: true, + rules, topics, host, port, protocol: "grpc".into(), ttl } + } + fn cx(&self) -> f64 { self.x + NW / 2.0 } + fn wire_count(&self, ts: &[ClTrace]) -> usize { ts.iter().filter(|t| t.kind == TraceKind::Wire && (t.from == self.id || t.to == self.id)).count() } + fn event_count(&self, ts: &[ClTrace]) -> usize { ts.iter().filter(|t| t.kind == TraceKind::Event && (t.from == self.id || t.to == self.id)).count() } +} + +#[derive(Clone, Debug, PartialEq)] +enum TraceKind { Wire, Event } + +#[derive(Clone, Debug, PartialEq)] +struct ClTrace { id: String, from: String, to: String, kind: TraceKind, topic: Option } + +impl ClTrace { + fn wire(a: &str, b: &str) -> Self { Self { id: next_id(), from: a.into(), to: b.into(), kind: TraceKind::Wire, topic: None } } + fn event(f: &str, t: &str, tp: &str) -> Self { Self { id: next_id(), from: f.into(), to: t.into(), kind: TraceKind::Event, topic: Some(tp.into()) } } +} + +// ── Interaction state ────────────────────────────────────────────────────────── + +#[derive(Clone, Debug, Default, PartialEq)] +enum Drag { + #[default] None, + Pan { sx: f64, sy: f64, px: f64, py: f64 }, + Node { id: String, sx: f64, sy: f64, nx: f64, ny: f64 }, + Pad { from_id: String, fx: f64, fy: f64, fd: i32, tx: f64, ty: f64 }, +} + +#[derive(Clone, Debug, PartialEq)] +enum MenuFor { Canvas { wx: f64, wy: f64 }, Node(String) } + +#[derive(Clone, Debug, PartialEq)] +struct Menu { x: f64, y: f64, for_: MenuFor } + +// ── Geometry ────────────────────────────────────────────────────────────────── + +const NW: f64 = 178.0; +const NH: f64 = 84.0; + +fn port_of(nx: f64, ny: f64, other_cx: f64) -> (f64, f64, i32) { + if other_cx >= nx + NW / 2.0 { (nx + NW, ny + NH / 2.0, 1) } + else { (nx, ny + NH / 2.0, -1) } +} + +fn route_pts(sx: f64, sy: f64, sd: i32, ex: f64, ey: f64, ed: i32) -> Vec<(f64, f64)> { + const STUB: f64 = 14.0; + let (p1x, p1y) = (sx + sd as f64 * STUB, sy); + let (p4x, p4y) = (ex + ed as f64 * STUB, ey); + let mut pts = vec![(sx, sy), (p1x, p1y)]; + let (dx, dy) = (p4x - p1x, p4y - p1y); + let (adx, ady) = (dx.abs(), dy.abs()); + let sgx: f64 = if dx >= 0.0 { 1.0 } else { -1.0 }; + let sgy: f64 = if dy >= 0.0 { 1.0 } else { -1.0 }; + if ady < 0.5 { + } else if sgx == sd as f64 && adx >= ady { + pts.push((p1x + sgx*(adx-ady), p1y)); + } else if sgx == sd as f64 && ady > adx { + pts.push((p1x + sgx*adx, p1y + sgy*adx)); + } else { + let mid_y = p1y + sgy*(ady/2.0).max(40.0); + pts.push((p1x, mid_y)); pts.push((p4x, mid_y)); + } + pts.push((p4x, p4y)); pts.push((ex, ey)); + let mut out: Vec<(f64,f64)> = Vec::new(); + for &p in &pts { + if out.last().map_or(true, |&q: &(f64,f64)| (p.0-q.0).abs()>0.25 || (p.1-q.1).abs()>0.25) { out.push(p); } + } + out +} + +fn pts_path(pts: &[(f64,f64)]) -> String { + pts.iter().enumerate().map(|(i,(x,y))| if i==0 { format!("M {x:.1} {y:.1}") } else { format!("L {x:.1} {y:.1}") }).collect::>().join(" ") +} + +fn poly_len(pts: &[(f64,f64)]) -> f64 { + pts.windows(2).map(|w| { let ((x0,y0),(x1,y1))=(w[0],w[1]); ((x1-x0).powi(2)+(y1-y0).powi(2)).sqrt() }).sum() +} + +fn point_at(pts: &[(f64,f64)], mut d: f64) -> (f64,f64,f64) { + for w in pts.windows(2) { + let ((x0,y0),(x1,y1)) = (w[0],w[1]); + let seg = ((x1-x0).powi(2)+(y1-y0).powi(2)).sqrt(); + if d <= seg { let t=if seg>0.0{d/seg}else{0.0}; return (x0+(x1-x0)*t, y0+(y1-y0)*t, (y1-y0).atan2(x1-x0)); } + d -= seg; + } + let &(lx,ly) = pts.last().unwrap_or(&(0.0,0.0)); + (lx, ly, 0.0) +} + +fn hex_alpha(hex: &str, a: f64) -> String { + let h = hex.trim_start_matches('#'); + let r = u8::from_str_radix(&h[0..2], 16).unwrap_or(61); + let g = u8::from_str_radix(&h[2..4], 16).unwrap_or(220); + let b = u8::from_str_radix(&h[4..6], 16).unwrap_or(151); + format!("rgba({r},{g},{b},{a:.3})") +} + +fn snap8(v: f64) -> f64 { (v / 8.0).round() * 8.0 } + +// ── Seed scene ──────────────────────────────────────────────────────────────── + +fn seed_nodes() -> Vec { + vec![ + ClNode::new(NodeKind::Blueprint, "blueprint-00", 470.0, 110.0), + ClNode::new(NodeKind::Fuse, "fuse-00", 120.0, 330.0), + ClNode::new(NodeKind::Service, "auth-svc", 470.0, 280.0), + ClNode::new(NodeKind::Service, "billing-svc", 470.0, 440.0), + ClNode::new(NodeKind::Catalyst, "catalyst-00", 830.0, 360.0), + ClNode::new(NodeKind::Service, "ledger-svc", 1150.0, 480.0), + ] +} + +fn seed_traces(nodes: &[ClNode]) -> Vec { + let id = |name: &str| nodes.iter().find(|n| n.name == name).map(|n| n.id.clone()).unwrap_or_default(); + vec![ + ClTrace::wire(&id("fuse-00"), &id("auth-svc")), + ClTrace::wire(&id("fuse-00"), &id("billing-svc")), + ClTrace::wire(&id("blueprint-00"), &id("auth-svc")), + ClTrace::event(&id("auth-svc"), &id("catalyst-00"), "agent.events"), + ClTrace::event(&id("billing-svc"), &id("catalyst-00"), "billing.tx"), + ClTrace::event(&id("catalyst-00"), &id("ledger-svc"), "billing.tx"), + ] +} + +// ── CSS for animations + helpers ────────────────────────────────────────────── + +const CLUSTER_CSS: &str = r#" +@keyframes cv-flow { from { stroke-dashoffset: 56; } to { stroke-dashoffset: 0; } } +.cv-node { cursor: grab; user-select: none; -webkit-user-select: none; } +.cv-node:active { cursor: grabbing; } +.cv-pad { opacity: 0; transition: opacity .12s; cursor: crosshair; } +.cv-node:hover .cv-pad { opacity: 1; } +.cv-ctl { opacity: 0; transition: opacity .12s; } +.cv-node:hover .cv-ctl { opacity: 1; } +.cv-flow-dot { stroke-dasharray: 4 52; animation: cv-flow 1.3s linear infinite; } +.cv-mi:hover { background: rgba(61,220,151,0.10); color: #3ddc97; } +.cv-mi-danger:hover { background: rgba(229,83,75,0.12); color: #e5534b; } +@media (prefers-reduced-motion: reduce) { .cv-flow-dot { animation: none; } } +"#; + +// ───────────────────────────────────────────────────────────────────────────── +// Main Cluster component +// ───────────────────────────────────────────────────────────────────────────── + +#[component] +pub fn Cluster() -> Element { + let ns0 = seed_nodes(); + let ts0 = seed_traces(&ns0); + let mut nodes = use_signal(|| ns0); + let mut traces = use_signal(|| ts0); + let mut pan_x = use_signal(|| 0.0_f64); + let mut pan_y = use_signal(|| 0.0_f64); + let mut zoom = use_signal(|| 1.0_f64); + let mut snap = use_signal(|| true); + let mut flow = use_signal(|| true); + let mut primary = use_signal(|| "#3ddc97".to_string()); + let mut drag = use_signal(Drag::default); + let mut menu = use_signal(|| Option::::None); + let mut drawer = use_signal(|| Option::::None); + let mut coord = use_signal(|| (0.0_f64, 0.0_f64)); + let mut stg_off = use_signal(|| (0.0_f64, 0.0_f64)); // (left, top) + + use_effect(move || { + use wasm_bindgen::closure::Closure; + use wasm_bindgen::JsCast; + if let Some(win) = web_sys::window() { + if let Some(doc) = win.document() { + if let Some(el) = doc.get_element_by_id("cv-stage") { + let r = el.get_bounding_client_rect(); + stg_off.set((r.left(), r.top())); + let cb = Closure::::new(|ev: web_sys::MouseEvent| { + ev.prevent_default(); + }); + el.add_event_listener_with_callback("contextmenu", cb.as_ref().unchecked_ref()).ok(); + cb.forget(); + } + } + } + }); + + // ── Derived ──────────────────────────────────────────────────────────── + let px = pan_x(); let py = pan_y(); let zk = zoom(); + let snap_on = snap(); let flow_on = flow(); let pri = primary(); + let (cx, cy) = coord(); + let node_ct = nodes.read().len(); + let trace_ct = traces.read().len(); + let zoom_pct = (zk * 100.0).round() as i32; + + // ── Grid background ─────────────────────────────────────────────────── + let cell = 16.0 * zk; let major = 80.0 * zk; + let gx = ((px % cell) + cell) % cell; let gy = ((py % cell) + cell) % cell; + let gX = ((px % major) + major) % major; let gY = ((py % major) + major) % major; + // Neutral gray grid — no color tint + let fc = "rgba(255,255,255,0.035)".to_string(); // minor lines + let mc = "rgba(255,255,255,0.09)".to_string(); // major lines + let grid_bg = format!( + "background-color:#0a0d10;\ + background-image:repeating-linear-gradient({mc} 0 1px,transparent 1px 100%),\ + repeating-linear-gradient(90deg,{mc} 0 1px,transparent 1px 100%),\ + repeating-linear-gradient({fc} 0 1px,transparent 1px 100%),\ + repeating-linear-gradient(90deg,{fc} 0 1px,transparent 1px 100%);\ + background-size:{major}px {major}px,{major}px {major}px,{cell}px {cell}px,{cell}px {cell}px;\ + background-position:{gX}px {gY}px,{gX}px {gY}px,{gx}px {gy}px,{gx}px {gy}px;" + ); + + // ── Helpers ─────────────────────────────────────────────────────────── + let to_world = move |sx: f64, sy: f64| -> (f64, f64) { + let (ol, ot) = stg_off(); + ((sx - ol - pan_x()) / zoom(), (sy - ot - pan_y()) / zoom()) + }; + let node_at = move |wx: f64, wy: f64| -> Option { + nodes.read().iter().find(|n| wx>=n.x && wx<=n.x+NW && wy>=n.y && wy<=n.y+NH).map(|n| n.id.clone()) + }; + + // ── Stage pointer handlers ───────────────────────────────────────────── + let on_stage_down = move |ev: Event| { + if ev.data().trigger_button() != Some(MouseButton::Primary) { return; } + let c = ev.data().client_coordinates(); + drag.set(Drag::Pan { sx: c.x, sy: c.y, px: pan_x(), py: pan_y() }); + menu.set(None); + }; + + let on_move = move |ev: Event| { + let c = ev.data().client_coordinates(); + let (sx, sy) = (c.x, c.y); + let (wx, wy) = to_world(sx, sy); + coord.set((wx, wy)); + match drag() { + Drag::Pan { sx: s0x, sy: s0y, px: p0x, py: p0y } => { + pan_x.set(p0x + sx - s0x); pan_y.set(p0y + sy - s0y); + } + Drag::Node { id, sx: s0x, sy: s0y, nx: n0x, ny: n0y } => { + let zk = zoom(); + let mut nx = n0x + (sx - s0x) / zk; + let mut ny = n0y + (sy - s0y) / zk; + if snap() { nx = snap8(nx); ny = snap8(ny); } + nodes.with_mut(|ns| { if let Some(n) = ns.iter_mut().find(|n| n.id == id) { n.x = nx; n.y = ny; } }); + } + Drag::Pad { from_id, fx, fy, fd, .. } => { + drag.set(Drag::Pad { from_id, fx, fy, fd, tx: wx, ty: wy }); + } + Drag::None => {} + } + }; + + let on_up = move |_ev: Event| { + if let Drag::Pad { ref from_id, tx, ty, .. } = drag() { + let from_id = from_id.clone(); + if let Some(to_id) = node_at(tx, ty) { + if to_id != from_id { + let dup = traces.read().iter().any(|t| t.kind == TraceKind::Wire && ((t.from==from_id && t.to==to_id)||(t.from==to_id && t.to==from_id))); + if !dup { traces.with_mut(|ts| ts.push(ClTrace::wire(&from_id, &to_id))); } + } + } + } + drag.set(Drag::None); + if let Some(w) = web_sys::window() { if let Some(d) = w.document() { + if let Some(el) = d.get_element_by_id("cv-stage") { + let r = el.get_bounding_client_rect(); stg_off.set((r.left(), r.top())); + } + }} + }; + + let on_wheel = move |ev: Event| { + let dy = ev.data().delta().strip_units().y; + let f = if dy < 0.0 { 1.1 } else { 1.0/1.1 }; + let nk = (zoom()*f).clamp(0.25, 3.0); + let c = ev.data().client_coordinates(); + let (ol, ot) = stg_off(); + let (wx, wy) = ((c.x - ol - pan_x())/zoom(), (c.y - ot - pan_y())/zoom()); + pan_x.set(c.x - ol - wx*nk); pan_y.set(c.y - ot - wy*nk); zoom.set(nk); + }; + + let on_ctx = move |ev: Event| { + let c = ev.data().client_coordinates(); + let (wx, wy) = to_world(c.x, c.y); + menu.set(Some(Menu { x: c.x, y: c.y, for_: MenuFor::Canvas { wx, wy } })); + }; + + let snap_bdr = if snap_on { format!("color-mix(in srgb,{pri} 45%,transparent)") } else { "rgba(255,255,255,.07)".to_string() }; + let snap_col = if snap_on { pri.clone() } else { "#5d6a76".to_string() }; + let snap_lbl = if snap_on { "SNAP: ON" } else { "SNAP: OFF" }; + let flow_bdr = if flow_on { format!("color-mix(in srgb,{pri} 45%,transparent)") } else { "rgba(255,255,255,.07)".to_string() }; + let flow_col = if flow_on { pri.clone() } else { "#5d6a76".to_string() }; + let flow_lbl = if flow_on { "FLOW: ON" } else { "FLOW: OFF" }; + + rsx! { + style { "{CLUSTER_CSS}" } + div { + class: "relative flex flex-col overflow-hidden", + style: "height:calc(100vh - 4rem);background:#0a0d10;font-family:'JetBrains Mono',ui-monospace,'SFMono-Regular',Menlo,Consolas,monospace;font-size:12px;color:#d7e0e8;", + + // ── Topbar ──────────────────────────────────────────────────── + div { + style: "height:42px;display:flex;align-items:center;gap:18px;padding:0 16px;\ + background:linear-gradient(180deg,rgba(10,13,16,.96),rgba(10,13,16,.82));\ + border-bottom:1px solid rgba(255,255,255,.07);flex-shrink:0;z-index:50;", + // Wordmark + div { style: "display:flex;align-items:baseline;gap:8px;letter-spacing:.18em;", + b { style: "color:{pri};font-weight:700;", "DRAFT" } + span { style: "color:#5d6a76;font-size:10px;", "// CLUSTER VIEW" } + } + // Color swatches + div { style: "display:flex;gap:6px;margin-left:6px;", + for (col, _) in [("#3ddc97",""), ("#e5534b",""), ("#58a6ff",""), ("#b48cff",""), ("#ffb454","")] { + { + let c = col.to_string(); let is_on = pri == col; + let outline = if is_on { format!("outline:2px solid {col};") } else { String::new() }; + rsx! { + div { + style: "width:14px;height:14px;background:{col};border:1px solid rgba(255,255,255,.07);cursor:pointer;box-sizing:border-box;{outline}", + onclick: move |_| primary.set(c.clone()), + } + } + } + } + } + div { style: "flex:1;" } + button { + style: "background:none;border:1px solid {snap_bdr};color:{snap_col};font:inherit;font-size:10px;letter-spacing:.12em;padding:5px 10px;cursor:pointer;", + onclick: move |_| snap.set(!snap()), + "{snap_lbl}" + } + button { + style: "background:none;border:1px solid {flow_bdr};color:{flow_col};font:inherit;font-size:10px;letter-spacing:.12em;padding:5px 10px;cursor:pointer;", + onclick: move |_| flow.set(!flow()), + "{flow_lbl}" + } + span { style: "color:#5d6a76;font-size:10px;letter-spacing:.12em;", "NODES " b { style: "color:#d7e0e8;", "{node_ct}" } } + span { style: "color:#5d6a76;font-size:10px;letter-spacing:.12em;", "TRACES " b { style: "color:#d7e0e8;", "{trace_ct}" } } + span { style: "color:#5d6a76;font-size:10px;letter-spacing:.12em;", "ZOOM " b { style: "color:#d7e0e8;", "{zoom_pct}%" } } + } + + // ── Stage ────────────────────────────────────────────────────────── + div { + id: "cv-stage", + class: "relative flex-1 overflow-hidden", + style: "{grid_bg}", + prevent_default: "oncontextmenu onwheel", + onpointerdown: on_stage_down, + onpointermove: on_move, + onpointerup: on_up, + onwheel: on_wheel, + oncontextmenu: on_ctx, + + // ── World (pan/zoom container) ──────────────────────────────── + div { + style: "position:absolute;left:0;top:0;transform-origin:0 0;\ + transform:translate({px}px,{py}px) scale({zk});\ + width:0;height:0;pointer-events:none;", + + // SVG trace layer — width/height 1 + overflow:visible keeps paths in world space + svg { + style: "position:absolute;left:0;top:0;pointer-events:none;overflow:visible;", + width: "1", + height: "1", + overflow: "visible", + TraceSvg { nodes: nodes(), traces: traces(), primary: pri.clone(), flow_on, drag: drag() } + } + + // Node cards + for node in nodes() { + { + let nid = node.id.clone(); + let nid_ctx = node.id.clone(); + let nid_cfg = node.id.clone(); + let nid_del = node.id.clone(); + let nid_pad = node.id.clone(); + let wc = node.wire_count(&traces()); + let ec = node.event_count(&traces()); + let nx0 = node.x; + let ny0 = node.y; + rsx! { + NodeCard { + node: node.clone(), + wire_count: wc, + event_count: ec, + on_node_down: move |coords: (f64,f64)| { + let cur_x = nodes.read().iter().find(|n|n.id==nid).map(|n|n.x).unwrap_or(nx0); + let cur_y = nodes.read().iter().find(|n|n.id==nid).map(|n|n.y).unwrap_or(ny0); + drag.set(Drag::Node { id: nid.clone(), sx: coords.0, sy: coords.1, nx: cur_x, ny: cur_y }); + }, + on_context: move |coords: (f64,f64)| { + menu.set(Some(Menu { x: coords.0, y: coords.1, for_: MenuFor::Node(nid_ctx.clone()) })); + }, + on_config: move |_| { drawer.set(Some(nid_cfg.clone())); }, + on_delete: move |_| { + let id = nid_del.clone(); + traces.with_mut(|ts| ts.retain(|t| t.from != id && t.to != id)); + nodes.with_mut(|ns| ns.retain(|n| n.id != id)); + if drawer() == Some(id) { drawer.set(None); } + }, + on_pad_down: move |(side, sx, sy): (i32, f64, f64)| { + let id = nid_pad.clone(); + let (fx, fy, fd) = nodes.read().iter().find(|n|n.id==id) + .map(|n| if side==1 { (n.x+NW, n.y+NH/2.0, 1i32) } else { (n.x, n.y+NH/2.0, -1i32) }) + .unwrap_or((0.0,0.0,1)); + drag.set(Drag::Pad { from_id: id, fx, fy, fd, tx: fx, ty: fy }); + let _ = (sx, sy); + }, + } + } + } + } + } + + // ── Context menu ────────────────────────────────────────────── + if let Some(m) = menu() { + CtxMenu { + m, + nodes: nodes(), + traces: traces(), + snap_on, + primary: pri.clone(), + on_close: move |_| menu.set(None), + on_add: move |(kind, name, wx, wy): (NodeKind, String, f64, f64)| { + nodes.with_mut(|ns| ns.push(ClNode::new(kind, &name, snap8(wx), snap8(wy)))); + menu.set(None); + }, + on_drawer: move |id: String| { drawer.set(Some(id)); menu.set(None); }, + on_snap: move |_| { snap.set(!snap()); menu.set(None); }, + on_reset: move |_| { pan_x.set(0.0); pan_y.set(0.0); zoom.set(1.0); menu.set(None); }, + on_delete: move |id: String| { + traces.with_mut(|ts| ts.retain(|t| t.from != id && t.to != id)); + nodes.with_mut(|ns| ns.retain(|n| n.id != id)); + menu.set(None); + }, + on_toggle_online: move |id: String| { + nodes.with_mut(|ns| { if let Some(n) = ns.iter_mut().find(|n|n.id==id) { n.online = !n.online; } }); + menu.set(None); + }, + on_disconnect: move |id: String| { + traces.with_mut(|ts| ts.retain(|t| t.from != id && t.to != id)); + menu.set(None); + }, + on_reg_bp: move |svc: String| { + if let Some(bp) = nodes.read().iter().find(|n|n.kind==NodeKind::Blueprint).map(|n|n.id.clone()) { + let dup = traces.read().iter().any(|t|t.kind==TraceKind::Wire&&((t.from==svc&&t.to==bp)||(t.from==bp&&t.to==svc))); + if !dup { traces.with_mut(|ts| ts.push(ClTrace::wire(&svc, &bp))); } + } + menu.set(None); + }, + on_pub: move |(nid, cat_id, tp): (String, String, String)| { + let dup = traces.read().iter().any(|t|t.kind==TraceKind::Event&&t.from==nid&&t.to==cat_id&&t.topic.as_deref()==Some(&tp)); + if !dup { traces.with_mut(|ts| ts.push(ClTrace::event(&nid, &cat_id, &tp))); } + menu.set(None); + }, + on_sub: move |(nid, cat_id, tp): (String, String, String)| { + let dup = traces.read().iter().any(|t|t.kind==TraceKind::Event&&t.from==cat_id&&t.to==nid&&t.topic.as_deref()==Some(&tp)); + if !dup { traces.with_mut(|ts| ts.push(ClTrace::event(&cat_id, &nid, &tp))); } + menu.set(None); + }, + } + } + + // ── Config drawer ───────────────────────────────────────────── + if let Some(ref nid) = drawer() { + if let Some(node) = nodes.read().iter().find(|n|&n.id==nid).cloned() { + { + let nid_r = node.id.clone(); + let nid_t = node.id.clone(); + let nid_e = node.id.clone(); + let nid_l = node.id.clone(); + rsx! { + ConfigDrawer { + node: node.clone(), + nodes: nodes(), + traces: traces(), + on_close: move |_| drawer.set(None), + on_rules: move |rules: Vec| { + nodes.with_mut(|ns| { if let Some(n) = ns.iter_mut().find(|n|n.id==nid_r) { n.rules = rules; } }); + }, + on_topics: move |topics: Vec| { + nodes.with_mut(|ns| { if let Some(n) = ns.iter_mut().find(|n|n.id==nid_t) { n.topics = topics; } }); + }, + on_endpoint: move |(h,p,proto): (String,u16,String)| { + nodes.with_mut(|ns| { if let Some(n) = ns.iter_mut().find(|n|n.id==nid_e) { n.host=h; n.port=p; n.protocol=proto; } }); + }, + on_ttl: move |ttl: String| { + nodes.with_mut(|ns| { if let Some(n) = ns.iter_mut().find(|n|n.id==nid_l) { n.ttl=ttl; } }); + }, + on_rm_trace: move |tid: String| { + traces.with_mut(|ts| ts.retain(|t|t.id!=tid)); + }, + } + } + } + } + } + } + + // ── Status bar ───────────────────────────────────────────────────── + div { + style: "height:30px;display:flex;align-items:center;gap:22px;padding:0 16px;\ + background:rgba(10,13,16,.92);border-top:1px solid rgba(255,255,255,.07);\ + color:#5d6a76;font-size:10px;letter-spacing:.14em;flex-shrink:0;", + span { style: "min-width:150px;color:{pri};", "X {cx:.0} · Y {cy:.0}" } + span { style: "opacity:.35;", "|" } + span { "RIGHT-CLICK · CONTEXT MENU" } + span { style: "opacity:.35;", "|" } + span { "DRAG BG · PAN" } + span { style: "opacity:.35;", "|" } + span { "SCROLL · ZOOM" } + span { style: "opacity:.35;", "|" } + span { "DRAG PAD ▸ NODE · CONNECT" } + span { style: "opacity:.35;", "|" } + span { span { style: "color:{pri};", "━" } " WIRE " span { style: "color:#58a6ff;", "┄▸" } " EVENT" } + } + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// SVG trace layer +// ───────────────────────────────────────────────────────────────────────────── + +#[component] +fn TraceSvg(nodes: Vec, traces: Vec, primary: String, flow_on: bool, drag: Drag) -> Element { + rsx! { + for tr in &traces { + { + let a = nodes.iter().find(|n| n.id == tr.from); + let b = nodes.iter().find(|n| n.id == tr.to); + if let (Some(a), Some(b)) = (a, b) { + let (sx,sy,sd) = port_of(a.x, a.y, b.cx()); + let (ex,ey,ed) = port_of(b.x, b.y, a.cx()); + let pts = route_pts(sx,sy,sd, ex,ey,ed); + let d = pts_path(&pts); + let len = poly_len(&pts); + match tr.kind { + TraceKind::Wire => { + let p = &primary; + let gc = hex_alpha(p, 0.18); + let lc = hex_alpha(p, 0.90); + rsx! { + path { d: "{d}", stroke: "{gc}", stroke_width: "4.5", fill: "none", stroke_linecap: "round", stroke_linejoin: "round" } + path { d: "{d}", stroke: "{lc}", stroke_width: "1.5", fill: "none", stroke_linecap: "round", stroke_linejoin: "round" } + WirePads { pts: pts.clone(), color: lc.clone() } + ViaDots { pts: pts.clone(), color: p.clone() } + } + } + TraceKind::Event => { + let col = "#58a6ff"; + let gc = hex_alpha(col, 0.13); + let lc = hex_alpha(col, 0.80); + let topic = tr.topic.clone().unwrap_or_default().to_uppercase(); + let last = *pts.last().unwrap_or(&(0.0,0.0)); + let first = pts[0]; + let mid = if len > 0.0 { point_at(&pts, len/2.0) } else { (0.0,0.0,0.0) }; + rsx! { + path { d: "{d}", stroke: "{gc}", stroke_width: "4.5", fill: "none", stroke_linecap: "round", stroke_linejoin: "round" } + path { d: "{d}", stroke: "{lc}", stroke_width: "1.3", fill: "none", stroke_dasharray: "6 5", stroke_linecap: "round" } + if flow_on { path { class: "cv-flow-dot", d: "{d}", stroke: "{col}", stroke_width: "2.5", fill: "none" } } + Chevrons { pts: pts.clone(), color: col.to_string() } + ViaDots { pts: pts.clone(), color: col.to_string() } + // Producer pad (filled square) + rect { x: "{first.0-3.5:.1}", y: "{first.1-3.5:.1}", width: "7", height: "7", fill: "{col}", opacity: "0.95" } + // Consumer pad (open ring) + circle { cx: "{last.0:.1}", cy: "{last.1:.1}", r: "3.5", stroke: "{col}", stroke_width: "1.5", fill: "none", opacity: "0.95" } + // Topic label + if !topic.is_empty() { + rect { x: "{mid.0-30.0:.1}", y: "{mid.1-7.0:.1}", width: "60", height: "13", fill: "#0a0d10" } + rect { x: "{mid.0-29.5:.1}", y: "{mid.1-6.5:.1}", width: "59", height: "12", fill: "none", stroke: "{hex_alpha(col,0.4)}", stroke_width: "1" } + text { + x: "{mid.0:.1}", y: "{mid.1+1.0:.1}", + text_anchor: "middle", dominant_baseline: "middle", + fill: "{hex_alpha(col,0.95)}", + font_family: "'JetBrains Mono',ui-monospace,monospace", + font_size: "7", letter_spacing: "0.05em", + "{topic}" + } + } + } + } + } + } else { rsx! {} } + } + } + // Ghost trace while dragging pad + if let Drag::Pad { fx, fy, fd, tx, ty, .. } = drag { + { + let pts = route_pts(fx,fy,fd, tx,ty, if tx>=fx { -1 } else { 1 }); + let d = pts_path(&pts); + rsx! { path { d: "{d}", stroke: "rgba(61,220,151,0.55)", stroke_width: "1.5", fill: "none", stroke_dasharray: "5 4", stroke_linecap: "round" } } + } + } + } +} + +#[component] +fn WirePads(pts: Vec<(f64,f64)>, color: String) -> Element { + if pts.len() < 2 { return rsx! {}; } + let (s, e) = (pts[0], *pts.last().unwrap()); + rsx! { + rect { x: "{s.0-3.5:.1}", y: "{s.1-3.5:.1}", width: "7", height: "7", fill: "{color}" } + rect { x: "{e.0-3.5:.1}", y: "{e.1-3.5:.1}", width: "7", height: "7", fill: "{color}" } + } +} + +#[component] +fn ViaDots(pts: Vec<(f64,f64)>, color: String) -> Element { + let outer = hex_alpha(&color, 0.95); + if pts.len() < 3 { return rsx! {}; } + rsx! { + for &(vx,vy) in pts[1..pts.len()-1].iter() { + circle { cx: "{vx:.1}", cy: "{vy:.1}", r: "2.6", fill: "{outer}" } + circle { cx: "{vx:.1}", cy: "{vy:.1}", r: "1.1", fill: "#0a0d10" } + } + } +} + +#[component] +fn Chevrons(pts: Vec<(f64,f64)>, color: String) -> Element { + let len = poly_len(&pts); + let mut positions: Vec<(f64,f64,f64)> = Vec::new(); + let mut d = 34.0; + while d < len - 26.0 { positions.push(point_at(&pts, d)); d += 64.0; } + rsx! { + for (cx, cy, angle) in positions { + { let deg = angle.to_degrees(); + rsx! { path { d: "M -3,-3.2 L 1.6,0 L -3,3.2", transform: "translate({cx:.1},{cy:.1}) rotate({deg:.1})", stroke: "{color}", stroke_width: "1.4", fill: "none", opacity: "0.85" } } + } + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Node card +// ───────────────────────────────────────────────────────────────────────────── + +#[component] +fn NodeCard( + node: ClNode, + wire_count: usize, + event_count: usize, + on_node_down: EventHandler<(f64,f64)>, + on_context: EventHandler<(f64,f64)>, + on_config: EventHandler<()>, + on_delete: EventHandler<()>, + on_pad_down: EventHandler<(i32,f64,f64)>, +) -> Element { + let col = node.kind.color(); + let sym = node.kind.sym(); + let el = node.kind.el(); + let num = node.kind.num(); + let role = node.kind.role(); + let name = node.name.to_uppercase(); + let led_style = if node.online { "background:#3ddc97;box-shadow:0 0 6px #3ddc97;" } else { "background:#e5534b;box-shadow:0 0 6px #e5534b;" }; + let st = if node.online { "ONLINE" } else { "OFFLINE" }; + let links = { + let mut p = Vec::new(); + if wire_count > 0 { p.push(format!("{wire_count} LINK{}", if wire_count>1{"S"}else{""})); } + if event_count > 0 { p.push(format!("{event_count} EVT")); } + if p.is_empty() { "NO LINKS".into() } else { p.join(" · ") } + }; + let bk_base = format!("position:absolute;width:9px;height:9px;border-color:{col};opacity:.9;"); + let bk_tl = format!("{bk_base}top:-1px;left:-1px;border-top:2px solid;border-left:2px solid;"); + let bk_tr = format!("{bk_base}top:-1px;right:-1px;border-top:2px solid;border-right:2px solid;"); + let bk_bl = format!("{bk_base}bottom:-1px;left:-1px;border-bottom:2px solid;border-left:2px solid;"); + let bk_br = format!("{bk_base}bottom:-1px;right:-1px;border-bottom:2px solid;border-right:2px solid;"); + + rsx! { + div { + class: "cv-node", + style: "position:absolute;left:{node.x}px;top:{node.y}px;width:{NW}px;min-height:{NH}px;\ + background:linear-gradient(180deg,#10161c,#0e1318);border:1px solid rgba(255,255,255,.07);\ + padding:10px 12px 8px;box-sizing:border-box;pointer-events:auto;", + prevent_default: "oncontextmenu", + onpointerdown: move |ev| { + if ev.data().trigger_button() != Some(MouseButton::Primary) { return; } + ev.stop_propagation(); + let c = ev.data().client_coordinates(); + on_node_down.call((c.x, c.y)); + }, + oncontextmenu: move |ev| { + ev.stop_propagation(); + ev.prevent_default(); + let c = ev.data().client_coordinates(); + on_context.call((c.x, c.y)); + }, + + // Bracket corners + div { style: "{bk_tl}" } + div { style: "{bk_tr}" } + div { style: "{bk_bl}" } + div { style: "{bk_br}" } + + // Head + div { style: "display:flex;gap:10px;align-items:flex-start;", + div { + style: "flex:0 0 36px;height:40px;border:1px solid {col};\ + display:flex;flex-direction:column;align-items:center;justify-content:center;\ + position:relative;color:{col};background:color-mix(in srgb,{col} 7%,transparent);", + span { style: "position:absolute;top:1px;left:3px;font-size:7px;opacity:.75;", "{num}" } + span { style: "font-size:15px;font-weight:700;line-height:1;", "{sym}" } + span { style: "font-size:6px;letter-spacing:.08em;margin-top:3px;opacity:.8;", "{el}" } + } + div { style: "flex:1;min-width:0;", + div { style: "font-size:12px;font-weight:600;letter-spacing:.08em;color:#d7e0e8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;", "{name}" } + div { style: "font-size:8px;letter-spacing:.2em;color:#5d6a76;margin-top:4px;", "{role}" } + } + } + + // Meta + div { style: "display:flex;align-items:center;gap:7px;margin-top:8px;font-size:8px;letter-spacing:.16em;color:#5d6a76;", + span { style: "width:5px;height:5px;border-radius:50%;display:inline-block;{led_style}" } + span { "{st}" } + span { style: "margin-left:auto;color:{col};", "{links}" } + } + + // Corner controls (CSS hover reveal) + div { + class: "cv-ctl", + style: "position:absolute;top:-9px;right:6px;display:flex;gap:4px;", + button { + style: "width:18px;height:18px;background:#0e1318;border:1px solid rgba(255,255,255,.07);\ + color:#5d6a76;font:inherit;font-size:10px;line-height:1;cursor:pointer;", + onclick: move |_| on_config.call(()), + title: "configure", + "≡" + } + button { + style: "width:18px;height:18px;background:#0e1318;border:1px solid rgba(255,255,255,.07);\ + color:#5d6a76;font:inherit;font-size:10px;line-height:1;cursor:pointer;", + onclick: move |_| on_delete.call(()), + title: "remove", + "×" + } + } + + // Left pad + div { + class: "cv-pad", + style: "position:absolute;width:9px;height:9px;background:#0a0d10;\ + border:1.5px solid {col};left:-5px;top:50%;transform:translateY(-50%);z-index:5;", + onpointerdown: move |ev| { + ev.stop_propagation(); + let c = ev.data().client_coordinates(); + on_pad_down.call((-1, c.x, c.y)); + }, + } + // Right pad + div { + class: "cv-pad", + style: "position:absolute;width:9px;height:9px;background:#0a0d10;\ + border:1.5px solid {col};right:-5px;top:50%;transform:translateY(-50%);z-index:5;", + onpointerdown: move |ev| { + ev.stop_propagation(); + let c = ev.data().client_coordinates(); + on_pad_down.call((1, c.x, c.y)); + }, + } + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Context menu +// ───────────────────────────────────────────────────────────────────────────── + +#[component] +fn CtxMenu( + m: Menu, + nodes: Vec, + traces: Vec, + snap_on: bool, + primary: String, + on_close: EventHandler<()>, + on_add: EventHandler<(NodeKind, String, f64, f64)>, + on_drawer: EventHandler, + on_snap: EventHandler<()>, + on_reset: EventHandler<()>, + on_delete: EventHandler, + on_toggle_online: EventHandler, + on_disconnect: EventHandler, + on_reg_bp: EventHandler, + on_pub: EventHandler<(String, String, String)>, + on_sub: EventHandler<(String, String, String)>, +) -> Element { + let (mx, my) = (m.x, m.y); + let mi = "display:flex;align-items:center;gap:10px;padding:6px 12px;cursor:pointer;color:#d7e0e8;font-size:11px;letter-spacing:.06em;"; + let hd = "padding:7px 12px 6px;font-size:9px;letter-spacing:.2em;color:#5d6a76;border-bottom:1px solid rgba(255,255,255,.07);margin-bottom:4px;display:flex;gap:8px;align-items:center;"; + let dv = "height:1px;background:rgba(255,255,255,.07);margin:4px 0;"; + + let body: Element = match m.for_ { + MenuFor::Canvas { wx, wy } => { + let n = uid_val(); + let cat_name = format!("catalyst-{n:02}"); + let bp_name = format!("blueprint-{n:02}"); + let fuse_name = format!("fuse-{n:02}"); + let svc_name = format!("svc-{n:02}"); + let snap_lbl = if snap_on { "SNAP TO GRID · ON" } else { "SNAP TO GRID · OFF" }; + rsx! { + div { style: "{hd}", span { style: "color:{primary};font-weight:700;", "◈" } span { "CANVAS" } } + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_add.call((NodeKind::Catalyst, cat_name.clone(), wx, wy)), "ADD · CATALYST" } + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_add.call((NodeKind::Blueprint, bp_name.clone(), wx, wy)), "ADD · BLUEPRINT" } + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_add.call((NodeKind::Fuse, fuse_name.clone(), wx, wy)), "ADD · FUSE" } + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_add.call((NodeKind::Service, svc_name.clone(), wx, wy)), "ADD · SERVICE" } + div { style: "{dv}" } + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_snap.call(()), "{snap_lbl}" } + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_reset.call(()), "RESET VIEW" } + } + } + MenuFor::Node(ref nid) => { + if let Some(node) = nodes.iter().find(|n| &n.id == nid).cloned() { + let col = node.kind.color(); + let sym = node.kind.sym(); + let title = format!("{} · {}", node.name.to_uppercase(), node.kind.role()); + let nid = nid.clone(); + let nid1 = nid.clone(); let nid2 = nid.clone(); + let nid3 = nid.clone(); + let online_lbl = if node.online { "MARK OFFLINE" } else { "MARK ONLINE" }; + + let type_items: Element = match node.kind { + NodeKind::Fuse => { let rc=node.rules.len(); let id=nid.clone(); + rsx! { + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_drawer.call(id.clone()), + "ROUTING RULES…" span { style: "margin-left:auto;color:#5d6a76;font-size:9px;", "{rc}" } + } + } + } + NodeKind::Catalyst => { let tc=node.topics.len(); let id=nid.clone(); + rsx! { + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_drawer.call(id.clone()), + "TOPICS…" span { style: "margin-left:auto;color:#5d6a76;font-size:9px;", "{tc}" } + } + } + } + NodeKind::Blueprint => { let id=nid.clone(); + rsx! { div { class: "cv-mi", style: "{mi}", onclick: move |_| on_drawer.call(id.clone()), "SERVICE REGISTRY…" } } + } + NodeKind::Service => { + let cats: Vec<(String, Vec)> = nodes.iter() + .filter(|n| n.kind == NodeKind::Catalyst) + .map(|c| (c.id.clone(), c.topics.iter().map(|t| t.name.clone()).collect())) + .collect(); + let has_bp = nodes.iter().any(|n| n.kind == NodeKind::Blueprint); + let id = nid.clone(); let id_ep = nid.clone(); let id_bp = nid.clone(); + rsx! { + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_drawer.call(id_ep.clone()), "ENDPOINT CONFIG…" } + for (cat_id, topics) in cats.clone() { + for tp in topics { + { + let n = id.clone(); let c = cat_id.clone(); let t = tp.clone(); + let lbl = format!("PUB · {}", tp.to_uppercase()); + rsx! { div { class: "cv-mi", style: "{mi}", onclick: move |_| on_pub.call((n.clone(), c.clone(), t.clone())), "{lbl}" } } + } + } + } + for (cat_id, topics) in cats { + for tp in topics { + { + let n = id.clone(); let c = cat_id.clone(); let t = tp.clone(); + let lbl = format!("SUB · {}", tp.to_uppercase()); + rsx! { div { class: "cv-mi", style: "{mi}", onclick: move |_| on_sub.call((n.clone(), c.clone(), t.clone())), "{lbl}" } } + } + } + } + if has_bp { + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_reg_bp.call(id_bp.clone()), "REGISTER WITH BLUEPRINT" } + } + } + } + }; + + rsx! { + div { style: "{hd}", span { style: "color:{col};font-weight:700;", "{sym}" } span { "{title}" } } + {type_items} + div { style: "{dv}" } + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_toggle_online.call(nid1.clone()), "{online_lbl}" } + div { class: "cv-mi", style: "{mi}", onclick: move |_| on_disconnect.call(nid2.clone()), "DISCONNECT ALL" } + div { style: "{dv}" } + div { class: "cv-mi cv-mi-danger", style: "{mi}color:#e5534b;", + onclick: move |_| on_delete.call(nid3.clone()), "REMOVE NODE" + } + } + } else { rsx! {} } + } + }; + + rsx! { + div { style: "position:fixed;inset:0;z-index:99;", onclick: move |_| on_close.call(()), } + div { + style: "position:fixed;left:{mx}px;top:{my}px;z-index:100;min-width:208px;\ + background:rgba(13,18,23,.97);border:1px solid rgba(255,255,255,.07);\ + box-shadow:0 12px 32px rgba(0,0,0,.55);padding:4px 0;", + onclick: move |ev| ev.stop_propagation(), + {body} + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Config drawer +// ───────────────────────────────────────────────────────────────────────────── + +#[component] +fn ConfigDrawer( + node: ClNode, + nodes: Vec, + traces: Vec, + on_close: EventHandler<()>, + on_rules: EventHandler>, + on_topics: EventHandler>, + on_endpoint: EventHandler<(String,u16,String)>, + on_ttl: EventHandler, + on_rm_trace: EventHandler, +) -> Element { + let col = node.kind.color(); + let sym = node.kind.sym(); + let role = format!("{} · {}", node.kind.el(), node.kind.role()); + let name = node.name.to_uppercase(); + + let fld = "width:100%;background:#0a0f13;border:1px solid rgba(255,255,255,.07);color:#d7e0e8;font:inherit;font-size:10px;padding:5px 6px;outline:none;box-sizing:border-box;"; + let sec = "font-size:9px;letter-spacing:.22em;color:#5d6a76;margin:14px 0 8px;display:block;"; + let note = format!("margin-top:14px;padding:9px 10px;border-left:2px solid {col};background:rgba(255,255,255,.025);font-size:9px;line-height:1.6;letter-spacing:.06em;color:#5d6a76;"); + let add = "width:100%;margin-top:10px;background:none;cursor:pointer;font:inherit;border:1px dashed rgba(61,220,151,.45);color:#3ddc97;font-size:10px;letter-spacing:.14em;padding:7px;"; + let kv = "display:grid;grid-template-columns:86px 1fr;gap:8px;align-items:center;margin-bottom:8px;"; + let lbl = "font-size:9px;letter-spacing:.16em;color:#5d6a76;"; + let th = "font-size:8px;letter-spacing:.18em;color:#5d6a76;text-align:left;padding:4px 6px;border-bottom:1px solid rgba(255,255,255,.07);font-weight:500;"; + let td = "padding:4px 3px;border-bottom:1px solid rgba(255,255,255,.04);"; + + let body: Element = match node.kind { + NodeKind::Fuse => { + let rules = node.rules.clone(); + let targets: Vec = nodes.iter().filter(|n| n.id!=node.id && n.kind!=NodeKind::Fuse).map(|n| n.name.clone()).collect(); + rsx! { + span { style: "{sec}", "ROUTING RULES" } + table { style: "width:100%;border-collapse:collapse;", + tr { + th { style: "{th}width:62px;", "METHOD" } + th { style: "{th}", "PATH PREFIX" } + th { style: "{th}width:88px;", "TARGET" } + th { style: "width:18px;border-bottom:1px solid rgba(255,255,255,.07);" } + } + for (i, rule) in rules.iter().enumerate() { + { + let r0 = rules.clone(); let r1 = rules.clone(); let r2 = rules.clone(); let r_del = rules.clone(); + let t0 = targets.clone(); + let (method, path, target) = (rule.method.clone(), rule.path.clone(), rule.target.clone()); + rsx! { + tr { + td { style: "{td}", select { style: "{fld}", value: "{method}", + onchange: { let mut a=r0; move |ev:Event| { a[i].method=ev.data().value(); on_rules.call(a.clone()); } }, + for m in ["GET","POST","PUT","DELETE","*"] { option { value:"{m}", selected: method==m, "{m}" } } + }} + td { style: "{td}", input { style: "{fld}", value: "{path}", + oninput: { let mut a=r1; move |ev:Event| { a[i].path=ev.data().value(); on_rules.call(a.clone()); } } + }} + td { style: "{td}", select { style: "{fld}", value: "{target}", + onchange: { let mut a=r2; move |ev:Event| { a[i].target=ev.data().value(); on_rules.call(a.clone()); } }, + if !t0.contains(&target) { option { value: "{target}", "{target}" } } + for t in &t0 { option { value: "{t}", selected: *t==target, "{t}" } } + }} + td { style: "{td}", button { style: "background:none;border:none;color:#5d6a76;cursor:pointer;font:inherit;", + onclick: { let mut a=r_del; move |_| { a.remove(i); on_rules.call(a.clone()); } }, "×" + }} + } + } + } + } + } + button { style: "{add}", + onclick: { let mut a=rules; let tgt=targets.first().cloned().unwrap_or_else(||"svc".into()); + move |_| { a.push(RoutingRule{method:"GET".into(),path:"/api/".into(),target:tgt.clone()}); on_rules.call(a.clone()); } }, + "+ ADD RULE" + } + div { style: "{note}", "RULES RESOLVE TARGETS THROUGH BLUEPRINT. FIRST MATCH WINS." } + } + } + NodeKind::Catalyst => { + let topics = node.topics.clone(); + let evs: Vec = traces.iter().filter(|t| t.kind==TraceKind::Event && (t.from==node.id||t.to==node.id)).cloned().collect(); + let nid = node.id.clone(); + rsx! { + span { style: "{sec}", "TOPICS" } + table { style: "width:100%;border-collapse:collapse;", + tr { + th { style: "{th}", "NAME" } + th { style: "{th}width:64px;", "RETAIN" } + th { style: "{th}width:46px;", "PARTS" } + th { style: "width:18px;border-bottom:1px solid rgba(255,255,255,.07);" } + } + for (i, tp) in topics.iter().enumerate() { + { + let t0=topics.clone(); let t1=topics.clone(); let t2=topics.clone(); let t_del=topics.clone(); + let (tname, tret, tpart) = (tp.name.clone(), tp.retention.clone(), tp.partitions); + rsx! { + tr { + td { style: "{td}", input { style: "{fld}", value: "{tname}", oninput: { let mut a=t0; move |ev:Event| { a[i].name=ev.data().value(); on_topics.call(a.clone()); } } }} + td { style: "{td}", input { style: "{fld}", value: "{tret}", oninput: { let mut a=t1; move |ev:Event| { a[i].retention=ev.data().value(); on_topics.call(a.clone()); } } }} + td { style: "{td}", input { style: "{fld}", r#type:"number", value: "{tpart}", oninput: { let mut a=t2; move |ev:Event| { if let Ok(v)=ev.data().value().parse() { a[i].partitions=v; on_topics.call(a.clone()); } } } }} + td { style: "{td}", button { style: "background:none;border:none;color:#5d6a76;cursor:pointer;font:inherit;", + onclick: { let mut a=t_del; move |_| { a.remove(i); on_topics.call(a.clone()); } }, "×" + }} + } + } + } + } + } + button { style: "{add}", + onclick: { let mut a=topics; move |_| { a.push(Topic{name:"new.topic".into(),retention:"24h".into(),partitions:1}); on_topics.call(a.clone()); } }, + "+ ADD TOPIC" + } + span { style: "{sec}", "PRODUCERS / CONSUMERS" } + if evs.is_empty() { + div { style: "{note}", "NO EVENT LINKS. RIGHT-CLICK A SERVICE ▸ PUB / SUB." } + } + for ev_tr in evs { + { + let is_sub = ev_tr.from == nid; + let other = nodes.iter().find(|n| n.id == if is_sub { ev_tr.to.clone() } else { ev_tr.from.clone() }).map(|n| n.name.to_uppercase()).unwrap_or_default(); + let tp_name = ev_tr.topic.clone().unwrap_or_default(); + let tid = ev_tr.id.clone(); + let tag = if is_sub { "SUB" } else { "PUB" }; + rsx! { + div { style: "display:flex;align-items:center;gap:9px;padding:7px 2px;border-bottom:1px solid rgba(255,255,255,.04);font-size:10px;", + span { style: "color:#58a6ff;font-size:8px;letter-spacing:.12em;", "{tag}" } + span { "{other}" } + span { style: "margin-left:auto;color:#5d6a76;font-size:9px;", "{tp_name}" } + button { style: "background:none;border:none;color:#5d6a76;cursor:pointer;font:inherit;", + onclick: move |_| on_rm_trace.call(tid.clone()), "×" + } + } + } + } + } + div { style: "{note}", "TOPICS PERSIST AS CLOUDEVENTS. CONSUMERS TRACK PER-DESTINATION CURSORS." } + } + } + NodeKind::Blueprint => { + let listed: Vec = nodes.iter().filter(|n| n.id != node.id).cloned().collect(); + let ttl = node.ttl.clone(); + rsx! { + span { style: "{sec}", "SERVICE REGISTRY" } + if listed.is_empty() { + div { style: "{note}", "NO SERVICES ON CANVAS. ADD NODES TO POPULATE THE REGISTRY." } + } + for svc in listed { + { + let led = if svc.online { "background:#3ddc97;box-shadow:0 0 5px #3ddc97;" } else { "background:#e5534b;box-shadow:0 0 5px #e5534b;" }; + let addr = if svc.host.is_empty() { format!("{}.cluster.local", svc.name) } else { svc.host.clone() }; + rsx! { + div { style: "display:flex;align-items:center;gap:9px;padding:7px 2px;border-bottom:1px solid rgba(255,255,255,.04);font-size:10px;", + span { style: "width:5px;height:5px;border-radius:50%;display:inline-block;{led}" } + span { "{svc.name.to_uppercase()}" } + span { style: "margin-left:auto;color:#5d6a76;font-size:9px;", "{svc.kind.sym()} · {addr}" } + } + } + } + } + span { style: "{sec}", "HEALTH CHECKS" } + div { style: "{kv}", label { style: "{lbl}", "LEASE TTL" } input { style: "{fld}", value: "{ttl}", oninput: move |ev:Event| on_ttl.call(ev.data().value()) } } + } + } + NodeKind::Service => { + let (host, port, proto) = (node.host.clone(), node.port, node.protocol.clone()); + rsx! { + span { style: "{sec}", "ENDPOINT" } + div { style: "{kv}", label { style: "{lbl}", "HOST" } + input { style: "{fld}", value: "{host}", + oninput: { let p=port; let pr=proto.clone(); move |ev:Event| on_endpoint.call((ev.data().value(), p, pr.clone())) } + } + } + div { style: "{kv}", label { style: "{lbl}", "PORT" } + input { style: "{fld}", r#type:"number", value: "{port}", + oninput: { let h=host.clone(); let pr=proto.clone(); move |ev:Event| { if let Ok(p)=ev.data().value().parse() { on_endpoint.call((h.clone(),p,pr.clone())); } } } + } + } + div { style: "{kv}", label { style: "{lbl}", "PROTOCOL" } + select { style: "{fld}", value: "{proto}", + onchange: { let h=host.clone(); let p=port; move |ev:Event| on_endpoint.call((h.clone(),p,ev.data().value())) }, + for opt in ["grpc","grpc-web","http"] { option { value:"{opt}", selected: proto==opt, "{opt}" } } + } + } + div { style: "{note}", "ON DEPLOY, THIS SERVICE SELF-REGISTERS WITH BLUEPRINT AND BECOMES ROUTABLE THROUGH FUSE." } + } + } + }; + + rsx! { + div { + style: "position:absolute;top:0;right:0;bottom:0;width:330px;z-index:60;\ + background:rgba(12,17,22,.97);border-left:1px solid rgba(255,255,255,.07);\ + display:flex;flex-direction:column;pointer-events:auto;", + // Header + div { style: "padding:14px 16px;border-bottom:1px solid rgba(255,255,255,.07);display:flex;align-items:center;gap:10px;", + span { style: "color:{col};font-weight:700;", "{sym}" } + div { + div { style: "font-size:11px;letter-spacing:.14em;", "{name}" } + div { style: "font-size:8px;letter-spacing:.2em;color:#5d6a76;margin-top:3px;", "{role}" } + } + button { + style: "margin-left:auto;background:none;border:1px solid rgba(255,255,255,.07);color:#5d6a76;width:22px;height:22px;cursor:pointer;font:inherit;", + onclick: move |_| on_close.call(()), + "×" + } + } + // Body (scrollable) + div { style: "flex:1;overflow-y:auto;padding:14px 16px;", {body} } + } + } +} diff --git a/services/core/blueprint/web-client/src/views/gateway.rs b/services/core/blueprint/web-client/src/views/gateway.rs new file mode 100644 index 00000000..7b1b5434 --- /dev/null +++ b/services/core/blueprint/web-client/src/views/gateway.rs @@ -0,0 +1,275 @@ +use dioxus::prelude::*; +use draft_api::proto::core_control_plane_networking_v1::{ + networking_service_client::NetworkingServiceClient, + AddRouteRequest, DeleteRouteRequest, Endpoint, ListRoutesRequest, Route, RouteMatch, +}; +use tonic_web_wasm_client::Client; + +const FUSE_URL: &str = "http://127.0.0.1:18000"; + +#[component] +pub fn Gateway() -> Element { + let mut list_result = use_resource(|| async { + let mut client = NetworkingServiceClient::new(Client::new(FUSE_URL.to_string())); + client.list_routes(ListRoutesRequest {}).await.map(|r| r.into_inner()) + }); + + let mut show_modal = use_signal(|| false); + let mut editing_name: Signal> = use_signal(|| None); + + let mut form_name = use_signal(String::new); + let mut form_prefix = use_signal(String::new); + let mut form_host = use_signal(String::new); + let mut form_ep_host = use_signal(String::new); + let mut form_ep_port = use_signal(|| String::from("0")); + let mut form_http2 = use_signal(|| false); + let mut status: Signal> = use_signal(|| None); + + let submit = move |_| { + let name = form_name(); + let prefix = form_prefix(); + let host = form_host(); + let ep_host = form_ep_host(); + let port: u32 = form_ep_port().parse().unwrap_or(0); + let http2 = form_http2(); + let original = editing_name(); + + spawn(async move { + let mut client = NetworkingServiceClient::new(Client::new(FUSE_URL.to_string())); + + if let Some(old_name) = original { + if let Err(e) = client.delete_route(DeleteRouteRequest { name: old_name }).await { + status.set(Some(format!("Error removing old route: {e}"))); + return; + } + } + + let route = Route { + name, + r#match: Some(RouteMatch { + prefix, + host, + headers: None, + grpc_match_options: None, + dynamic_metadata: None, + }), + endpoint: Some(Endpoint { host: ep_host, port }), + enable_http2: http2, + auth: None, + }; + + match client.add_route(AddRouteRequest { route: Some(route) }).await { + Ok(_) => { + show_modal.set(false); + status.set(Some("Route saved.".to_string())); + list_result.restart(); + } + Err(e) => status.set(Some(format!("Error: {e}"))), + } + }); + }; + + rsx! { + div { class: "p-4", + div { class: "flex items-center justify-between mb-4", + h1 { class: "text-2xl font-bold", "Gateway" } + button { + class: "btn btn-primary btn-sm", + onclick: move |_| { + form_name.set(String::new()); + form_prefix.set(String::new()); + form_host.set(String::new()); + form_ep_host.set(String::new()); + form_ep_port.set("0".to_string()); + form_http2.set(false); + editing_name.set(None); + show_modal.set(true); + }, + "+ Add Route" + } + } + + if let Some(msg) = status() { + div { class: "alert alert-info mb-4", + span { "{msg}" } + } + } + + div { class: "overflow-x-auto", + table { class: "table table-xs", + thead { + tr { + th { "Name" } + th { "Match Prefix" } + th { "Match Host" } + th { "Endpoint Host" } + th { "Port" } + th { "HTTP2" } + th { "Actions" } + } + } + tbody { + match &*list_result.read() { + Some(Ok(response)) => { + rsx! { + for route in response.routes.clone() { + { + let key = route.name.clone(); + let col_name = route.name.clone(); + let col_prefix = route.r#match.as_ref().map(|m| m.prefix.clone()).unwrap_or_default(); + let col_host = route.r#match.as_ref().map(|m| m.host.clone()).unwrap_or_default(); + let col_ep_host = route.endpoint.as_ref().map(|e| e.host.clone()).unwrap_or_default(); + let col_port = route.endpoint.as_ref().map(|e| e.port).unwrap_or(0); + let col_http2 = route.enable_http2; + + let edit_name = route.name.clone(); + let edit_prefix = col_prefix.clone(); + let edit_host = col_host.clone(); + let edit_ep_host = col_ep_host.clone(); + let edit_port = col_port; + let edit_http2 = col_http2; + + let del_name = route.name.clone(); + + rsx! { + tr { key: "{key}", class: "hover:bg-base-300", + td { "{col_name}" } + td { "{col_prefix}" } + td { "{col_host}" } + td { "{col_ep_host}" } + td { "{col_port}" } + td { { if col_http2 { "Yes" } else { "No" } } } + td { + div { class: "flex gap-2", + button { + class: "btn btn-xs btn-ghost", + onclick: move |_| { + form_name.set(edit_name.clone()); + form_prefix.set(edit_prefix.clone()); + form_host.set(edit_host.clone()); + form_ep_host.set(edit_ep_host.clone()); + form_ep_port.set(edit_port.to_string()); + form_http2.set(edit_http2); + editing_name.set(Some(edit_name.clone())); + show_modal.set(true); + }, + "Edit" + } + button { + class: "btn btn-xs btn-ghost btn-error", + onclick: move |_| { + let name = del_name.clone(); + spawn(async move { + let mut client = NetworkingServiceClient::new( + Client::new(FUSE_URL.to_string()), + ); + match client.delete_route(DeleteRouteRequest { name }).await { + Ok(_) => { + status.set(Some("Route deleted.".to_string())); + list_result.restart(); + } + Err(e) => status.set(Some(format!("Error: {e}"))), + } + }); + }, + "Delete" + } + } + } + } + } + } + } + } + } + Some(Err(e)) => rsx! { + tr { + td { colspan: "7", class: "text-center text-error", "Error: {e}" } + } + }, + None => rsx! { + tr { + td { colspan: "7", class: "text-center", "Loading..." } + } + }, + } + } + } + } + + if show_modal() { + div { class: "modal modal-open", + div { class: "modal-box", + h3 { class: "font-bold text-lg mb-4", + { if editing_name().is_some() { "Edit Route" } else { "Add Route" } } + } + div { class: "form-control mb-2", + label { class: "label", span { class: "label-text", "Name" } } + input { + class: "input input-bordered input-sm w-full", + value: "{form_name}", + oninput: move |e| form_name.set(e.value()), + } + } + div { class: "form-control mb-2", + label { class: "label", span { class: "label-text", "Match Prefix" } } + input { + class: "input input-bordered input-sm w-full", + value: "{form_prefix}", + oninput: move |e| form_prefix.set(e.value()), + } + } + div { class: "form-control mb-2", + label { class: "label", span { class: "label-text", "Match Host" } } + input { + class: "input input-bordered input-sm w-full", + value: "{form_host}", + oninput: move |e| form_host.set(e.value()), + } + } + div { class: "form-control mb-2", + label { class: "label", span { class: "label-text", "Endpoint Host" } } + input { + class: "input input-bordered input-sm w-full", + value: "{form_ep_host}", + oninput: move |e| form_ep_host.set(e.value()), + } + } + div { class: "form-control mb-2", + label { class: "label", span { class: "label-text", "Endpoint Port" } } + input { + r#type: "number", + class: "input input-bordered input-sm w-full", + value: "{form_ep_port}", + oninput: move |e| form_ep_port.set(e.value()), + } + } + div { class: "form-control mb-4", + label { class: "label cursor-pointer", + span { class: "label-text", "Enable HTTP2" } + input { + r#type: "checkbox", + class: "toggle", + checked: form_http2(), + onchange: move |e| form_http2.set(e.checked()), + } + } + } + div { class: "modal-action", + button { + class: "btn btn-ghost btn-sm", + onclick: move |_| show_modal.set(false), + "Cancel" + } + button { + class: "btn btn-primary btn-sm", + onclick: submit, + "Save" + } + } + } + } + } + } + } +} diff --git a/services/core/blueprint/web-client/src/views/home.rs b/services/core/blueprint/web-client/src/views/home.rs deleted file mode 100644 index ada36efd..00000000 --- a/services/core/blueprint/web-client/src/views/home.rs +++ /dev/null @@ -1,10 +0,0 @@ -use dioxus::prelude::*; - -use crate::components::Hero; - -#[component] -pub fn Home() -> Element { - rsx! { - Hero {} - } -} diff --git a/services/core/blueprint/web-client/src/views/key_value.rs b/services/core/blueprint/web-client/src/views/key_value.rs index 21302207..9789fe98 100644 --- a/services/core/blueprint/web-client/src/views/key_value.rs +++ b/services/core/blueprint/web-client/src/views/key_value.rs @@ -1,75 +1,81 @@ -use std::fmt; -use std::collections::HashMap; -use once_cell::sync::Lazy; -use serde::{Deserialize, Serialize}; use dioxus::prelude::*; -use dioxus_logger::tracing::debug; +use gloo_timers::future::TimeoutFuture; +use draft_api::hook::core_registry_key_value_v1::{ + key_value_service_client::KeyValueServiceClient, + DeleteRequest, ListRequest, SetRequest, Value, +}; +use prost::Message as _; +use prost_types::Any; +use tonic_web_wasm_client::Client as WasmClient; -use crate::API_DOMAIN; - -pub static PATH: Lazy = Lazy::new(|| { - "/core.registry.key_value.v1.KeyValueService/List".to_string() -}); +const VALUE_TYPE_URL: &str = "type.googleapis.com/core.registry.key_value.v1.Value"; #[component] pub fn KeyValueView() -> Element { - let mut list = use_signal(|| { - KeyValueListResponse { - values: HashMap::new(), - } + let mut list_result = use_resource(|| async { + let mut client = KeyValueServiceClient::new(WasmClient::new(crate::API_DOMAIN.clone())); + client.list(ListRequest { + value: Some(Any { + type_url: VALUE_TYPE_URL.to_string(), + value: vec![], + }), + }).await.map(|r| r.into_inner()) }); - // TODO: When adding a spinner, use the output from `use_resource` to show the spinner, display data, and handle the error - // currently using the `use_signal` hook to show the data which is not the most efficient way - let _key_value = use_resource(move || async move { - let url = format!("{}{}", *API_DOMAIN, *PATH); - debug!("URL: {}", url); - let response = reqwest::Client::new() - .post(url) - .json(&KeyValueListRequest { - value: QueryValue { - type_url: "type.googleapis.com/core.registry.key_value.v1.Value".to_string(), - }, - }) - .send() - .await; + let mut show_modal = use_signal(|| false); + let mut form_key = use_signal(String::new); + let mut form_value = use_signal(String::new); + let mut status: Signal> = use_signal(|| None); - // TODO: Error handling - match response { - Ok(resp) => { - let json = resp.json::().await; - match json { - Ok(data) => { - let mut d = HashMap::new(); - // iterate over the values and remove the key type prefix - // (type.googleapis.com/core.registry.key_value.v1.Value-) - data.values.iter().for_each(|(key, val)| { - let mut new_key = key.clone(); - if let Some(pos) = new_key.find("type.googleapis.com/core.registry.key_value.v1.Value-") { - new_key.replace_range(..pos + "type.googleapis.com/core.registry.key_value.v1.Value-".len(), ""); - } - // info!("Key: {}", new_key); - d.insert(new_key, val.clone()); - }); + let submit = move |_| { + let key = form_key(); + let value = form_value(); + spawn(async move { + let mut client = KeyValueServiceClient::new(WasmClient::new(crate::API_DOMAIN.clone())); + let any = Any { + type_url: VALUE_TYPE_URL.to_string(), + value: Value { data: value }.encode_to_vec(), + }; + match client.set(SetRequest { key, value: Some(any) }).await { + Ok(_) => { + show_modal.set(false); + form_key.set(String::new()); + form_value.set(String::new()); + list_result.restart(); + status.set(Some("Key/value saved.".to_string())); + spawn(async move { + TimeoutFuture::new(3_000).await; + status.set(None); + }); + } + Err(e) => status.set(Some(format!("Error: {e}"))), + } + }); + }; - list.set(KeyValueListResponse { - values: d, - }); + rsx! { + div { class: "p-4", + div { class: "flex items-center justify-between mb-4", + h1 { class: "text-2xl font-bold", "Key / Value" } + button { + class: "btn btn-primary btn-sm", + onclick: move |_| { + form_key.set(String::new()); + form_value.set(String::new()); + show_modal.set(true); + }, + "+ Add Entry" + } + } - Ok(()) - }, - // Error so we need to render something on the screen (Maybe some popup) - Err(err) => Err(format!("Failed to parse JSON: {}", err)), + if let Some(msg) = status() { + div { class: "toast toast-end toast-bottom z-50", + div { class: "alert alert-success", + span { "{msg}" } } } - // Error so we need to render something on the screen (Maybe some popup) - Err(err) => Err(format!("Failed to fetch data: {}", err)), } - }); - rsx! { - div { - // TODO: Add a loading spinner div { class: "overflow-x-auto", table { class: "table table-xs", thead { @@ -77,22 +83,112 @@ pub fn KeyValueView() -> Element { th { "Key" } th { "Value" } th { "Type Url" } + th { "" } } } tbody { - for (key, val) in list().values.iter() { - tr { class: "hover:bg-base-300", - td { "{key}" } - td { "{val.data}" } - td { "{val.type_url}" } - } + match &*list_result.read() { + Some(Ok(response)) => { + let key_prefix = format!("{}-", VALUE_TYPE_URL); + let mut rows: Vec<(String, String, String)> = response.values + .iter() + .map(|(key, any)| { + let type_url = any.type_url.clone(); + let data = Value::decode(any.value.as_slice()) + .map(|v| v.data) + .unwrap_or_else(|_| "(binary)".to_string()); + let display_key = key.strip_prefix(key_prefix.as_str()).unwrap_or(key).to_string(); + (display_key, data, type_url) + }) + .collect(); + rows.sort_by(|a, b| a.0.cmp(&b.0)); + rsx! { + for (key, data, type_url) in rows { + { + let delete_key = key.clone(); + rsx! { + tr { class: "hover:bg-base-300", + td { "{key}" } + td { "{data}" } + td { "{type_url}" } + td { + button { + class: "btn btn-xs btn-error", + onclick: move |_| { + let key = delete_key.clone(); + spawn(async move { + let mut client = KeyValueServiceClient::new( + WasmClient::new(crate::API_DOMAIN.clone()) + ); + let _ = client.delete(DeleteRequest { + key, + value: Some(Any { + type_url: VALUE_TYPE_URL.to_string(), + value: vec![], + }), + }).await; + list_result.restart(); + }); + }, + "Delete" + } + } + } + } + } + } + } + }, + Some(Err(err)) => rsx! { + tr { + td { colspan: "4", class: "text-center text-red-500", + "Error: {err}" + } + } + }, + None => rsx! { + tr { + td { colspan: "4", class: "text-center", + "Loading..." + } + } + }, } } - tfoot { - tr { - th { "Key" } - th { "Value" } - th { "Type Url" } + } + } + + if show_modal() { + div { class: "modal modal-open", + div { class: "modal-box", + h3 { class: "font-bold text-lg mb-4", "Add Key / Value" } + div { class: "form-control mb-2", + label { class: "label", span { class: "label-text", "Key" } } + input { + class: "input input-bordered input-sm w-full", + value: "{form_key}", + oninput: move |e| form_key.set(e.value()), + } + } + div { class: "form-control mb-4", + label { class: "label", span { class: "label-text", "Value" } } + input { + class: "input input-bordered input-sm w-full", + value: "{form_value}", + oninput: move |e| form_value.set(e.value()), + } + } + div { class: "modal-action", + button { + class: "btn btn-ghost btn-sm", + onclick: move |_| show_modal.set(false), + "Cancel" + } + button { + class: "btn btn-primary btn-sm", + onclick: submit, + "Save" + } } } } @@ -100,43 +196,3 @@ pub fn KeyValueView() -> Element { } } } - -/// curl: -/// curl --header "Content-Type: application/json" \ -/// --data '{"value": {"type_url": "type.googleapis.com/core.registry.key_value.v1.Value"}}' \ -/// http://localhost:2221/core.registry.key_value.v1.KeyValueService/List -/// -/// RES: {"value": {"type_url": "type.googleapis.com/core.registry.key_value.v1.Value"}} -#[derive(Serialize, Deserialize)] -struct KeyValueListRequest { - value: QueryValue, -} - -#[derive(Serialize, Deserialize )] -struct QueryValue { - type_url: String -} - -/// Response from the server -#[derive(Serialize, Deserialize, Clone)] -struct KeyValueListResponse { - values: HashMap, -} - -// Implementing Display trait for KeyValueListResponse -// so it can be printed in a readable format -impl fmt::Display for KeyValueListResponse { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for (key, value) in &self.values { - writeln!(f, "Key: {}\nType URL: {}\nData: {}\n", key, value.type_url, value.data)?; - } - Ok(()) - } -} - -#[derive(Serialize, Deserialize, Clone)] -struct Value { - #[serde(rename = "@type")] - type_url: String, - data: String, -} \ No newline at end of file diff --git a/services/core/blueprint/web-client/src/views/mcp.rs b/services/core/blueprint/web-client/src/views/mcp.rs new file mode 100644 index 00000000..e1e5ea77 --- /dev/null +++ b/services/core/blueprint/web-client/src/views/mcp.rs @@ -0,0 +1,11 @@ +use dioxus::prelude::*; + +#[component] +pub fn Mcp() -> Element { + rsx! { + div { class: "p-4", + h1 { class: "text-2xl font-bold mb-4", "MCP" } + p { class: "text-base-content/60", "Model Context Protocol servers will appear here." } + } + } +} diff --git a/services/core/blueprint/web-client/src/views/metrics.rs b/services/core/blueprint/web-client/src/views/metrics.rs index b51cf246..1620cc71 100644 --- a/services/core/blueprint/web-client/src/views/metrics.rs +++ b/services/core/blueprint/web-client/src/views/metrics.rs @@ -1,18 +1,466 @@ use dioxus::prelude::*; +use tonic_web_wasm_client::Client as WasmClient; +use draft_api::proto::core_message_broker_actors_v1::{ + metrics_client::MetricsClient, + resource_metrics_client::ResourceMetricsClient, + topology_client::TopologyClient, + EdgeVolume, + GetMetricsRequest, + GetResourceMetricsRequest, + GetTopologyRequest, + TopologyEdge, +}; -// const METRICS_CSS: Asset = asset!("/assets/styling/metrics.css"); +use gloo_timers::callback::Interval; +use crate::components::{MetricCard, MetricIcon, WaveLoader, event_color}; + + +#[derive(Clone, PartialEq, Copy)] +enum TimeRange { + Min15, + Hour1, + Hour3, + Hour24, + AllTime, +} + +impl TimeRange { + fn label(self) -> &'static str { + match self { + TimeRange::Min15 => "15m", + TimeRange::Hour1 => "1h", + TimeRange::Hour3 => "3h", + TimeRange::Hour24 => "24h", + TimeRange::AllTime => "all", + } + } + + fn description(self) -> &'static str { + match self { + TimeRange::Min15 => "last 15 minutes", + TimeRange::Hour1 => "last 1 hour", + TimeRange::Hour3 => "last 3 hours", + TimeRange::Hour24 => "last 24 hours", + TimeRange::AllTime => "all time", + } + } + + /// Returns the window in seconds. -1 means no time filter (all stored events). + fn window_seconds(self) -> i32 { + match self { + TimeRange::Min15 => 900, + TimeRange::Hour1 => 3_600, + TimeRange::Hour3 => 10_800, + TimeRange::Hour24 => 86_400, + TimeRange::AllTime => -1, + } + } +} + +#[derive(Clone, Default)] +struct MetricsData { + msgs_per_min: u32, + median_ms: f64, + p95_ms: f64, + edge_volumes: Vec, + topology_edges: Vec, + loaded: bool, +} + +#[derive(Clone, Default)] +struct ResourceData { + published_total: u64, + dropped_total: u64, + queue_depth: u32, + queue_capacity: u32, + active_consumers: u32, + active_producers: u32, + flush_p95_ms: f64, + flush_count: u32, + loaded: bool, +} #[component] pub fn Metrics() -> Element { + let mut time_range = use_signal(|| TimeRange::Hour3); + let mut metrics = use_signal(MetricsData::default); + let mut resource = use_signal(ResourceData::default); + let mut updated_ago = use_signal(|| "loading…".to_string()); + let mut tick = use_signal(|| 0u32); + + // Increment tick every 5 s — effects that read tick() re-run automatically. + let _poll_interval = use_signal(move || { + Interval::new(5_000, move || { + *tick.write() += 1; + }) + }); + + use_effect(move || { + let _ = tick(); // re-run on every 5 s tick + let range = time_range(); + let host = crate::CATALYST_DOMAIN.clone(); + spawn(async move { + let metrics_res = { + let mut client = MetricsClient::new(WasmClient::new(host.clone())); + client.get_metrics(GetMetricsRequest { window_seconds: range.window_seconds() }).await + }; + let topo_edges = { + let mut client = TopologyClient::new(WasmClient::new(host)); + client.get_topology(GetTopologyRequest {}).await + .ok() + .map(|t| t.into_inner().edges) + .unwrap_or_default() + }; + match metrics_res { + Ok(resp) => { + let r = resp.into_inner(); + metrics.set(MetricsData { + msgs_per_min: r.total_messages_per_min, + median_ms: r.median_latency_ms, + p95_ms: r.p95_latency_ms, + edge_volumes: r.edge_volumes, + topology_edges: topo_edges, + loaded: true, + }); + updated_ago.set("just now".to_string()); + } + Err(_) => { + updated_ago.set("unavailable".to_string()); + } + } + }); + + // Resource metrics are point-in-time and independent of the time window. + let host = crate::CATALYST_DOMAIN.clone(); + spawn(async move { + let mut client = ResourceMetricsClient::new(WasmClient::new(host)); + if let Ok(resp) = client.get_resource_metrics(GetResourceMetricsRequest {}).await { + let r = resp.into_inner(); + resource.set(ResourceData { + published_total: r.messages_published_total, + dropped_total: r.messages_dropped_total, + queue_depth: r.queue_depth, + queue_capacity: r.queue_capacity, + active_consumers: r.active_consumers, + active_producers: r.active_producers, + flush_p95_ms: r.store_flush_p95_ms, + flush_count: r.store_flush_count, + loaded: true, + }); + } + }); + }); + + + let m = metrics(); + let res = resource(); + let flush_p95_str = if res.loaded { format!("{:.1}", res.flush_p95_ms) } else { "—".to_string() }; + + // Consumers per event_type from live topology edges. + let consumer_idx: std::collections::HashMap> = { + let mut idx: std::collections::HashMap> = + std::collections::HashMap::new(); + for e in &m.topology_edges { + idx.entry(e.event_type.clone()) + .or_default() + .insert(e.consumer_source.clone()); + } + idx + }; + + let is_all_time = time_range() == TimeRange::AllTime; + // Aggregate edge_volumes by event_type: sum counts and count distinct producer sources. + let window_mins = if is_all_time { 0.0 } else { time_range().window_seconds() as f64 / 60.0 }; + // rows: (event_type, total_count, producer_count, consumer_count) + let topic_rows: Vec<(String, u32, u32, u32)> = { + let mut map: std::collections::HashMap)> = + std::collections::HashMap::new(); + for ev in &m.edge_volumes { + let entry = map.entry(ev.event_type.clone()).or_default(); + entry.0 += ev.count; + entry.1.insert(ev.source.clone()); + } + let mut rows: Vec<(String, u32, u32, u32)> = map.into_iter() + .map(|(typ, (count, srcs))| { + let consumers = consumer_idx.get(&typ).map(|s| s.len() as u32).unwrap_or(0); + (typ, count, srcs.len() as u32, consumers) + }) + .collect(); + rows.sort_by(|a, b| b.1.cmp(&a.1)); + rows + }; + let max_count = topic_rows.first().map(|r| r.1).unwrap_or(1).max(1); + + // Sparklines are placeholders — a time-series endpoint would provide real buckets. + let msgs_data = vec![280.0f32, 295.0, 310.0, 290.0, 305.0, 298.0, m.msgs_per_min as f32]; + let median_data = vec![32.0f32, 30.0, 28.0, 31.0, 27.0, 29.0, m.median_ms as f32]; + let p95_data = vec![80.0f32, 85.0, 88.0, 90.0, 92.0, 91.0, m.p95_ms as f32]; + let error_data = vec![1.8f32, 1.6, 1.5, 1.7, 1.4, 1.5, 1.4]; + rsx! { - // document::Link { rel: "stylesheet", href: METRICS_CSS } + div { class: "p-6 flex flex-col gap-6", + div { class: "flex items-center justify-between flex-wrap gap-3", + div { class: "flex items-baseline gap-3", + h1 { class: "text-xl font-bold", "Metrics" } + span { class: "text-sm text-base-content/40", + "{time_range().description()} · updated {updated_ago()}" + } + } + div { class: "join", + for range in [TimeRange::Min15, TimeRange::Hour1, TimeRange::Hour3, TimeRange::Hour24, TimeRange::AllTime] { + button { + class: if time_range() == range { + "btn btn-sm join-item btn-neutral" + } else { + "btn btn-sm join-item btn-ghost" + }, + onclick: move |_| time_range.set(range), + "{range.label()}" + } + } + } + } + + if !m.loaded { + div { style: "position:fixed;top:50%;left:0;right:0;width:fit-content;margin-inline:auto;", + WaveLoader { width: 80, height: 28 } + } + } else { + div { class: "flex flex-col gap-6", + div { class: "flex flex-col gap-3", + h2 { class: "text-xs font-semibold tracking-wide text-base-content/40 uppercase", "Event Metrics" } + div { class: "grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4", + MetricCard { + icon: MetricIcon::Messages, + label: "MESSAGES / MIN".to_string(), + value: if m.loaded { m.msgs_per_min.to_string() } else { "—".to_string() }, + unit: None, + trend_up: true, + trend_good: true, + trend_delta: "live".to_string(), + sparkline_data: msgs_data, + sparkline_color: "#4ade80".to_string(), + } + MetricCard { + icon: MetricIcon::Clock, + label: "MEDIAN LATENCY".to_string(), + value: if m.loaded { format!("{:.1}", m.median_ms) } else { "—".to_string() }, + unit: Some("ms".to_string()), + trend_up: false, + trend_good: true, + trend_delta: "live".to_string(), + sparkline_data: median_data, + sparkline_color: "#60a5fa".to_string(), + } + MetricCard { + icon: MetricIcon::Clock, + label: "P95 LATENCY".to_string(), + value: if m.loaded { format!("{:.1}", m.p95_ms) } else { "—".to_string() }, + unit: Some("ms".to_string()), + trend_up: true, + trend_good: false, + trend_delta: "live".to_string(), + sparkline_data: p95_data, + sparkline_color: "#fb923c".to_string(), + } + MetricCard { + icon: MetricIcon::Warning, + label: "ERROR RATE".to_string(), + value: "—".to_string(), + unit: Some("%".to_string()), + trend_up: false, + trend_good: true, + trend_delta: "n/a".to_string(), + sparkline_data: error_data, + sparkline_color: "#f87171".to_string(), + } + } + } - div { - id: "metrics", + // Resource metrics + div { class: "flex flex-col gap-3", + h2 { class: "text-xs font-semibold tracking-wide text-base-content/40 uppercase", "Resource Metrics" } + div { class: "grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4", + { + let v = res.queue_capacity.max(1); + let depth = res.queue_depth; + let flat = vec![depth as f32; 7]; + rsx! { + MetricCard { + icon: MetricIcon::Server, + label: "QUEUE DEPTH".to_string(), + value: if res.loaded { format!("{} / {}", depth, res.queue_capacity) } else { "—".to_string() }, + unit: None, + trend_up: false, + trend_good: depth < v / 2, + trend_delta: "live".to_string(), + sparkline_data: flat, + sparkline_color: if depth > v * 4 / 5 { "#ef4444".to_string() } + else if depth > v / 2 { "#f97316".to_string() } + else { "#4ade80".to_string() }, + } + } + } + MetricCard { + icon: MetricIcon::Users, + label: "ACTIVE CONSUMERS".to_string(), + value: if res.loaded { res.active_consumers.to_string() } else { "—".to_string() }, + unit: None, + trend_up: res.active_consumers > 0, + trend_good: res.active_consumers > 0, + trend_delta: "live".to_string(), + sparkline_data: vec![res.active_consumers as f32; 7], + sparkline_color: "#60a5fa".to_string(), + } + MetricCard { + icon: MetricIcon::Users, + label: "ACTIVE PRODUCERS".to_string(), + value: if res.loaded { res.active_producers.to_string() } else { "—".to_string() }, + unit: None, + trend_up: true, + trend_good: true, + trend_delta: "live".to_string(), + sparkline_data: vec![res.active_producers as f32; 7], + sparkline_color: "#fbbf24".to_string(), + } + MetricCard { + icon: MetricIcon::ArrowUp, + label: "PUBLISHED TOTAL".to_string(), + value: if res.loaded { res.published_total.to_string() } else { "—".to_string() }, + unit: None, + trend_up: true, + trend_good: true, + trend_delta: "since start".to_string(), + sparkline_data: vec![res.published_total as f32; 7], + sparkline_color: "#4ade80".to_string(), + } + MetricCard { + icon: MetricIcon::Warning, + label: "DROPPED TOTAL".to_string(), + value: if res.loaded { res.dropped_total.to_string() } else { "—".to_string() }, + unit: None, + trend_up: res.dropped_total > 0, + trend_good: res.dropped_total == 0, + trend_delta: "since start".to_string(), + sparkline_data: vec![res.dropped_total as f32; 7], + sparkline_color: if res.dropped_total > 0 { "#f87171".to_string() } else { "#4ade80".to_string() }, + } + MetricCard { + icon: MetricIcon::Clock, + label: "FLUSH P95".to_string(), + value: if res.loaded { flush_p95_str.clone() } else { "—".to_string() }, + unit: Some("ms".to_string()), + trend_up: false, + trend_good: res.flush_p95_ms < 50.0, + trend_delta: "live".to_string(), + sparkline_data: vec![res.flush_p95_ms as f32; 7], + sparkline_color: "#fb923c".to_string(), + } + MetricCard { + icon: MetricIcon::Server, + label: "FLUSH COUNT".to_string(), + value: if res.loaded { res.flush_count.to_string() } else { "—".to_string() }, + unit: None, + trend_up: true, + trend_good: true, + trend_delta: "since start".to_string(), + sparkline_data: vec![res.flush_count as f32; 7], + sparkline_color: "#a78bfa".to_string(), + } + } + } - // Content - h1 { "Metrics" } - p { "This is the metrics page. Here, we will show how to use the Dioxus metrics to monitor our application." } + // Topics table + div { class: "rounded-xl border border-base-content/10 overflow-hidden", + div { class: "px-4 py-3 border-b border-base-content/10 flex items-center gap-2", + h2 { class: "text-sm font-semibold tracking-wide text-base-content/70 uppercase", + "Topics" + } + if m.loaded { + span { class: "text-xs text-base-content/40", + "· {topic_rows.len()} event types in {time_range().description()}" + } + } + } + if !m.loaded { + div { class: "px-4 py-8 text-center text-base-content/30 text-sm", "Loading…" } + } else if topic_rows.is_empty() { + div { class: "px-4 py-8 text-center text-base-content/30 text-sm", "No events in this window." } + } else { + table { class: "w-full text-sm", + thead { + tr { class: "border-b border-base-content/10 text-left text-xs text-base-content/40 uppercase tracking-wide", + th { class: "px-4 py-2 font-medium", "Topic" } + th { class: "px-4 py-2 font-medium text-right", "Producers" } + th { class: "px-4 py-2 font-medium text-right", "Consumers" } + th { class: "px-4 py-2 font-medium text-right", "Events" } + if !is_all_time { + th { class: "px-4 py-2 font-medium text-right", "/ min" } + } + th { class: "px-4 py-2", style: "width:160px;", "" } + } + } + tbody { + for (topic, count, producers, consumers) in topic_rows.iter() { + { + let mut hovered = use_signal(|| false); + let per_min = if window_mins > 0.0 { + (*count as f64 / window_mins).round() as u32 + } else { 0 }; + let bar_pct = (*count as f64 / max_count as f64 * 100.0).round() as u32; + let color = event_color(topic.as_str()); + let topic = topic.clone(); + let count = *count; + let producers = *producers; + let consumers = *consumers; + let dot_color = if consumers > 0 { "#4ade80" } else { "#f87171" }; + let row_bg = if hovered() { "rgba(255,255,255,0.08)" } else { "transparent" }; + rsx! { + tr { + style: "border-bottom:1px solid rgba(255,255,255,0.05);transition:background 120ms;background:{row_bg};", + onmouseenter: move |_| hovered.set(true), + onmouseleave: move |_| hovered.set(false), + td { class: "px-4 py-3", + div { class: "flex items-center gap-2", + span { + style: "display:inline-block;width:8px;height:8px;border-radius:50%;background:{dot_color};flex-shrink:0;", + } + span { class: "font-mono text-xs", "{topic}" } + } + } + td { class: "px-4 py-3 text-right tabular-nums text-base-content/60", + "{producers}" + } + td { class: "px-4 py-3 text-right tabular-nums text-base-content/60", + "{consumers}" + } + td { class: "px-4 py-3 text-right tabular-nums", + "{count}" + } + if !is_all_time { + td { class: "px-4 py-3 text-right tabular-nums text-base-content/70", + "{per_min}" + } + } + td { class: "px-4 py-3", + div { class: "w-full bg-base-content/10 rounded-full overflow-hidden", + style: "height:4px;", + div { + style: "height:4px;width:{bar_pct}%;background:{color};border-radius:9999px;", + } + } + } + } + } + } + } + } + } + } + } + } + } } + } -} \ No newline at end of file +} diff --git a/services/core/blueprint/web-client/src/views/mod.rs b/services/core/blueprint/web-client/src/views/mod.rs index 7d6e2d91..fd962a8c 100644 --- a/services/core/blueprint/web-client/src/views/mod.rs +++ b/services/core/blueprint/web-client/src/views/mod.rs @@ -1,14 +1,35 @@ -mod home; -pub use home::Home; - mod key_value; pub use key_value::KeyValueView; mod service_registry; pub use service_registry::ServiceRegistry; +mod gateway; +pub use gateway::Gateway; + +mod agents; +pub use agents::Agents; + +mod mcp; +pub use mcp::Mcp; + +mod tools; +pub use tools::Tools; + +mod store; +pub use store::Store; + +mod topology; +pub use topology::Topology; + +mod cluster; +pub use cluster::Cluster; + mod metrics; pub use metrics::Metrics; +mod settings; +pub use settings::Settings; + mod page_not_found; -pub use page_not_found::PageNotFound; \ No newline at end of file +pub use page_not_found::PageNotFound; diff --git a/services/core/blueprint/web-client/src/views/service_registry.rs b/services/core/blueprint/web-client/src/views/service_registry.rs index 7473dbc2..cc5e8817 100644 --- a/services/core/blueprint/web-client/src/views/service_registry.rs +++ b/services/core/blueprint/web-client/src/views/service_registry.rs @@ -1,18 +1,143 @@ -use dioxus::prelude::*; +use std::collections::HashMap; -// const SERVICE_REGISTRY_CSS: Asset = asset!("/assets/styling/service_registry.css"); +use dioxus::prelude::*; +use draft_api::{ + hook::core_registry_service_discovery_v1::{ + filter, use_service_discovery_service_service, Filter, QueryRequest, + }, + proto::core_registry_service_discovery_v1::{ + service_discovery_service_client::ServiceDiscoveryServiceClient, ProcessHealthState, + ProcessRunningState, WatchRequest, + }, +}; +use dioxus_grpc::GrpcConfig; +use tonic_web_wasm_client::Client as WasmClient; #[component] pub fn ServiceRegistry() -> Element { - rsx! { - // document::Link { rel: "stylesheet", href: SERVICE_REGISTRY_CSS } + let query_request = use_signal(|| QueryRequest { + filter: Some(Filter { + attribute: Some(filter::Attribute::All(String::new())), + }), + }); + + let service = use_service_discovery_service_service(); + let query_result = service.query(query_request); + + // processes map seeded by Query and updated by Watch + let mut processes: Signal> = + use_signal(HashMap::new); + + // seed from query result + use_effect(move || { + if let Some(Ok(ref resp)) = *query_result.read() { + *processes.write() = resp.data.clone(); + } + }); + + // background coroutine: open Watch stream and upsert updates + let config = use_context::(); + use_coroutine(move |_rx: UnboundedReceiver<()>| { + let host = config.host.clone(); + async move { + let wasm_client = WasmClient::new(host); + let mut client = ServiceDiscoveryServiceClient::new(wasm_client); + let Ok(response) = client.watch(WatchRequest {}).await else { + return; + }; + let mut stream = response.into_inner(); + loop { + match stream.message().await { + Ok(Some(msg)) => { + if msg.removed { + if let Some(process) = msg.process { + processes.write().remove(&process.pid); + } + } else if let Some(process) = msg.process { + processes.write().insert(process.pid.clone(), process); + } + } + Ok(None) => break, + Err(_) => break, + } + } + } + }); + let mut sorted: Vec<_> = processes.read().values().cloned().collect(); + sorted.sort_by(|a, b| a.name.cmp(&b.name)); + + rsx! { div { - id: "service-registry", + div { class: "overflow-x-auto", + table { class: "table table-xs", + thead { + tr { + th { "Name" } + th { "PID" } + th { "IP Address" } + th { "Running State" } + th { "Health" } + } + } + tbody { + if sorted.is_empty() { + if query_result.read().is_none() { + tr { + td { colspan: "5", class: "text-center", "Loading..." } + } + } else { + tr { + td { colspan: "5", class: "text-center text-base-content/50", + "No processes registered" + } + } + } + } + for process in sorted { + { + let running = ProcessRunningState::try_from(process.running_state) + .map(|s| s.as_str_name().trim_start_matches("PROCESS_").to_string()) + .unwrap_or_else(|_| "UNKNOWN".to_string()); + let health = ProcessHealthState::try_from(process.health_state) + .map(|s| s.as_str_name().trim_start_matches("PROCESS_").to_string()) + .unwrap_or_else(|_| "UNKNOWN".to_string()); + + let running_class = match process.running_state { + s if s == ProcessRunningState::ProcessRunning as i32 => "badge badge-success badge-sm", + s if s == ProcessRunningState::ProcessDiconnected as i32 => "badge badge-error badge-sm", + s if s == ProcessRunningState::ProcessStarting as i32 => "badge badge-warning badge-sm", + _ => "badge badge-ghost badge-sm", + }; + let health_class = match process.health_state { + s if s == ProcessHealthState::ProcessHealthy as i32 => "badge badge-success badge-sm", + s if s == ProcessHealthState::ProcessUnhealthy as i32 => "badge badge-error badge-sm", + _ => "badge badge-ghost badge-sm", + }; - // Content - h1 { "Service Registry" } - p { "This is the service registry page. Here, we will show how to use the Dioxus service registry to manage services in our application." } + rsx! { + tr { class: "hover:bg-base-300", + td { "{process.name}" } + td { class: "font-mono text-xs", "{process.pid}" } + td { "{process.ip_address}" } + td { span { class: "{running_class}", "{running}" } } + td { span { class: "{health_class}", "{health}" } } + } + } + } + } + } + tfoot { + tr { + th { "Name" } + th { "PID" } + th { "IP Address" } + th { "Running State" } + th { "Health" } + } + } + } + } } } -} \ No newline at end of file +} diff --git a/services/core/blueprint/web-client/src/views/settings.rs b/services/core/blueprint/web-client/src/views/settings.rs new file mode 100644 index 00000000..465735f8 --- /dev/null +++ b/services/core/blueprint/web-client/src/views/settings.rs @@ -0,0 +1,251 @@ +use dioxus::prelude::*; +use gloo_timers::future::TimeoutFuture; +use draft_api::proto::core_registry_key_value_v1::{NavigationConfig, NavigationSection, NavigationItem}; +use draft_api::hook::core_registry_key_value_v1::{ + key_value_service_client::KeyValueServiceClient, + SetRequest, +}; +use prost::Message as _; +use prost_types::Any; +use tonic_web_wasm_client::Client as WasmClient; + +#[component] +pub fn Settings() -> Element { + // Shared signal provided by dashboard_layout — reading it reflects the live drawer config, + // writing it causes the drawer to re-render immediately without a page reload. + let nav_config_ctx: Signal> = use_context(); + + // Local working copy. Starts with the compile-time default; synced from context once the + // KV fetch completes (handled by the use_effect below). + let mut local_config: Signal = use_signal(crate::default_nav_config); + let mut initialized = use_signal(|| false); + let mut status: Signal> = use_signal(|| None); + + // Sync from context exactly once — when the KV fetch in dashboard_layout resolves. + use_effect(move || { + if !initialized() { + if let Some(cfg) = nav_config_ctx() { + local_config.set(cfg); + initialized.set(true); + } + } + }); + + let save = move |_| { + let config = local_config(); + let mut nav_config_ctx = nav_config_ctx; + spawn(async move { + let mut client = KeyValueServiceClient::new(WasmClient::new(crate::API_DOMAIN.clone())); + let any = Any { + type_url: crate::NAV_CONFIG_TYPE_URL.to_string(), + value: config.clone().encode_to_vec(), + }; + match client.set(SetRequest { + key: crate::NAV_CONFIG_KV_KEY.to_string(), + value: Some(any), + }).await { + Ok(_) => { + // Update the shared signal so the drawer reflects the new config immediately. + nav_config_ctx.set(Some(config)); + status.set(Some("Navigation saved.".to_string())); + spawn(async move { + TimeoutFuture::new(3_000).await; + status.set(None); + }); + } + Err(e) => status.set(Some(format!("Error: {e}"))), + } + }); + }; + + let section_count = local_config().sections.len(); + + rsx! { + div { class: "p-4 max-w-2xl", + h1 { class: "text-2xl font-bold mb-6", "Settings" } + + if let Some(msg) = status() { + div { class: "toast toast-end toast-bottom z-50", + div { class: "alert alert-success", + span { "{msg}" } + } + } + } + + // ── Navigation sub-section ──────────────────────────────────────── + div { class: "card bg-base-200 mb-4", + div { class: "card-body", + h2 { class: "card-title text-lg mb-1", "Navigation" } + p { class: "text-sm text-base-content/70 mb-4", + "Configure the sections and items shown in the navigation drawer. \ + Changes take effect immediately after saving." + } + + div { class: "space-y-3", + for (si, section) in local_config().sections.into_iter().enumerate() { + { + let section_label = section.label.clone(); + let item_count = section.items.len(); + rsx! { + div { key: "{si}", class: "border border-base-300 rounded-lg p-3", + + // Section header row + div { class: "flex items-center gap-2 mb-3", + input { + class: "input input-bordered input-sm flex-1", + value: "{section_label}", + placeholder: "Section name", + oninput: move |e| { + let mut cfg = local_config(); + cfg.sections[si].label = e.value(); + local_config.set(cfg); + }, + } + button { + class: "btn btn-xs btn-ghost", + disabled: si == 0, + title: "Move up", + onclick: move |_| { + let mut cfg = local_config(); + cfg.sections.swap(si, si - 1); + local_config.set(cfg); + }, + "↑" + } + button { + class: "btn btn-xs btn-ghost", + disabled: si == section_count - 1, + title: "Move down", + onclick: move |_| { + let mut cfg = local_config(); + cfg.sections.swap(si, si + 1); + local_config.set(cfg); + }, + "↓" + } + button { + class: "btn btn-xs btn-error btn-outline", + title: "Remove section", + onclick: move |_| { + let mut cfg = local_config(); + cfg.sections.remove(si); + local_config.set(cfg); + }, + "×" + } + } + + // Items list + div { class: "ml-3 space-y-1", + for (ii, item) in section.items.into_iter().enumerate() { + { + let item_label = item.label.clone(); + let item_path = item.path.clone(); + rsx! { + div { key: "{ii}", class: "flex items-center gap-2", + input { + class: "input input-bordered input-xs w-28", + value: "{item_label}", + placeholder: "Label", + oninput: move |e| { + let mut cfg = local_config(); + cfg.sections[si].items[ii].label = e.value(); + local_config.set(cfg); + }, + } + select { + class: "select select-bordered select-xs flex-1", + onchange: move |e| { + let mut cfg = local_config(); + cfg.sections[si].items[ii].path = e.value(); + local_config.set(cfg); + }, + for &(path, name) in crate::KNOWN_ROUTES { + option { + value: "{path}", + selected: item_path.as_str() == path, + "{name}" + } + } + } + button { + class: "btn btn-xs btn-ghost", + disabled: ii == 0, + title: "Move up", + onclick: move |_| { + let mut cfg = local_config(); + cfg.sections[si].items.swap(ii, ii - 1); + local_config.set(cfg); + }, + "↑" + } + button { + class: "btn btn-xs btn-ghost", + disabled: ii == item_count - 1, + title: "Move down", + onclick: move |_| { + let mut cfg = local_config(); + cfg.sections[si].items.swap(ii, ii + 1); + local_config.set(cfg); + }, + "↓" + } + button { + class: "btn btn-xs btn-error btn-outline", + title: "Remove item", + onclick: move |_| { + let mut cfg = local_config(); + cfg.sections[si].items.remove(ii); + local_config.set(cfg); + }, + "×" + } + } + } + } + } + + button { + class: "btn btn-xs btn-ghost mt-1", + onclick: move |_| { + let mut cfg = local_config(); + cfg.sections[si].items.push(NavigationItem { + label: "New Item".to_string(), + path: "/".to_string(), + }); + local_config.set(cfg); + }, + "+ Add Item" + } + } + } + } + } + } + } + + button { + class: "btn btn-sm btn-ghost mt-3", + onclick: move |_| { + let mut cfg = local_config(); + cfg.sections.push(NavigationSection { + label: "New Section".to_string(), + items: vec![], + }); + local_config.set(cfg); + }, + "+ Add Section" + } + + div { class: "card-actions justify-end mt-4", + button { + class: "btn btn-primary btn-sm", + onclick: save, + "Save" + } + } + } + } + } + } +} diff --git a/services/core/blueprint/web-client/src/views/store.rs b/services/core/blueprint/web-client/src/views/store.rs new file mode 100644 index 00000000..7ebb05d4 --- /dev/null +++ b/services/core/blueprint/web-client/src/views/store.rs @@ -0,0 +1,463 @@ +use dioxus::prelude::*; +use dioxus_core::Task; +use tonic_web_wasm_client::Client as WasmClient; + +use draft_api::proto::core_message_broker_actors_v1::{ + cloud_event::{cloud_event_attribute_value, Data as CloudEventData}, + query_client::QueryClient, + CloudEvent, OrderDirection, QueryRequest, +}; + +use crate::components::{CesqlBar, QueryBuilder, SortDir, TypeBadge, WaveLoader}; + +// Cap stored events so the table doesn't grow without bound. +const MAX_EVENTS: usize = 1_000; + +#[derive(Clone, PartialEq)] +enum StreamStatus { + Connecting, + Connected, + Disconnected, +} + +#[component] +pub fn Store() -> Element { + let mut expression = use_signal(String::new); + let mut streaming = use_signal(|| false); + let mut events: Signal> = use_signal(Vec::new); + let mut query_results: Signal> = use_signal(Vec::new); + let mut sort_dir: Signal = use_signal(|| SortDir::Desc); + let mut status: Signal = use_signal(|| StreamStatus::Disconnected); + let mut querying = use_signal(|| true); + // Holds the active stream task so it can be cancelled when the toggle turns off. + let mut stream_task: Signal> = use_signal(|| None); + + // Spawns a QueryStream task and stores the handle. Cancels any prior task first. + let start_stream = use_callback(move |_: ()| { + if let Some(t) = stream_task.write().take() { + t.cancel(); + } + events.set(Vec::new()); + status.set(StreamStatus::Connecting); + let host = crate::CATALYST_DOMAIN.clone(); + let task = spawn(async move { + let mut client = QueryClient::new(WasmClient::new(host)); + let stream_response = client + .query_stream(QueryRequest { + expression: None, + limit: 0, + after: String::new(), + order_by: OrderDirection::Asc as i32, + }) + .await; + let Ok(response) = stream_response else { + status.set(StreamStatus::Disconnected); + return; + }; + status.set(StreamStatus::Connected); + let mut stream = response.into_inner(); + loop { + match stream.message().await { + Ok(Some(msg)) => { + if let Some(event) = msg.event { + let mut ev = events.write(); + if ev.len() >= MAX_EVENTS { + ev.pop(); + } + ev.insert(0, event); + } + } + Ok(None) | Err(_) => { + status.set(StreamStatus::Disconnected); + break; + } + } + } + }); + stream_task.set(Some(task)); + }); + + let run_query = use_callback(move |_: ()| { + querying.set(true); + let host = crate::CATALYST_DOMAIN.clone(); + // peek() reads the current value without creating a reactive subscription, + // preventing use_effect from re-firing whenever sort_dir changes. + let order_by = match sort_dir.peek().clone() { + SortDir::Asc => OrderDirection::Asc as i32, + SortDir::Desc => OrderDirection::Desc as i32, + }; + spawn(async move { + let mut client = QueryClient::new(WasmClient::new(host)); + if let Ok(resp) = client + .query(QueryRequest { + expression: None, + limit: 0, + after: String::new(), + order_by, + }) + .await + { + query_results.set(resp.into_inner().events); + } + querying.set(false); + }); + }); + + // On first render: default is query mode, fetch historical events immediately. + use_effect(move || { + run_query.call(()); + }); + + let stream_events = events.read(); + let static_events = query_results.read(); + let all_events: &Vec = if streaming() { &stream_events } else { &static_events }; + let filter = expression.read(); + + let filtered: Vec<&CloudEvent> = all_events + .iter() + .filter(|e| matches_filter(&filter, e)) + .collect(); + + rsx! { + div { class: "p-4 flex flex-col gap-3 h-screen", + + div { class: "flex items-center gap-2", + label { class: "flex items-center gap-2 cursor-pointer select-none shrink-0", + input { + r#type: "checkbox", + class: "toggle toggle-xs toggle-primary", + checked: streaming(), + onchange: move |_| { + let was_streaming = streaming(); + streaming.toggle(); + if was_streaming { + // turned off — cancel the stream task and fetch a snapshot + if let Some(t) = stream_task.write().take() { + t.cancel(); + } + events.set(Vec::new()); + run_query.call(()); + } else { + // turned on — discard static snapshot and open the stream + query_results.set(Vec::new()); + start_stream.call(()); + } + }, + } + span { class: "text-xs text-base-content/50", "Stream" } + } + CesqlBar { + expression, + on_run: move |_| { + if !streaming() { run_query.call(()); } + }, + on_clear: move |_| { + expression.set(String::new()); + query_results.set(Vec::new()); + }, + } + } + + QueryBuilder { + has_expression: !expression.read().is_empty(), + sort_dir: sort_dir(), + on_sort_change: move |dir: SortDir| { + sort_dir.set(dir); + if !streaming() { run_query.call(()); } + }, + on_add: move |fragment: String| { + let current = expression.read().clone(); + let new_expr = if current.trim().is_empty() { + fragment + } else { + format!("{current} {fragment}") + }; + expression.set(new_expr); + }, + } + + div { class: "flex items-center gap-2", + match (streaming(), status()) { + (true, StreamStatus::Disconnected) => rsx! { + span { + class: "tooltip tooltip-right", + "data-tip": "Catalyst server disconnected", + svg { + class: "w-4 h-4 text-error", + xmlns: "http://www.w3.org/2000/svg", + view_box: "0 0 20 20", + fill: "currentColor", + path { + fill_rule: "evenodd", + clip_rule: "evenodd", + d: "M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z", + } + } + } + }, + _ => rsx! {}, + } + } + + div { class: "flex-1 overflow-auto min-h-0", + if all_events.is_empty() && (!streaming() && querying() || streaming() && status() == StreamStatus::Connecting) { + div { style: "position:fixed;top:50%;left:0;right:0;width:fit-content;margin-inline:auto;", + WaveLoader { width: 80, height: 28 } + } + } else { + table { class: "table table-xs", + thead { + tr { + th { "TIME (UTC)" } + th { "FORWARDED AT" } + th { "TYPE" } + th { "SOURCE" } + th { "SUBJECT" } + th { "ID" } + th { "BODY" } + } + } + tbody { + if filtered.is_empty() { + tr { + td { + colspan: "7", + class: "text-center text-base-content/40 py-6", + if all_events.is_empty() { "Waiting for events…" } else { "No events match the filter." } + } + } + } + for event in filtered.iter() { + { + let time = event_time(event); + let forwarded_at = event_forwarded_at(event); + let subject = event_subject(event); + let etype = event.r#type.clone(); + let source = event.source.clone(); + let id = event.id.clone(); + let body = event_text_data(event).to_string(); + rsx! { + tr { class: "hover:bg-base-300", + td { class: "font-mono text-xs text-base-content/60 whitespace-nowrap", "{time}" } + td { class: "font-mono text-xs text-base-content/60 whitespace-nowrap", "{forwarded_at}" } + td { TypeBadge { event_type: etype } } + td { class: "text-xs", "{source}" } + td { class: "font-mono text-xs", "{subject}" } + td { class: "font-mono text-xs text-base-content/40", "{id}" } + td { + class: "font-mono text-xs text-base-content/60", + style: "max-width:280px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;", + title: "{body}", + "{body}" + } + } + } + } + } + } + } + } + } + } + } +} + +// ─── Filter ─────────────────────────────────────────────────────────────────── + +// Evaluates a CESQL-subset expression against a CloudEvent. +// Supported forms: +// field = 'value' exact match (case-insensitive) +// field LIKE '%pattern%' contains (% wildcards stripped) +// body.field = 'value' JSON body field exact match +// body.field LIKE '%pattern%' JSON body field contains +// A OR B either branch matches +// A AND B both branches must match +// fallback: substring across all fields including body +fn matches_filter(filter: &str, event: &CloudEvent) -> bool { + let filter = filter.trim(); + if filter.is_empty() { + return true; + } + let lower = filter.to_lowercase(); + // OR has lower precedence — split first so AND binds tighter. + if let Some(pos) = lower.find(" or ") { + return matches_filter(&filter[..pos], event) + || matches_filter(&filter[pos + 4..], event); + } + if let Some(pos) = lower.find(" and ") { + return matches_filter(&filter[..pos], event) + && matches_filter(&filter[pos + 5..], event); + } + matches_single(filter, event) +} + +fn matches_single(filter: &str, event: &CloudEvent) -> bool { + if let Some(val) = extract_eq(filter, "type") { + return event.r#type.eq_ignore_ascii_case(&val); + } + if let Some(val) = extract_eq(filter, "source") { + return event.source.eq_ignore_ascii_case(&val); + } + if let Some(val) = extract_eq(filter, "id") { + return event.id.eq_ignore_ascii_case(&val); + } + if let Some(val) = extract_like(filter, "type") { + return event.r#type.to_lowercase().contains(&val.to_lowercase()); + } + if let Some(val) = extract_like(filter, "source") { + return event.source.to_lowercase().contains(&val.to_lowercase()); + } + if let Some(val) = extract_like(filter, "subject") { + return event_subject(event).to_lowercase().contains(&val.to_lowercase()); + } + // body.field = 'value' + if let Some((field, val)) = extract_body_eq(filter) { + let body: serde_json::Value = + serde_json::from_str(event_text_data(event)).unwrap_or_default(); + return body + .get(&field) + .map(|v| match v { + serde_json::Value::String(s) => s.eq_ignore_ascii_case(&val), + other => other.to_string().eq_ignore_ascii_case(&val), + }) + .unwrap_or(false); + } + // body.field LIKE '%pattern%' + if let Some((field, pat)) = extract_body_like(filter) { + let body: serde_json::Value = + serde_json::from_str(event_text_data(event)).unwrap_or_default(); + return body + .get(&field) + .map(|v| match v { + serde_json::Value::String(s) => s.to_lowercase().contains(&pat.to_lowercase()), + other => other.to_string().to_lowercase().contains(&pat.to_lowercase()), + }) + .unwrap_or(false); + } + // Fallback: substring across all visible fields including the JSON body. + let lf = filter.to_lowercase(); + event.r#type.to_lowercase().contains(&lf) + || event.source.to_lowercase().contains(&lf) + || event.id.to_lowercase().contains(&lf) + || event_subject(event).to_lowercase().contains(&lf) + || event_text_data(event).to_lowercase().contains(&lf) +} + +// Parses `field = 'value'` or `field = "value"`, returns the inner value. +fn extract_eq(filter: &str, field: &str) -> Option { + let lower = filter.to_lowercase(); + let field_lower = field.to_lowercase(); + let offset = if let Some(s) = lower.strip_prefix(&format!("{field_lower} =")) { + filter.len() - s.len() + } else if let Some(s) = lower.strip_prefix(&format!("{field_lower}=")) { + filter.len() - s.len() + } else { + return None; + }; + extract_quoted(&filter[offset..]).map(str::to_string) +} + +// Parses `field LIKE '%pattern%'`, returns the inner pattern with % stripped. +fn extract_like(filter: &str, field: &str) -> Option { + let lower = filter.to_lowercase(); + let prefix = format!("{} like ", field.to_lowercase()); + if !lower.starts_with(&prefix) { + return None; + } + let rest = filter[prefix.len()..].trim(); + let inner = extract_quoted(rest)?; + let stripped = inner.trim_matches('%'); + if stripped.is_empty() { None } else { Some(stripped.to_string()) } +} + +// Parses `body.field = 'value'`, returns (field_name, value). +// Field names from protojson are camelCase (e.g. "modelName", "userId"). +fn extract_body_eq(filter: &str) -> Option<(String, String)> { + let lower = filter.to_lowercase(); + if !lower.starts_with("body.") { return None; } + let rest = &filter[5..]; // after "body." + let rest_lower = rest.to_lowercase(); + let eq_pos = rest_lower.find('=')?; + // Reject if this is actually a LIKE expression. + if rest_lower[..eq_pos].contains("like") { return None; } + let field_name = rest[..eq_pos].trim().to_string(); + if field_name.is_empty() { return None; } + let after_eq = rest[eq_pos + 1..].trim(); + let val = extract_quoted(after_eq)?.to_string(); + Some((field_name, val)) +} + +// Parses `body.field LIKE '%pattern%'`, returns (field_name, pattern_without_%). +fn extract_body_like(filter: &str) -> Option<(String, String)> { + let lower = filter.to_lowercase(); + if !lower.starts_with("body.") { return None; } + let rest = &filter[5..]; + let rest_lower = rest.to_lowercase(); + let like_pos = rest_lower.find(" like ")?; + let field_name = rest[..like_pos].trim().to_string(); + if field_name.is_empty() { return None; } + let after_like = rest[like_pos + 6..].trim(); + let inner = extract_quoted(after_like)?; + let stripped = inner.trim_matches('%'); + if stripped.is_empty() { return None; } + Some((field_name, stripped.to_string())) +} + +// Returns the content inside the outermost single or double quotes. +fn extract_quoted(s: &str) -> Option<&str> { + let s = s.trim(); + if s.len() >= 2 { + if s.starts_with('\'') && s.ends_with('\'') { + return Some(&s[1..s.len() - 1]); + } + if s.starts_with('"') && s.ends_with('"') { + return Some(&s[1..s.len() - 1]); + } + } + None +} + +// ─── Helpers ────────────────────────────────────────────────────────────────── + +fn event_time(event: &CloudEvent) -> String { + if let Some(attr) = event.attributes.get("time") { + if let Some(cloud_event_attribute_value::Attr::CeTimestamp(ts)) = &attr.attr { + let dt = chrono::DateTime::from_timestamp(ts.seconds, ts.nanos as u32); + if let Some(dt) = dt { + return dt.format("%Y-%m-%d %H:%M:%S").to_string(); + } + } + if let Some(cloud_event_attribute_value::Attr::CeString(s)) = &attr.attr { + return s.clone(); + } + } + "—".to_string() +} + +fn event_forwarded_at(event: &CloudEvent) -> String { + if let Some(attr) = event.attributes.get("forwarded_at") { + if let Some(cloud_event_attribute_value::Attr::CeTimestamp(ts)) = &attr.attr { + let dt = chrono::DateTime::from_timestamp(ts.seconds, ts.nanos as u32); + if let Some(dt) = dt { + return dt.format("%Y-%m-%d %H:%M:%S").to_string(); + } + } + } + "—".to_string() +} + +fn event_text_data(event: &CloudEvent) -> &str { + match &event.data { + Some(CloudEventData::TextData(s)) => s.as_str(), + _ => "", + } +} + +fn event_subject(event: &CloudEvent) -> String { + if let Some(attr) = event.attributes.get("subject") { + if let Some(cloud_event_attribute_value::Attr::CeString(s)) = &attr.attr { + return s.clone(); + } + } + "—".to_string() +} diff --git a/services/core/blueprint/web-client/src/views/tools.rs b/services/core/blueprint/web-client/src/views/tools.rs new file mode 100644 index 00000000..96286c4b --- /dev/null +++ b/services/core/blueprint/web-client/src/views/tools.rs @@ -0,0 +1,11 @@ +use dioxus::prelude::*; + +#[component] +pub fn Tools() -> Element { + rsx! { + div { class: "p-4", + h1 { class: "text-2xl font-bold mb-4", "Tools" } + p { class: "text-base-content/60", "Automation tools will appear here." } + } + } +} diff --git a/services/core/blueprint/web-client/src/views/topology.rs b/services/core/blueprint/web-client/src/views/topology.rs new file mode 100644 index 00000000..fe369057 --- /dev/null +++ b/services/core/blueprint/web-client/src/views/topology.rs @@ -0,0 +1,107 @@ +use dioxus::prelude::*; +use tonic_web_wasm_client::Client as WasmClient; +use draft_api::proto::core_message_broker_actors_v1::{ + query_client::QueryClient, + topology_client::TopologyClient, + CloudEvent, GetTopologyResponse, GetTopologyRequest, + OrderDirection, QueryRequest, WatchTopologyRequest, +}; +use crate::components::{FullCircle, TopologyData, TopologyNode, TopologyEdge, WaveLoader}; + +fn topology_from_response(resp: GetTopologyResponse) -> TopologyData { + let producers = resp.producers.into_iter() + .map(|n| TopologyNode { + id: n.id.clone(), + name: if n.name.is_empty() { n.id } else { n.name }, + }) + .collect(); + let consumers = resp.consumers.into_iter() + .map(|n| TopologyNode { + id: n.id.clone(), + name: if n.name.is_empty() { n.id } else { n.name }, + }) + .collect(); + let edges = resp.edges.into_iter() + .map(|e| TopologyEdge { + producer_id: e.producer_source, + consumer_id: e.consumer_source, + event_type: e.event_type, + vol: e.vol, + }) + .collect(); + TopologyData { producers, consumers, edges } +} + +// Fallback: derive producers from raw event source fields when GetTopology is unavailable. +fn topology_from_events(events: &[CloudEvent]) -> TopologyData { + let mut producers: Vec = Vec::new(); + for ev in events { + if !ev.source.is_empty() && !producers.iter().any(|p| p.id == ev.source) { + producers.push(TopologyNode { id: ev.source.clone(), name: ev.source.clone() }); + } + } + producers.sort_by(|a, b| a.id.cmp(&b.id)); + TopologyData { producers, consumers: vec![], edges: vec![] } +} + +#[component] +pub fn Topology() -> Element { + let mut data: Signal = use_signal(TopologyData::default); + let mut loading = use_signal(|| true); + + use_effect(move || { + // Task 1: GetTopology snapshot — producers + consumers + edges with server-computed vol. + // Falls back to QueryClient history if the Topology RPC is unavailable. + let host = crate::CATALYST_DOMAIN.clone(); + spawn(async move { + let mut client = TopologyClient::new(WasmClient::new(host.clone())); + match client.get_topology(GetTopologyRequest {}).await { + Ok(resp) => data.set(topology_from_response(resp.into_inner())), + Err(_) => { + let mut qclient = QueryClient::new(WasmClient::new(host)); + if let Ok(resp) = qclient.query(QueryRequest { + expression: None, + limit: 0, + after: String::new(), + order_by: OrderDirection::Desc as i32, + }).await { + data.set(topology_from_events(&resp.into_inner().events)); + } + } + } + loading.set(false); + }); + + // Task 2: WatchTopology — re-fetch the full snapshot on any topology change. + let host = crate::CATALYST_DOMAIN.clone(); + spawn(async move { + let mut client = TopologyClient::new(WasmClient::new(host.clone())); + let Ok(resp) = client.watch_topology(WatchTopologyRequest {}).await else { return; }; + let mut stream = resp.into_inner(); + loop { + match stream.message().await { + Ok(Some(_)) => { + let mut refresh = TopologyClient::new(WasmClient::new(host.clone())); + if let Ok(r) = refresh.get_topology(GetTopologyRequest {}).await { + data.set(topology_from_response(r.into_inner())); + } + } + Ok(None) | Err(_) => break, + } + } + }); + }); + + rsx! { + div { + style: "width:100%;height:calc(100dvh - 4rem);overflow:hidden;background:#080808;", + if loading() { + div { style: "position:fixed;top:50%;left:0;right:0;width:fit-content;margin-inline:auto;", + WaveLoader { width: 80, height: 28 } + } + } else { + FullCircle { data: data() } + } + } + } +} diff --git a/services/core/blueprint/web-client/target/.rustc_info.json b/services/core/blueprint/web-client/target/.rustc_info.json deleted file mode 100644 index b9eb30f2..00000000 --- a/services/core/blueprint/web-client/target/.rustc_info.json +++ /dev/null @@ -1 +0,0 @@ -{"rustc_fingerprint":6246323488554177982,"outputs":{"13331785392996375709":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/andrew/.rustup/toolchains/stable-aarch64-apple-darwin\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"11447291655969039981":{"success":true,"status":"","code":0,"stdout":"___.wasm\nlib___.rlib\n___.wasm\nlib___.a\n/Users/andrew/.rustup/toolchains/stable-aarch64-apple-darwin\noff\n___\ndebug_assertions\npanic=\"abort\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"wasm32\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"wasm\"\ntarget_feature=\"multivalue\"\ntarget_feature=\"mutable-globals\"\ntarget_feature=\"reference-types\"\ntarget_feature=\"sign-ext\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"unknown\"\ntarget_pointer_width=\"32\"\ntarget_vendor=\"unknown\"\n","stderr":"warning: dropping unsupported crate type `dylib` for target `wasm32-unknown-unknown`\n\nwarning: dropping unsupported crate type `proc-macro` for target `wasm32-unknown-unknown`\n\nwarning: 2 warnings emitted\n\n"},"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.85.0 (4d91de4e4 2025-02-17)\nbinary: rustc\ncommit-hash: 4d91de4e48198da2e33413efdcd9cd2cc0c46688\ncommit-date: 2025-02-17\nhost: aarch64-apple-darwin\nrelease: 1.85.0\nLLVM version: 19.1.7\n","stderr":""}},"successes":{}} \ No newline at end of file diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/.cli-version b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/.cli-version deleted file mode 100644 index 724d8b1c..00000000 --- a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/.cli-version +++ /dev/null @@ -1 +0,0 @@ -0.6.3 (was built without git repository) \ No newline at end of file diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/.gitkeep b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa-26b188856e373044.js b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa-26b188856e373044.js deleted file mode 100644 index 66c6f823..00000000 --- a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa-26b188856e373044.js +++ /dev/null @@ -1,2 +0,0 @@ -function setAttributeInner(node,field,value,ns){if(ns==="style"){node.style.setProperty(field,value);return;}if(ns){node.setAttributeNS(ns,field,value);return;}switch(field){case"value":if(node.value!==value)node.value=value;break;case"initial_value":node.defaultValue=value;break;case"checked":node.checked=truthy(value);break;case"initial_checked":node.defaultChecked=truthy(value);break;case"selected":node.selected=truthy(value);break;case"initial_selected":node.defaultSelected=truthy(value);break;case"dangerous_inner_html":node.innerHTML=value;break;default:if(!truthy(value)&&isBoolAttr(field))node.removeAttribute(field);else node.setAttribute(field,value);}}var truthy=function(val){return val==="true"||val===!0;},isBoolAttr=function(field){switch(field){case"allowfullscreen":case"allowpaymentrequest":case"async":case"autofocus":case"autoplay":case"checked":case"controls":case"default":case"defer":case"disabled":case"formnovalidate":case"hidden":case"ismap":case"itemscope":case"loop":case"multiple":case"muted":case"nomodule":case"novalidate":case"open":case"playsinline":case"readonly":case"required":case"reversed":case"selected":case"truespeed":case"webkitdirectory":return!0;default:return!1;}};class BaseInterpreter{global;local;root;handler;resizeObserver;intersectionObserver;nodes;stack;templates;m;constructor(){}initialize(root,handler=null){this.global={},this.local={},this.root=root,this.nodes=[root],this.stack=[root],this.templates={},this.handler=handler,root.setAttribute("data-dioxus-id","0");}handleResizeEvent(entry){const target=entry.target;let event=new CustomEvent("resize",{bubbles:!1,detail:entry});target.dispatchEvent(event);}createResizeObserver(element){if(!this.resizeObserver)this.resizeObserver=new ResizeObserver(entries=>{for(let entry of entries)this.handleResizeEvent(entry);});this.resizeObserver.observe(element);}removeResizeObserver(element){if(this.resizeObserver)this.resizeObserver.unobserve(element);}handleIntersectionEvent(entry){const target=entry.target;let event=new CustomEvent("visible",{bubbles:!1,detail:entry});target.dispatchEvent(event);}createIntersectionObserver(element){if(!this.intersectionObserver)this.intersectionObserver=new IntersectionObserver(entries=>{for(let entry of entries)this.handleIntersectionEvent(entry);});this.intersectionObserver.observe(element);}removeIntersectionObserver(element){if(this.intersectionObserver)this.intersectionObserver.unobserve(element);}createListener(event_name,element,bubbles){if(event_name=="resize")this.createResizeObserver(element);else if(event_name=="visible")this.createIntersectionObserver(element);if(bubbles)if(this.global[event_name]===void 0)this.global[event_name]={active:1,callback:this.handler},this.root.addEventListener(event_name,this.handler);else this.global[event_name].active++;else{const id=element.getAttribute("data-dioxus-id");if(!this.local[id])this.local[id]={};element.addEventListener(event_name,this.handler);}}removeListener(element,event_name,bubbles){if(event_name=="resize")this.removeResizeObserver(element);else if(event_name=="visible")this.removeIntersectionObserver(element);else if(bubbles)this.removeBubblingListener(event_name);else this.removeNonBubblingListener(element,event_name);}removeBubblingListener(event_name){if(this.global[event_name].active--,this.global[event_name].active===0)this.root.removeEventListener(event_name,this.global[event_name].callback),delete this.global[event_name];}removeNonBubblingListener(element,event_name){const id=element.getAttribute("data-dioxus-id");if(delete this.local[id][event_name],Object.keys(this.local[id]).length===0)delete this.local[id];element.removeEventListener(event_name,this.handler);}removeAllNonBubblingListeners(element){const id=element.getAttribute("data-dioxus-id");delete this.local[id];}getNode(id){return this.nodes[id];}pushRoot(node){this.stack.push(node);}appendChildren(id,many){const root=this.nodes[id],els=this.stack.splice(this.stack.length-many);for(let k=0;k0;end--)node=node.nextSibling;}return node;}saveTemplate(nodes,tmpl_id){this.templates[tmpl_id]=nodes;}hydrate_node(hydrateNode,ids){const split=hydrateNode.getAttribute("data-node-hydration").split(","),id=ids[parseInt(split[0])];if(this.nodes[id]=hydrateNode,split.length>1){hydrateNode.listening=split.length-1,hydrateNode.setAttribute("data-dioxus-id",id.toString());for(let j=1;j{if(!treeWalker.nextNode())return!1;return treeWalker.currentNode!==nextSibling;};while(treeWalker.currentNode){const currentNode=treeWalker.currentNode;if(currentNode.nodeType===Node.COMMENT_NODE){const id=currentNode.textContent,placeholderSplit=id.split("placeholder");if(placeholderSplit.length>1){if(this.nodes[ids[parseInt(placeholderSplit[1])]]=currentNode,!continueToNextNode())break;continue;}const textNodeSplit=id.split("node-id");if(textNodeSplit.length>1){let next=currentNode.nextSibling;currentNode.remove();let commentAfterText,textNode;if(next.nodeType===Node.COMMENT_NODE){const newText=next.parentElement.insertBefore(document.createTextNode(""),next);commentAfterText=next,textNode=newText;}else textNode=next,commentAfterText=textNode.nextSibling;treeWalker.currentNode=commentAfterText,this.nodes[ids[parseInt(textNodeSplit[1])]]=textNode;let exit=currentNode===under||!continueToNextNode();if(commentAfterText.remove(),exit)break;continue;}}if(!continueToNextNode())break;}}}setAttributeInner(node,field,value,ns){setAttributeInner(node,field,value,ns);}}let field,many,ns,bubbles,id;class RawInterpreter extends BaseInterpreter{constructor(r){super();this.d=r;this.m=null;this.p=null;this.ls=null;this.t=null;this.op=null;this.e=null;this.z=null;this.metaflags=null;this.namespace=[];this.namespace_cache_hit=null;this.namespace_cache_idx;this.get_namespace=function(){this.namespace_cache_idx=this.u8buf[this.u8bufp++];if(this.namespace_cache_idx&128){this.namespace_cache_hit=this.s.substring(this.sp,this.sp+=this.u8buf[this.u8bufp++]);this.namespace[this.namespace_cache_idx&0xffffff7f]=this.namespace_cache_hit;return this.namespace_cache_hit;}else{return this.namespace[this.namespace_cache_idx&0xffffff7f];}};this.u8buf=null;this.u8bufp=null;this.evt=[];this.evt_cache_hit=null;this.evt_cache_idx;this.get_evt=function(){this.evt_cache_idx=this.u8buf[this.u8bufp++];if(this.evt_cache_idx&128){this.evt_cache_hit=this.s.substring(this.sp,this.sp+=this.u8buf[this.u8bufp++]);this.evt[this.evt_cache_idx&0xffffff7f]=this.evt_cache_hit;return this.evt_cache_hit;}else{return this.evt[this.evt_cache_idx&0xffffff7f];}};this.u16buf=null;this.u16bufp=null;this.el=[];this.el_cache_hit=null;this.el_cache_idx;this.get_el=function(){this.el_cache_idx=this.u8buf[this.u8bufp++];if(this.el_cache_idx&128){this.el_cache_hit=this.s.substring(this.sp,this.sp+=this.u8buf[this.u8bufp++]);this.el[this.el_cache_idx&0xffffff7f]=this.el_cache_hit;return this.el_cache_hit;}else{return this.el[this.el_cache_idx&0xffffff7f];}};this.attr=[];this.attr_cache_hit=null;this.attr_cache_idx;this.get_attr=function(){this.attr_cache_idx=this.u8buf[this.u8bufp++];if(this.attr_cache_idx&128){this.attr_cache_hit=this.s.substring(this.sp,this.sp+=this.u8buf[this.u8bufp++]);this.attr[this.attr_cache_idx&0xffffff7f]=this.attr_cache_hit;return this.attr_cache_hit;}else{return this.attr[this.attr_cache_idx&0xffffff7f];}};this.s="";this.lsp=null;this.sp=null;this.sl=null;this.c=new TextDecoder;this.u32buf=null;this.u32bufp=null;this.ns_cache=[];this.ns_cache_cache_hit=null;this.ns_cache_cache_idx;this.get_ns_cache=function(){this.ns_cache_cache_idx=this.u8buf[this.u8bufp++];if(this.ns_cache_cache_idx&128){this.ns_cache_cache_hit=this.s.substring(this.sp,this.sp+=this.u8buf[this.u8bufp++]);this.ns_cache[this.ns_cache_cache_idx&0xffffff7f]=this.ns_cache_cache_hit;return this.ns_cache_cache_hit;}else{return this.ns_cache[this.ns_cache_cache_idx&0xffffff7f];}};}update_memory(b){this.m=new DataView(b.buffer);}run(){this.metaflags=this.m.getUint32(this.d,true);if(this.metaflags>>>6&1){this.ls=this.m.getUint32(this.d+6*4,true);}this.p=this.ls;if(this.metaflags>>>5&1){this.t=this.m.getUint32(this.d+5*4,true);this.u8buf=new Uint8Array(this.m.buffer,this.t,(this.m.buffer.byteLength-this.t-(this.m.buffer.byteLength-this.t)%1)/1);}this.u8bufp=0;if(this.metaflags>>>4&1){this.t=this.m.getUint32(this.d+4*4,true);this.u16buf=new Uint16Array(this.m.buffer,this.t,(this.m.buffer.byteLength-this.t-(this.m.buffer.byteLength-this.t)%2)/2);}this.u16bufp=0;if(this.metaflags&1){this.lsp=this.m.getUint32(this.d+1*4,true);}if(this.metaflags>>>2&1){this.sl=this.m.getUint32(this.d+2*4,true);if(this.metaflags>>>1&1){this.sp=this.lsp;this.s="";this.e=this.sp+(this.sl/4|0)*4;while(this.sp>8,(this.t&0xff0000)>>16,this.t>>24);this.sp+=4;}while(this.sp>>3&1){this.t=this.m.getUint32(this.d+3*4,true);this.u32buf=new Uint32Array(this.m.buffer,this.t,(this.m.buffer.byteLength-this.t-(this.m.buffer.byteLength-this.t)%4)/4);}this.u32bufp=0;for(;;){this.op=this.m.getUint32(this.p,true);this.p+=4;this.z=0;while(this.z++<4){switch(this.op&255){case 0:{this.pushRoot(this.nodes[this.u32buf[this.u32bufp++]]);}break;case 1:{this.appendChildren(this.u32buf[this.u32bufp++],this.u16buf[this.u16bufp++]);}break;case 2:{this.stack.pop();}break;case 3:{const root=this.nodes[this.u32buf[this.u32bufp++]];let els=this.stack.splice(this.stack.length-this.u16buf[this.u16bufp++]);if(root.listening){this.removeAllNonBubblingListeners(root);}root.replaceWith(...els);}break;case 4:{let node=this.nodes[this.u32buf[this.u32bufp++]];node.after(...this.stack.splice(this.stack.length-this.u16buf[this.u16bufp++]));}break;case 5:{let node=this.nodes[this.u32buf[this.u32bufp++]];node.before(...this.stack.splice(this.stack.length-this.u16buf[this.u16bufp++]));}break;case 6:{let node=this.nodes[this.u32buf[this.u32bufp++]];if(node!==undefined){if(node.listening){this.removeAllNonBubblingListeners(node);}node.remove();}}break;case 7:{this.stack.push(document.createTextNode(this.s.substring(this.sp,this.sp+=this.u32buf[this.u32bufp++])));}break;case 8:{let node=document.createTextNode(this.s.substring(this.sp,this.sp+=this.u32buf[this.u32bufp++]));this.nodes[this.u32buf[this.u32bufp++]]=node;this.stack.push(node);}break;case 9:{let node=document.createComment("placeholder");this.stack.push(node);this.nodes[this.u32buf[this.u32bufp++]]=node;}break;case 10:id=this.u32buf[this.u32bufp++];const node=this.nodes[id];if(node.listening){node.listening+=1;}else{node.listening=1;}node.setAttribute("data-dioxus-id",`${id}`);this.createListener(this.get_evt(),node,this.u8buf[this.u8bufp++]);break;case 11:{let node=this.nodes[this.u32buf[this.u32bufp++]];node.listening-=1;node.removeAttribute("data-dioxus-id");this.removeListener(node,this.get_evt(),this.u8buf[this.u8bufp++]);}break;case 12:{this.nodes[this.u32buf[this.u32bufp++]].textContent=this.s.substring(this.sp,this.sp+=this.u32buf[this.u32bufp++]);}break;case 13:{let node=this.nodes[this.u32buf[this.u32bufp++]];this.setAttributeInner(node,this.get_attr(),this.s.substring(this.sp,this.sp+=this.u32buf[this.u32bufp++]),this.get_ns_cache());}break;case 14:field=this.get_attr();ns=this.get_ns_cache();{let node=this.nodes[this.u32buf[this.u32bufp++]];if(!ns){switch(field){case"value":node.value="";node.removeAttribute("value");break;case"checked":node.checked=false;break;case"selected":node.selected=false;break;case"dangerous_inner_html":node.innerHTML="";break;default:node.removeAttribute(field);break;}}else if(ns=="style"){node.style.removeProperty(field);}else{node.removeAttributeNS(ns,field);}}break;case 15:{this.nodes[this.u32buf[this.u32bufp++]]=this.loadChild(this.u32buf[this.u32bufp++],this.u8buf[this.u8bufp++]);}break;case 16:{let els=this.stack.splice(this.stack.length-this.u16buf[this.u16bufp++]);let node=this.loadChild(this.u32buf[this.u32bufp++],this.u8buf[this.u8bufp++]);node.replaceWith(...els);}break;case 17:{let node=this.templates[this.u16buf[this.u16bufp++]][this.u16buf[this.u16bufp++]].cloneNode(true);this.nodes[this.u32buf[this.u32bufp++]]=node;this.stack.push(node);}break;case 18:many=this.u16buf[this.u16bufp++];{let root=this.stack[this.stack.length-many-1];let els=this.stack.splice(this.stack.length-many);for(let k=0;k{this.handler(event,event_name,bubbles);});}break;case 25:{this.nodes[this.u32buf[this.u32bufp++]]=this.loadChild((()=>{this.e=this.u8bufp+this.u32buf[this.u32bufp++];const final_array=this.u8buf.slice(this.u8bufp,this.e);this.u8bufp=this.e;return final_array;})());}break;case 26:{let els=this.stack.splice(this.stack.length-this.u16buf[this.u16bufp++]);let node=this.loadChild((()=>{this.e=this.u8bufp+this.u32buf[this.u32bufp++];const final_array=this.u8buf.slice(this.u8bufp,this.e);this.u8bufp=this.e;return final_array;})());node.replaceWith(...els);}break;case 27:return true;}this.op>>>=8;}}}run_from_bytes(bytes){this.d=0;this.update_memory(new Uint8Array(bytes));this.run();}}function setAttributeInner1(node,field,value,ns){if(ns==="style"){node.style.setProperty(field,value);return;}if(ns){node.setAttributeNS(ns,field,value);return;}switch(field){case"value":if(node.value!==value)node.value=value;break;case"initial_value":node.defaultValue=value;break;case"checked":node.checked=truthy1(value);break;case"initial_checked":node.defaultChecked=truthy1(value);break;case"selected":node.selected=truthy1(value);break;case"initial_selected":node.defaultSelected=truthy1(value);break;case"dangerous_inner_html":node.innerHTML=value;break;default:if(!truthy1(value)&&isBoolAttr1(field))node.removeAttribute(field);else node.setAttribute(field,value);}}var truthy1=function(val){return val==="true"||val===!0;},isBoolAttr1=function(field){switch(field){case"allowfullscreen":case"allowpaymentrequest":case"async":case"autofocus":case"autoplay":case"checked":case"controls":case"default":case"defer":case"disabled":case"formnovalidate":case"hidden":case"ismap":case"itemscope":case"loop":case"multiple":case"muted":case"nomodule":case"novalidate":case"open":case"playsinline":case"readonly":case"required":case"reversed":case"selected":case"truespeed":case"webkitdirectory":return!0;default:return!1;}};function get_select_data(select){let values=[];for(let i=0;i0){this.waiting.shift()(data);return;}this.pending.push(data);}async recv(){return new Promise((resolve,_reject)=>{if(this.pending.length>0){resolve(this.pending.shift());return;}this.waiting.push(resolve);});}}class WeakDioxusChannel{inner;constructor(channel){this.inner=new WeakRef(channel);}rustSend(data){let channel=this.inner.deref();if(channel)channel.rustSend(data);}async rustRecv(){let channel=this.inner.deref();if(channel)return await channel.rustRecv();}}class DioxusChannel{weak(){return new WeakDioxusChannel(this);}}class WebDioxusChannel extends DioxusChannel{js_to_rust;rust_to_js;owner;constructor(owner){super();this.owner=owner,this.js_to_rust=new Channel,this.rust_to_js=new Channel;}weak(){return new WeakDioxusChannel(this);}async recv(){return await this.rust_to_js.recv();}send(data){this.js_to_rust.send(data);}rustSend(data){this.rust_to_js.send(data);}async rustRecv(){return await this.js_to_rust.recv();}}function get_form_data(form){let values=new Map;const formData=new FormData(form);for(let name of formData.keys()){values.set(name,formData.getAll(name));}return values;}const mod={get_form_data:get_form_data};const importMeta={url:"/Users/andrew/Projects/steady-bytes/draft/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/wasm-bindgen/blueprint-pwa.js",main:import.meta.main};let wasm;let WASM_VECTOR_LEN=0;let cachedUint8ArrayMemory0=null;function getUint8ArrayMemory0(){if(cachedUint8ArrayMemory0===null||cachedUint8ArrayMemory0.byteLength===0){cachedUint8ArrayMemory0=new Uint8Array(wasm.memory.buffer);}return cachedUint8ArrayMemory0;}const cachedTextEncoder=typeof TextEncoder!=="undefined"?new TextEncoder("utf-8"):{encode:()=>{throw Error("TextEncoder not available");}};const encodeString=typeof cachedTextEncoder.encodeInto==="function"?function(arg,view){return cachedTextEncoder.encodeInto(arg,view);}:function(arg,view){const buf=cachedTextEncoder.encode(arg);view.set(buf);return{read:arg.length,written:buf.length};};function passStringToWasm0(arg,malloc,realloc){if(realloc===undefined){const buf=cachedTextEncoder.encode(arg);const ptr=malloc(buf.length,1)>>>0;getUint8ArrayMemory0().subarray(ptr,ptr+buf.length).set(buf);WASM_VECTOR_LEN=buf.length;return ptr;}let len=arg.length;let ptr=malloc(len,1)>>>0;const mem=getUint8ArrayMemory0();let offset=0;for(;offset127)break;mem[ptr+offset]=code;}if(offset!==len){if(offset!==0){arg=arg.slice(offset);}ptr=realloc(ptr,len,len=offset+arg.length*3,1)>>>0;const view=getUint8ArrayMemory0().subarray(ptr+offset,ptr+len);const ret=encodeString(arg,view);offset+=ret.written;ptr=realloc(ptr,len,offset,1)>>>0;}WASM_VECTOR_LEN=offset;return ptr;}let cachedDataViewMemory0=null;function getDataViewMemory0(){if(cachedDataViewMemory0===null||cachedDataViewMemory0.buffer.detached===true||cachedDataViewMemory0.buffer.detached===undefined&&cachedDataViewMemory0.buffer!==wasm.memory.buffer){cachedDataViewMemory0=new DataView(wasm.memory.buffer);}return cachedDataViewMemory0;}const cachedTextDecoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-8",{ignoreBOM:true,fatal:true}):{decode:()=>{throw Error("TextDecoder not available");}};if(typeof TextDecoder!=="undefined"){cachedTextDecoder.decode();}function getStringFromWasm0(ptr,len){ptr=ptr>>>0;return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr,ptr+len));}function addToExternrefTable0(obj){const idx=wasm.__externref_table_alloc();wasm.__wbindgen_export_4.set(idx,obj);return idx;}function handleError(f,args){try{return f.apply(this,args);}catch(e){const idx=addToExternrefTable0(e);wasm.__wbindgen_exn_store(idx);}}function isLikeNone(x){return x===undefined||x===null;}function passArrayJsValueToWasm0(array,malloc){const ptr=malloc(array.length*4,4)>>>0;for(let i=0;i>>0;const mem=getDataViewMemory0();const result=[];for(let i=ptr;i{},unregister:()=>{}}:new FinalizationRegistry(state=>{wasm.__wbindgen_export_7.get(state.dtor)(state.a,state.b);});function makeMutClosure(arg0,arg1,dtor,f){const state={a:arg0,b:arg1,cnt:1,dtor};const real=(...args)=>{state.cnt++;const a=state.a;state.a=0;try{return f(a,state.b,...args);}finally{if(--state.cnt===0){wasm.__wbindgen_export_7.get(state.dtor)(a,state.b);CLOSURE_DTORS.unregister(state);}else{state.a=a;}}};real.original=state;CLOSURE_DTORS.register(real,state,state);return real;}function makeClosure(arg0,arg1,dtor,f){const state={a:arg0,b:arg1,cnt:1,dtor};const real=(...args)=>{state.cnt++;try{return f(state.a,state.b,...args);}finally{if(--state.cnt===0){wasm.__wbindgen_export_7.get(state.dtor)(state.a,state.b);state.a=0;CLOSURE_DTORS.unregister(state);}}};real.original=state;CLOSURE_DTORS.register(real,state,state);return real;}function debugString(val){const type=typeof val;if(type=="number"||type=="boolean"||val==null){return`${val}`;}if(type=="string"){return`"${val}"`;}if(type=="symbol"){const description=val.description;if(description==null){return"Symbol";}else{return`Symbol(${description})`;}}if(type=="function"){const name=val.name;if(typeof name=="string"&&name.length>0){return`Function(${name})`;}else{return"Function";}}if(Array.isArray(val)){const length=val.length;let debug="[";if(length>0){debug+=debugString(val[0]);}for(let i=1;i1){className=builtInMatches[1];}else{return toString.call(val);}if(className=="Object"){try{return"Object("+JSON.stringify(val)+")";}catch(_){return"Object";}}if(val instanceof Error){return`${val.name}: ${val.message} -${val.stack}`;}return className;}function __wbg_adapter_50(arg0,arg1){wasm._ZN132__LT_dyn_u20_core__ops__function__FnMut_LT__LP__RP__GT__u2b_Output_u20__u3d__u20_R_u20_as_u20_wasm_bindgen__closure__WasmClosure_GT_8describe6invoke17h6ac0c02543bfd8dcE(arg0,arg1);}function __wbg_adapter_53(arg0,arg1){wasm._ZN132__LT_dyn_u20_core__ops__function__FnMut_LT__LP__RP__GT__u2b_Output_u20__u3d__u20_R_u20_as_u20_wasm_bindgen__closure__WasmClosure_GT_8describe6invoke17h20b85583f7a8d057E(arg0,arg1);}function __wbg_adapter_56(arg0,arg1,arg2){wasm.closure345_externref_shim(arg0,arg1,arg2);}function __wbg_adapter_59(arg0,arg1,arg2){wasm.closure349_externref_shim(arg0,arg1,arg2);}function __wbg_adapter_62(arg0,arg1,arg2){wasm.closure675_externref_shim(arg0,arg1,arg2);}const __wbindgen_enum_RequestCredentials=["omit","same-origin","include"];const __wbindgen_enum_RequestMode=["same-origin","no-cors","cors","navigate"];const __wbindgen_enum_ScrollBehavior=["auto","instant","smooth"];const __wbindgen_enum_ScrollRestoration=["auto","manual"];const JSOwnerFinalization=typeof FinalizationRegistry==="undefined"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(ptr=>wasm.__wbg_jsowner_free(ptr>>>0,1));class JSOwner{static __wrap(ptr){ptr=ptr>>>0;const obj=Object.create(JSOwner.prototype);obj.__wbg_ptr=ptr;JSOwnerFinalization.register(obj,obj.__wbg_ptr,obj);return obj;}__destroy_into_raw(){const ptr=this.__wbg_ptr;this.__wbg_ptr=0;JSOwnerFinalization.unregister(this);return ptr;}free(){const ptr=this.__destroy_into_raw();wasm.__wbg_jsowner_free(ptr,0);}}async function __wbg_load(module,imports){if(typeof Response==="function"&&module instanceof Response){if(typeof WebAssembly.instantiateStreaming==="function"){try{return await WebAssembly.instantiateStreaming(module,imports);}catch(e){if(module.headers.get("Content-Type")!="application/wasm"){console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",e);}else{throw e;}}}const bytes=await module.arrayBuffer();return await WebAssembly.instantiate(bytes,imports);}else{const instance=await WebAssembly.instantiate(module,imports);if(instance instanceof WebAssembly.Instance){return{instance,module};}else{return instance;}}}function __wbg_get_imports(){const imports={};imports.wbg={};imports.wbg.__wbg_String_eecc4a11987127d6=function(arg0,arg1){const ret=String(arg1);const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_abort_410ec47a64ac6117=function(arg0,arg1){arg0.abort(arg1);};imports.wbg.__wbg_abort_775ef1d17fc65868=function(arg0){arg0.abort();};imports.wbg.__wbg_addEventListener_90e553fdce254421=function(){return handleError(function(arg0,arg1,arg2,arg3){arg0.addEventListener(getStringFromWasm0(arg1,arg2),arg3);},arguments);};imports.wbg.__wbg_altKey_c33c03aed82e4275=function(arg0){const ret=arg0.altKey;return ret;};imports.wbg.__wbg_altKey_d7495666df921121=function(arg0){const ret=arg0.altKey;return ret;};imports.wbg.__wbg_altKey_e86f36ea33b3de8b=function(arg0){const ret=arg0.altKey;return ret;};imports.wbg.__wbg_animationName_e8ef6512e25f6a3b=function(arg0,arg1){const ret=arg1.animationName;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_appendChild_8204974b7328bf98=function(){return handleError(function(arg0,arg1){const ret=arg0.appendChild(arg1);return ret;},arguments);};imports.wbg.__wbg_append_8c7dd8d641a5f01b=function(){return handleError(function(arg0,arg1,arg2,arg3,arg4){arg0.append(getStringFromWasm0(arg1,arg2),getStringFromWasm0(arg3,arg4));},arguments);};imports.wbg.__wbg_arrayBuffer_d1b44c4390db422f=function(){return handleError(function(arg0){const ret=arg0.arrayBuffer();return ret;},arguments);};imports.wbg.__wbg_back_2ed2050faebe67d8=function(){return handleError(function(arg0){arg0.back();},arguments);};imports.wbg.__wbg_blockSize_1490803190b57a34=function(arg0){const ret=arg0.blockSize;return ret;};imports.wbg.__wbg_blur_c2ad8cc71bac3974=function(){return handleError(function(arg0){arg0.blur();},arguments);};imports.wbg.__wbg_borderBoxSize_accab6f99ed79aad=function(arg0){const ret=arg0.borderBoxSize;return ret;};imports.wbg.__wbg_boundingClientRect_03be67107f632a97=function(arg0){const ret=arg0.boundingClientRect;return ret;};imports.wbg.__wbg_bubbles_afd8dd1d14b05aba=function(arg0){const ret=arg0.bubbles;return ret;};imports.wbg.__wbg_buffer_609cc3eee51ed158=function(arg0){const ret=arg0.buffer;return ret;};imports.wbg.__wbg_button_f75c56aec440ea04=function(arg0){const ret=arg0.button;return ret;};imports.wbg.__wbg_buttons_b6346af6f04e4686=function(arg0){const ret=arg0.buttons;return ret;};imports.wbg.__wbg_call_672a4d21634d4a24=function(){return handleError(function(arg0,arg1){const ret=arg0.call(arg1);return ret;},arguments);};imports.wbg.__wbg_call_7cccdd69e0791ae2=function(){return handleError(function(arg0,arg1,arg2){const ret=arg0.call(arg1,arg2);return ret;},arguments);};imports.wbg.__wbg_changedTouches_3654bea4294f2e86=function(arg0){const ret=arg0.changedTouches;return ret;};imports.wbg.__wbg_charCodeAt_abe5953e37f4b5a6=function(arg0,arg1){const ret=arg0.charCodeAt(arg1>>>0);return ret;};imports.wbg.__wbg_checked_0591091c28a685f0=function(arg0){const ret=arg0.checked;return ret;};imports.wbg.__wbg_clearTimeout_86721db0036bea98=function(arg0){const ret=clearTimeout(arg0);return ret;};imports.wbg.__wbg_clientX_5eb380a5f1fec6fd=function(arg0){const ret=arg0.clientX;return ret;};imports.wbg.__wbg_clientX_687c1a16e03e1f58=function(arg0){const ret=arg0.clientX;return ret;};imports.wbg.__wbg_clientY_78d0605ac74642c2=function(arg0){const ret=arg0.clientY;return ret;};imports.wbg.__wbg_clientY_d8b9c7f0c4e2e677=function(arg0){const ret=arg0.clientY;return ret;};imports.wbg.__wbg_code_459c120478e1ab6e=function(arg0,arg1){const ret=arg1.code;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_contentBoxSize_638692469db816f2=function(arg0){const ret=arg0.contentBoxSize;return ret;};imports.wbg.__wbg_createComment_8b540d4b9d22f212=function(arg0,arg1,arg2){const ret=arg0.createComment(getStringFromWasm0(arg1,arg2));return ret;};imports.wbg.__wbg_createElementNS_914d752e521987da=function(){return handleError(function(arg0,arg1,arg2,arg3,arg4){const ret=arg0.createElementNS(arg1===0?undefined:getStringFromWasm0(arg1,arg2),getStringFromWasm0(arg3,arg4));return ret;},arguments);};imports.wbg.__wbg_createElement_8c9931a732ee2fea=function(){return handleError(function(arg0,arg1,arg2){const ret=arg0.createElement(getStringFromWasm0(arg1,arg2));return ret;},arguments);};imports.wbg.__wbg_createTextNode_42af1a9f21bb3360=function(arg0,arg1,arg2){const ret=arg0.createTextNode(getStringFromWasm0(arg1,arg2));return ret;};imports.wbg.__wbg_ctrlKey_1e826e468105ac11=function(arg0){const ret=arg0.ctrlKey;return ret;};imports.wbg.__wbg_ctrlKey_cdbe8154dfb00d1f=function(arg0){const ret=arg0.ctrlKey;return ret;};imports.wbg.__wbg_ctrlKey_fb23aad8b73f7459=function(arg0){const ret=arg0.ctrlKey;return ret;};imports.wbg.__wbg_dataTransfer_86283b0702a1aff1=function(arg0){const ret=arg0.dataTransfer;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_data_e77bd5c125ecc8a8=function(arg0,arg1){const ret=arg1.data;var ptr1=isLikeNone(ret)?0:passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);var len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_deltaMode_9bfd9fe3f6b4b240=function(arg0){const ret=arg0.deltaMode;return ret;};imports.wbg.__wbg_deltaX_5c1121715746e4b7=function(arg0){const ret=arg0.deltaX;return ret;};imports.wbg.__wbg_deltaY_f9318542caea0c36=function(arg0){const ret=arg0.deltaY;return ret;};imports.wbg.__wbg_deltaZ_a515df5539e84914=function(arg0){const ret=arg0.deltaZ;return ret;};imports.wbg.__wbg_detail_f0595503cf47e6d4=function(arg0){const ret=arg0.detail;return ret;};imports.wbg.__wbg_document_d249400bd7bd996d=function(arg0){const ret=arg0.document;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_done_769e5ede4b31c67b=function(arg0){const ret=arg0.done;return ret;};imports.wbg.__wbg_elapsedTime_0bb4cd6e7aefb5bb=function(arg0){const ret=arg0.elapsedTime;return ret;};imports.wbg.__wbg_elapsedTime_1aa80b6dcb7427f3=function(arg0){const ret=arg0.elapsedTime;return ret;};imports.wbg.__wbg_entries_3265d4158b33e5dc=function(arg0){const ret=Object.entries(arg0);return ret;};imports.wbg.__wbg_entries_c8a90a7ed73e84ce=function(arg0){const ret=arg0.entries();return ret;};imports.wbg.__wbg_error_1004b8c64097413f=function(arg0,arg1){console.error(arg0,arg1);};imports.wbg.__wbg_error_524f506f44df1645=function(arg0){console.error(arg0);};imports.wbg.__wbg_error_7534b8e9a36f1ab4=function(arg0,arg1){let deferred0_0;let deferred0_1;try{deferred0_0=arg0;deferred0_1=arg1;console.error(getStringFromWasm0(arg0,arg1));}finally{wasm.__wbindgen_free(deferred0_0,deferred0_1,1);}};imports.wbg.__wbg_error_80de38b3f7cc3c3c=function(arg0,arg1,arg2,arg3){console.error(arg0,arg1,arg2,arg3);};imports.wbg.__wbg_fetch_509096533071c657=function(arg0,arg1){const ret=arg0.fetch(arg1);return ret;};imports.wbg.__wbg_fetch_d36a73832f0a45e8=function(arg0){const ret=fetch(arg0);return ret;};imports.wbg.__wbg_files_5f07ac9b6f9116a7=function(arg0){const ret=arg0.files;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_files_790cda07a2445fac=function(arg0){const ret=arg0.files;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_focus_7d08b55eba7b368d=function(){return handleError(function(arg0){arg0.focus();},arguments);};imports.wbg.__wbg_force_6e5acfdea2af0a4f=function(arg0){const ret=arg0.force;return ret;};imports.wbg.__wbg_forward_9cb3721c72abe28a=function(){return handleError(function(arg0){arg0.forward();},arguments);};imports.wbg.__wbg_getAttribute_ea5166be2deba45e=function(arg0,arg1,arg2,arg3){const ret=arg1.getAttribute(getStringFromWasm0(arg2,arg3));var ptr1=isLikeNone(ret)?0:passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);var len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_getBoundingClientRect_9073b0ff7574d76b=function(arg0){const ret=arg0.getBoundingClientRect();return ret;};imports.wbg.__wbg_getElementById_f827f0d6648718a8=function(arg0,arg1,arg2){const ret=arg0.getElementById(getStringFromWasm0(arg1,arg2));return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_getNode_6a7efced3b43c423=function(arg0,arg1){const ret=arg0.getNode(arg1>>>0);return ret;};imports.wbg.__wbg_get_3091cb4339203d1a=function(arg0,arg1){const ret=arg0[arg1>>>0];return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_get_67b2ba62fc30de12=function(){return handleError(function(arg0,arg1){const ret=Reflect.get(arg0,arg1);return ret;},arguments);};imports.wbg.__wbg_get_b9b93047fe3cf45b=function(arg0,arg1){const ret=arg0[arg1>>>0];return ret;};imports.wbg.__wbg_getselectdata_1e17d70818773a7c=function(arg0,arg1){const ret=get_select_data(arg1);const ptr1=passArrayJsValueToWasm0(ret,wasm.__wbindgen_malloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_has_a5ea9117f258a0ec=function(){return handleError(function(arg0,arg1){const ret=Reflect.has(arg0,arg1);return ret;},arguments);};imports.wbg.__wbg_hash_dd4b49269c385c8a=function(){return handleError(function(arg0,arg1){const ret=arg1.hash;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);},arguments);};imports.wbg.__wbg_headers_9cb51cfd2ac780a4=function(arg0){const ret=arg0.headers;return ret;};imports.wbg.__wbg_height_1f8226c8f6875110=function(arg0){const ret=arg0.height;return ret;};imports.wbg.__wbg_height_46ca33dbfea52e29=function(arg0){const ret=arg0.height;return ret;};imports.wbg.__wbg_height_592a89ec0fb63726=function(arg0){const ret=arg0.height;return ret;};imports.wbg.__wbg_history_b8221edd09c17656=function(){return handleError(function(arg0){const ret=arg0.history;return ret;},arguments);};imports.wbg.__wbg_identifier_59e0705aef81ff93=function(arg0){const ret=arg0.identifier;return ret;};imports.wbg.__wbg_initialize_bde49e46877e9432=function(arg0,arg1,arg2){arg0.initialize(arg1,arg2);};imports.wbg.__wbg_inlineSize_8ff96b3ec1b24423=function(arg0){const ret=arg0.inlineSize;return ret;};imports.wbg.__wbg_instanceof_ArrayBuffer_e14585432e3737fc=function(arg0){let result;try{result=arg0 instanceof ArrayBuffer;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_DragEvent_953618f4738dd2e6=function(arg0){let result;try{result=arg0 instanceof DragEvent;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_Element_0af65443936d5154=function(arg0){let result;try{result=arg0 instanceof Element;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_HtmlElement_51378c201250b16c=function(arg0){let result;try{result=arg0 instanceof HTMLElement;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_HtmlFormElement_339aa0fb9076db8e=function(arg0){let result;try{result=arg0 instanceof HTMLFormElement;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_HtmlInputElement_12d71bf2d15dd19e=function(arg0){let result;try{result=arg0 instanceof HTMLInputElement;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_HtmlSelectElement_2ae72edd07bf938c=function(arg0){let result;try{result=arg0 instanceof HTMLSelectElement;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_HtmlTextAreaElement_83a92f8ba4fb63ae=function(arg0){let result;try{result=arg0 instanceof HTMLTextAreaElement;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_Node_fbc6b87f5ed2e230=function(arg0){let result;try{result=arg0 instanceof Node;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_Response_f2cc20d9f7dfd644=function(arg0){let result;try{result=arg0 instanceof Response;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_Uint8Array_17156bcf118086a9=function(arg0){let result;try{result=arg0 instanceof Uint8Array;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_instanceof_Window_def73ea0955fc569=function(arg0){let result;try{result=arg0 instanceof Window;}catch(_){result=false;}const ret=result;return ret;};imports.wbg.__wbg_intersectionRatio_c90601ed000a5562=function(arg0){const ret=arg0.intersectionRatio;return ret;};imports.wbg.__wbg_intersectionRect_7b3d4027f111d12d=function(arg0){const ret=arg0.intersectionRect;return ret;};imports.wbg.__wbg_isArray_a1eab7e0d067391b=function(arg0){const ret=Array.isArray(arg0);return ret;};imports.wbg.__wbg_isComposing_36511555ff1869a4=function(arg0){const ret=arg0.isComposing;return ret;};imports.wbg.__wbg_isIntersecting_e68706dac9c5f2e9=function(arg0){const ret=arg0.isIntersecting;return ret;};imports.wbg.__wbg_isPrimary_50d7d610b8b63e41=function(arg0){const ret=arg0.isPrimary;return ret;};imports.wbg.__wbg_isSafeInteger_343e2beeeece1bb0=function(arg0){const ret=Number.isSafeInteger(arg0);return ret;};imports.wbg.__wbg_item_152181ce9027baaf=function(arg0,arg1){const ret=arg0.item(arg1>>>0);return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_iterator_9a24c88df860dc65=function(){const ret=Symbol.iterator;return ret;};imports.wbg.__wbg_key_7b5c6cb539be8e13=function(arg0,arg1){const ret=arg1.key;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_left_e46801720267b66d=function(arg0){const ret=arg0.left;return ret;};imports.wbg.__wbg_length_802483321c8130cf=function(arg0){const ret=arg0.length;return ret;};imports.wbg.__wbg_length_a446193dc22c12f8=function(arg0){const ret=arg0.length;return ret;};imports.wbg.__wbg_length_cfc862ec0ccc7ca0=function(arg0){const ret=arg0.length;return ret;};imports.wbg.__wbg_length_d56737991078581b=function(arg0){const ret=arg0.length;return ret;};imports.wbg.__wbg_length_e2d2a49132c1b256=function(arg0){const ret=arg0.length;return ret;};imports.wbg.__wbg_location_350d99456c2f3693=function(arg0){const ret=arg0.location;return ret;};imports.wbg.__wbg_location_9b435486be8f98c2=function(arg0){const ret=arg0.location;return ret;};imports.wbg.__wbg_log_0cc1b7768397bcfe=function(arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7){let deferred0_0;let deferred0_1;try{deferred0_0=arg0;deferred0_1=arg1;console.log(getStringFromWasm0(arg0,arg1),getStringFromWasm0(arg2,arg3),getStringFromWasm0(arg4,arg5),getStringFromWasm0(arg6,arg7));}finally{wasm.__wbindgen_free(deferred0_0,deferred0_1,1);}};imports.wbg.__wbg_log_cb9e190acc5753fb=function(arg0,arg1){let deferred0_0;let deferred0_1;try{deferred0_0=arg0;deferred0_1=arg1;console.log(getStringFromWasm0(arg0,arg1));}finally{wasm.__wbindgen_free(deferred0_0,deferred0_1,1);}};imports.wbg.__wbg_mark_7438147ce31e9d4b=function(arg0,arg1){performance.mark(getStringFromWasm0(arg0,arg1));};imports.wbg.__wbg_measure_fb7825c11612c823=function(){return handleError(function(arg0,arg1,arg2,arg3){let deferred0_0;let deferred0_1;let deferred1_0;let deferred1_1;try{deferred0_0=arg0;deferred0_1=arg1;deferred1_0=arg2;deferred1_1=arg3;performance.measure(getStringFromWasm0(arg0,arg1),getStringFromWasm0(arg2,arg3));}finally{wasm.__wbindgen_free(deferred0_0,deferred0_1,1);wasm.__wbindgen_free(deferred1_0,deferred1_1,1);}},arguments);};imports.wbg.__wbg_metaKey_0b25f7848e014cc8=function(arg0){const ret=arg0.metaKey;return ret;};imports.wbg.__wbg_metaKey_5734dfddca604fc6=function(arg0){const ret=arg0.metaKey;return ret;};imports.wbg.__wbg_metaKey_e1dd47d709a80ce5=function(arg0){const ret=arg0.metaKey;return ret;};imports.wbg.__wbg_name_28c43f147574bf08=function(arg0,arg1){const ret=arg1.name;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_new_018dcc2d6c8c2f6a=function(){return handleError(function(){const ret=new Headers;return ret;},arguments);};imports.wbg.__wbg_new_092fb7d145d02979=function(arg0){const ret=new RawInterpreter(arg0>>>0);return ret;};imports.wbg.__wbg_new_405e22f390576ce2=function(){const ret=new Object;return ret;};imports.wbg.__wbg_new_46e8134c3341d05a=function(){return handleError(function(){const ret=new FileReader;return ret;},arguments);};imports.wbg.__wbg_new_5e0be73521bc8c17=function(){const ret=new Map;return ret;};imports.wbg.__wbg_new_78feb108b6472713=function(){const ret=new Array;return ret;};imports.wbg.__wbg_new_85e2deaa8ec21f74=function(arg0){const ret=new WebDioxusChannel(JSOwner.__wrap(arg0));return ret;};imports.wbg.__wbg_new_8a6f238a6ece86ea=function(){const ret=new Error;return ret;};imports.wbg.__wbg_new_a12002a7f91c75be=function(arg0){const ret=new Uint8Array(arg0);return ret;};imports.wbg.__wbg_new_e25e5aab09ff45db=function(){return handleError(function(){const ret=new AbortController;return ret;},arguments);};imports.wbg.__wbg_newnoargs_105ed471475aaf50=function(arg0,arg1){const ret=new Function(getStringFromWasm0(arg0,arg1));return ret;};imports.wbg.__wbg_newwithargs_ab6ffe8cd6c19c04=function(arg0,arg1,arg2,arg3){const ret=new Function(getStringFromWasm0(arg0,arg1),getStringFromWasm0(arg2,arg3));return ret;};imports.wbg.__wbg_newwithbyteoffsetandlength_d97e637ebe145a9a=function(arg0,arg1,arg2){const ret=new Uint8Array(arg0,arg1>>>0,arg2>>>0);return ret;};imports.wbg.__wbg_newwithstrandinit_06c535e0a867c635=function(){return handleError(function(arg0,arg1,arg2){const ret=new Request(getStringFromWasm0(arg0,arg1),arg2);return ret;},arguments);};imports.wbg.__wbg_next_25feadfc0913fea9=function(arg0){const ret=arg0.next;return ret;};imports.wbg.__wbg_next_6574e1a8a62d1055=function(){return handleError(function(arg0){const ret=arg0.next();return ret;},arguments);};imports.wbg.__wbg_offsetX_adb14e39bdd32e22=function(arg0){const ret=arg0.offsetX;return ret;};imports.wbg.__wbg_offsetY_e88dc24ec0418dd4=function(arg0){const ret=arg0.offsetY;return ret;};imports.wbg.__wbg_origin_7c5d649acdace3ea=function(){return handleError(function(arg0,arg1){const ret=arg1.origin;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);},arguments);};imports.wbg.__wbg_ownerDocument_243e06ce3350b842=function(arg0){const ret=arg0.ownerDocument;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_pageX_a8745ff969d1e665=function(arg0){const ret=arg0.pageX;return ret;};imports.wbg.__wbg_pageX_ce146fc8b9d1c155=function(arg0){const ret=arg0.pageX;return ret;};imports.wbg.__wbg_pageY_4d1412e9ba1fdcde=function(arg0){const ret=arg0.pageY;return ret;};imports.wbg.__wbg_pageY_b7706f3dab029427=function(arg0){const ret=arg0.pageY;return ret;};imports.wbg.__wbg_parentElement_be28a1a931f9c9b7=function(arg0){const ret=arg0.parentElement;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_pathname_f525fe3ba3d01fcf=function(){return handleError(function(arg0,arg1){const ret=arg1.pathname;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);},arguments);};imports.wbg.__wbg_pointerId_585e63ee80a49927=function(arg0){const ret=arg0.pointerId;return ret;};imports.wbg.__wbg_pointerType_6bd934aa20d9db49=function(arg0,arg1){const ret=arg1.pointerType;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_pressure_adda5a83a9cec94d=function(arg0){const ret=arg0.pressure;return ret;};imports.wbg.__wbg_preventDefault_c2314fd813c02b3c=function(arg0){arg0.preventDefault();};imports.wbg.__wbg_propertyName_95755b7de403ec53=function(arg0,arg1){const ret=arg1.propertyName;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_pseudoElement_4aac34144e5bd419=function(arg0,arg1){const ret=arg1.pseudoElement;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_pseudoElement_652df792fba77dd6=function(arg0,arg1){const ret=arg1.pseudoElement;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_pushState_d132f15566570786=function(){return handleError(function(arg0,arg1,arg2,arg3,arg4,arg5){arg0.pushState(arg1,getStringFromWasm0(arg2,arg3),arg4===0?undefined:getStringFromWasm0(arg4,arg5));},arguments);};imports.wbg.__wbg_push_737cfc8c1432c2c6=function(arg0,arg1){const ret=arg0.push(arg1);return ret;};imports.wbg.__wbg_queueMicrotask_97d92b4fcc8a61c5=function(arg0){queueMicrotask(arg0);};imports.wbg.__wbg_queueMicrotask_d3219def82552485=function(arg0){const ret=arg0.queueMicrotask;return ret;};imports.wbg.__wbg_radiusX_1994f2d1df7354cd=function(arg0){const ret=arg0.radiusX;return ret;};imports.wbg.__wbg_radiusY_d30b27848016213d=function(arg0){const ret=arg0.radiusY;return ret;};imports.wbg.__wbg_readAsArrayBuffer_e51cb3c4fcc962de=function(){return handleError(function(arg0,arg1){arg0.readAsArrayBuffer(arg1);},arguments);};imports.wbg.__wbg_readAsText_b48ba55794326a02=function(){return handleError(function(arg0,arg1){arg0.readAsText(arg1);},arguments);};imports.wbg.__wbg_repeat_1882aa0d0072c705=function(arg0){const ret=arg0.repeat;return ret;};imports.wbg.__wbg_replaceState_79f3b896be12c919=function(){return handleError(function(arg0,arg1,arg2,arg3,arg4,arg5){arg0.replaceState(arg1,getStringFromWasm0(arg2,arg3),arg4===0?undefined:getStringFromWasm0(arg4,arg5));},arguments);};imports.wbg.__wbg_requestAnimationFrame_d7fd890aaefc3246=function(){return handleError(function(arg0,arg1){const ret=arg0.requestAnimationFrame(arg1);return ret;},arguments);};imports.wbg.__wbg_resolve_4851785c9c5f573d=function(arg0){const ret=Promise.resolve(arg0);return ret;};imports.wbg.__wbg_result_dadbdcc801180072=function(){return handleError(function(arg0){const ret=arg0.result;return ret;},arguments);};imports.wbg.__wbg_rootBounds_25b6a3efe03c3a57=function(arg0){const ret=arg0.rootBounds;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_rotationAngle_669e06b358d3c745=function(arg0){const ret=arg0.rotationAngle;return ret;};imports.wbg.__wbg_run_b869ac02fd3748d0=function(arg0){arg0.run();};imports.wbg.__wbg_rustRecv_9c15f2c4f8582493=function(arg0){const ret=arg0.rustRecv();return ret;};imports.wbg.__wbg_rustSend_eaddd4d5cf7c3f99=function(arg0,arg1){arg0.rustSend(arg1);};imports.wbg.__wbg_saveTemplate_604e277cddda20d5=function(arg0,arg1,arg2,arg3){var v0=getArrayJsValueFromWasm0(arg1,arg2).slice();wasm.__wbindgen_free(arg1,arg2*4,4);arg0.saveTemplate(v0,arg3);};imports.wbg.__wbg_screenX_ad7e620ee9a265ab=function(arg0){const ret=arg0.screenX;return ret;};imports.wbg.__wbg_screenX_ded8917b3affae10=function(arg0){const ret=arg0.screenX;return ret;};imports.wbg.__wbg_screenY_781818ca5673e32c=function(arg0){const ret=arg0.screenY;return ret;};imports.wbg.__wbg_screenY_f77ce1ae06a86fff=function(arg0){const ret=arg0.screenY;return ret;};imports.wbg.__wbg_scrollHeight_6c5a5fc7dbce3f36=function(arg0){const ret=arg0.scrollHeight;return ret;};imports.wbg.__wbg_scrollIntoView_c8c0faa10ba6968a=function(arg0,arg1){arg0.scrollIntoView(arg1);};imports.wbg.__wbg_scrollLeft_b195ce13f48fdfef=function(arg0){const ret=arg0.scrollLeft;return ret;};imports.wbg.__wbg_scrollTo_26cd993048111460=function(arg0,arg1,arg2){arg0.scrollTo(arg1,arg2);};imports.wbg.__wbg_scrollTop_fa6a185d62b9a4ab=function(arg0){const ret=arg0.scrollTop;return ret;};imports.wbg.__wbg_scrollWidth_14cd601c190e01a7=function(arg0){const ret=arg0.scrollWidth;return ret;};imports.wbg.__wbg_scrollX_02fa7e84cc48b8fe=function(){return handleError(function(arg0){const ret=arg0.scrollX;return ret;},arguments);};imports.wbg.__wbg_scrollY_94bf061418186bb3=function(){return handleError(function(arg0){const ret=arg0.scrollY;return ret;},arguments);};imports.wbg.__wbg_search_c1c3bfbeadd96c47=function(){return handleError(function(arg0,arg1){const ret=arg1.search;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);},arguments);};imports.wbg.__wbg_setAttributeInner_f9028661db548305=function(arg0,arg1,arg2,arg3,arg4,arg5){setAttributeInner1(arg0,getStringFromWasm0(arg1,arg2),arg3,arg4===0?undefined:getStringFromWasm0(arg4,arg5));};imports.wbg.__wbg_setTimeout_2e707715f8cc9497=function(arg0,arg1){const ret=setTimeout(arg0,arg1);return ret;};imports.wbg.__wbg_set_37837023f3d740e8=function(arg0,arg1,arg2){arg0[arg1>>>0]=arg2;};imports.wbg.__wbg_set_3807d5f0bfc24aa7=function(arg0,arg1,arg2){arg0[arg1]=arg2;};imports.wbg.__wbg_set_65595bdd868b3009=function(arg0,arg1,arg2){arg0.set(arg1,arg2>>>0);};imports.wbg.__wbg_set_8fc6bf8a5b1071d1=function(arg0,arg1,arg2){const ret=arg0.set(arg1,arg2);return ret;};imports.wbg.__wbg_setbehavior_7927939a0bc6d379=function(arg0,arg1){arg0.behavior=__wbindgen_enum_ScrollBehavior[arg1];};imports.wbg.__wbg_setbody_5923b78a95eedf29=function(arg0,arg1){arg0.body=arg1;};imports.wbg.__wbg_setcredentials_c3a22f1cd105a2c6=function(arg0,arg1){arg0.credentials=__wbindgen_enum_RequestCredentials[arg1];};imports.wbg.__wbg_setheaders_834c0bdb6a8949ad=function(arg0,arg1){arg0.headers=arg1;};imports.wbg.__wbg_sethref_7eb69a6b9ae98056=function(){return handleError(function(arg0,arg1,arg2){arg0.href=getStringFromWasm0(arg1,arg2);},arguments);};imports.wbg.__wbg_setmethod_3c5280fe5d890842=function(arg0,arg1,arg2){arg0.method=getStringFromWasm0(arg1,arg2);};imports.wbg.__wbg_setmode_5dc300b865044b65=function(arg0,arg1){arg0.mode=__wbindgen_enum_RequestMode[arg1];};imports.wbg.__wbg_setonload_1302417ca59f658b=function(arg0,arg1){arg0.onload=arg1;};imports.wbg.__wbg_setscrollRestoration_3ac82da5fd0922ae=function(){return handleError(function(arg0,arg1){arg0.scrollRestoration=__wbindgen_enum_ScrollRestoration[arg1];},arguments);};imports.wbg.__wbg_setsignal_75b21ef3a81de905=function(arg0,arg1){arg0.signal=arg1;};imports.wbg.__wbg_shiftKey_2bebb3b703254f47=function(arg0){const ret=arg0.shiftKey;return ret;};imports.wbg.__wbg_shiftKey_86e737105bab1a54=function(arg0){const ret=arg0.shiftKey;return ret;};imports.wbg.__wbg_shiftKey_c745a96baa2d27af=function(arg0){const ret=arg0.shiftKey;return ret;};imports.wbg.__wbg_signal_aaf9ad74119f20a4=function(arg0){const ret=arg0.signal;return ret;};imports.wbg.__wbg_size_3808d41635a9c259=function(arg0){const ret=arg0.size;return ret;};imports.wbg.__wbg_stack_0ed75d68575b0f3c=function(arg0,arg1){const ret=arg1.stack;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_state_16d8f531272cd08b=function(){return handleError(function(arg0){const ret=arg0.state;return ret;},arguments);};imports.wbg.__wbg_static_accessor_GLOBAL_88a902d13a557d07=function(){const ret=typeof global==="undefined"?null:global;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_static_accessor_GLOBAL_THIS_56578be7e9f832b0=function(){const ret=typeof globalThis==="undefined"?null:globalThis;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_static_accessor_SELF_37c5d418e4bf5819=function(){const ret=typeof self==="undefined"?null:self;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_static_accessor_WINDOW_5de37043a91a9c40=function(){const ret=typeof window==="undefined"?null:window;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_status_f6360336ca686bf0=function(arg0){const ret=arg0.status;return ret;};imports.wbg.__wbg_stringify_f7ed6987935b4a24=function(){return handleError(function(arg0){const ret=JSON.stringify(arg0);return ret;},arguments);};imports.wbg.__wbg_tangentialPressure_ee3abd4259233d0a=function(arg0){const ret=arg0.tangentialPressure;return ret;};imports.wbg.__wbg_targetTouches_0b95aa10ef47d769=function(arg0){const ret=arg0.targetTouches;return ret;};imports.wbg.__wbg_target_0a62d9d79a2a1ede=function(arg0){const ret=arg0.target;return isLikeNone(ret)?0:addToExternrefTable0(ret);};imports.wbg.__wbg_textContent_215d0f87d539368a=function(arg0,arg1){const ret=arg1.textContent;var ptr1=isLikeNone(ret)?0:passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);var len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_then_44b73946d2fb3e7d=function(arg0,arg1){const ret=arg0.then(arg1);return ret;};imports.wbg.__wbg_then_48b406749878a531=function(arg0,arg1,arg2){const ret=arg0.then(arg1,arg2);return ret;};imports.wbg.__wbg_tiltX_ffc5b340f3484031=function(arg0){const ret=arg0.tiltX;return ret;};imports.wbg.__wbg_tiltY_e01bc77dd789806e=function(arg0){const ret=arg0.tiltY;return ret;};imports.wbg.__wbg_time_805cb6c0545e6446=function(arg0){const ret=arg0.time;return ret;};imports.wbg.__wbg_top_ec9fceb1f030f2ea=function(arg0){const ret=arg0.top;return ret;};imports.wbg.__wbg_touches_6831ee0099511603=function(arg0){const ret=arg0.touches;return ret;};imports.wbg.__wbg_twist_a22a43045193e78f=function(arg0){const ret=arg0.twist;return ret;};imports.wbg.__wbg_type_16f2b8031796512f=function(arg0,arg1){const ret=arg1.type;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_type_647b08efadd633f2=function(arg0,arg1){const ret=arg1.type;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_updatememory_899f4fb250883b4b=function(arg0,arg1){arg0.update_memory(arg1);};imports.wbg.__wbg_url_ae10c34ca209681d=function(arg0,arg1){const ret=arg1.url;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_value_1d971aac958c6f2f=function(arg0,arg1){const ret=arg1.value;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_value_91cbf0dd3ab84c1e=function(arg0,arg1){const ret=arg1.value;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_value_cd1ffa7b1ab794f1=function(arg0){const ret=arg0.value;return ret;};imports.wbg.__wbg_value_d2c3b815cdf98d46=function(arg0,arg1){const ret=arg1.value;const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbg_weak_3ff0a094352976a4=function(arg0){const ret=arg0.weak();return ret;};imports.wbg.__wbg_width_aed87bf6026ca08f=function(arg0){const ret=arg0.width;return ret;};imports.wbg.__wbg_width_cdaf02311c1621d1=function(arg0){const ret=arg0.width;return ret;};imports.wbg.__wbg_width_f0759bd8bad335bd=function(arg0){const ret=arg0.width;return ret;};imports.wbg.__wbg_x_e74d824489c3f1a2=function(arg0){const ret=arg0.x;return ret;};imports.wbg.__wbg_y_9eb151d4ac38ddf3=function(arg0){const ret=arg0.y;return ret;};imports.wbg.__wbindgen_bigint_from_i64=function(arg0){const ret=arg0;return ret;};imports.wbg.__wbindgen_bigint_from_u64=function(arg0){const ret=BigInt.asUintN(64,arg0);return ret;};imports.wbg.__wbindgen_bigint_get_as_i64=function(arg0,arg1){const v=arg1;const ret=typeof v==="bigint"?v:undefined;getDataViewMemory0().setBigInt64(arg0+8*1,isLikeNone(ret)?BigInt(0):ret,true);getDataViewMemory0().setInt32(arg0+4*0,!isLikeNone(ret),true);};imports.wbg.__wbindgen_boolean_get=function(arg0){const v=arg0;const ret=typeof v==="boolean"?v?1:0:2;return ret;};imports.wbg.__wbindgen_cb_drop=function(arg0){const obj=arg0.original;if(obj.cnt--==1){obj.a=0;return true;}const ret=false;return ret;};imports.wbg.__wbindgen_closure_wrapper1303=function(arg0,arg1,arg2){const ret=makeMutClosure(arg0,arg1,676,__wbg_adapter_62);return ret;};imports.wbg.__wbindgen_closure_wrapper651=function(arg0,arg1,arg2){const ret=makeMutClosure(arg0,arg1,219,__wbg_adapter_50);return ret;};imports.wbg.__wbindgen_closure_wrapper865=function(arg0,arg1,arg2){const ret=makeMutClosure(arg0,arg1,346,__wbg_adapter_53);return ret;};imports.wbg.__wbindgen_closure_wrapper866=function(arg0,arg1,arg2){const ret=makeClosure(arg0,arg1,346,__wbg_adapter_56);return ret;};imports.wbg.__wbindgen_closure_wrapper868=function(arg0,arg1,arg2){const ret=makeMutClosure(arg0,arg1,346,__wbg_adapter_59);return ret;};imports.wbg.__wbindgen_debug_string=function(arg0,arg1){const ret=debugString(arg1);const ptr1=passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbindgen_error_new=function(arg0,arg1){const ret=new Error(getStringFromWasm0(arg0,arg1));return ret;};imports.wbg.__wbindgen_in=function(arg0,arg1){const ret=arg0 in arg1;return ret;};imports.wbg.__wbindgen_init_externref_table=function(){const table=wasm.__wbindgen_export_4;const offset=table.grow(4);table.set(0,undefined);table.set(offset+0,undefined);table.set(offset+1,null);table.set(offset+2,true);table.set(offset+3,false);};imports.wbg.__wbindgen_is_bigint=function(arg0){const ret=typeof arg0==="bigint";return ret;};imports.wbg.__wbindgen_is_function=function(arg0){const ret=typeof arg0==="function";return ret;};imports.wbg.__wbindgen_is_object=function(arg0){const val=arg0;const ret=typeof val==="object"&&val!==null;return ret;};imports.wbg.__wbindgen_is_string=function(arg0){const ret=typeof arg0==="string";return ret;};imports.wbg.__wbindgen_is_undefined=function(arg0){const ret=arg0===undefined;return ret;};imports.wbg.__wbindgen_jsval_eq=function(arg0,arg1){const ret=arg0===arg1;return ret;};imports.wbg.__wbindgen_jsval_loose_eq=function(arg0,arg1){const ret=arg0==arg1;return ret;};imports.wbg.__wbindgen_memory=function(){const ret=wasm.memory;return ret;};imports.wbg.__wbindgen_number_get=function(arg0,arg1){const obj=arg1;const ret=typeof obj==="number"?obj:undefined;getDataViewMemory0().setFloat64(arg0+8*1,isLikeNone(ret)?0:ret,true);getDataViewMemory0().setInt32(arg0+4*0,!isLikeNone(ret),true);};imports.wbg.__wbindgen_number_new=function(arg0){const ret=arg0;return ret;};imports.wbg.__wbindgen_string_get=function(arg0,arg1){const obj=arg1;const ret=typeof obj==="string"?obj:undefined;var ptr1=isLikeNone(ret)?0:passStringToWasm0(ret,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);var len1=WASM_VECTOR_LEN;getDataViewMemory0().setInt32(arg0+4*1,len1,true);getDataViewMemory0().setInt32(arg0+4*0,ptr1,true);};imports.wbg.__wbindgen_string_new=function(arg0,arg1){const ret=getStringFromWasm0(arg0,arg1);return ret;};imports.wbg.__wbindgen_throw=function(arg0,arg1){throw new Error(getStringFromWasm0(arg0,arg1));};imports["./snippets/dioxus-web-bf44d47c344f35d0/inline1.js"]=mod;return imports;}function __wbg_init_memory(imports,memory){}function __wbg_finalize_init(instance,module){wasm=instance.exports;__wbg_init.__wbindgen_wasm_module=module;cachedDataViewMemory0=null;cachedUint8ArrayMemory0=null;wasm.__wbindgen_start();return wasm;}function initSync(module){if(wasm!==undefined)return wasm;if(typeof module!=="undefined"){if(Object.getPrototypeOf(module)===Object.prototype){({module}=module);}else{console.warn("using deprecated parameters for `initSync()`; pass a single object instead");}}const imports=__wbg_get_imports();__wbg_init_memory(imports);if(!(module instanceof WebAssembly.Module)){module=new WebAssembly.Module(module);}const instance=new WebAssembly.Instance(module,imports);return __wbg_finalize_init(instance,module);}async function __wbg_init(module_or_path){if(wasm!==undefined)return wasm;if(typeof module_or_path!=="undefined"){if(Object.getPrototypeOf(module_or_path)===Object.prototype){({module_or_path}=module_or_path);}else{console.warn("using deprecated parameters for the initialization function; pass a single object instead");}}if(typeof module_or_path==="undefined"){module_or_path=new URL("blueprint-pwa_bg.wasm",importMeta.url);}const imports=__wbg_get_imports();if(typeof module_or_path==="string"||typeof Request==="function"&&module_or_path instanceof Request||typeof URL==="function"&&module_or_path instanceof URL){module_or_path=fetch(module_or_path);}__wbg_init_memory(imports);const{instance,module}=await __wbg_load(await module_or_path,imports);return __wbg_finalize_init(instance,module);}export{initSync as initSync,JSOwner as JSOwner,__wbg_init as default}; \ No newline at end of file diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa-26b188856e373044.js.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa-26b188856e373044.js.br deleted file mode 100644 index a0a75d6e..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa-26b188856e373044.js.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa_bg-626613b38704f6fd.wasm b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa_bg-626613b38704f6fd.wasm deleted file mode 100644 index fe3449e9..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa_bg-626613b38704f6fd.wasm and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa_bg-626613b38704f6fd.wasm.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa_bg-626613b38704f6fd.wasm.br deleted file mode 100644 index 5de2682c..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint-pwa_bg-626613b38704f6fd.wasm.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint.png b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint.png deleted file mode 100644 index cdc1da6c..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint.png and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint.png.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint.png.br deleted file mode 100644 index 2171efd8..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/blueprint.png.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui-theme.css b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui-theme.css deleted file mode 100644 index d5f75e2e..00000000 --- a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui-theme.css +++ /dev/null @@ -1,2 +0,0 @@ -/*! 🌼 daisyUI 5.0.11 - MIT License */ -:root,[data-theme=light]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f8f8f8;--color-base-300:#eee;--color-base-content:#18181b;--color-primary:#422ad5;--color-primary-content:#e0e7ff;--color-secondary:#f43098;--color-secondary-content:#f9e4f0;--color-accent:#00d1bb;--color-accent-content:#084d49;--color-neutral:#09090b;--color-neutral-content:#e4e4e7;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#00d193;--color-success-content:#004c39;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff657f;--color-error-content:#4d0218;--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root,[data-theme=light]{--color-base-100:lab(100% 0 0);--color-base-200:lab(97.68% -.0000298023 .0000119209);--color-base-300:lab(94.2% 0 0);--color-base-content:lab(8.30603% .618205 -2.16572);--color-primary:lab(31.573% 49.867 -84.7065);--color-primary-content:lab(91.6577% 1.04591 -12.7199);--color-secondary:lab(56.234% 76.7852 -8.06803);--color-secondary-content:lab(92.6584% 9.01151 -3.1507);--color-accent:lab(75.1988% -53.3697 -2.27784);--color-accent-content:lab(28.81% -21.4781 -3.59725);--color-neutral:lab(2.45787% .239417 -.873864);--color-neutral-content:lab(90.6853% .399232 -1.45452);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(74.4967% -60.7579 19.4189);--color-success-content:lab(27.9355% -26.9592 5.46191);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(64.1803% 63.0275 19.2122);--color-error-content:lab(14.1162% 34.0067 9.81536)}}:root:has(input.theme-controller[value=light]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f8f8f8;--color-base-300:#eee;--color-base-content:#18181b;--color-primary:#422ad5;--color-primary-content:#e0e7ff;--color-secondary:#f43098;--color-secondary-content:#f9e4f0;--color-accent:#00d1bb;--color-accent-content:#084d49;--color-neutral:#09090b;--color-neutral-content:#e4e4e7;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#00d193;--color-success-content:#004c39;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff657f;--color-error-content:#4d0218;--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=light]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(97.68% -.0000298023 .0000119209);--color-base-300:lab(94.2% 0 0);--color-base-content:lab(8.30603% .618205 -2.16572);--color-primary:lab(31.573% 49.867 -84.7065);--color-primary-content:lab(91.6577% 1.04591 -12.7199);--color-secondary:lab(56.234% 76.7852 -8.06803);--color-secondary-content:lab(92.6584% 9.01151 -3.1507);--color-accent:lab(75.1988% -53.3697 -2.27784);--color-accent-content:lab(28.81% -21.4781 -3.59725);--color-neutral:lab(2.45787% .239417 -.873864);--color-neutral-content:lab(90.6853% .399232 -1.45452);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(74.4967% -60.7579 19.4189);--color-success-content:lab(27.9355% -26.9592 5.46191);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(64.1803% 63.0275 19.2122);--color-error-content:lab(14.1162% 34.0067 9.81536)}}[data-theme=dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#1d232a;--color-base-200:#191e24;--color-base-300:#15191e;--color-base-content:#f2f8ff;--color-primary:#605dff;--color-primary-content:#edf1fe;--color-secondary:#f43098;--color-secondary-content:#f9e4f0;--color-accent:#00d1bb;--color-accent-content:#084d49;--color-neutral:#09090b;--color-neutral-content:#e4e4e7;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#00d193;--color-success-content:#004c39;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff657f;--color-error-content:#4d0218;--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=dark]{--color-base-100:lab(13.3466% -1.2732 -5.67451);--color-base-200:lab(10.9483% -1.07221 -4.98787);--color-base-300:lab(8.5032% -.863373 -4.30144);--color-base-content:lab(97.3754% -1.86676 -10.6283);--color-primary:lab(47.6934% 38.5675 -81.9644);--color-primary-content:lab(95.2498% .41151 -6.78517);--color-secondary:lab(56.234% 76.7852 -8.06803);--color-secondary-content:lab(92.6584% 9.01151 -3.1507);--color-accent:lab(75.1988% -53.3697 -2.27784);--color-accent-content:lab(28.81% -21.4781 -3.59725);--color-neutral:lab(2.45787% .239417 -.873864);--color-neutral-content:lab(90.6853% .399232 -1.45452);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(74.4967% -60.7579 19.4189);--color-success-content:lab(27.9355% -26.9592 5.46191);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(64.1803% 63.0275 19.2122);--color-error-content:lab(14.1162% 34.0067 9.81536)}}:root:has(input.theme-controller[value=dark]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#1d232a;--color-base-200:#191e24;--color-base-300:#15191e;--color-base-content:#f2f8ff;--color-primary:#605dff;--color-primary-content:#edf1fe;--color-secondary:#f43098;--color-secondary-content:#f9e4f0;--color-accent:#00d1bb;--color-accent-content:#084d49;--color-neutral:#09090b;--color-neutral-content:#e4e4e7;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#00d193;--color-success-content:#004c39;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff657f;--color-error-content:#4d0218;--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=dark]:checked){--color-base-100:lab(13.3466% -1.2732 -5.67451);--color-base-200:lab(10.9483% -1.07221 -4.98787);--color-base-300:lab(8.5032% -.863373 -4.30144);--color-base-content:lab(97.3754% -1.86676 -10.6283);--color-primary:lab(47.6934% 38.5675 -81.9644);--color-primary-content:lab(95.2498% .41151 -6.78517);--color-secondary:lab(56.234% 76.7852 -8.06803);--color-secondary-content:lab(92.6584% 9.01151 -3.1507);--color-accent:lab(75.1988% -53.3697 -2.27784);--color-accent-content:lab(28.81% -21.4781 -3.59725);--color-neutral:lab(2.45787% .239417 -.873864);--color-neutral-content:lab(90.6853% .399232 -1.45452);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(74.4967% -60.7579 19.4189);--color-success-content:lab(27.9355% -26.9592 5.46191);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(64.1803% 63.0275 19.2122);--color-error-content:lab(14.1162% 34.0067 9.81536)}}[data-theme=cupcake]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#faf7f5;--color-base-200:#efeae6;--color-base-300:#e7e2df;--color-base-content:#291334;--color-primary:#44ebd3;--color-primary-content:#005d58;--color-secondary:#f9cbe5;--color-secondary-content:#9e004a;--color-accent:#ffd6a7;--color-accent-content:#9f2d00;--color-neutral:#262629;--color-neutral-content:#e4e4e7;--color-info:#00a4ed;--color-info-content:#042e49;--color-success:#00b97d;--color-success-content:#002c21;--color-warning:#ebb000;--color-warning-content:#411e03;--color-error:#fe1c55;--color-error-content:#4d0218;--radius-selector:1rem;--radius-field:2rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:2px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=cupcake]{--color-base-100:lab(97.4237% .740707 1.27707);--color-base-200:lab(93.009% 1.12194 2.35903);--color-base-300:lab(90.22% 1.19972 1.85103);--color-base-content:lab(10.3261% 16.8409 -17.2906);--color-primary:lab(84.3177% -48.1616 -1.33156);--color-primary-content:lab(34.7855% -26.6758 -4.34272);--color-secondary:lab(86.4064% 19.5977 -6.46622);--color-secondary-content:lab(33.9116% 60.2466 6.01266);--color-accent:lab(88.3709% 9.95103 28.8399);--color-accent-content:lab(37.1566% 46.6433 50.5562);--color-neutral:lab(15.2665% .614211 -2.16932);--color-neutral-content:lab(90.6853% .399232 -1.45452);--color-info:lab(62.7193% -18.3316 -51.028);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(66.2791% -58.306 19.5483);--color-success-content:lab(14.8262% -17.9582 2.38395);--color-warning:lab(75.8062% 14.5847 99.3117);--color-warning-content:lab(16.1155% 15.7892 22.7155);--color-error:lab(55.5201% 79.431 31.509);--color-error-content:lab(14.1162% 34.0067 9.81536)}}:root:has(input.theme-controller[value=cupcake]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#faf7f5;--color-base-200:#efeae6;--color-base-300:#e7e2df;--color-base-content:#291334;--color-primary:#44ebd3;--color-primary-content:#005d58;--color-secondary:#f9cbe5;--color-secondary-content:#9e004a;--color-accent:#ffd6a7;--color-accent-content:#9f2d00;--color-neutral:#262629;--color-neutral-content:#e4e4e7;--color-info:#00a4ed;--color-info-content:#042e49;--color-success:#00b97d;--color-success-content:#002c21;--color-warning:#ebb000;--color-warning-content:#411e03;--color-error:#fe1c55;--color-error-content:#4d0218;--radius-selector:1rem;--radius-field:2rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:2px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=cupcake]:checked){--color-base-100:lab(97.4237% .740707 1.27707);--color-base-200:lab(93.009% 1.12194 2.35903);--color-base-300:lab(90.22% 1.19972 1.85103);--color-base-content:lab(10.3261% 16.8409 -17.2906);--color-primary:lab(84.3177% -48.1616 -1.33156);--color-primary-content:lab(34.7855% -26.6758 -4.34272);--color-secondary:lab(86.4064% 19.5977 -6.46622);--color-secondary-content:lab(33.9116% 60.2466 6.01266);--color-accent:lab(88.3709% 9.95103 28.8399);--color-accent-content:lab(37.1566% 46.6433 50.5562);--color-neutral:lab(15.2665% .614211 -2.16932);--color-neutral-content:lab(90.6853% .399232 -1.45452);--color-info:lab(62.7193% -18.3316 -51.028);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(66.2791% -58.306 19.5483);--color-success-content:lab(14.8262% -17.9582 2.38395);--color-warning:lab(75.8062% 14.5847 99.3117);--color-warning-content:lab(16.1155% 15.7892 22.7155);--color-error:lab(55.5201% 79.431 31.509);--color-error-content:lab(14.1162% 34.0067 9.81536)}}[data-theme=bumblebee]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f5f5f5;--color-base-300:#e4e4e4;--color-base-content:#161616;--color-primary:#f7c800;--color-primary-content:#733e0a;--color-secondary:#ff8b1a;--color-secondary-content:#7c2808;--color-accent:#000;--color-accent-content:#fff;--color-neutral:#433f3a;--color-neutral-content:#e6e4e3;--color-info:#00bafc;--color-info-content:#014a70;--color-success:#00d193;--color-success-content:#004c39;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff6266;--color-error-content:#801518;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=bumblebee]{--color-base-100:lab(100% 0 0);--color-base-200:lab(96.52% -.0000298023 .0000119209);--color-base-300:lab(90.72% .0000298023 -.0000119209);--color-base-content:lab(7.22637% -.0000149012 0);--color-primary:lab(83.0329% 8.6751 107.243);--color-primary-content:lab(32.27% 21.1356 38.6464);--color-secondary:lab(70.0429% 42.5156 75.8207);--color-secondary-content:lab(29.363% 36.096 38.1255);--color-accent:lab(0% 0 0);--color-accent-content:lab(100% 0 0);--color-neutral:lab(26.9171% 1.32994 3.57846);--color-neutral-content:lab(90.707% .663102 .865555);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(29.079% -8.32883 -28.2429);--color-success:lab(74.4967% -60.7579 19.4189);--color-success-content:lab(27.9355% -26.9592 5.46191);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(63.2406% 60.7498 31.3402);--color-error-content:lab(27.8157% 44.5725 29.2331)}}:root:has(input.theme-controller[value=bumblebee]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f5f5f5;--color-base-300:#e4e4e4;--color-base-content:#161616;--color-primary:#f7c800;--color-primary-content:#733e0a;--color-secondary:#ff8b1a;--color-secondary-content:#7c2808;--color-accent:#000;--color-accent-content:#fff;--color-neutral:#433f3a;--color-neutral-content:#e6e4e3;--color-info:#00bafc;--color-info-content:#014a70;--color-success:#00d193;--color-success-content:#004c39;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff6266;--color-error-content:#801518;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=bumblebee]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(96.52% -.0000298023 .0000119209);--color-base-300:lab(90.72% .0000298023 -.0000119209);--color-base-content:lab(7.22637% -.0000149012 0);--color-primary:lab(83.0329% 8.6751 107.243);--color-primary-content:lab(32.27% 21.1356 38.6464);--color-secondary:lab(70.0429% 42.5156 75.8207);--color-secondary-content:lab(29.363% 36.096 38.1255);--color-accent:lab(0% 0 0);--color-accent-content:lab(100% 0 0);--color-neutral:lab(26.9171% 1.32994 3.57846);--color-neutral-content:lab(90.707% .663102 .865555);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(29.079% -8.32883 -28.2429);--color-success:lab(74.4967% -60.7579 19.4189);--color-success-content:lab(27.9355% -26.9592 5.46191);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(63.2406% 60.7498 31.3402);--color-error-content:lab(27.8157% 44.5725 29.2331)}}[data-theme=emerald]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#e8e8e8;--color-base-300:#d1d1d1;--color-base-content:#333c4d;--color-primary:#66cc8a;--color-primary-content:#223d30;--color-secondary:#377cfb;--color-secondary-content:#fff;--color-accent:#f68067;--color-accent-content:#000;--color-neutral:#333c4d;--color-neutral-content:#f9fafb;--color-info:#00b4fa;--color-info-content:#000;--color-success:#00a96e;--color-success-content:#000;--color-warning:#ffc100;--color-warning-content:#000;--color-error:#ff676a;--color-error-content:#000;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=emerald]{--color-base-100:lab(100% 0 0);--color-base-200:lab(91.88% .0000298023 -.0000119209);--color-base-300:lab(83.76% -.0000298023 0);--color-base-content:lab(25.0321% -.305712 -11.697);--color-primary:lab(74.6827% -42.1368 23.4071);--color-primary-content:lab(23.2638% -13.2605 4.58165);--color-secondary:lab(53.1158% 13.16 -70.857);--color-secondary-content:lab(100% 0 0);--color-accent:lab(67.1348% 44.315 34.9118);--color-accent-content:lab(0% 0 0);--color-neutral:lab(25.0321% -.305712 -11.697);--color-neutral-content:lab(98.2157% -.123829 -.353503);--color-info:lab(67.7131% -26.5106 -53.6881);--color-info-content:lab(0% 0 0);--color-success:lab(61.1386% -50.3277 19.7345);--color-success-content:lab(0% 0 0);--color-warning:lab(82.3443% 18.4214 108.428);--color-warning-content:lab(0% 0 0);--color-error:lab(64.956% 70.4222 37.0322);--color-error-content:lab(0% 0 0)}}:root:has(input.theme-controller[value=emerald]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#e8e8e8;--color-base-300:#d1d1d1;--color-base-content:#333c4d;--color-primary:#66cc8a;--color-primary-content:#223d30;--color-secondary:#377cfb;--color-secondary-content:#fff;--color-accent:#f68067;--color-accent-content:#000;--color-neutral:#333c4d;--color-neutral-content:#f9fafb;--color-info:#00b4fa;--color-info-content:#000;--color-success:#00a96e;--color-success-content:#000;--color-warning:#ffc100;--color-warning-content:#000;--color-error:#ff676a;--color-error-content:#000;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=emerald]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(91.88% .0000298023 -.0000119209);--color-base-300:lab(83.76% -.0000298023 0);--color-base-content:lab(25.0321% -.305712 -11.697);--color-primary:lab(74.6827% -42.1368 23.4071);--color-primary-content:lab(23.2638% -13.2605 4.58165);--color-secondary:lab(53.1158% 13.16 -70.857);--color-secondary-content:lab(100% 0 0);--color-accent:lab(67.1348% 44.315 34.9118);--color-accent-content:lab(0% 0 0);--color-neutral:lab(25.0321% -.305712 -11.697);--color-neutral-content:lab(98.2157% -.123829 -.353503);--color-info:lab(67.7131% -26.5106 -53.6881);--color-info-content:lab(0% 0 0);--color-success:lab(61.1386% -50.3277 19.7345);--color-success-content:lab(0% 0 0);--color-warning:lab(82.3443% 18.4214 108.428);--color-warning-content:lab(0% 0 0);--color-error:lab(64.956% 70.4222 37.0322);--color-error-content:lab(0% 0 0)}}[data-theme=corporate]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#e8e8e8;--color-base-300:#d1d1d1;--color-base-content:#181a2a;--color-primary:#0082c4;--color-primary-content:#fff;--color-secondary:#61738d;--color-secondary-content:#fff;--color-accent:#009588;--color-accent-content:#fff;--color-neutral:#000;--color-neutral-content:#fff;--color-info:#008fb2;--color-info-content:#fff;--color-success:#00a242;--color-success-content:#fff;--color-warning:#f7c800;--color-warning-content:#000;--color-error:#ff6266;--color-error-content:#000;--radius-selector:.25rem;--radius-field:.25rem;--radius-box:.25rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=corporate]{--color-base-100:lab(100% 0 0);--color-base-200:lab(91.88% .0000298023 -.0000119209);--color-base-300:lab(83.76% -.0000298023 0);--color-base-content:lab(9.67606% 2.78211 -11.1624);--color-primary:lab(50.8378% -11.263 -49.8134);--color-primary-content:lab(100% 0 0);--color-secondary:lab(47.6231% -2.02695 -16.5784);--color-secondary-content:lab(100% 0 0);--color-accent:lab(55.0223% -41.0774 -3.90277);--color-accent-content:lab(100% 0 0);--color-neutral:lab(0% 0 0);--color-neutral-content:lab(100% 0 0);--color-info:lab(54.1295% -26.6648 -30.4973);--color-info-content:lab(100% 0 0);--color-success:lab(58.2832% -58.6949 41.339);--color-success-content:lab(100% 0 0);--color-warning:lab(83.0329% 8.6751 107.243);--color-warning-content:lab(0% 0 0);--color-error:lab(63.2406% 60.7498 31.3402);--color-error-content:lab(0% 0 0)}}:root:has(input.theme-controller[value=corporate]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#e8e8e8;--color-base-300:#d1d1d1;--color-base-content:#181a2a;--color-primary:#0082c4;--color-primary-content:#fff;--color-secondary:#61738d;--color-secondary-content:#fff;--color-accent:#009588;--color-accent-content:#fff;--color-neutral:#000;--color-neutral-content:#fff;--color-info:#008fb2;--color-info-content:#fff;--color-success:#00a242;--color-success-content:#fff;--color-warning:#f7c800;--color-warning-content:#000;--color-error:#ff6266;--color-error-content:#000;--radius-selector:.25rem;--radius-field:.25rem;--radius-box:.25rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=corporate]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(91.88% .0000298023 -.0000119209);--color-base-300:lab(83.76% -.0000298023 0);--color-base-content:lab(9.67606% 2.78211 -11.1624);--color-primary:lab(50.8378% -11.263 -49.8134);--color-primary-content:lab(100% 0 0);--color-secondary:lab(47.6231% -2.02695 -16.5784);--color-secondary-content:lab(100% 0 0);--color-accent:lab(55.0223% -41.0774 -3.90277);--color-accent-content:lab(100% 0 0);--color-neutral:lab(0% 0 0);--color-neutral-content:lab(100% 0 0);--color-info:lab(54.1295% -26.6648 -30.4973);--color-info-content:lab(100% 0 0);--color-success:lab(58.2832% -58.6949 41.339);--color-success-content:lab(100% 0 0);--color-warning:lab(83.0329% 8.6751 107.243);--color-warning-content:lab(0% 0 0);--color-error:lab(63.2406% 60.7498 31.3402);--color-error-content:lab(0% 0 0)}}[data-theme=synthwave]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#09002f;--color-base-200:#120b3d;--color-base-300:#1c184b;--color-base-content:#a2b2ff;--color-primary:#f861b4;--color-primary-content:#500323;--color-secondary:#71d1fe;--color-secondary-content:#042e49;--color-accent:#ff8b1a;--color-accent-content:#421104;--color-neutral:#422ad5;--color-neutral-content:#c7d2ff;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#00d1bb;--color-success-content:#002d2c;--color-warning:#fede1c;--color-warning-content:#733e0a;--color-error:#ec8c78;--color-error-content:#201047;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=synthwave]{--color-base-100:lab(2.11652% 12.2165 -26.8745);--color-base-200:lab(5.86105% 16.6448 -30.9194);--color-base-300:lab(11.6513% 15.2245 -31.331);--color-base-content:lab(73.4414% 8.57419 -41.5995);--color-primary:lab(63.6312% 64.3341 -12.7966);--color-primary-content:lab(15.1475% 35.1998 3.5461);--color-secondary:lab(79.4011% -20.258 -31.3754);--color-secondary-content:lab(17.4794% -5.25944 -21.1512);--color-accent:lab(70.0429% 42.5156 75.8207);--color-accent-content:lab(13.4759% 23.4865 18.9563);--color-neutral:lab(31.573% 49.867 -84.7065);--color-neutral-content:lab(84.4329% 3.18977 -23.9688);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(75.1988% -53.3697 -2.27784);--color-success-content:lab(15.825% -15.3228 -3.81451);--color-warning:lab(89.1205% -.43565 84.7279);--color-warning-content:lab(32.27% 21.1356 38.6464);--color-error:lab(68.4643% 35.8183 27.1229);--color-error-content:lab(9.61015% 20.4438 -31.961)}}:root:has(input.theme-controller[value=synthwave]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#09002f;--color-base-200:#120b3d;--color-base-300:#1c184b;--color-base-content:#a2b2ff;--color-primary:#f861b4;--color-primary-content:#500323;--color-secondary:#71d1fe;--color-secondary-content:#042e49;--color-accent:#ff8b1a;--color-accent-content:#421104;--color-neutral:#422ad5;--color-neutral-content:#c7d2ff;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#00d1bb;--color-success-content:#002d2c;--color-warning:#fede1c;--color-warning-content:#733e0a;--color-error:#ec8c78;--color-error-content:#201047;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=synthwave]:checked){--color-base-100:lab(2.11652% 12.2165 -26.8745);--color-base-200:lab(5.86105% 16.6448 -30.9194);--color-base-300:lab(11.6513% 15.2245 -31.331);--color-base-content:lab(73.4414% 8.57419 -41.5995);--color-primary:lab(63.6312% 64.3341 -12.7966);--color-primary-content:lab(15.1475% 35.1998 3.5461);--color-secondary:lab(79.4011% -20.258 -31.3754);--color-secondary-content:lab(17.4794% -5.25944 -21.1512);--color-accent:lab(70.0429% 42.5156 75.8207);--color-accent-content:lab(13.4759% 23.4865 18.9563);--color-neutral:lab(31.573% 49.867 -84.7065);--color-neutral-content:lab(84.4329% 3.18977 -23.9688);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(75.1988% -53.3697 -2.27784);--color-success-content:lab(15.825% -15.3228 -3.81451);--color-warning:lab(89.1205% -.43565 84.7279);--color-warning-content:lab(32.27% 21.1356 38.6464);--color-error:lab(68.4643% 35.8183 27.1229);--color-error-content:lab(9.61015% 20.4438 -31.961)}}[data-theme=retro]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#ece3ca;--color-base-200:#e4d8b4;--color-base-300:#dbca9b;--color-base-content:#793205;--color-primary:#ff9fa0;--color-primary-content:#801518;--color-secondary:#b7f6cd;--color-secondary-content:#00642e;--color-accent:#cd8800;--color-accent-content:#793205;--color-neutral:#56524c;--color-neutral-content:#d4d0ce;--color-info:#0082c4;--color-info-content:#fef2c6;--color-success:#00766e;--color-success-content:#fef2c6;--color-warning:#ed4f00;--color-warning-content:#fef2c6;--color-error:#ff6266;--color-error-content:#7c2808;--radius-selector:.25rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=retro]{--color-base-100:lab(90.4617% .120908 13.1948);--color-base-200:lab(86.6288% .0505149 19.2233);--color-base-300:lab(81.8682% .804782 25.918);--color-base-content:lab(30.7627% 30.2938 40.2828);--color-primary:lab(75.6231% 36.4237 15.5413);--color-primary-content:lab(27.8157% 44.5725 29.2331);--color-secondary:lab(91.8421% -26.4725 12.9439);--color-secondary-content:lab(36.5316% -36.8287 23.0138);--color-accent:lab(62.6632% 22.4314 86.3469);--color-accent-content:lab(30.7627% 30.2938 40.2828);--color-neutral:lab(35.0527% 1.08673 4.07879);--color-neutral-content:lab(83.7469% .928104 1.59742);--color-info:lab(50.8378% -11.263 -49.8134);--color-info-content:lab(95.6839% -1.21453 23.113);--color-success:lab(44.2974% -33.1456 -4.22121);--color-success-content:lab(95.6839% -1.21453 23.113);--color-warning:lab(56.4023% 64.3122 91.3904);--color-warning-content:lab(95.6839% -1.21453 23.113);--color-error:lab(63.2406% 60.7498 31.3402);--color-error-content:lab(29.363% 36.096 38.1255)}}:root:has(input.theme-controller[value=retro]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#ece3ca;--color-base-200:#e4d8b4;--color-base-300:#dbca9b;--color-base-content:#793205;--color-primary:#ff9fa0;--color-primary-content:#801518;--color-secondary:#b7f6cd;--color-secondary-content:#00642e;--color-accent:#cd8800;--color-accent-content:#793205;--color-neutral:#56524c;--color-neutral-content:#d4d0ce;--color-info:#0082c4;--color-info-content:#fef2c6;--color-success:#00766e;--color-success-content:#fef2c6;--color-warning:#ed4f00;--color-warning-content:#fef2c6;--color-error:#ff6266;--color-error-content:#7c2808;--radius-selector:.25rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=retro]:checked){--color-base-100:lab(90.4617% .120908 13.1948);--color-base-200:lab(86.6288% .0505149 19.2233);--color-base-300:lab(81.8682% .804782 25.918);--color-base-content:lab(30.7627% 30.2938 40.2828);--color-primary:lab(75.6231% 36.4237 15.5413);--color-primary-content:lab(27.8157% 44.5725 29.2331);--color-secondary:lab(91.8421% -26.4725 12.9439);--color-secondary-content:lab(36.5316% -36.8287 23.0138);--color-accent:lab(62.6632% 22.4314 86.3469);--color-accent-content:lab(30.7627% 30.2938 40.2828);--color-neutral:lab(35.0527% 1.08673 4.07879);--color-neutral-content:lab(83.7469% .928104 1.59742);--color-info:lab(50.8378% -11.263 -49.8134);--color-info-content:lab(95.6839% -1.21453 23.113);--color-success:lab(44.2974% -33.1456 -4.22121);--color-success-content:lab(95.6839% -1.21453 23.113);--color-warning:lab(56.4023% 64.3122 91.3904);--color-warning-content:lab(95.6839% -1.21453 23.113);--color-error:lab(63.2406% 60.7498 31.3402);--color-error-content:lab(29.363% 36.096 38.1255)}}[data-theme=cyberpunk]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff25a;--color-base-200:#f7e83a;--color-base-300:#e3d40e;--color-base-content:#000;--color-primary:#ff7299;--color-primary-content:#180408;--color-secondary:#00e5f9;--color-secondary-content:#001215;--color-accent:#cb78ff;--color-accent-content:#0f0517;--color-neutral:#111a3b;--color-neutral-content:#fff25a;--color-info:#00b4fa;--color-info-content:#000;--color-success:#00a96e;--color-success-content:#000;--color-warning:#ffc100;--color-warning-content:#000;--color-error:#ff676a;--color-error-content:#000;--radius-selector:0rem;--radius-field:0rem;--radius-box:0rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=cyberpunk]{--color-base-100:lab(94.6107% -8.04743 78.1535);--color-base-200:lab(91.1162% -7.81739 79.1069);--color-base-300:lab(84.1243% -7.31358 81.5778);--color-base-content:lab(0% 0 0);--color-primary:lab(67.5939% 68.2092 10.1527);--color-primary-content:lab(2.70907% 7.786 .901061);--color-secondary:lab(82.2338% -53.9253 -28.4139);--color-secondary-content:lab(4.3844% -6.22819 -4.37175);--color-accent:lab(63.9419% 54.2561 -59.1877);--color-accent-content:lab(2.36873% 5.55266 -7.74226);--color-neutral:lab(10.0256% 5.86083 -23.149);--color-neutral-content:lab(94.6107% -8.04743 78.1535);--color-info:lab(67.7131% -26.5106 -53.6881);--color-info-content:lab(0% 0 0);--color-success:lab(61.1386% -50.3277 19.7345);--color-success-content:lab(0% 0 0);--color-warning:lab(82.3443% 18.4214 108.428);--color-warning-content:lab(0% 0 0);--color-error:lab(64.956% 70.4222 37.0322);--color-error-content:lab(0% 0 0)}}:root:has(input.theme-controller[value=cyberpunk]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff25a;--color-base-200:#f7e83a;--color-base-300:#e3d40e;--color-base-content:#000;--color-primary:#ff7299;--color-primary-content:#180408;--color-secondary:#00e5f9;--color-secondary-content:#001215;--color-accent:#cb78ff;--color-accent-content:#0f0517;--color-neutral:#111a3b;--color-neutral-content:#fff25a;--color-info:#00b4fa;--color-info-content:#000;--color-success:#00a96e;--color-success-content:#000;--color-warning:#ffc100;--color-warning-content:#000;--color-error:#ff676a;--color-error-content:#000;--radius-selector:0rem;--radius-field:0rem;--radius-box:0rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=cyberpunk]:checked){--color-base-100:lab(94.6107% -8.04743 78.1535);--color-base-200:lab(91.1162% -7.81739 79.1069);--color-base-300:lab(84.1243% -7.31358 81.5778);--color-base-content:lab(0% 0 0);--color-primary:lab(67.5939% 68.2092 10.1527);--color-primary-content:lab(2.70907% 7.786 .901061);--color-secondary:lab(82.2338% -53.9253 -28.4139);--color-secondary-content:lab(4.3844% -6.22819 -4.37175);--color-accent:lab(63.9419% 54.2561 -59.1877);--color-accent-content:lab(2.36873% 5.55266 -7.74226);--color-neutral:lab(10.0256% 5.86083 -23.149);--color-neutral-content:lab(94.6107% -8.04743 78.1535);--color-info:lab(67.7131% -26.5106 -53.6881);--color-info-content:lab(0% 0 0);--color-success:lab(61.1386% -50.3277 19.7345);--color-success-content:lab(0% 0 0);--color-warning:lab(82.3443% 18.4214 108.428);--color-warning-content:lab(0% 0 0);--color-error:lab(64.956% 70.4222 37.0322);--color-error-content:lab(0% 0 0)}}[data-theme=valentine]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fcf2f8;--color-base-200:#f9e4f0;--color-base-300:#f9cbe5;--color-base-content:#c2005b;--color-primary:#f43098;--color-primary-content:#fff;--color-secondary:#a948ff;--color-secondary-content:#f8f3fd;--color-accent:#71d1fe;--color-accent-content:#014a70;--color-neutral:#830c41;--color-neutral-content:#f9cbe5;--color-info:#51e8fb;--color-info-content:#005885;--color-success:#5ce8b3;--color-success-content:#005f45;--color-warning:#ff8b1a;--color-warning-content:#421104;--color-error:#f82834;--color-error-content:#fef2f2;--radius-selector:1rem;--radius-field:2rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=valentine]{--color-base-100:lab(96.3299% 4.53994 -1.49432);--color-base-200:lab(92.6584% 9.01151 -3.1507);--color-base-300:lab(86.4064% 19.5977 -6.46622);--color-base-content:lab(41.5936% 71.7765 7.4325);--color-primary:lab(56.234% 76.7852 -8.06803);--color-primary-content:lab(100% 0 0);--color-secondary:lab(51.1822% 66.2953 -78.2252);--color-secondary-content:lab(96.3506% 2.99954 -4.13384);--color-accent:lab(79.4011% -20.258 -31.3754);--color-accent-content:lab(29.079% -8.32883 -28.2429);--color-neutral:lab(28.5085% 49.3611 3.36679);--color-neutral-content:lab(86.4064% 19.5977 -6.46622);--color-info:lab(84.8082% -36.7548 -21.568);--color-info-content:lab(34.813% -9.51259 -34.399);--color-success:lab(83.3402% -48.7252 13.8865);--color-success-content:lab(35.1354% -33.1288 8.04085);--color-warning:lab(70.0429% 42.5156 75.8207);--color-warning-content:lab(13.4759% 23.4865 18.9563);--color-error:lab(54.6666% 75.0951 49.1053);--color-error-content:lab(96.3845% 4.18508 1.52329)}}:root:has(input.theme-controller[value=valentine]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fcf2f8;--color-base-200:#f9e4f0;--color-base-300:#f9cbe5;--color-base-content:#c2005b;--color-primary:#f43098;--color-primary-content:#fff;--color-secondary:#a948ff;--color-secondary-content:#f8f3fd;--color-accent:#71d1fe;--color-accent-content:#014a70;--color-neutral:#830c41;--color-neutral-content:#f9cbe5;--color-info:#51e8fb;--color-info-content:#005885;--color-success:#5ce8b3;--color-success-content:#005f45;--color-warning:#ff8b1a;--color-warning-content:#421104;--color-error:#f82834;--color-error-content:#fef2f2;--radius-selector:1rem;--radius-field:2rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=valentine]:checked){--color-base-100:lab(96.3299% 4.53994 -1.49432);--color-base-200:lab(92.6584% 9.01151 -3.1507);--color-base-300:lab(86.4064% 19.5977 -6.46622);--color-base-content:lab(41.5936% 71.7765 7.4325);--color-primary:lab(56.234% 76.7852 -8.06803);--color-primary-content:lab(100% 0 0);--color-secondary:lab(51.1822% 66.2953 -78.2252);--color-secondary-content:lab(96.3506% 2.99954 -4.13384);--color-accent:lab(79.4011% -20.258 -31.3754);--color-accent-content:lab(29.079% -8.32883 -28.2429);--color-neutral:lab(28.5085% 49.3611 3.36679);--color-neutral-content:lab(86.4064% 19.5977 -6.46622);--color-info:lab(84.8082% -36.7548 -21.568);--color-info-content:lab(34.813% -9.51259 -34.399);--color-success:lab(83.3402% -48.7252 13.8865);--color-success-content:lab(35.1354% -33.1288 8.04085);--color-warning:lab(70.0429% 42.5156 75.8207);--color-warning-content:lab(13.4759% 23.4865 18.9563);--color-error:lab(54.6666% 75.0951 49.1053);--color-error-content:lab(96.3845% 4.18508 1.52329)}}[data-theme=halloween]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#1b1816;--color-base-200:#0b0908;--color-base-300:#000;--color-base-content:#cdcdcd;--color-primary:#ff960c;--color-primary-content:#131616;--color-secondary:#7900bf;--color-secondary-content:#e3d4f6;--color-accent:#4fa700;--color-accent-content:#000;--color-neutral:#2f1b05;--color-neutral-content:#d2ccc7;--color-info:#2563eb;--color-info-content:#d2e2ff;--color-success:#18a34a;--color-success-content:#000a02;--color-warning:#d97708;--color-warning-content:#110500;--color-error:#f35248;--color-error-content:#140202;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=halloween]{--color-base-100:lab(8.3423% 1.15404 1.88783);--color-base-200:lab(2.47049% .413664 .515226);--color-base-300:lab(0% 0 0);--color-base-content:lab(82.5478% -.0000298023 0);--color-primary:lab(72.9406% 44.1269 101.331);--color-primary-content:lab(6.93668% -1.15924 -.413656);--color-secondary:lab(32.3587% 66.5841 -72.2722);--color-secondary-content:lab(86.8693% 10.002 -14.9236);--color-accent:lab(61.4445% -51.4412 77.1776);--color-accent-content:lab(0% 0 0);--color-neutral:lab(12.1418% 8.28672 15.9582);--color-neutral-content:lab(82.4494% 1.2486 3.14918);--color-info:lab(44.7953% 20.9956 -75.5263);--color-info-content:lab(89.2766% -1.02177 -15.9354);--color-success:lab(58.8245% -50.7956 35.2154);--color-success-content:lab(1.93592% -3.28699 2.01724);--color-warning:lab(60.4958% 34.777 66.1666);--color-warning-content:lab(2.07311% 3.08444 3.10305);--color-error:lab(58.2957% 62.1912 41.5307);--color-error-content:lab(1.9019% 5.61917 2.22845)}}:root:has(input.theme-controller[value=halloween]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#1b1816;--color-base-200:#0b0908;--color-base-300:#000;--color-base-content:#cdcdcd;--color-primary:#ff960c;--color-primary-content:#131616;--color-secondary:#7900bf;--color-secondary-content:#e3d4f6;--color-accent:#4fa700;--color-accent-content:#000;--color-neutral:#2f1b05;--color-neutral-content:#d2ccc7;--color-info:#2563eb;--color-info-content:#d2e2ff;--color-success:#18a34a;--color-success-content:#000a02;--color-warning:#d97708;--color-warning-content:#110500;--color-error:#f35248;--color-error-content:#140202;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=halloween]:checked){--color-base-100:lab(8.3423% 1.15404 1.88783);--color-base-200:lab(2.47049% .413664 .515226);--color-base-300:lab(0% 0 0);--color-base-content:lab(82.5478% -.0000298023 0);--color-primary:lab(72.9406% 44.1269 101.331);--color-primary-content:lab(6.93668% -1.15924 -.413656);--color-secondary:lab(32.3587% 66.5841 -72.2722);--color-secondary-content:lab(86.8693% 10.002 -14.9236);--color-accent:lab(61.4445% -51.4412 77.1776);--color-accent-content:lab(0% 0 0);--color-neutral:lab(12.1418% 8.28672 15.9582);--color-neutral-content:lab(82.4494% 1.2486 3.14918);--color-info:lab(44.7953% 20.9956 -75.5263);--color-info-content:lab(89.2766% -1.02177 -15.9354);--color-success:lab(58.8245% -50.7956 35.2154);--color-success-content:lab(1.93592% -3.28699 2.01724);--color-warning:lab(60.4958% 34.777 66.1666);--color-warning-content:lab(2.07311% 3.08444 3.10305);--color-error:lab(58.2957% 62.1912 41.5307);--color-error-content:lab(1.9019% 5.61917 2.22845)}}[data-theme=garden]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#e9e7e7;--color-base-200:#d4d2d2;--color-base-300:#bebdbd;--color-base-content:#100f0f;--color-primary:#f80076;--color-primary-content:#fff;--color-secondary:#8e4162;--color-secondary-content:#ead7de;--color-accent:#5c7f67;--color-accent-content:#fff;--color-neutral:#291e00;--color-neutral-content:#e9e7e7;--color-info:#00b4fa;--color-info-content:#000;--color-success:#00a96e;--color-success-content:#000;--color-warning:#ffc100;--color-warning-content:#000;--color-error:#ff676a;--color-error-content:#000;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=garden]{--color-base-100:lab(91.8023% .644386 .231373);--color-base-200:lab(84.2553% .644416 .231373);--color-base-300:lab(76.7176% .322223 .115633);--color-base-content:lab(4.40042% .217006 .0779897);--color-primary:lab(53.0394% 89.3459 9.07078);--color-primary-content:lab(100% 0 0);--color-secondary:lab(38.8217% 35.7639 -3.1522);--color-secondary-content:lab(87.7654% 7.39187 -.64286);--color-accent:lab(49.9948% -16.7927 8.87276);--color-accent-content:lab(100% 0 0);--color-neutral:lab(12.1163% 2.66051 17.8295);--color-neutral-content:lab(91.8023% .644386 .231373);--color-info:lab(67.7131% -26.5106 -53.6881);--color-info-content:lab(0% 0 0);--color-success:lab(61.1386% -50.3277 19.7345);--color-success-content:lab(0% 0 0);--color-warning:lab(82.3443% 18.4214 108.428);--color-warning-content:lab(0% 0 0);--color-error:lab(64.956% 70.4222 37.0322);--color-error-content:lab(0% 0 0)}}:root:has(input.theme-controller[value=garden]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#e9e7e7;--color-base-200:#d4d2d2;--color-base-300:#bebdbd;--color-base-content:#100f0f;--color-primary:#f80076;--color-primary-content:#fff;--color-secondary:#8e4162;--color-secondary-content:#ead7de;--color-accent:#5c7f67;--color-accent-content:#fff;--color-neutral:#291e00;--color-neutral-content:#e9e7e7;--color-info:#00b4fa;--color-info-content:#000;--color-success:#00a96e;--color-success-content:#000;--color-warning:#ffc100;--color-warning-content:#000;--color-error:#ff676a;--color-error-content:#000;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=garden]:checked){--color-base-100:lab(91.8023% .644386 .231373);--color-base-200:lab(84.2553% .644416 .231373);--color-base-300:lab(76.7176% .322223 .115633);--color-base-content:lab(4.40042% .217006 .0779897);--color-primary:lab(53.0394% 89.3459 9.07078);--color-primary-content:lab(100% 0 0);--color-secondary:lab(38.8217% 35.7639 -3.1522);--color-secondary-content:lab(87.7654% 7.39187 -.64286);--color-accent:lab(49.9948% -16.7927 8.87276);--color-accent-content:lab(100% 0 0);--color-neutral:lab(12.1163% 2.66051 17.8295);--color-neutral-content:lab(91.8023% .644386 .231373);--color-info:lab(67.7131% -26.5106 -53.6881);--color-info-content:lab(0% 0 0);--color-success:lab(61.1386% -50.3277 19.7345);--color-success-content:lab(0% 0 0);--color-warning:lab(82.3443% 18.4214 108.428);--color-warning-content:lab(0% 0 0);--color-error:lab(64.956% 70.4222 37.0322);--color-error-content:lab(0% 0 0)}}[data-theme=forest]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#1b1717;--color-base-200:#161212;--color-base-300:#110d0d;--color-base-content:#cac9c9;--color-primary:#1fb854;--color-primary-content:#000;--color-secondary:#1eb88e;--color-secondary-content:#000c07;--color-accent:#1fb8ab;--color-accent-content:#010c0b;--color-neutral:#19362d;--color-neutral-content:#cdd3d1;--color-info:#00b4fa;--color-info-content:#000;--color-success:#00a96e;--color-success-content:#000;--color-warning:#ffc100;--color-warning-content:#000;--color-error:#ff676a;--color-error-content:#000;--radius-selector:1rem;--radius-field:2rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=forest]{--color-base-100:lab(8.09134% 2.56916 .954789);--color-base-200:lab(5.68172% 1.83339 .660554);--color-base-300:lab(3.79809% 1.40669 .504038);--color-base-content:lab(81.1606% .320822 .120199);--color-primary:lab(65.8881% -55.3999 38.8875);--color-primary-content:lab(0% 0 0);--color-secondary:lab(66.724% -46.9684 10.1177);--color-secondary-content:lab(2.62073% -3.9018 .895014);--color-accent:lab(67.3489% -41.0592 -4.73224);--color-accent-content:lab(2.67576% -3.41386 -.455385);--color-neutral:lab(20.1225% -13.4512 2.12126);--color-neutral-content:lab(84.0137% -2.35045 .377643);--color-info:lab(67.7131% -26.5106 -53.6881);--color-info-content:lab(0% 0 0);--color-success:lab(61.1386% -50.3277 19.7345);--color-success-content:lab(0% 0 0);--color-warning:lab(82.3443% 18.4214 108.428);--color-warning-content:lab(0% 0 0);--color-error:lab(64.956% 70.4222 37.0322);--color-error-content:lab(0% 0 0)}}:root:has(input.theme-controller[value=forest]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#1b1717;--color-base-200:#161212;--color-base-300:#110d0d;--color-base-content:#cac9c9;--color-primary:#1fb854;--color-primary-content:#000;--color-secondary:#1eb88e;--color-secondary-content:#000c07;--color-accent:#1fb8ab;--color-accent-content:#010c0b;--color-neutral:#19362d;--color-neutral-content:#cdd3d1;--color-info:#00b4fa;--color-info-content:#000;--color-success:#00a96e;--color-success-content:#000;--color-warning:#ffc100;--color-warning-content:#000;--color-error:#ff676a;--color-error-content:#000;--radius-selector:1rem;--radius-field:2rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=forest]:checked){--color-base-100:lab(8.09134% 2.56916 .954789);--color-base-200:lab(5.68172% 1.83339 .660554);--color-base-300:lab(3.79809% 1.40669 .504038);--color-base-content:lab(81.1606% .320822 .120199);--color-primary:lab(65.8881% -55.3999 38.8875);--color-primary-content:lab(0% 0 0);--color-secondary:lab(66.724% -46.9684 10.1177);--color-secondary-content:lab(2.62073% -3.9018 .895014);--color-accent:lab(67.3489% -41.0592 -4.73224);--color-accent-content:lab(2.67576% -3.41386 -.455385);--color-neutral:lab(20.1225% -13.4512 2.12126);--color-neutral-content:lab(84.0137% -2.35045 .377643);--color-info:lab(67.7131% -26.5106 -53.6881);--color-info-content:lab(0% 0 0);--color-success:lab(61.1386% -50.3277 19.7345);--color-success-content:lab(0% 0 0);--color-warning:lab(82.3443% 18.4214 108.428);--color-warning-content:lab(0% 0 0);--color-error:lab(64.956% 70.4222 37.0322);--color-error-content:lab(0% 0 0)}}[data-theme=aqua]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#1a368b;--color-base-200:#162455;--color-base-300:#091444;--color-base-content:#b8e6fe;--color-primary:#13ecf3;--color-primary-content:#015355;--color-secondary:#966fb3;--color-secondary-content:#f2f0fc;--color-accent:#ffe999;--color-accent-content:#161309;--color-neutral:#05176c;--color-neutral-content:#9cbcff;--color-info:#2563eb;--color-info-content:#d2e2ff;--color-success:#18a34a;--color-success-content:#000a02;--color-warning:#d97708;--color-warning-content:#431700;--color-error:#ff7c6f;--color-error-content:#180403;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=aqua]{--color-base-100:lab(25.0745% 16.2581 -51.5406);--color-base-200:lab(15.4352% 8.93655 -32.2903);--color-base-300:lab(8.26711% 11.823 -32.2031);--color-base-content:lab(88.5823% -11.3969 -16.8484);--color-primary:lab(84.7953% -45.6578 -17.3339);--color-primary-content:lab(31.2314% -21.7673 -7.75777);--color-secondary:lab(52.8668% 25.5024 -30.1393);--color-secondary-content:lab(95.1976% 2.28897 -5.51624);--color-accent:lab(92.8354% -.198632 41.6209);--color-accent-content:lab(5.96724% -.0408217 5.34988);--color-neutral:lab(12.855% 24.2161 -51.6803);--color-neutral-content:lab(75.6741% 5.20781 -52.489);--color-info:lab(44.7953% 20.9956 -75.5263);--color-info-content:lab(89.2766% -1.02177 -15.9354);--color-success:lab(58.8245% -50.7956 35.2154);--color-success-content:lab(1.93592% -3.28699 2.01724);--color-warning:lab(60.4958% 34.777 66.1666);--color-warning-content:lab(14.762% 20.9832 22.5643);--color-error:lab(67.9585% 59.0817 38.1436);--color-error-content:lab(2.73994% 6.78001 2.83679)}}:root:has(input.theme-controller[value=aqua]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#1a368b;--color-base-200:#162455;--color-base-300:#091444;--color-base-content:#b8e6fe;--color-primary:#13ecf3;--color-primary-content:#015355;--color-secondary:#966fb3;--color-secondary-content:#f2f0fc;--color-accent:#ffe999;--color-accent-content:#161309;--color-neutral:#05176c;--color-neutral-content:#9cbcff;--color-info:#2563eb;--color-info-content:#d2e2ff;--color-success:#18a34a;--color-success-content:#000a02;--color-warning:#d97708;--color-warning-content:#431700;--color-error:#ff7c6f;--color-error-content:#180403;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=aqua]:checked){--color-base-100:lab(25.0745% 16.2581 -51.5406);--color-base-200:lab(15.4352% 8.93655 -32.2903);--color-base-300:lab(8.26711% 11.823 -32.2031);--color-base-content:lab(88.5823% -11.3969 -16.8484);--color-primary:lab(84.7953% -45.6578 -17.3339);--color-primary-content:lab(31.2314% -21.7673 -7.75777);--color-secondary:lab(52.8668% 25.5024 -30.1393);--color-secondary-content:lab(95.1976% 2.28897 -5.51624);--color-accent:lab(92.8354% -.198632 41.6209);--color-accent-content:lab(5.96724% -.0408217 5.34988);--color-neutral:lab(12.855% 24.2161 -51.6803);--color-neutral-content:lab(75.6741% 5.20781 -52.489);--color-info:lab(44.7953% 20.9956 -75.5263);--color-info-content:lab(89.2766% -1.02177 -15.9354);--color-success:lab(58.8245% -50.7956 35.2154);--color-success-content:lab(1.93592% -3.28699 2.01724);--color-warning:lab(60.4958% 34.777 66.1666);--color-warning-content:lab(14.762% 20.9832 22.5643);--color-error:lab(67.9585% 59.0817 38.1436);--color-error-content:lab(2.73994% 6.78001 2.83679)}}[data-theme=lofi]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f5f5f5;--color-base-300:#ebebeb;--color-base-content:#000;--color-primary:#0d0d0d;--color-primary-content:#fff;--color-secondary:#1a1919;--color-secondary-content:#fff;--color-accent:#262626;--color-accent-content:#fff;--color-neutral:#000;--color-neutral-content:#fff;--color-info:#5fcfdd;--color-info-content:#031011;--color-success:#69fec3;--color-success-content:#04160e;--color-warning:#ffd07a;--color-warning-content:#170f04;--color-error:#ff9789;--color-error-content:#180706;--radius-selector:2rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=lofi]{--color-base-100:lab(100% 0 0);--color-base-200:lab(96.52% -.0000298023 .0000119209);--color-base-300:lab(93.04% .0000298023 -.0000119209);--color-base-content:lab(0% 0 0);--color-primary:lab(3.63507% 0 -.00000298023);--color-primary-content:lab(100% 0 0);--color-secondary:lab(8.87738% .322074 .116277);--color-secondary-content:lab(100% 0 0);--color-accent:lab(15.1588% 0 0);--color-accent-content:lab(100% 0 0);--color-neutral:lab(0% 0 0);--color-neutral-content:lab(100% 0 0);--color-info:lab(77.1489% -30.3908 -16.8724);--color-info-content:lab(3.73884% -3.30169 -2.18307);--color-success:lab(90.5846% -51.8982 15.71);--color-success-content:lab(5.59951% -7.16073 2.22964);--color-warning:lab(86.6011% 13.0272 57.5883);--color-warning-content:lab(5.00037% 1.96134 5.97627);--color-error:lab(73.8629% 45.9496 30.0008);--color-error-content:lab(3.3596% 5.78914 2.75533)}}:root:has(input.theme-controller[value=lofi]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f5f5f5;--color-base-300:#ebebeb;--color-base-content:#000;--color-primary:#0d0d0d;--color-primary-content:#fff;--color-secondary:#1a1919;--color-secondary-content:#fff;--color-accent:#262626;--color-accent-content:#fff;--color-neutral:#000;--color-neutral-content:#fff;--color-info:#5fcfdd;--color-info-content:#031011;--color-success:#69fec3;--color-success-content:#04160e;--color-warning:#ffd07a;--color-warning-content:#170f04;--color-error:#ff9789;--color-error-content:#180706;--radius-selector:2rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=lofi]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(96.52% -.0000298023 .0000119209);--color-base-300:lab(93.04% .0000298023 -.0000119209);--color-base-content:lab(0% 0 0);--color-primary:lab(3.63507% 0 -.00000298023);--color-primary-content:lab(100% 0 0);--color-secondary:lab(8.87738% .322074 .116277);--color-secondary-content:lab(100% 0 0);--color-accent:lab(15.1588% 0 0);--color-accent-content:lab(100% 0 0);--color-neutral:lab(0% 0 0);--color-neutral-content:lab(100% 0 0);--color-info:lab(77.1489% -30.3908 -16.8724);--color-info-content:lab(3.73884% -3.30169 -2.18307);--color-success:lab(90.5846% -51.8982 15.71);--color-success-content:lab(5.59951% -7.16073 2.22964);--color-warning:lab(86.6011% 13.0272 57.5883);--color-warning-content:lab(5.00037% 1.96134 5.97627);--color-error:lab(73.8629% 45.9496 30.0008);--color-error-content:lab(3.3596% 5.78914 2.75533)}}[data-theme=pastel]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f9fafb;--color-base-300:#e5e6e7;--color-base-content:#161616;--color-primary:#e8d4ff;--color-primary-content:#8000d7;--color-secondary:#feccd2;--color-secondary-content:#c00038;--color-accent:#a3f2ce;--color-accent-content:#007654;--color-neutral:#61738d;--color-neutral-content:#dfe5ed;--color-info:#51e8fb;--color-info-content:#007492;--color-success:#7af1a7;--color-success-content:#007f38;--color-warning:#ffb668;--color-warning-content:#c43b00;--color-error:#ff9fa0;--color-error-content:#bd000d;--radius-selector:1rem;--radius-field:2rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:2px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=pastel]{--color-base-100:lab(100% 0 0);--color-base-200:lab(98.2157% -.123829 -.353503);--color-base-300:lab(91.2557% -.123799 -.353503);--color-base-content:lab(7.22637% -.0000149012 0);--color-primary:lab(87.6083% 13.4293 -18.7152);--color-primary-content:lab(35.4395% 70.1461 -80.0542);--color-secondary:lab(86.5739% 19.1907 4.07769);--color-secondary-content:lab(40.7001% 71.6241 30.3848);--color-accent:lab(89.6446% -31.0431 9.47143);--color-accent-content:lab(43.5587% -41.0853 11.0409);--color-neutral:lab(47.6231% -2.02695 -16.5784);--color-neutral-content:lab(90.6912% -.998229 -4.7694);--color-info:lab(84.8082% -36.7548 -21.568);--color-info-content:lab(44.7267% -21.5987 -26.118);--color-success:lab(86.8793% -47.2708 25.0066);--color-success-content:lab(46.2187% -47.0551 31.5394);--color-warning:lab(79.9919% 21.7666 50.531);--color-warning-content:lab(46.1115% 57.752 71.3111);--color-error:lab(75.6231% 36.4237 15.5413);--color-error-content:lab(39.8445% 67.2859 54.361)}}:root:has(input.theme-controller[value=pastel]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f9fafb;--color-base-300:#e5e6e7;--color-base-content:#161616;--color-primary:#e8d4ff;--color-primary-content:#8000d7;--color-secondary:#feccd2;--color-secondary-content:#c00038;--color-accent:#a3f2ce;--color-accent-content:#007654;--color-neutral:#61738d;--color-neutral-content:#dfe5ed;--color-info:#51e8fb;--color-info-content:#007492;--color-success:#7af1a7;--color-success-content:#007f38;--color-warning:#ffb668;--color-warning-content:#c43b00;--color-error:#ff9fa0;--color-error-content:#bd000d;--radius-selector:1rem;--radius-field:2rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:2px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=pastel]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(98.2157% -.123829 -.353503);--color-base-300:lab(91.2557% -.123799 -.353503);--color-base-content:lab(7.22637% -.0000149012 0);--color-primary:lab(87.6083% 13.4293 -18.7152);--color-primary-content:lab(35.4395% 70.1461 -80.0542);--color-secondary:lab(86.5739% 19.1907 4.07769);--color-secondary-content:lab(40.7001% 71.6241 30.3848);--color-accent:lab(89.6446% -31.0431 9.47143);--color-accent-content:lab(43.5587% -41.0853 11.0409);--color-neutral:lab(47.6231% -2.02695 -16.5784);--color-neutral-content:lab(90.6912% -.998229 -4.7694);--color-info:lab(84.8082% -36.7548 -21.568);--color-info-content:lab(44.7267% -21.5987 -26.118);--color-success:lab(86.8793% -47.2708 25.0066);--color-success-content:lab(46.2187% -47.0551 31.5394);--color-warning:lab(79.9919% 21.7666 50.531);--color-warning-content:lab(46.1115% 57.752 71.3111);--color-error:lab(75.6231% 36.4237 15.5413);--color-error-content:lab(39.8445% 67.2859 54.361)}}[data-theme=fantasy]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#e8e8e8;--color-base-300:#d1d1d1;--color-base-content:#1f2937;--color-primary:#6b0072;--color-primary-content:#e3cee4;--color-secondary:#0075b8;--color-secondary-content:#cfe4f4;--color-accent:#ff8e19;--color-accent-content:#170700;--color-neutral:#1f2937;--color-neutral-content:#cdd0d3;--color-info:#00b4fa;--color-info-content:#000;--color-success:#00a96e;--color-success-content:#000;--color-warning:#ffc100;--color-warning-content:#000;--color-error:#ff676a;--color-error-content:#000;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=fantasy]{--color-base-100:lab(100% 0 0);--color-base-200:lab(91.88% .0000298023 -.0000119209);--color-base-300:lab(83.76% -.0000298023 0);--color-base-content:lab(16.1381% -1.17826 -10.3674);--color-primary:lab(24.2282% 54.292 -38.6561);--color-primary-content:lab(84.986% 10.3485 -7.90401);--color-secondary:lab(46.0503% -10.5367 -50.6385);--color-secondary-content:lab(89.3384% -4.78709 -10.5816);--color-accent:lab(71.0498% 47.5041 95.0293);--color-accent-content:lab(3.05717% 5.51852 4.94197);--color-neutral:lab(16.1381% -1.17826 -10.3674);--color-neutral-content:lab(83.2388% -.357687 -1.85149);--color-info:lab(67.7131% -26.5106 -53.6881);--color-info-content:lab(0% 0 0);--color-success:lab(61.1386% -50.3277 19.7345);--color-success-content:lab(0% 0 0);--color-warning:lab(82.3443% 18.4214 108.428);--color-warning-content:lab(0% 0 0);--color-error:lab(64.956% 70.4222 37.0322);--color-error-content:lab(0% 0 0)}}:root:has(input.theme-controller[value=fantasy]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#e8e8e8;--color-base-300:#d1d1d1;--color-base-content:#1f2937;--color-primary:#6b0072;--color-primary-content:#e3cee4;--color-secondary:#0075b8;--color-secondary-content:#cfe4f4;--color-accent:#ff8e19;--color-accent-content:#170700;--color-neutral:#1f2937;--color-neutral-content:#cdd0d3;--color-info:#00b4fa;--color-info-content:#000;--color-success:#00a96e;--color-success-content:#000;--color-warning:#ffc100;--color-warning-content:#000;--color-error:#ff676a;--color-error-content:#000;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=fantasy]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(91.88% .0000298023 -.0000119209);--color-base-300:lab(83.76% -.0000298023 0);--color-base-content:lab(16.1381% -1.17826 -10.3674);--color-primary:lab(24.2282% 54.292 -38.6561);--color-primary-content:lab(84.986% 10.3485 -7.90401);--color-secondary:lab(46.0503% -10.5367 -50.6385);--color-secondary-content:lab(89.3384% -4.78709 -10.5816);--color-accent:lab(71.0498% 47.5041 95.0293);--color-accent-content:lab(3.05717% 5.51852 4.94197);--color-neutral:lab(16.1381% -1.17826 -10.3674);--color-neutral-content:lab(83.2388% -.357687 -1.85149);--color-info:lab(67.7131% -26.5106 -53.6881);--color-info-content:lab(0% 0 0);--color-success:lab(61.1386% -50.3277 19.7345);--color-success-content:lab(0% 0 0);--color-warning:lab(82.3443% 18.4214 108.428);--color-warning-content:lab(0% 0 0);--color-error:lab(64.956% 70.4222 37.0322);--color-error-content:lab(0% 0 0)}}[data-theme=wireframe]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f5f5f5;--color-base-300:#ebebeb;--color-base-content:#161616;--color-primary:#d4d4d4;--color-primary-content:#242424;--color-secondary:#d4d4d4;--color-secondary-content:#242424;--color-accent:#d4d4d4;--color-accent-content:#242424;--color-neutral:#d4d4d4;--color-neutral-content:#242424;--color-info:#005885;--color-info-content:#b8e6fe;--color-success:#005f45;--color-success-content:#a3f2ce;--color-warning:#943c00;--color-warning-content:#fde484;--color-error:#9d0410;--color-error-content:#fec8c8;--radius-selector:0rem;--radius-field:.25rem;--radius-box:.25rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=wireframe]{--color-base-100:lab(100% 0 0);--color-base-200:lab(96.52% -.0000298023 .0000119209);--color-base-300:lab(93.04% .0000298023 -.0000119209);--color-base-content:lab(7.22637% -.0000149012 0);--color-primary:lab(84.92% 0 -.0000119209);--color-primary-content:lab(14.16% 0 0);--color-secondary:lab(84.92% 0 -.0000119209);--color-secondary-content:lab(14.16% 0 0);--color-accent:lab(84.92% 0 -.0000119209);--color-accent-content:lab(14.16% 0 0);--color-neutral:lab(84.92% 0 -.0000119209);--color-neutral-content:lab(14.16% 0 0);--color-info:lab(34.813% -9.51259 -34.399);--color-info-content:lab(88.5823% -11.3969 -16.8484);--color-success:lab(35.1354% -33.1288 8.04085);--color-success-content:lab(89.6446% -31.0431 9.47143);--color-warning:lab(37.5324% 37.1958 52.5706);--color-warning-content:lab(91.2553% -.488907 49.9405);--color-error:lab(33.2514% 55.9157 41.3049);--color-error-content:lab(85.4369% 19.8817 7.75958)}}:root:has(input.theme-controller[value=wireframe]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f5f5f5;--color-base-300:#ebebeb;--color-base-content:#161616;--color-primary:#d4d4d4;--color-primary-content:#242424;--color-secondary:#d4d4d4;--color-secondary-content:#242424;--color-accent:#d4d4d4;--color-accent-content:#242424;--color-neutral:#d4d4d4;--color-neutral-content:#242424;--color-info:#005885;--color-info-content:#b8e6fe;--color-success:#005f45;--color-success-content:#a3f2ce;--color-warning:#943c00;--color-warning-content:#fde484;--color-error:#9d0410;--color-error-content:#fec8c8;--radius-selector:0rem;--radius-field:.25rem;--radius-box:.25rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=wireframe]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(96.52% -.0000298023 .0000119209);--color-base-300:lab(93.04% .0000298023 -.0000119209);--color-base-content:lab(7.22637% -.0000149012 0);--color-primary:lab(84.92% 0 -.0000119209);--color-primary-content:lab(14.16% 0 0);--color-secondary:lab(84.92% 0 -.0000119209);--color-secondary-content:lab(14.16% 0 0);--color-accent:lab(84.92% 0 -.0000119209);--color-accent-content:lab(14.16% 0 0);--color-neutral:lab(84.92% 0 -.0000119209);--color-neutral-content:lab(14.16% 0 0);--color-info:lab(34.813% -9.51259 -34.399);--color-info-content:lab(88.5823% -11.3969 -16.8484);--color-success:lab(35.1354% -33.1288 8.04085);--color-success-content:lab(89.6446% -31.0431 9.47143);--color-warning:lab(37.5324% 37.1958 52.5706);--color-warning-content:lab(91.2553% -.488907 49.9405);--color-error:lab(33.2514% 55.9157 41.3049);--color-error-content:lab(85.4369% 19.8817 7.75958)}}[data-theme=black]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#000;--color-base-200:#141414;--color-base-300:#1b1b1b;--color-base-content:#d6d6d6;--color-primary:#3a3a3a;--color-primary-content:#fff;--color-secondary:#3a3a3a;--color-secondary-content:#fff;--color-accent:#3a3a3a;--color-accent-content:#fff;--color-neutral:#3a3a3a;--color-neutral-content:#fff;--color-info:#002cea;--color-info-content:#c9dbff;--color-success:#028002;--color-success-content:#d3e6d0;--color-warning:#ff0;--color-warning-content:#161600;--color-error:#ff0301;--color-error-content:#160000;--radius-selector:0rem;--radius-field:0rem;--radius-box:0rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=black]{--color-base-100:lab(0% 0 0);--color-base-200:lab(6.19571% 0 0);--color-base-300:lab(9.52% -.00000745058 0);--color-base-content:lab(85.6264% -.0000298023 .0000119209);--color-primary:lab(24.6% 0 0);--color-primary-content:lab(100% 0 0);--color-secondary:lab(24.6% 0 0);--color-secondary-content:lab(100% 0 0);--color-accent:lab(24.6% 0 0);--color-accent-content:lab(100% 0 0);--color-neutral:lab(24.6% 0 0);--color-neutral-content:lab(100% 0 0);--color-info:lab(29.5786% 68.1828 -111.947);--color-info-content:lab(86.9649% -.614971 -22.8506);--color-success:lab(46.2693% -47.3199 48.2556);--color-success-content:lab(89.311% -9.46093 8.0988);--color-warning:lab(97.6067% -15.7493 93.39);--color-warning-content:lab(6.78697% -2.72717 9.99282);--color-error:lab(54.2976% 80.5821 69.4726);--color-error-content:lab(1.60986% 7.06433 2.5444)}}:root:has(input.theme-controller[value=black]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#000;--color-base-200:#141414;--color-base-300:#1b1b1b;--color-base-content:#d6d6d6;--color-primary:#3a3a3a;--color-primary-content:#fff;--color-secondary:#3a3a3a;--color-secondary-content:#fff;--color-accent:#3a3a3a;--color-accent-content:#fff;--color-neutral:#3a3a3a;--color-neutral-content:#fff;--color-info:#002cea;--color-info-content:#c9dbff;--color-success:#028002;--color-success-content:#d3e6d0;--color-warning:#ff0;--color-warning-content:#161600;--color-error:#ff0301;--color-error-content:#160000;--radius-selector:0rem;--radius-field:0rem;--radius-box:0rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=black]:checked){--color-base-100:lab(0% 0 0);--color-base-200:lab(6.19571% 0 0);--color-base-300:lab(9.52% -.00000745058 0);--color-base-content:lab(85.6264% -.0000298023 .0000119209);--color-primary:lab(24.6% 0 0);--color-primary-content:lab(100% 0 0);--color-secondary:lab(24.6% 0 0);--color-secondary-content:lab(100% 0 0);--color-accent:lab(24.6% 0 0);--color-accent-content:lab(100% 0 0);--color-neutral:lab(24.6% 0 0);--color-neutral-content:lab(100% 0 0);--color-info:lab(29.5786% 68.1828 -111.947);--color-info-content:lab(86.9649% -.614971 -22.8506);--color-success:lab(46.2693% -47.3199 48.2556);--color-success-content:lab(89.311% -9.46093 8.0988);--color-warning:lab(97.6067% -15.7493 93.39);--color-warning-content:lab(6.78697% -2.72717 9.99282);--color-error:lab(54.2976% 80.5821 69.4726);--color-error-content:lab(1.60986% 7.06433 2.5444)}}[data-theme=luxury]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#09090b;--color-base-200:#171618;--color-base-300:#1e1d1f;--color-base-content:#dca54d;--color-primary:#fff;--color-primary-content:#161616;--color-secondary:#152747;--color-secondary-content:#cbd0d7;--color-accent:#513448;--color-accent-content:#dad3d7;--color-neutral:#331800;--color-neutral-content:#ffe7a4;--color-info:#67c6ff;--color-info-content:#040e16;--color-success:#87d03a;--color-success-content:#061001;--color-warning:#e2d563;--color-warning-content:#121003;--color-error:#ff6f6f;--color-error-content:#160404;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=luxury]{--color-base-100:lab(2.50264% .19034 -.700414);--color-base-200:lab(7.42005% .822872 -1.15513);--color-base-300:lab(10.8856% .856862 -1.18123);--color-base-content:lab(71.7826% 14.2739 52.6436);--color-primary:lab(100% 0 0);--color-primary-content:lab(7.22637% -.0000149012 0);--color-secondary:lab(15.5052% 1.79671 -22.6367);--color-secondary-content:lab(83.1564% -.534475 -4.48828);--color-accent:lab(25.829% 15.8493 -6.75252);--color-accent-content:lab(85.1709% 3.16435 -1.34234);--color-neutral:lab(11.9002% 12.2587 17.9702);--color-neutral-content:lab(92.4653% 1.52498 36.0272);--color-info:lab(75.7634% -16.8923 -37.0682);--color-info-content:lab(3.57734% -1.88227 -5.37754);--color-success:lab(76.5839% -40.7654 62.3711);--color-success-content:lab(3.67156% -4.33461 4.86201);--color-warning:lab(84.6678% -5.78606 56.9625);--color-warning-content:lab(4.72219% -.802323 5.64092);--color-error:lab(65.4465% 55.8225 28.8768);--color-error-content:lab(2.50196% 5.96539 2.14048)}}:root:has(input.theme-controller[value=luxury]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#09090b;--color-base-200:#171618;--color-base-300:#1e1d1f;--color-base-content:#dca54d;--color-primary:#fff;--color-primary-content:#161616;--color-secondary:#152747;--color-secondary-content:#cbd0d7;--color-accent:#513448;--color-accent-content:#dad3d7;--color-neutral:#331800;--color-neutral-content:#ffe7a4;--color-info:#67c6ff;--color-info-content:#040e16;--color-success:#87d03a;--color-success-content:#061001;--color-warning:#e2d563;--color-warning-content:#121003;--color-error:#ff6f6f;--color-error-content:#160404;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=luxury]:checked){--color-base-100:lab(2.50264% .19034 -.700414);--color-base-200:lab(7.42005% .822872 -1.15513);--color-base-300:lab(10.8856% .856862 -1.18123);--color-base-content:lab(71.7826% 14.2739 52.6436);--color-primary:lab(100% 0 0);--color-primary-content:lab(7.22637% -.0000149012 0);--color-secondary:lab(15.5052% 1.79671 -22.6367);--color-secondary-content:lab(83.1564% -.534475 -4.48828);--color-accent:lab(25.829% 15.8493 -6.75252);--color-accent-content:lab(85.1709% 3.16435 -1.34234);--color-neutral:lab(11.9002% 12.2587 17.9702);--color-neutral-content:lab(92.4653% 1.52498 36.0272);--color-info:lab(75.7634% -16.8923 -37.0682);--color-info-content:lab(3.57734% -1.88227 -5.37754);--color-success:lab(76.5839% -40.7654 62.3711);--color-success-content:lab(3.67156% -4.33461 4.86201);--color-warning:lab(84.6678% -5.78606 56.9625);--color-warning-content:lab(4.72219% -.802323 5.64092);--color-error:lab(65.4465% 55.8225 28.8768);--color-error-content:lab(2.50196% 5.96539 2.14048)}}[data-theme=dracula]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#282a36;--color-base-200:#232530;--color-base-300:#1f202a;--color-base-content:#f8f8f3;--color-primary:#ff79c6;--color-primary-content:#16050e;--color-secondary:#bd93f9;--color-secondary-content:#0d0815;--color-accent:#ffb86c;--color-accent-content:#160d04;--color-neutral:#414558;--color-neutral-content:#d6d7db;--color-info:#8be9fd;--color-info-content:#071316;--color-success:#51fa7b;--color-success-content:#021505;--color-warning:#f1fa8c;--color-warning-content:#141507;--color-error:#f55;--color-error-content:#160202;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=dracula]{--color-base-100:lab(17.2524% 1.51786 -8.05813);--color-base-200:lab(14.9297% 1.37024 -7.32936);--color-base-300:lab(12.5964% 1.31262 -6.95863);--color-base-content:lab(97.4463% -.689149 2.55519);--color-primary:lab(69.0262% 58.0846 -15.0602);--color-primary-content:lab(2.84991% 6.68752 -1.64467);--color-secondary:lab(68.0159% 31.2086 -45.3959);--color-secondary-content:lab(2.75031% 3.25137 -5.84603);--color-accent:lab(80.471% 20.7739 48.7146);--color-accent-content:lab(4.15832% 2.70925 4.51265);--color-neutral:lab(29.5027% 1.8976 -11.7512);--color-neutral-content:lab(85.9117% .229746 -2.26382);--color-info:lab(87.0503% -25.2196 -18.88);--color-info-content:lab(5.06288% -3.4086 -2.98281);--color-success:lab(87.7296% -64.5391 47.0763);--color-success-content:lab(5.15977% -8.17823 5.26169);--color-warning:lab(95.867% -14.4629 51.2514);--color-warning-content:lab(6.47631% -2.38353 6.58255);--color-error:lab(61.0594% 65.1267 38.0719);--color-error-content:lab(2.11937% 6.45687 2.31729)}}:root:has(input.theme-controller[value=dracula]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#282a36;--color-base-200:#232530;--color-base-300:#1f202a;--color-base-content:#f8f8f3;--color-primary:#ff79c6;--color-primary-content:#16050e;--color-secondary:#bd93f9;--color-secondary-content:#0d0815;--color-accent:#ffb86c;--color-accent-content:#160d04;--color-neutral:#414558;--color-neutral-content:#d6d7db;--color-info:#8be9fd;--color-info-content:#071316;--color-success:#51fa7b;--color-success-content:#021505;--color-warning:#f1fa8c;--color-warning-content:#141507;--color-error:#f55;--color-error-content:#160202;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=dracula]:checked){--color-base-100:lab(17.2524% 1.51786 -8.05813);--color-base-200:lab(14.9297% 1.37024 -7.32936);--color-base-300:lab(12.5964% 1.31262 -6.95863);--color-base-content:lab(97.4463% -.689149 2.55519);--color-primary:lab(69.0262% 58.0846 -15.0602);--color-primary-content:lab(2.84991% 6.68752 -1.64467);--color-secondary:lab(68.0159% 31.2086 -45.3959);--color-secondary-content:lab(2.75031% 3.25137 -5.84603);--color-accent:lab(80.471% 20.7739 48.7146);--color-accent-content:lab(4.15832% 2.70925 4.51265);--color-neutral:lab(29.5027% 1.8976 -11.7512);--color-neutral-content:lab(85.9117% .229746 -2.26382);--color-info:lab(87.0503% -25.2196 -18.88);--color-info-content:lab(5.06288% -3.4086 -2.98281);--color-success:lab(87.7296% -64.5391 47.0763);--color-success-content:lab(5.15977% -8.17823 5.26169);--color-warning:lab(95.867% -14.4629 51.2514);--color-warning-content:lab(6.47631% -2.38353 6.58255);--color-error:lab(61.0594% 65.1267 38.0719);--color-error-content:lab(2.11937% 6.45687 2.31729)}}[data-theme=cmyk]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#eee;--color-base-300:#dedede;--color-base-content:#161616;--color-primary:#45aeee;--color-primary-content:#020b13;--color-secondary:#e8488a;--color-secondary-content:#130207;--color-accent:#fff234;--color-accent-content:#161401;--color-neutral:#1a1a1a;--color-neutral-content:#cbcbcb;--color-info:#4ba8c0;--color-info-content:#020a0d;--color-success:#823290;--color-success-content:#e6d5e9;--color-warning:#ee8134;--color-warning-content:#130601;--color-error:#e93f33;--color-error-content:#130101;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=cmyk]{--color-base-100:lab(100% 0 0);--color-base-200:lab(94.2% 0 0);--color-base-300:lab(88.4% 0 .0000119209);--color-base-content:lab(7.22637% -.0000149012 0);--color-primary:lab(67.1656% -15.4515 -41.4696);--color-primary-content:lab(2.66377% -1.40604 -5.10406);--color-secondary:lab(56.2371% 65.3899 .0332475);--color-secondary-content:lab(1.74688% 5.7414 .00218153);--color-accent:lab(94.3504% -9.26513 83.7781);--color-accent-content:lab(6.2185% -1.53024 8.70785);--color-neutral:lab(9.26248% -.00000745058 .00000298023);--color-neutral-content:lab(81.8518% 0 -.0000119209);--color-info:lab(63.9872% -23.2842 -21.0783);--color-info-content:lab(2.36743% -1.86116 -2.07067);--color-success:lab(35.8861% 44.8675 -36.25);--color-success-content:lab(87.2634% 8.56784 -7.45302);--color-warning:lab(65.7245% 38.8108 58.4563);--color-warning-content:lab(2.52973% 3.88878 3.42022);--color-error:lab(53.918% 64.84 47.6033);--color-error-content:lab(1.58436% 5.32448 2.10135)}}:root:has(input.theme-controller[value=cmyk]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#eee;--color-base-300:#dedede;--color-base-content:#161616;--color-primary:#45aeee;--color-primary-content:#020b13;--color-secondary:#e8488a;--color-secondary-content:#130207;--color-accent:#fff234;--color-accent-content:#161401;--color-neutral:#1a1a1a;--color-neutral-content:#cbcbcb;--color-info:#4ba8c0;--color-info-content:#020a0d;--color-success:#823290;--color-success-content:#e6d5e9;--color-warning:#ee8134;--color-warning-content:#130601;--color-error:#e93f33;--color-error-content:#130101;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=cmyk]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(94.2% 0 0);--color-base-300:lab(88.4% 0 .0000119209);--color-base-content:lab(7.22637% -.0000149012 0);--color-primary:lab(67.1656% -15.4515 -41.4696);--color-primary-content:lab(2.66377% -1.40604 -5.10406);--color-secondary:lab(56.2371% 65.3899 .0332475);--color-secondary-content:lab(1.74688% 5.7414 .00218153);--color-accent:lab(94.3504% -9.26513 83.7781);--color-accent-content:lab(6.2185% -1.53024 8.70785);--color-neutral:lab(9.26248% -.00000745058 .00000298023);--color-neutral-content:lab(81.8518% 0 -.0000119209);--color-info:lab(63.9872% -23.2842 -21.0783);--color-info-content:lab(2.36743% -1.86116 -2.07067);--color-success:lab(35.8861% 44.8675 -36.25);--color-success-content:lab(87.2634% 8.56784 -7.45302);--color-warning:lab(65.7245% 38.8108 58.4563);--color-warning-content:lab(2.52973% 3.88878 3.42022);--color-error:lab(53.918% 64.84 47.6033);--color-error-content:lab(1.58436% 5.32448 2.10135)}}[data-theme=autumn]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#f1f1f1;--color-base-200:#dbdbdb;--color-base-300:#c5c5c5;--color-base-content:#141414;--color-primary:#8c0327;--color-primary-content:#edd0d0;--color-secondary:#d85251;--color-secondary-content:#110202;--color-accent:#d59b6b;--color-accent-content:#100904;--color-neutral:#826a5c;--color-neutral-content:#e5e0dd;--color-info:#44adbb;--color-info-content:#020b0d;--color-success:#499380;--color-success-content:#020806;--color-warning:#e97f16;--color-warning-content:#130600;--color-error:#cf001e;--color-error-content:#ffd4d1;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=autumn]{--color-base-100:lab(95.1442% 0 -.0000238419);--color-base-200:lab(87.3641% -.0000298023 0);--color-base-300:lab(79.584% -.0000596046 .0000119209);--color-base-content:lab(6.35555% 0 0);--color-primary:lab(29.4724% 51.9149 22.2512);--color-primary-content:lab(85.9131% 10.2968 3.8025);--color-secondary:lab(53.8426% 53.436 29.869);--color-secondary-content:lab(1.58011% 4.18492 1.53311);--color-accent:lab(68.8829% 17.9884 34.1655);--color-accent-content:lab(2.83324% 1.79562 2.58717);--color-neutral:lab(46.9075% 8.11514 11.5455);--color-neutral-content:lab(89.3871% 1.45191 2.11754);--color-info:lab(65.0988% -28.0567 -16.6103);--color-info-content:lab(2.46755% -2.31844 -1.66594);--color-success:lab(55.7916% -27.7726 2.62657);--color-success-content:lab(1.71304% -1.81498 .184056);--color-warning:lab(64.4787% 37.2631 67.1194);--color-warning-content:lab(2.41567% 3.61173 3.52702);--color-error:lab(43.0311% 76.9557 53.0846);--color-error-content:lab(88.6592% 14.8478 7.74316)}}:root:has(input.theme-controller[value=autumn]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#f1f1f1;--color-base-200:#dbdbdb;--color-base-300:#c5c5c5;--color-base-content:#141414;--color-primary:#8c0327;--color-primary-content:#edd0d0;--color-secondary:#d85251;--color-secondary-content:#110202;--color-accent:#d59b6b;--color-accent-content:#100904;--color-neutral:#826a5c;--color-neutral-content:#e5e0dd;--color-info:#44adbb;--color-info-content:#020b0d;--color-success:#499380;--color-success-content:#020806;--color-warning:#e97f16;--color-warning-content:#130600;--color-error:#cf001e;--color-error-content:#ffd4d1;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=autumn]:checked){--color-base-100:lab(95.1442% 0 -.0000238419);--color-base-200:lab(87.3641% -.0000298023 0);--color-base-300:lab(79.584% -.0000596046 .0000119209);--color-base-content:lab(6.35555% 0 0);--color-primary:lab(29.4724% 51.9149 22.2512);--color-primary-content:lab(85.9131% 10.2968 3.8025);--color-secondary:lab(53.8426% 53.436 29.869);--color-secondary-content:lab(1.58011% 4.18492 1.53311);--color-accent:lab(68.8829% 17.9884 34.1655);--color-accent-content:lab(2.83324% 1.79562 2.58717);--color-neutral:lab(46.9075% 8.11514 11.5455);--color-neutral-content:lab(89.3871% 1.45191 2.11754);--color-info:lab(65.0988% -28.0567 -16.6103);--color-info-content:lab(2.46755% -2.31844 -1.66594);--color-success:lab(55.7916% -27.7726 2.62657);--color-success-content:lab(1.71304% -1.81498 .184056);--color-warning:lab(64.4787% 37.2631 67.1194);--color-warning-content:lab(2.41567% 3.61173 3.52702);--color-error:lab(43.0311% 76.9557 53.0846);--color-error-content:lab(88.6592% 14.8478 7.74316)}}[data-theme=business]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#202020;--color-base-200:#1c1c1c;--color-base-300:#181818;--color-base-content:#cdcdcd;--color-primary:#1c4e80;--color-primary-content:#d0dae5;--color-secondary:#7c909a;--color-secondary-content:#050708;--color-accent:#ea6947;--color-accent-content:#130402;--color-neutral:#23282e;--color-neutral-content:#cecfd0;--color-info:#0291d5;--color-info-content:#000710;--color-success:#6bb187;--color-success-content:#040b07;--color-warning:#dbae5a;--color-warning-content:#110b03;--color-error:#ac3e31;--color-error-content:#f2d8d4;--radius-selector:0rem;--radius-field:.25rem;--radius-box:.25rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=business]{--color-base-100:lab(12.2495% -.00000745058 -.00000298023);--color-base-200:lab(10.2717% 0 0);--color-base-300:lab(8.29504% 0 0);--color-base-content:lab(82.4492% 0 -.0000119209);--color-primary:lab(31.8716% -2.55647 -33.6151);--color-primary-content:lab(86.4485% -1.85522 -6.80977);--color-secondary:lab(58.4477% -5.63756 -7.73355);--color-secondary-content:lab(1.9096% -.396445 -.583071);--color-accent:lab(60.6254% 49.1955 43.9053);--color-accent-content:lab(2.08437% 4.57403 2.49923);--color-neutral:lab(15.8035% -1.0516 -4.6513);--color-neutral-content:lab(83.1632% -.188679 -.729144);--color-info:lab(56.4211% -14.0871 -44.5288);--color-info-content:lab(1.75948% -.97622 -4.41895);--color-success:lab(66.7083% -30.0021 14.2385);--color-success-content:lab(2.61434% -2.50937 1.17262);--color-warning:lab(74.0041% 9.92858 48.9734);--color-warning-content:lab(3.3752% 1.14586 3.9538);--color-error:lab(42.4958% 45.0087 32.6711);--color-error-content:lab(88.5293% 8.54063 5.60535)}}:root:has(input.theme-controller[value=business]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#202020;--color-base-200:#1c1c1c;--color-base-300:#181818;--color-base-content:#cdcdcd;--color-primary:#1c4e80;--color-primary-content:#d0dae5;--color-secondary:#7c909a;--color-secondary-content:#050708;--color-accent:#ea6947;--color-accent-content:#130402;--color-neutral:#23282e;--color-neutral-content:#cecfd0;--color-info:#0291d5;--color-info-content:#000710;--color-success:#6bb187;--color-success-content:#040b07;--color-warning:#dbae5a;--color-warning-content:#110b03;--color-error:#ac3e31;--color-error-content:#f2d8d4;--radius-selector:0rem;--radius-field:.25rem;--radius-box:.25rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=business]:checked){--color-base-100:lab(12.2495% -.00000745058 -.00000298023);--color-base-200:lab(10.2717% 0 0);--color-base-300:lab(8.29504% 0 0);--color-base-content:lab(82.4492% 0 -.0000119209);--color-primary:lab(31.8716% -2.55647 -33.6151);--color-primary-content:lab(86.4485% -1.85522 -6.80977);--color-secondary:lab(58.4477% -5.63756 -7.73355);--color-secondary-content:lab(1.9096% -.396445 -.583071);--color-accent:lab(60.6254% 49.1955 43.9053);--color-accent-content:lab(2.08437% 4.57403 2.49923);--color-neutral:lab(15.8035% -1.0516 -4.6513);--color-neutral-content:lab(83.1632% -.188679 -.729144);--color-info:lab(56.4211% -14.0871 -44.5288);--color-info-content:lab(1.75948% -.97622 -4.41895);--color-success:lab(66.7083% -30.0021 14.2385);--color-success-content:lab(2.61434% -2.50937 1.17262);--color-warning:lab(74.0041% 9.92858 48.9734);--color-warning-content:lab(3.3752% 1.14586 3.9538);--color-error:lab(42.4958% 45.0087 32.6711);--color-error-content:lab(88.5293% 8.54063 5.60535)}}[data-theme=acid]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#f8f8f8;--color-base-200:#eee;--color-base-300:#e1e1e1;--color-base-content:#000;--color-primary:#ff24fb;--color-primary-content:#180016;--color-secondary:#ff7a0d;--color-secondary-content:#180500;--color-accent:#cbfe00;--color-accent-content:#0f1600;--color-neutral:#140151;--color-neutral-content:#c7cadc;--color-info:#0082f4;--color-info-content:#000614;--color-success:#00f69e;--color-success-content:#001509;--color-warning:#ffe300;--color-warning-content:#161200;--color-error:#ff1d12;--color-error-content:#180000;--radius-selector:1rem;--radius-field:1rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=acid]{--color-base-100:lab(97.68% -.0000298023 .0000119209);--color-base-200:lab(94.2% 0 0);--color-base-300:lab(89.56% -.0000298023 0);--color-base-content:lab(0% 0 0);--color-primary:lab(61.6426% 104.584 -62.3431);--color-primary-content:lab(2.17017% 11.703 -7.9728);--color-secondary:lab(67.5395% 59.7689 99.8903);--color-secondary-content:lab(2.70272% 6.65647 4.46881);--color-accent:lab(93.8021% -39.8923 114.351);--color-accent-content:lab(6.12505% -6.06422 9.80839);--color-neutral:lab(6.09747% 29.3225 -44.9201);--color-neutral-content:lab(81.553% 1.56942 -9.27624);--color-info:lab(52.6019% 6.68359 -76.4472);--color-info-content:lab(1.49683% .423439 -8.81159);--color-success:lab(86.8718% -90.1122 38.3471);--color-success-content:lab(5.03825% -10.6981 4.49026);--color-warning:lab(90.4358% -2.37459 107.692);--color-warning-content:lab(5.5819% -.383124 8.88906);--color-error:lab(56.2732% 92.2163 95.7598);--color-error-content:lab(1.75027% 8.75349 2.9845)}}:root:has(input.theme-controller[value=acid]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#f8f8f8;--color-base-200:#eee;--color-base-300:#e1e1e1;--color-base-content:#000;--color-primary:#ff24fb;--color-primary-content:#180016;--color-secondary:#ff7a0d;--color-secondary-content:#180500;--color-accent:#cbfe00;--color-accent-content:#0f1600;--color-neutral:#140151;--color-neutral-content:#c7cadc;--color-info:#0082f4;--color-info-content:#000614;--color-success:#00f69e;--color-success-content:#001509;--color-warning:#ffe300;--color-warning-content:#161200;--color-error:#ff1d12;--color-error-content:#180000;--radius-selector:1rem;--radius-field:1rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=acid]:checked){--color-base-100:lab(97.68% -.0000298023 .0000119209);--color-base-200:lab(94.2% 0 0);--color-base-300:lab(89.56% -.0000298023 0);--color-base-content:lab(0% 0 0);--color-primary:lab(61.6426% 104.584 -62.3431);--color-primary-content:lab(2.17017% 11.703 -7.9728);--color-secondary:lab(67.5395% 59.7689 99.8903);--color-secondary-content:lab(2.70272% 6.65647 4.46881);--color-accent:lab(93.8021% -39.8923 114.351);--color-accent-content:lab(6.12505% -6.06422 9.80839);--color-neutral:lab(6.09747% 29.3225 -44.9201);--color-neutral-content:lab(81.553% 1.56942 -9.27624);--color-info:lab(52.6019% 6.68359 -76.4472);--color-info-content:lab(1.49683% .423439 -8.81159);--color-success:lab(86.8718% -90.1122 38.3471);--color-success-content:lab(5.03825% -10.6981 4.49026);--color-warning:lab(90.4358% -2.37459 107.692);--color-warning-content:lab(5.5819% -.383124 8.88906);--color-error:lab(56.2732% 92.2163 95.7598);--color-error-content:lab(1.75027% 8.75349 2.9845)}}[data-theme=lemonade]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#f8fdef;--color-base-200:#e1e6d9;--color-base-300:#cbcfc3;--color-base-content:#151614;--color-primary:#4b9200;--color-primary-content:#020800;--color-secondary:#bcc000;--color-secondary-content:#0d0e00;--color-accent:#ebd100;--color-accent-content:#131000;--color-neutral:#343300;--color-neutral-content:#d2d3c7;--color-info:#b1d9e9;--color-info-content:#0c1113;--color-success:#b9dbc6;--color-success-content:#0d110e;--color-warning:#d7d3b0;--color-warning-content:#11100c;--color-error:#efc6c2;--color-error-content:#140e0e;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=lemonade]{--color-base-100:lab(98.7263% -3.77017 6.34241);--color-base-200:lab(90.6886% -3.39469 5.70672);--color-base-300:lab(82.6618% -3.20518 5.39055);--color-base-content:lab(6.99094% -.683971 1.12266);--color-primary:lab(54.3367% -44.1267 71.4774);--color-primary-content:lab(1.60884% -2.56838 2.54891);--color-secondary:lab(75.3931% -15.13 95.3231);--color-secondary-content:lab(3.53378% -1.68499 5.69809);--color-accent:lab(83.8756% -2.44945 103.072);--color-accent-content:lab(4.61222% -.342384 7.41318);--color-neutral:lab(20.366% -4.6878 31.5163);--color-neutral-content:lab(84.1187% -1.61752 5.43684);--color-info:lab(84.2095% -10.844 -12.3281);--color-info-content:lab(4.65755% -1.41581 -1.76235);--color-success:lab(84.6144% -14.9354 6.6524);--color-success-content:lab(4.71173% -1.94321 .862303);--color-warning:lab(84.3071% -2.8984 17.9641);--color-warning-content:lab(4.6707% -.388689 2.16907);--color-error:lab(83.5496% 14.3623 8.07523);--color-error-content:lab(4.56993% 1.95403 1.01659)}}:root:has(input.theme-controller[value=lemonade]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#f8fdef;--color-base-200:#e1e6d9;--color-base-300:#cbcfc3;--color-base-content:#151614;--color-primary:#4b9200;--color-primary-content:#020800;--color-secondary:#bcc000;--color-secondary-content:#0d0e00;--color-accent:#ebd100;--color-accent-content:#131000;--color-neutral:#343300;--color-neutral-content:#d2d3c7;--color-info:#b1d9e9;--color-info-content:#0c1113;--color-success:#b9dbc6;--color-success-content:#0d110e;--color-warning:#d7d3b0;--color-warning-content:#11100c;--color-error:#efc6c2;--color-error-content:#140e0e;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=lemonade]:checked){--color-base-100:lab(98.7263% -3.77017 6.34241);--color-base-200:lab(90.6886% -3.39469 5.70672);--color-base-300:lab(82.6618% -3.20518 5.39055);--color-base-content:lab(6.99094% -.683971 1.12266);--color-primary:lab(54.3367% -44.1267 71.4774);--color-primary-content:lab(1.60884% -2.56838 2.54891);--color-secondary:lab(75.3931% -15.13 95.3231);--color-secondary-content:lab(3.53378% -1.68499 5.69809);--color-accent:lab(83.8756% -2.44945 103.072);--color-accent-content:lab(4.61222% -.342384 7.41318);--color-neutral:lab(20.366% -4.6878 31.5163);--color-neutral-content:lab(84.1187% -1.61752 5.43684);--color-info:lab(84.2095% -10.844 -12.3281);--color-info-content:lab(4.65755% -1.41581 -1.76235);--color-success:lab(84.6144% -14.9354 6.6524);--color-success-content:lab(4.71173% -1.94321 .862303);--color-warning:lab(84.3071% -2.8984 17.9641);--color-warning-content:lab(4.6707% -.388689 2.16907);--color-error:lab(83.5496% 14.3623 8.07523);--color-error-content:lab(4.56993% 1.95403 1.01659)}}[data-theme=night]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#0f172a;--color-base-200:#0c1425;--color-base-300:#0a1120;--color-base-content:#c9cbd0;--color-primary:#3abdf7;--color-primary-content:#010d15;--color-secondary:#818cf8;--color-secondary-content:#060715;--color-accent:#f471b5;--color-accent-content:#14040c;--color-neutral:#1e293b;--color-neutral-content:#cdd0d4;--color-info:#0ca5e9;--color-info-content:#000;--color-success:#2fd4bf;--color-success-content:#01100d;--color-warning:#f4bf51;--color-warning-content:#140d02;--color-error:#fb7085;--color-error-content:#150406;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=night]{--color-base-100:lab(7.78565% 1.50348 -14.0094);--color-base-200:lab(6.25486% 1.27754 -13.0361);--color-base-300:lab(4.94775% .99355 -11.3494);--color-base-content:lab(81.586% -.131369 -2.64797);--color-primary:lab(71.5903% -21.6132 -39.8504);--color-primary-content:lab(3.11124% -2.14361 -5.32374);--color-secondary:lab(61.1158% 17.6693 -56.1728);--color-secondary-content:lab(2.12706% 1.49039 -6.71019);--color-accent:lab(65.5697% 56.4195 -10.8487);--color-accent-content:lab(2.51391% 6.05859 -1.0757);--color-neutral:lab(16.2295% -.501111 -12.9309);--color-neutral-content:lab(83.261% -.366569 -2.61757);--color-info:lab(63.3387% -17.6767 -44.8666);--color-info-content:lab(0% 0 0);--color-success:lab(76.6362% -46.052 -1.99498);--color-success-content:lab(3.67713% -4.80961 -.237116);--color-warning:lab(80.7185% 11.4659 61.1291);--color-warning-content:lab(4.18896% 1.46458 5.26781);--color-error:lab(65.3604% 55.3293 16.2444);--color-error-content:lab(2.49336% 5.93162 1.3272)}}:root:has(input.theme-controller[value=night]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#0f172a;--color-base-200:#0c1425;--color-base-300:#0a1120;--color-base-content:#c9cbd0;--color-primary:#3abdf7;--color-primary-content:#010d15;--color-secondary:#818cf8;--color-secondary-content:#060715;--color-accent:#f471b5;--color-accent-content:#14040c;--color-neutral:#1e293b;--color-neutral-content:#cdd0d4;--color-info:#0ca5e9;--color-info-content:#000;--color-success:#2fd4bf;--color-success-content:#01100d;--color-warning:#f4bf51;--color-warning-content:#140d02;--color-error:#fb7085;--color-error-content:#150406;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=night]:checked){--color-base-100:lab(7.78565% 1.50348 -14.0094);--color-base-200:lab(6.25486% 1.27754 -13.0361);--color-base-300:lab(4.94775% .99355 -11.3494);--color-base-content:lab(81.586% -.131369 -2.64797);--color-primary:lab(71.5903% -21.6132 -39.8504);--color-primary-content:lab(3.11124% -2.14361 -5.32374);--color-secondary:lab(61.1158% 17.6693 -56.1728);--color-secondary-content:lab(2.12706% 1.49039 -6.71019);--color-accent:lab(65.5697% 56.4195 -10.8487);--color-accent-content:lab(2.51391% 6.05859 -1.0757);--color-neutral:lab(16.2295% -.501111 -12.9309);--color-neutral-content:lab(83.261% -.366569 -2.61757);--color-info:lab(63.3387% -17.6767 -44.8666);--color-info-content:lab(0% 0 0);--color-success:lab(76.6362% -46.052 -1.99498);--color-success-content:lab(3.67713% -4.80961 -.237116);--color-warning:lab(80.7185% 11.4659 61.1291);--color-warning-content:lab(4.18896% 1.46458 5.26781);--color-error:lab(65.3604% 55.3293 16.2444);--color-error-content:lab(2.49336% 5.93162 1.3272)}}[data-theme=coffee]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#261b25;--color-base-200:#1e151d;--color-base-300:#120a11;--color-base-content:#c59f61;--color-primary:#db924c;--color-primary-content:#110802;--color-secondary:#273e3f;--color-secondary-content:#d0d5d5;--color-accent:#11576d;--color-accent-content:#d0dbe0;--color-neutral:#120c12;--color-neutral-content:#c9c7c9;--color-info:#8ecac1;--color-info-content:#070f0e;--color-success:#9db787;--color-success-content:#090c07;--color-warning:#ffd260;--color-warning-content:#161003;--color-error:#fc9581;--color-error-content:#150806;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=coffee]{--color-base-100:lab(11.5186% 6.73094 -4.28204);--color-base-200:lab(8.06616% 6.14451 -3.90737);--color-base-300:lab(3.54214% 3.45968 -2.28596);--color-base-content:lab(68.0107% 8.72469 37.8636);--color-primary:lab(67.1253% 23.4281 48.0589);--color-primary-content:lab(2.66053% 2.32654 3.1773);--color-secondary:lab(24.2685% -9.19533 -3.64553);--color-secondary-content:lab(84.8464% -1.59159 -.640059);--color-accent:lab(33.7195% -15.1877 -18.9201);--color-accent-content:lab(86.7598% -3.31101 -3.73704);--color-neutral:lab(3.93372% 2.78965 -2.10369);--color-neutral-content:lab(80.5901% .850797 -.625491);--color-info:lab(76.9699% -21.4916 -2.07351);--color-info-content:lab(3.71591% -2.33059 -.240013);--color-success:lab(71.4935% -15.6754 21.279);--color-success-content:lab(3.09833% -1.55634 1.90848);--color-warning:lab(86.5754% 7.29615 61.0827);--color-warning-content:lab(4.99662% 1.08391 6.19825);--color-error:lab(72.5858% 38.1292 28.0821);--color-error-content:lab(3.22106% 4.46529 2.48123)}}:root:has(input.theme-controller[value=coffee]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#261b25;--color-base-200:#1e151d;--color-base-300:#120a11;--color-base-content:#c59f61;--color-primary:#db924c;--color-primary-content:#110802;--color-secondary:#273e3f;--color-secondary-content:#d0d5d5;--color-accent:#11576d;--color-accent-content:#d0dbe0;--color-neutral:#120c12;--color-neutral-content:#c9c7c9;--color-info:#8ecac1;--color-info-content:#070f0e;--color-success:#9db787;--color-success-content:#090c07;--color-warning:#ffd260;--color-warning-content:#161003;--color-error:#fc9581;--color-error-content:#150806;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=coffee]:checked){--color-base-100:lab(11.5186% 6.73094 -4.28204);--color-base-200:lab(8.06616% 6.14451 -3.90737);--color-base-300:lab(3.54214% 3.45968 -2.28596);--color-base-content:lab(68.0107% 8.72469 37.8636);--color-primary:lab(67.1253% 23.4281 48.0589);--color-primary-content:lab(2.66053% 2.32654 3.1773);--color-secondary:lab(24.2685% -9.19533 -3.64553);--color-secondary-content:lab(84.8464% -1.59159 -.640059);--color-accent:lab(33.7195% -15.1877 -18.9201);--color-accent-content:lab(86.7598% -3.31101 -3.73704);--color-neutral:lab(3.93372% 2.78965 -2.10369);--color-neutral-content:lab(80.5901% .850797 -.625491);--color-info:lab(76.9699% -21.4916 -2.07351);--color-info-content:lab(3.71591% -2.33059 -.240013);--color-success:lab(71.4935% -15.6754 21.279);--color-success-content:lab(3.09833% -1.55634 1.90848);--color-warning:lab(86.5754% 7.29615 61.0827);--color-warning-content:lab(4.99662% 1.08391 6.19825);--color-error:lab(72.5858% 38.1292 28.0821);--color-error-content:lab(3.22106% 4.46529 2.48123)}}[data-theme=winter]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f2f7fe;--color-base-300:#e3e9f4;--color-base-content:#394e6a;--color-primary:#006ef6;--color-primary-content:#d0e4ff;--color-secondary:#463aa2;--color-secondary-content:#d5d7ee;--color-accent:#c148ac;--color-accent-content:#0e020b;--color-neutral:#021431;--color-neutral-content:#c5cbd2;--color-info:#94e7fb;--color-info-content:#081315;--color-success:#81cfd1;--color-success-content:#060f10;--color-warning:#efd7bc;--color-warning-content:#14110d;--color-error:#e58b8b;--color-error-content:#120707;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=winter]{--color-base-100:lab(100% 0 0);--color-base-200:lab(97.0256% -.579119 -4.10503);--color-base-300:lab(92.1275% -.540108 -5.99967);--color-base-content:lab(32.3645% -2.07642 -18.7618);--color-primary:lab(46.9717% 23.075 -88.0595);--color-primary-content:lab(89.8181% -2.65494 -18.5583);--color-secondary:lab(30.8474% 28.7337 -55.8122);--color-secondary-content:lab(86.4008% 2.72575 -11.7019);--color-accent:lab(50.708% 57.2543 -28.9765);--color-accent-content:lab(1.37536% 4.26588 -2.26665);--color-neutral:lab(6.34021% 2.31444 -21.6251);--color-neutral-content:lab(81.318% -.772327 -4.44012);--color-info:lab(86.8071% -22.5711 -18.0407);--color-info-content:lab(5.03021% -3.14728 -2.92687);--color-success:lab(78.1574% -24.6619 -9.01252);--color-success-content:lab(3.8616% -2.78492 -1.14045);--color-warning:lab(87.452% 5.30511 16.744);--color-warning-content:lab(5.12547% .797942 2.26245);--color-error:lab(67.6569% 35.0793 15.4131);--color-error-content:lab(2.71029% 3.75202 1.3437)}}:root:has(input.theme-controller[value=winter]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f2f7fe;--color-base-300:#e3e9f4;--color-base-content:#394e6a;--color-primary:#006ef6;--color-primary-content:#d0e4ff;--color-secondary:#463aa2;--color-secondary-content:#d5d7ee;--color-accent:#c148ac;--color-accent-content:#0e020b;--color-neutral:#021431;--color-neutral-content:#c5cbd2;--color-info:#94e7fb;--color-info-content:#081315;--color-success:#81cfd1;--color-success-content:#060f10;--color-warning:#efd7bc;--color-warning-content:#14110d;--color-error:#e58b8b;--color-error-content:#120707;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=winter]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(97.0256% -.579119 -4.10503);--color-base-300:lab(92.1275% -.540108 -5.99967);--color-base-content:lab(32.3645% -2.07642 -18.7618);--color-primary:lab(46.9717% 23.075 -88.0595);--color-primary-content:lab(89.8181% -2.65494 -18.5583);--color-secondary:lab(30.8474% 28.7337 -55.8122);--color-secondary-content:lab(86.4008% 2.72575 -11.7019);--color-accent:lab(50.708% 57.2543 -28.9765);--color-accent-content:lab(1.37536% 4.26588 -2.26665);--color-neutral:lab(6.34021% 2.31444 -21.6251);--color-neutral-content:lab(81.318% -.772327 -4.44012);--color-info:lab(86.8071% -22.5711 -18.0407);--color-info-content:lab(5.03021% -3.14728 -2.92687);--color-success:lab(78.1574% -24.6619 -9.01252);--color-success-content:lab(3.8616% -2.78492 -1.14045);--color-warning:lab(87.452% 5.30511 16.744);--color-warning-content:lab(5.12547% .797942 2.26245);--color-error:lab(67.6569% 35.0793 15.4131);--color-error-content:lab(2.71029% 3.75202 1.3437)}}[data-theme=dim]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#2a303c;--color-base-200:#242933;--color-base-300:#20252e;--color-base-content:#b2ccd6;--color-primary:#9fe88d;--color-primary-content:#091307;--color-secondary:#ff7d5d;--color-secondary-content:#160503;--color-accent:#c792e9;--color-accent-content:#0e0813;--color-neutral:#1c212b;--color-neutral-content:#b2ccd6;--color-info:#28ebff;--color-info-content:#011316;--color-success:#62efbd;--color-success-content:#03140d;--color-warning:#efd057;--color-warning-content:#141003;--color-error:#ffae9b;--color-error-content:#160b09;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=dim]{--color-base-100:lab(19.6723% -.17938 -8.46498);--color-base-200:lab(16.4233% -.185296 -7.00837);--color-base-300:lab(14.4764% -.382513 -6.61221);--color-base-content:lab(80.3291% -7.40752 -8.00557);--color-primary:lab(85.5861% -36.0239 36.5857);--color-primary-content:lab(4.85138% -4.71839 4.19818);--color-secondary:lab(67.7323% 48.4987 41.8244);--color-secondary-content:lab(2.71785% 5.38566 3.00674);--color-accent:lab(68.2164% 32.1265 -36.2513);--color-accent-content:lab(2.76961% 3.36669 -4.41874);--color-neutral:lab(12.58% -.122048 -7.34576);--color-neutral-content:lab(80.3291% -7.40752 -8.00557);--color-info:lab(85.0419% -41.3861 -23.3216);--color-info-content:lab(4.77313% -5.26147 -3.71018);--color-success:lab(85.8434% -48.6696 12.3112);--color-success-content:lab(4.88647% -6.17752 1.62921);--color-warning:lab(84.4832% 1.40542 62.0505);--color-warning-content:lab(4.69617% .184178 5.89212);--color-error:lab(78.8025% 28.7108 22.315);--color-error-content:lab(3.94852% 3.67327 2.33457)}}:root:has(input.theme-controller[value=dim]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#2a303c;--color-base-200:#242933;--color-base-300:#20252e;--color-base-content:#b2ccd6;--color-primary:#9fe88d;--color-primary-content:#091307;--color-secondary:#ff7d5d;--color-secondary-content:#160503;--color-accent:#c792e9;--color-accent-content:#0e0813;--color-neutral:#1c212b;--color-neutral-content:#b2ccd6;--color-info:#28ebff;--color-info-content:#011316;--color-success:#62efbd;--color-success-content:#03140d;--color-warning:#efd057;--color-warning-content:#141003;--color-error:#ffae9b;--color-error-content:#160b09;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=dim]:checked){--color-base-100:lab(19.6723% -.17938 -8.46498);--color-base-200:lab(16.4233% -.185296 -7.00837);--color-base-300:lab(14.4764% -.382513 -6.61221);--color-base-content:lab(80.3291% -7.40752 -8.00557);--color-primary:lab(85.5861% -36.0239 36.5857);--color-primary-content:lab(4.85138% -4.71839 4.19818);--color-secondary:lab(67.7323% 48.4987 41.8244);--color-secondary-content:lab(2.71785% 5.38566 3.00674);--color-accent:lab(68.2164% 32.1265 -36.2513);--color-accent-content:lab(2.76961% 3.36669 -4.41874);--color-neutral:lab(12.58% -.122048 -7.34576);--color-neutral-content:lab(80.3291% -7.40752 -8.00557);--color-info:lab(85.0419% -41.3861 -23.3216);--color-info-content:lab(4.77313% -5.26147 -3.71018);--color-success:lab(85.8434% -48.6696 12.3112);--color-success-content:lab(4.88647% -6.17752 1.62921);--color-warning:lab(84.4832% 1.40542 62.0505);--color-warning-content:lab(4.69617% .184178 5.89212);--color-error:lab(78.8025% 28.7108 22.315);--color-error-content:lab(3.94852% 3.67327 2.33457)}}[data-theme=nord]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#eceff4;--color-base-200:#e5e9f0;--color-base-300:#d8dee9;--color-base-content:#2e3440;--color-primary:#5e81ac;--color-primary-content:#03060b;--color-secondary:#81a1c1;--color-secondary-content:#06090d;--color-accent:#88c0d0;--color-accent-content:#070d10;--color-neutral:#4c566a;--color-neutral-content:#d8dee9;--color-info:#b48ead;--color-info-content:#0c070b;--color-success:#a3be8d;--color-success-content:#0a0d07;--color-warning:#ebcb8b;--color-warning-content:#130f07;--color-error:#bf616a;--color-error-content:#0d0304;--radius-selector:1rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=nord]{--color-base-100:lab(94.324% -.339657 -2.62373);--color-base-200:lab(92.1906% -.413388 -3.75246);--color-base-300:lab(88.2495% -.537157 -5.99798);--color-base-content:lab(21.5129% -.214115 -8.11484);--color-primary:lab(52.6518% -3.74743 -27.0171);--color-primary-content:lab(1.49876% -.241503 -2.13669);--color-secondary:lab(64.6969% -5.5643 -20.3257);--color-secondary-content:lab(2.43381% -.470936 -1.96204);--color-accent:lab(74.2453% -15.8457 -14.1565);--color-accent-content:lab(3.40084% -1.66879 -1.69079);--color-neutral:lab(36.2786% -.24499 -12.8697);--color-neutral-content:lab(88.2495% -.537157 -5.99798);--color-info:lab(63.4156% 18.5962 -10.5133);--color-info-content:lab(2.32111% 1.66221 -.960082);--color-success:lab(73.9575% -16.0914 21.8886);--color-success-content:lab(3.36525% -1.64589 2.02379);--color-warning:lab(83.3692% 5.34141 36.1947);--color-warning-content:lab(4.54197% .693284 3.83488);--color-error:lab(52.9945% 38.9133 13.1792);--color-error-content:lab(1.52051% 2.92406 .778365)}}:root:has(input.theme-controller[value=nord]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#eceff4;--color-base-200:#e5e9f0;--color-base-300:#d8dee9;--color-base-content:#2e3440;--color-primary:#5e81ac;--color-primary-content:#03060b;--color-secondary:#81a1c1;--color-secondary-content:#06090d;--color-accent:#88c0d0;--color-accent-content:#070d10;--color-neutral:#4c566a;--color-neutral-content:#d8dee9;--color-info:#b48ead;--color-info-content:#0c070b;--color-success:#a3be8d;--color-success-content:#0a0d07;--color-warning:#ebcb8b;--color-warning-content:#130f07;--color-error:#bf616a;--color-error-content:#0d0304;--radius-selector:1rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=nord]:checked){--color-base-100:lab(94.324% -.339657 -2.62373);--color-base-200:lab(92.1906% -.413388 -3.75246);--color-base-300:lab(88.2495% -.537157 -5.99798);--color-base-content:lab(21.5129% -.214115 -8.11484);--color-primary:lab(52.6518% -3.74743 -27.0171);--color-primary-content:lab(1.49876% -.241503 -2.13669);--color-secondary:lab(64.6969% -5.5643 -20.3257);--color-secondary-content:lab(2.43381% -.470936 -1.96204);--color-accent:lab(74.2453% -15.8457 -14.1565);--color-accent-content:lab(3.40084% -1.66879 -1.69079);--color-neutral:lab(36.2786% -.24499 -12.8697);--color-neutral-content:lab(88.2495% -.537157 -5.99798);--color-info:lab(63.4156% 18.5962 -10.5133);--color-info-content:lab(2.32111% 1.66221 -.960082);--color-success:lab(73.9575% -16.0914 21.8886);--color-success-content:lab(3.36525% -1.64589 2.02379);--color-warning:lab(83.3692% 5.34141 36.1947);--color-warning-content:lab(4.54197% .693284 3.83488);--color-error:lab(52.9945% 38.9133 13.1792);--color-error-content:lab(1.52051% 2.92406 .778365)}}[data-theme=sunset]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#121c22;--color-base-200:#0e171e;--color-base-300:#091319;--color-base-content:#9fb9d0;--color-primary:#ff865b;--color-primary-content:#160603;--color-secondary:#fd6f9c;--color-secondary-content:#160409;--color-accent:#b387fa;--color-accent-content:#0c0615;--color-neutral:#1b262c;--color-neutral-content:#94a0a9;--color-info:#89e0eb;--color-info-content:#071213;--color-success:#addfad;--color-success-content:#0b120b;--color-warning:#f1c892;--color-warning-content:#140f08;--color-error:#ffbbbd;--color-error-content:#160d0d;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=sunset]{--color-base-100:lab(9.54204% -2.95451 -5.95486);--color-base-200:lab(7.245% -2.6449 -5.89687);--color-base-300:lab(5.28114% -2.09552 -5.26116);--color-base-content:lab(73.751% -5.3086 -14.5723);--color-primary:lab(69.4524% 44.4451 44.5169);--color-primary-content:lab(2.89117% 4.96126 3.23885);--color-secondary:lab(65.9623% 57.9306 4.05995);--color-secondary-content:lab(2.5512% 6.26259 .363874);--color-accent:lab(64.3289% 34.6406 -51.7657);--color-accent-content:lab(2.40093% 3.39989 -6.53992);--color-neutral:lab(14.1853% -3.02286 -5.97882);--color-neutral-content:lab(65.2362% -3.2492 -6.07528);--color-info:lab(83.9831% -25.2179 -14.0713);--color-info-content:lab(4.62664% -3.30009 -2.1173);--color-success:lab(84.3332% -23.6885 18.923);--color-success-content:lab(4.67607% -3.13393 2.36688);--color-warning:lab(83.2812% 9.57519 32.9211);--color-warning-content:lab(4.53047% 1.26158 3.54228);--color-error:lab(82.3653% 25.1849 9.08245);--color-error-content:lab(4.41046% 3.4458 1.11386)}}:root:has(input.theme-controller[value=sunset]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#121c22;--color-base-200:#0e171e;--color-base-300:#091319;--color-base-content:#9fb9d0;--color-primary:#ff865b;--color-primary-content:#160603;--color-secondary:#fd6f9c;--color-secondary-content:#160409;--color-accent:#b387fa;--color-accent-content:#0c0615;--color-neutral:#1b262c;--color-neutral-content:#94a0a9;--color-info:#89e0eb;--color-info-content:#071213;--color-success:#addfad;--color-success-content:#0b120b;--color-warning:#f1c892;--color-warning-content:#140f08;--color-error:#ffbbbd;--color-error-content:#160d0d;--radius-selector:1rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=sunset]:checked){--color-base-100:lab(9.54204% -2.95451 -5.95486);--color-base-200:lab(7.245% -2.6449 -5.89687);--color-base-300:lab(5.28114% -2.09552 -5.26116);--color-base-content:lab(73.751% -5.3086 -14.5723);--color-primary:lab(69.4524% 44.4451 44.5169);--color-primary-content:lab(2.89117% 4.96126 3.23885);--color-secondary:lab(65.9623% 57.9306 4.05995);--color-secondary-content:lab(2.5512% 6.26259 .363874);--color-accent:lab(64.3289% 34.6406 -51.7657);--color-accent-content:lab(2.40093% 3.39989 -6.53992);--color-neutral:lab(14.1853% -3.02286 -5.97882);--color-neutral-content:lab(65.2362% -3.2492 -6.07528);--color-info:lab(83.9831% -25.2179 -14.0713);--color-info-content:lab(4.62664% -3.30009 -2.1173);--color-success:lab(84.3332% -23.6885 18.923);--color-success-content:lab(4.67607% -3.13393 2.36688);--color-warning:lab(83.2812% 9.57519 32.9211);--color-warning-content:lab(4.53047% 1.26158 3.54228);--color-error:lab(82.3653% 25.1849 9.08245);--color-error-content:lab(4.41046% 3.4458 1.11386)}}[data-theme=caramellatte]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff7ed;--color-base-200:#feecd3;--color-base-300:#ffd6a7;--color-base-content:#7c2808;--color-primary:#000;--color-primary-content:#fff;--color-secondary:#360a00;--color-secondary-content:#ffd6a7;--color-accent:#8c3f27;--color-accent-content:#ffd6a7;--color-neutral:#c43b00;--color-neutral-content:#fff7ed;--color-info:#193ab7;--color-info-content:#ffd6a7;--color-success:#005f45;--color-success-content:#ffd6a7;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff6266;--color-error-content:#801518;--radius-selector:2rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:2px;--depth:1;--noise:1}@supports (color:lab(0% 0 0)){[data-theme=caramellatte]{--color-base-100:lab(97.7008% 1.53735 5.90649);--color-base-200:lab(94.2486% 3.58573 14.3166);--color-base-300:lab(88.3709% 9.95103 28.8399);--color-base-content:lab(29.363% 36.096 38.1255);--color-primary:lab(0% 0 0);--color-primary-content:lab(100% 0 0);--color-secondary:lab(9.39577% 22.1975 14.8477);--color-secondary-content:lab(88.3709% 9.95103 28.8399);--color-accent:lab(36.9721% 32.0881 30.5761);--color-accent-content:lab(88.3709% 9.95103 28.8399);--color-neutral:lab(46.1115% 57.752 71.3111);--color-neutral-content:lab(97.7008% 1.53735 5.90649);--color-info:lab(29.7615% 28.117 -70.2765);--color-info-content:lab(88.3709% 9.95103 28.8399);--color-success:lab(35.1354% -33.1288 8.04085);--color-success-content:lab(88.3709% 9.95103 28.8399);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(63.2406% 60.7498 31.3402);--color-error-content:lab(27.8157% 44.5725 29.2331)}}:root:has(input.theme-controller[value=caramellatte]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff7ed;--color-base-200:#feecd3;--color-base-300:#ffd6a7;--color-base-content:#7c2808;--color-primary:#000;--color-primary-content:#fff;--color-secondary:#360a00;--color-secondary-content:#ffd6a7;--color-accent:#8c3f27;--color-accent-content:#ffd6a7;--color-neutral:#c43b00;--color-neutral-content:#fff7ed;--color-info:#193ab7;--color-info-content:#ffd6a7;--color-success:#005f45;--color-success-content:#ffd6a7;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff6266;--color-error-content:#801518;--radius-selector:2rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:2px;--depth:1;--noise:1}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=caramellatte]:checked){--color-base-100:lab(97.7008% 1.53735 5.90649);--color-base-200:lab(94.2486% 3.58573 14.3166);--color-base-300:lab(88.3709% 9.95103 28.8399);--color-base-content:lab(29.363% 36.096 38.1255);--color-primary:lab(0% 0 0);--color-primary-content:lab(100% 0 0);--color-secondary:lab(9.39577% 22.1975 14.8477);--color-secondary-content:lab(88.3709% 9.95103 28.8399);--color-accent:lab(36.9721% 32.0881 30.5761);--color-accent-content:lab(88.3709% 9.95103 28.8399);--color-neutral:lab(46.1115% 57.752 71.3111);--color-neutral-content:lab(97.7008% 1.53735 5.90649);--color-info:lab(29.7615% 28.117 -70.2765);--color-info-content:lab(88.3709% 9.95103 28.8399);--color-success:lab(35.1354% -33.1288 8.04085);--color-success-content:lab(88.3709% 9.95103 28.8399);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(63.2406% 60.7498 31.3402);--color-error-content:lab(27.8157% 44.5725 29.2331)}}[data-theme=abyss]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#001b20;--color-base-200:#000f14;--color-base-300:#000406;--color-base-content:#ffd6a7;--color-primary:#c2fd00;--color-primary-content:#526f00;--color-secondary:#cebef4;--color-secondary-content:#564775;--color-accent:#505050;--color-accent-content:#f8f8f8;--color-neutral:#00363e;--color-neutral-content:#ffd6a7;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#01df72;--color-success-content:#022d14;--color-warning:#ffc211;--color-warning-content:#6e4f00;--color-error:#f04e4f;--color-error-content:#540002;--radius-selector:2rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=abyss]{--color-base-100:lab(7.74345% -16.0152 -13.8988);--color-base-200:lab(3.31509% -7.8967 -11.288);--color-base-300:lab(.997793% -2.5271 -6.08849);--color-base-content:lab(88.3709% 9.95103 28.8399);--color-primary:lab(93.0044% -43.5133 110.402);--color-primary-content:lab(43.7867% -36.9067 132.72);--color-secondary:lab(79.6831% 13.6768 -24.7723);--color-secondary-content:lab(33.1826% 14.7743 -24.3602);--color-accent:lab(33.88% -.0000149012 0);--color-accent-content:lab(97.68% -.0000298023 .0000119209);--color-neutral:lab(19.3866% -21.5231 -14.1394);--color-neutral-content:lab(88.3709% 9.95103 28.8399);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(78.2706% -64.9343 39.7594);--color-success-content:lab(14.9873% -20.4447 11.747);--color-warning:lab(82.4885% 17.1464 104.766);--color-warning-content:lab(35.6098% 24.6044 106.49);--color-error:lab(57.3933% 62.8183 36.4469);--color-error-content:lab(13.1003% 64.0786 29.5479)}}:root:has(input.theme-controller[value=abyss]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#001b20;--color-base-200:#000f14;--color-base-300:#000406;--color-base-content:#ffd6a7;--color-primary:#c2fd00;--color-primary-content:#526f00;--color-secondary:#cebef4;--color-secondary-content:#564775;--color-accent:#505050;--color-accent-content:#f8f8f8;--color-neutral:#00363e;--color-neutral-content:#ffd6a7;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#01df72;--color-success-content:#022d14;--color-warning:#ffc211;--color-warning-content:#6e4f00;--color-error:#f04e4f;--color-error-content:#540002;--radius-selector:2rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=abyss]:checked){--color-base-100:lab(7.74345% -16.0152 -13.8988);--color-base-200:lab(3.31509% -7.8967 -11.288);--color-base-300:lab(.997793% -2.5271 -6.08849);--color-base-content:lab(88.3709% 9.95103 28.8399);--color-primary:lab(93.0044% -43.5133 110.402);--color-primary-content:lab(43.7867% -36.9067 132.72);--color-secondary:lab(79.6831% 13.6768 -24.7723);--color-secondary-content:lab(33.1826% 14.7743 -24.3602);--color-accent:lab(33.88% -.0000149012 0);--color-accent-content:lab(97.68% -.0000298023 .0000119209);--color-neutral:lab(19.3866% -21.5231 -14.1394);--color-neutral-content:lab(88.3709% 9.95103 28.8399);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(78.2706% -64.9343 39.7594);--color-success-content:lab(14.9873% -20.4447 11.747);--color-warning:lab(82.4885% 17.1464 104.766);--color-warning-content:lab(35.6098% 24.6044 106.49);--color-error:lab(57.3933% 62.8183 36.4469);--color-error-content:lab(13.1003% 64.0786 29.5479)}}[data-theme=silk]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#f7f5f3;--color-base-200:#f3ede9;--color-base-300:#e2ddd9;--color-base-content:#4b4743;--color-primary:#1c1c29;--color-primary-content:#e2fd00;--color-secondary:#1c1c29;--color-secondary-content:#ff8117;--color-accent:#1c1c29;--color-accent-content:#00faf1;--color-neutral:#161616;--color-neutral-content:#c2bdb9;--color-info:#7ac8ff;--color-info-content:#003256;--color-success:#afd89e;--color-success-content:#092700;--color-warning:#efc375;--color-warning-content:#6d4b00;--color-error:#ff817f;--color-error-content:#79000d;--radius-selector:2rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:2px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=silk]{--color-base-100:lab(96.5204% .438988 1.23949);--color-base-200:lab(94.1881% 1.30171 2.73036);--color-base-300:lab(88.3881% 1.30269 2.73099);--color-base-content:lab(30.3869% 1.32547 2.74618);--color-primary:lab(10.7425% 2.83168 -8.84131);--color-primary-content:lab(95.1282% -29.3419 114.737);--color-secondary:lab(10.7425% 2.83168 -8.84131);--color-secondary-content:lab(68.3672% 54.7379 94.4974);--color-accent:lab(10.7425% 2.83168 -8.84131);--color-accent-content:lab(89.4854% -70.28 -13.5608);--color-neutral:lab(7.22637% -.0000149012 0);--color-neutral-content:lab(76.7879% 1.30498 2.73246);--color-info:lab(77.1732% -13.3722 -36.8832);--color-info-content:lab(18.7333% -3.93628 -35.7778);--color-success:lab(82.4233% -22.0588 24.1106);--color-success-content:lab(12.6615% -21.1196 21.0789);--color-warning:lab(81.459% 9.80556 44.8909);--color-warning-content:lab(34.8844% 12.7342 57.7817);--color-error:lab(69.2714% 57.5662 29.44);--color-error-content:lab(22.7589% 58.2524 35.871)}}:root:has(input.theme-controller[value=silk]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#f7f5f3;--color-base-200:#f3ede9;--color-base-300:#e2ddd9;--color-base-content:#4b4743;--color-primary:#1c1c29;--color-primary-content:#e2fd00;--color-secondary:#1c1c29;--color-secondary-content:#ff8117;--color-accent:#1c1c29;--color-accent-content:#00faf1;--color-neutral:#161616;--color-neutral-content:#c2bdb9;--color-info:#7ac8ff;--color-info-content:#003256;--color-success:#afd89e;--color-success-content:#092700;--color-warning:#efc375;--color-warning-content:#6d4b00;--color-error:#ff817f;--color-error-content:#79000d;--radius-selector:2rem;--radius-field:.5rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:2px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=silk]:checked){--color-base-100:lab(96.5204% .438988 1.23949);--color-base-200:lab(94.1881% 1.30171 2.73036);--color-base-300:lab(88.3881% 1.30269 2.73099);--color-base-content:lab(30.3869% 1.32547 2.74618);--color-primary:lab(10.7425% 2.83168 -8.84131);--color-primary-content:lab(95.1282% -29.3419 114.737);--color-secondary:lab(10.7425% 2.83168 -8.84131);--color-secondary-content:lab(68.3672% 54.7379 94.4974);--color-accent:lab(10.7425% 2.83168 -8.84131);--color-accent-content:lab(89.4854% -70.28 -13.5608);--color-neutral:lab(7.22637% -.0000149012 0);--color-neutral-content:lab(76.7879% 1.30498 2.73246);--color-info:lab(77.1732% -13.3722 -36.8832);--color-info-content:lab(18.7333% -3.93628 -35.7778);--color-success:lab(82.4233% -22.0588 24.1106);--color-success-content:lab(12.6615% -21.1196 21.0789);--color-warning:lab(81.459% 9.80556 44.8909);--color-warning-content:lab(34.8844% 12.7342 57.7817);--color-error:lab(69.2714% 57.5662 29.44);--color-error-content:lab(22.7589% 58.2524 35.871)}} \ No newline at end of file diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui-theme.css.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui-theme.css.br deleted file mode 100644 index 8f526940..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui-theme.css.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui.css b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui.css deleted file mode 100644 index 8cad5f49..00000000 --- a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui.css +++ /dev/null @@ -1 +0,0 @@ -@layer base{:root,[data-theme=light]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f8f8f8;--color-base-300:#eee;--color-base-content:#18181b;--color-primary:#422ad5;--color-primary-content:#e0e7ff;--color-secondary:#f43098;--color-secondary-content:#f9e4f0;--color-accent:#00d1bb;--color-accent-content:#084d49;--color-neutral:#09090b;--color-neutral-content:#e4e4e7;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#00d193;--color-success-content:#004c39;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff657f;--color-error-content:#4d0218;--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root,[data-theme=light]{--color-base-100:lab(100% 0 0);--color-base-200:lab(97.68% -.0000298023 .0000119209);--color-base-300:lab(94.2% 0 0);--color-base-content:lab(8.30603% .618205 -2.16572);--color-primary:lab(31.573% 49.867 -84.7065);--color-primary-content:lab(91.6577% 1.04591 -12.7199);--color-secondary:lab(56.234% 76.7852 -8.06803);--color-secondary-content:lab(92.6584% 9.01151 -3.1507);--color-accent:lab(75.1988% -53.3697 -2.27784);--color-accent-content:lab(28.81% -21.4781 -3.59725);--color-neutral:lab(2.45787% .239417 -.873864);--color-neutral-content:lab(90.6853% .399232 -1.45452);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(74.4967% -60.7579 19.4189);--color-success-content:lab(27.9355% -26.9592 5.46191);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(64.1803% 63.0275 19.2122);--color-error-content:lab(14.1162% 34.0067 9.81536)}}:root:has(input.theme-controller[value=light]:checked){--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--color-base-100:#fff;--color-base-200:#f8f8f8;--color-base-300:#eee;--color-base-content:#18181b;--color-primary:#422ad5;--color-primary-content:#e0e7ff;--color-secondary:#f43098;--color-secondary-content:#f9e4f0;--color-accent:#00d1bb;--color-accent-content:#084d49;--color-neutral:#09090b;--color-neutral-content:#e4e4e7;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#00d193;--color-success-content:#004c39;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff657f;--color-error-content:#4d0218;--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=light]:checked){--color-base-100:lab(100% 0 0);--color-base-200:lab(97.68% -.0000298023 .0000119209);--color-base-300:lab(94.2% 0 0);--color-base-content:lab(8.30603% .618205 -2.16572);--color-primary:lab(31.573% 49.867 -84.7065);--color-primary-content:lab(91.6577% 1.04591 -12.7199);--color-secondary:lab(56.234% 76.7852 -8.06803);--color-secondary-content:lab(92.6584% 9.01151 -3.1507);--color-accent:lab(75.1988% -53.3697 -2.27784);--color-accent-content:lab(28.81% -21.4781 -3.59725);--color-neutral:lab(2.45787% .239417 -.873864);--color-neutral-content:lab(90.6853% .399232 -1.45452);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(74.4967% -60.7579 19.4189);--color-success-content:lab(27.9355% -26.9592 5.46191);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(64.1803% 63.0275 19.2122);--color-error-content:lab(14.1162% 34.0067 9.81536)}}[data-theme=dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#1d232a;--color-base-200:#191e24;--color-base-300:#15191e;--color-base-content:#f2f8ff;--color-primary:#605dff;--color-primary-content:#edf1fe;--color-secondary:#f43098;--color-secondary-content:#f9e4f0;--color-accent:#00d1bb;--color-accent-content:#084d49;--color-neutral:#09090b;--color-neutral-content:#e4e4e7;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#00d193;--color-success-content:#004c39;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff657f;--color-error-content:#4d0218;--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){[data-theme=dark]{--color-base-100:lab(13.3466% -1.2732 -5.67451);--color-base-200:lab(10.9483% -1.07221 -4.98787);--color-base-300:lab(8.5032% -.863373 -4.30144);--color-base-content:lab(97.3754% -1.86676 -10.6283);--color-primary:lab(47.6934% 38.5675 -81.9644);--color-primary-content:lab(95.2498% .41151 -6.78517);--color-secondary:lab(56.234% 76.7852 -8.06803);--color-secondary-content:lab(92.6584% 9.01151 -3.1507);--color-accent:lab(75.1988% -53.3697 -2.27784);--color-accent-content:lab(28.81% -21.4781 -3.59725);--color-neutral:lab(2.45787% .239417 -.873864);--color-neutral-content:lab(90.6853% .399232 -1.45452);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(74.4967% -60.7579 19.4189);--color-success-content:lab(27.9355% -26.9592 5.46191);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(64.1803% 63.0275 19.2122);--color-error-content:lab(14.1162% 34.0067 9.81536)}}:root:has(input.theme-controller[value=dark]:checked){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--color-base-100:#1d232a;--color-base-200:#191e24;--color-base-300:#15191e;--color-base-content:#f2f8ff;--color-primary:#605dff;--color-primary-content:#edf1fe;--color-secondary:#f43098;--color-secondary-content:#f9e4f0;--color-accent:#00d1bb;--color-accent-content:#084d49;--color-neutral:#09090b;--color-neutral-content:#e4e4e7;--color-info:#00bafc;--color-info-content:#042e49;--color-success:#00d193;--color-success-content:#004c39;--color-warning:#f9b800;--color-warning-content:#793205;--color-error:#ff657f;--color-error-content:#4d0218;--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@supports (color:lab(0% 0 0)){:root:has(input.theme-controller[value=dark]:checked){--color-base-100:lab(13.3466% -1.2732 -5.67451);--color-base-200:lab(10.9483% -1.07221 -4.98787);--color-base-300:lab(8.5032% -.863373 -4.30144);--color-base-content:lab(97.3754% -1.86676 -10.6283);--color-primary:lab(47.6934% 38.5675 -81.9644);--color-primary-content:lab(95.2498% .41151 -6.78517);--color-secondary:lab(56.234% 76.7852 -8.06803);--color-secondary-content:lab(92.6584% 9.01151 -3.1507);--color-accent:lab(75.1988% -53.3697 -2.27784);--color-accent-content:lab(28.81% -21.4781 -3.59725);--color-neutral:lab(2.45787% .239417 -.873864);--color-neutral-content:lab(90.6853% .399232 -1.45452);--color-info:lab(69.9876% -23.5256 -45.9352);--color-info-content:lab(17.4794% -5.25944 -21.1512);--color-success:lab(74.4967% -60.7579 19.4189);--color-success-content:lab(27.9355% -26.9592 5.46191);--color-warning:lab(79.2305% 16.6936 100.392);--color-warning-content:lab(30.7627% 30.2938 40.2828);--color-error:lab(64.1803% 63.0275 19.2122);--color-error-content:lab(14.1162% 34.0067 9.81536)}}:root{scrollbar-color:color-mix(in oklch,currentColor 35%,transparent)transparent;--fx-noise:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E")}.chat{--mask-chat:url("data:image/svg+xml,%3csvg width='13' height='13' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='M0 11.5004C0 13.0004 2 13.0004 2 13.0004H12H13V0.00036329L12.5 0C12.5 0 11.977 2.09572 11.8581 2.50033C11.6075 3.35237 10.9149 4.22374 9 5.50036C6 7.50036 0 10.0004 0 11.5004Z'/%3e%3c/svg%3e")}*,:after,:before{box-sizing:border-box;border:0 solid;margin:0;padding:0}::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html{line-height:1.5;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");-webkit-tap-highlight-color:transparent}:host{line-height:1.5;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");-webkit-tap-highlight-color:transparent}body{line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;background:0 0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;background:0 0}select,textarea{border-width:1px}input:where(:not(:is([type=button],[type=reset],[type=submit]))){border-width:1px}button{appearance:button}::file-selector-button{appearance:button}input:where([type=button],[type=reset],[type=submit]){appearance:button}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}::-webkit-search-decoration{-webkit-appearance:none}menu,ol,ul{list-style:none}textarea{resize:vertical}::placeholder{opacity:1;color:color-mix(in oklch,currentColor 50%,transparent)}audio,canvas,embed,iframe,img,object,svg,video{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}:where(:root:has(.modal-open,.modal[open],.modal:target,.modal-toggle:checked,.drawer:not(.drawer-open)>.drawer-toggle:checked)){scrollbar-gutter:stable;background-image:linear-gradient(var(--color-base-100),var(--color-base-100));--root-bg:color-mix(in srgb,var(--color-base-100),#000 40%)}@supports (color:lab(0% 0 0)){:where(:root:has(.modal-open,.modal[open],.modal:target,.modal-toggle:checked,.drawer:not(.drawer-open)>.drawer-toggle:checked)){--root-bg:color-mix(in srgb,var(--color-base-100),lab(0% 0 0) 40%)}}:root,[data-theme]{background-color:var(--root-bg,var(--color-base-100));color:var(--color-base-content)}@property --radialprogress{syntax: ""; inherits: true; initial-value: 0%;}:root:has(.modal-open,.modal[open],.modal:target,.modal-toggle:checked,.drawer:not([class*=drawer-open])>.drawer-toggle:checked){overflow:hidden}}@layer utilities{.input{cursor:text;border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;font-size:.875rem;display:inline-flex;position:relative}.input:where(input){display:inline-flex}.input :where(input){appearance:none;background-color:transparent;border:none;width:100%;height:100%;display:inline-flex}.input :where(input):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.input :where(input):focus{outline-offset:2px;outline:2px solid transparent}}.input :where(input):focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.input :where(input):focus-within{outline-offset:2px;outline:2px solid transparent}}.input :where(input[type=date]){display:inline-block}.input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.input::-webkit-date-and-time-value{text-align:inherit}.input[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.input::-webkit-calendar-picker-indicator{position:absolute;inset-inline-end:.75em}.input-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.input-neutral{--input-color:var(--color-neutral)}.input-neutral:focus{--input-color:var(--color-neutral)}.input-neutral:focus-within{--input-color:var(--color-neutral)}.input-primary{--input-color:var(--color-primary)}.input-primary:focus{--input-color:var(--color-primary)}.input-primary:focus-within{--input-color:var(--color-primary)}.input-secondary{--input-color:var(--color-secondary)}.input-secondary:focus{--input-color:var(--color-secondary)}.input-secondary:focus-within{--input-color:var(--color-secondary)}.input-accent{--input-color:var(--color-accent)}.input-accent:focus{--input-color:var(--color-accent)}.input-accent:focus-within{--input-color:var(--color-accent)}.input-info{--input-color:var(--color-info)}.input-info:focus{--input-color:var(--color-info)}.input-info:focus-within{--input-color:var(--color-info)}.input-success{--input-color:var(--color-success)}.input-success:focus{--input-color:var(--color-success)}.input-success:focus-within{--input-color:var(--color-success)}.input-warning{--input-color:var(--color-warning)}.input-warning:focus{--input-color:var(--color-warning)}.input-warning:focus-within{--input-color:var(--color-warning)}.input-error{--input-color:var(--color-error)}.input-error:focus{--input-color:var(--color-error)}.input-error:focus-within{--input-color:var(--color-error)}.input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.input-xs[type=number]::-webkit-inner-spin-button{margin-block:-.25rem;margin-inline-end:-.75rem}.input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.input-sm[type=number]::-webkit-inner-spin-button{margin-block:-.5rem;margin-inline-end:-.75rem}.input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.input-md[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.input-lg[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.input-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}.input-xl[type=number]::-webkit-inner-spin-button{margin-block:-1rem;margin-inline-end:-.75rem}@media (min-width:640px){.sm\:input{cursor:text;border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;font-size:.875rem;display:inline-flex;position:relative}.sm\:input:where(input){display:inline-flex}.sm\:input :where(input){appearance:none;background-color:transparent;border:none;width:100%;height:100%;display:inline-flex}.sm\:input :where(input):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:input :where(input):focus{outline-offset:2px;outline:2px solid transparent}}.sm\:input :where(input):focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:input :where(input):focus-within{outline-offset:2px;outline:2px solid transparent}}.sm\:input :where(input[type=date]){display:inline-block}.sm\:input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.sm\:input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.sm\:input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.sm\:input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.sm\:input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.sm\:input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.sm\:input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.sm\:input::-webkit-date-and-time-value{text-align:inherit}.sm\:input[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.sm\:input::-webkit-calendar-picker-indicator{position:absolute;inset-inline-end:.75em}.sm\:input-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.sm\:input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.sm\:input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.sm\:input-neutral{--input-color:var(--color-neutral)}.sm\:input-neutral:focus{--input-color:var(--color-neutral)}.sm\:input-neutral:focus-within{--input-color:var(--color-neutral)}.sm\:input-primary{--input-color:var(--color-primary)}.sm\:input-primary:focus{--input-color:var(--color-primary)}.sm\:input-primary:focus-within{--input-color:var(--color-primary)}.sm\:input-secondary{--input-color:var(--color-secondary)}.sm\:input-secondary:focus{--input-color:var(--color-secondary)}.sm\:input-secondary:focus-within{--input-color:var(--color-secondary)}.sm\:input-accent{--input-color:var(--color-accent)}.sm\:input-accent:focus{--input-color:var(--color-accent)}.sm\:input-accent:focus-within{--input-color:var(--color-accent)}.sm\:input-info{--input-color:var(--color-info)}.sm\:input-info:focus{--input-color:var(--color-info)}.sm\:input-info:focus-within{--input-color:var(--color-info)}.sm\:input-success{--input-color:var(--color-success)}.sm\:input-success:focus{--input-color:var(--color-success)}.sm\:input-success:focus-within{--input-color:var(--color-success)}.sm\:input-warning{--input-color:var(--color-warning)}.sm\:input-warning:focus{--input-color:var(--color-warning)}.sm\:input-warning:focus-within{--input-color:var(--color-warning)}.sm\:input-error{--input-color:var(--color-error)}.sm\:input-error:focus{--input-color:var(--color-error)}.sm\:input-error:focus-within{--input-color:var(--color-error)}.sm\:input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.sm\:input-xs[type=number]::-webkit-inner-spin-button{margin-block:-.25rem;margin-inline-end:-.75rem}.sm\:input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.sm\:input-sm[type=number]::-webkit-inner-spin-button{margin-block:-.5rem;margin-inline-end:-.75rem}.sm\:input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.sm\:input-md[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.sm\:input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.sm\:input-lg[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.sm\:input-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}.sm\:input-xl[type=number]::-webkit-inner-spin-button{margin-block:-1rem;margin-inline-end:-.75rem}}@media (min-width:768px){.md\:input{cursor:text;border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;font-size:.875rem;display:inline-flex;position:relative}.md\:input:where(input){display:inline-flex}.md\:input :where(input){appearance:none;background-color:transparent;border:none;width:100%;height:100%;display:inline-flex}.md\:input :where(input):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:input :where(input):focus{outline-offset:2px;outline:2px solid transparent}}.md\:input :where(input):focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:input :where(input):focus-within{outline-offset:2px;outline:2px solid transparent}}.md\:input :where(input[type=date]){display:inline-block}.md\:input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.md\:input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.md\:input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.md\:input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.md\:input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.md\:input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.md\:input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.md\:input::-webkit-date-and-time-value{text-align:inherit}.md\:input[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.md\:input::-webkit-calendar-picker-indicator{position:absolute;inset-inline-end:.75em}.md\:input-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.md\:input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.md\:input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.md\:input-neutral{--input-color:var(--color-neutral)}.md\:input-neutral:focus{--input-color:var(--color-neutral)}.md\:input-neutral:focus-within{--input-color:var(--color-neutral)}.md\:input-primary{--input-color:var(--color-primary)}.md\:input-primary:focus{--input-color:var(--color-primary)}.md\:input-primary:focus-within{--input-color:var(--color-primary)}.md\:input-secondary{--input-color:var(--color-secondary)}.md\:input-secondary:focus{--input-color:var(--color-secondary)}.md\:input-secondary:focus-within{--input-color:var(--color-secondary)}.md\:input-accent{--input-color:var(--color-accent)}.md\:input-accent:focus{--input-color:var(--color-accent)}.md\:input-accent:focus-within{--input-color:var(--color-accent)}.md\:input-info{--input-color:var(--color-info)}.md\:input-info:focus{--input-color:var(--color-info)}.md\:input-info:focus-within{--input-color:var(--color-info)}.md\:input-success{--input-color:var(--color-success)}.md\:input-success:focus{--input-color:var(--color-success)}.md\:input-success:focus-within{--input-color:var(--color-success)}.md\:input-warning{--input-color:var(--color-warning)}.md\:input-warning:focus{--input-color:var(--color-warning)}.md\:input-warning:focus-within{--input-color:var(--color-warning)}.md\:input-error{--input-color:var(--color-error)}.md\:input-error:focus{--input-color:var(--color-error)}.md\:input-error:focus-within{--input-color:var(--color-error)}.md\:input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.md\:input-xs[type=number]::-webkit-inner-spin-button{margin-block:-.25rem;margin-inline-end:-.75rem}.md\:input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.md\:input-sm[type=number]::-webkit-inner-spin-button{margin-block:-.5rem;margin-inline-end:-.75rem}.md\:input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.md\:input-md[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.md\:input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.md\:input-lg[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.md\:input-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}.md\:input-xl[type=number]::-webkit-inner-spin-button{margin-block:-1rem;margin-inline-end:-.75rem}}@media (min-width:1024px){.lg\:input{cursor:text;border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;font-size:.875rem;display:inline-flex;position:relative}.lg\:input:where(input){display:inline-flex}.lg\:input :where(input){appearance:none;background-color:transparent;border:none;width:100%;height:100%;display:inline-flex}.lg\:input :where(input):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:input :where(input):focus{outline-offset:2px;outline:2px solid transparent}}.lg\:input :where(input):focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:input :where(input):focus-within{outline-offset:2px;outline:2px solid transparent}}.lg\:input :where(input[type=date]){display:inline-block}.lg\:input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.lg\:input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.lg\:input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.lg\:input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.lg\:input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.lg\:input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.lg\:input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.lg\:input::-webkit-date-and-time-value{text-align:inherit}.lg\:input[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.lg\:input::-webkit-calendar-picker-indicator{position:absolute;inset-inline-end:.75em}.lg\:input-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.lg\:input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.lg\:input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.lg\:input-neutral{--input-color:var(--color-neutral)}.lg\:input-neutral:focus{--input-color:var(--color-neutral)}.lg\:input-neutral:focus-within{--input-color:var(--color-neutral)}.lg\:input-primary{--input-color:var(--color-primary)}.lg\:input-primary:focus{--input-color:var(--color-primary)}.lg\:input-primary:focus-within{--input-color:var(--color-primary)}.lg\:input-secondary{--input-color:var(--color-secondary)}.lg\:input-secondary:focus{--input-color:var(--color-secondary)}.lg\:input-secondary:focus-within{--input-color:var(--color-secondary)}.lg\:input-accent{--input-color:var(--color-accent)}.lg\:input-accent:focus{--input-color:var(--color-accent)}.lg\:input-accent:focus-within{--input-color:var(--color-accent)}.lg\:input-info{--input-color:var(--color-info)}.lg\:input-info:focus{--input-color:var(--color-info)}.lg\:input-info:focus-within{--input-color:var(--color-info)}.lg\:input-success{--input-color:var(--color-success)}.lg\:input-success:focus{--input-color:var(--color-success)}.lg\:input-success:focus-within{--input-color:var(--color-success)}.lg\:input-warning{--input-color:var(--color-warning)}.lg\:input-warning:focus{--input-color:var(--color-warning)}.lg\:input-warning:focus-within{--input-color:var(--color-warning)}.lg\:input-error{--input-color:var(--color-error)}.lg\:input-error:focus{--input-color:var(--color-error)}.lg\:input-error:focus-within{--input-color:var(--color-error)}.lg\:input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.lg\:input-xs[type=number]::-webkit-inner-spin-button{margin-block:-.25rem;margin-inline-end:-.75rem}.lg\:input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.lg\:input-sm[type=number]::-webkit-inner-spin-button{margin-block:-.5rem;margin-inline-end:-.75rem}.lg\:input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.lg\:input-md[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.lg\:input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.lg\:input-lg[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.lg\:input-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}.lg\:input-xl[type=number]::-webkit-inner-spin-button{margin-block:-1rem;margin-inline-end:-.75rem}}@media (min-width:1280px){.xl\:input{cursor:text;border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;font-size:.875rem;display:inline-flex;position:relative}.xl\:input:where(input){display:inline-flex}.xl\:input :where(input){appearance:none;background-color:transparent;border:none;width:100%;height:100%;display:inline-flex}.xl\:input :where(input):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:input :where(input):focus{outline-offset:2px;outline:2px solid transparent}}.xl\:input :where(input):focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:input :where(input):focus-within{outline-offset:2px;outline:2px solid transparent}}.xl\:input :where(input[type=date]){display:inline-block}.xl\:input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.xl\:input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.xl\:input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.xl\:input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.xl\:input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.xl\:input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.xl\:input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.xl\:input::-webkit-date-and-time-value{text-align:inherit}.xl\:input[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.xl\:input::-webkit-calendar-picker-indicator{position:absolute;inset-inline-end:.75em}.xl\:input-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.xl\:input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.xl\:input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.xl\:input-neutral{--input-color:var(--color-neutral)}.xl\:input-neutral:focus{--input-color:var(--color-neutral)}.xl\:input-neutral:focus-within{--input-color:var(--color-neutral)}.xl\:input-primary{--input-color:var(--color-primary)}.xl\:input-primary:focus{--input-color:var(--color-primary)}.xl\:input-primary:focus-within{--input-color:var(--color-primary)}.xl\:input-secondary{--input-color:var(--color-secondary)}.xl\:input-secondary:focus{--input-color:var(--color-secondary)}.xl\:input-secondary:focus-within{--input-color:var(--color-secondary)}.xl\:input-accent{--input-color:var(--color-accent)}.xl\:input-accent:focus{--input-color:var(--color-accent)}.xl\:input-accent:focus-within{--input-color:var(--color-accent)}.xl\:input-info{--input-color:var(--color-info)}.xl\:input-info:focus{--input-color:var(--color-info)}.xl\:input-info:focus-within{--input-color:var(--color-info)}.xl\:input-success{--input-color:var(--color-success)}.xl\:input-success:focus{--input-color:var(--color-success)}.xl\:input-success:focus-within{--input-color:var(--color-success)}.xl\:input-warning{--input-color:var(--color-warning)}.xl\:input-warning:focus{--input-color:var(--color-warning)}.xl\:input-warning:focus-within{--input-color:var(--color-warning)}.xl\:input-error{--input-color:var(--color-error)}.xl\:input-error:focus{--input-color:var(--color-error)}.xl\:input-error:focus-within{--input-color:var(--color-error)}.xl\:input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.xl\:input-xs[type=number]::-webkit-inner-spin-button{margin-block:-.25rem;margin-inline-end:-.75rem}.xl\:input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.xl\:input-sm[type=number]::-webkit-inner-spin-button{margin-block:-.5rem;margin-inline-end:-.75rem}.xl\:input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.xl\:input-md[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.xl\:input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.xl\:input-lg[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.xl\:input-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}.xl\:input-xl[type=number]::-webkit-inner-spin-button{margin-block:-1rem;margin-inline-end:-.75rem}}@media (min-width:1536px){.\32 xl\:input{cursor:text;border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;font-size:.875rem;display:inline-flex;position:relative}.\32 xl\:input:where(input){display:inline-flex}.\32 xl\:input :where(input){appearance:none;background-color:transparent;border:none;width:100%;height:100%;display:inline-flex}.\32 xl\:input :where(input):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:input :where(input):focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:input :where(input):focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:input :where(input):focus-within{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:input :where(input[type=date]){display:inline-block}.\32 xl\:input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.\32 xl\:input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.\32 xl\:input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.\32 xl\:input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.\32 xl\:input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.\32 xl\:input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.\32 xl\:input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.\32 xl\:input::-webkit-date-and-time-value{text-align:inherit}.\32 xl\:input[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.\32 xl\:input::-webkit-calendar-picker-indicator{position:absolute;inset-inline-end:.75em}.\32 xl\:input-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.\32 xl\:input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.\32 xl\:input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.\32 xl\:input-neutral{--input-color:var(--color-neutral)}.\32 xl\:input-neutral:focus{--input-color:var(--color-neutral)}.\32 xl\:input-neutral:focus-within{--input-color:var(--color-neutral)}.\32 xl\:input-primary{--input-color:var(--color-primary)}.\32 xl\:input-primary:focus{--input-color:var(--color-primary)}.\32 xl\:input-primary:focus-within{--input-color:var(--color-primary)}.\32 xl\:input-secondary{--input-color:var(--color-secondary)}.\32 xl\:input-secondary:focus{--input-color:var(--color-secondary)}.\32 xl\:input-secondary:focus-within{--input-color:var(--color-secondary)}.\32 xl\:input-accent{--input-color:var(--color-accent)}.\32 xl\:input-accent:focus{--input-color:var(--color-accent)}.\32 xl\:input-accent:focus-within{--input-color:var(--color-accent)}.\32 xl\:input-info{--input-color:var(--color-info)}.\32 xl\:input-info:focus{--input-color:var(--color-info)}.\32 xl\:input-info:focus-within{--input-color:var(--color-info)}.\32 xl\:input-success{--input-color:var(--color-success)}.\32 xl\:input-success:focus{--input-color:var(--color-success)}.\32 xl\:input-success:focus-within{--input-color:var(--color-success)}.\32 xl\:input-warning{--input-color:var(--color-warning)}.\32 xl\:input-warning:focus{--input-color:var(--color-warning)}.\32 xl\:input-warning:focus-within{--input-color:var(--color-warning)}.\32 xl\:input-error{--input-color:var(--color-error)}.\32 xl\:input-error:focus{--input-color:var(--color-error)}.\32 xl\:input-error:focus-within{--input-color:var(--color-error)}.\32 xl\:input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.\32 xl\:input-xs[type=number]::-webkit-inner-spin-button{margin-block:-.25rem;margin-inline-end:-.75rem}.\32 xl\:input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.\32 xl\:input-sm[type=number]::-webkit-inner-spin-button{margin-block:-.5rem;margin-inline-end:-.75rem}.\32 xl\:input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.\32 xl\:input-md[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.\32 xl\:input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.\32 xl\:input-lg[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.\32 xl\:input-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}.\32 xl\:input-xl[type=number]::-webkit-inner-spin-button{margin-block:-1rem;margin-inline-end:-.75rem}}.swap{cursor:pointer;vertical-align:middle;-webkit-user-select:none;user-select:none;place-content:center;display:inline-grid;position:relative}.swap input{appearance:none;border:none}.swap>*{grid-row-start:1;grid-column-start:1;transition-property:transform,rotate,opacity;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1)}.swap .swap-on{opacity:0}.swap .swap-indeterminate{opacity:0}.swap input:indeterminate~.swap-on{opacity:0}.swap input:is(:checked,:indeterminate)~.swap-off{opacity:0}.swap input:checked~.swap-on{opacity:1}.swap input:indeterminate~.swap-indeterminate{opacity:1}.swap-active .swap-off{opacity:0}.swap-active .swap-on{opacity:1}.swap-rotate .swap-on{rotate:45deg}.swap-rotate input:indeterminate~.swap-on{rotate:45deg}.swap-rotate input:is(:checked,:indeterminate)~.swap-on{rotate:none}.swap-rotate.swap-active .swap-on{rotate:none}.swap-rotate input:is(:checked,:indeterminate)~.swap-off{rotate:-45deg}.swap-rotate.swap-active .swap-off{rotate:-45deg}.swap-flip{transform-style:preserve-3d;perspective:20rem}.swap-flip .swap-on{backface-visibility:hidden;opacity:1;transform:rotateY(180deg)}.swap-flip .swap-indeterminate{backface-visibility:hidden;opacity:1;transform:rotateY(180deg)}.swap-flip input:indeterminate~.swap-on{backface-visibility:hidden;opacity:1;transform:rotateY(180deg)}.swap-flip input:is(:checked,:indeterminate)~.swap-on{transform:rotateY(0)}.swap-flip.swap-active .swap-on{transform:rotateY(0)}.swap-flip input:is(:checked,:indeterminate)~.swap-off{backface-visibility:hidden;opacity:1;transform:rotateY(-180deg)}.swap-flip.swap-active .swap-off{backface-visibility:hidden;opacity:1;transform:rotateY(-180deg)}.rating{vertical-align:middle;display:inline-flex;position:relative}.rating input{appearance:none;border:none}.rating :where(*){background-color:var(--color-base-content);opacity:.2;border-radius:0;width:1.5rem;height:1.5rem;animation:.25s ease-out rating}.rating :where(*):is(input){cursor:pointer}.rating .rating-hidden{background-color:transparent;width:.5rem}.rating input[type=radio]:checked{background-image:none}.rating *:checked{opacity:1}.rating *[aria-checked=true]{opacity:1}.rating *[aria-current=true]{opacity:1}.rating *:has(~:checked,~[aria-checked=true],~[aria-current=true]){opacity:1}.rating *:focus-visible{transition:scale .2s ease-out;scale:1.1}.rating :active:focus{animation:none;scale:1.1}.rating.rating-xs :where(:not(.rating-hidden)){width:1rem;height:1rem}.rating.rating-sm :where(:not(.rating-hidden)){width:1.25rem;height:1.25rem}.rating.rating-md :where(:not(.rating-hidden)){width:1.5rem;height:1.5rem}.rating.rating-lg :where(:not(.rating-hidden)){width:1.75rem;height:1.75rem}.rating.rating-xl :where(:not(.rating-hidden)){width:2rem;height:2rem}.rating-half :where(:not(.rating-hidden)){width:.75rem}.rating-half.rating-xs :not(.rating-hidden){width:.5rem}.rating-half.rating-sm :not(.rating-hidden){width:.625rem}.rating-half.rating-md :not(.rating-hidden){width:.75rem}.rating-half.rating-lg :not(.rating-hidden){width:.875rem}.rating-half.rating-xl :not(.rating-hidden){width:1rem}@keyframes rating{0%,40%{filter:brightness(1.05)contrast(1.05);scale:1.1}}@media (min-width:640px){.sm\:rating{vertical-align:middle;display:inline-flex;position:relative}.sm\:rating input{appearance:none;border:none}.sm\:rating :where(*){background-color:var(--color-base-content);opacity:.2;border-radius:0;width:1.5rem;height:1.5rem;animation:.25s ease-out rating}.sm\:rating :where(*):is(input){cursor:pointer}.sm\:rating .rating-hidden{background-color:transparent;width:.5rem}.sm\:rating input[type=radio]:checked{background-image:none}.sm\:rating *:checked{opacity:1}.sm\:rating *[aria-checked=true]{opacity:1}.sm\:rating *[aria-current=true]{opacity:1}.sm\:rating *:has(~:checked,~[aria-checked=true],~[aria-current=true]){opacity:1}.sm\:rating *:focus-visible{transition:scale .2s ease-out;scale:1.1}.sm\:rating :active:focus{animation:none;scale:1.1}.sm\:rating.rating-xs :where(:not(.rating-hidden)){width:1rem;height:1rem}.sm\:rating.rating-sm :where(:not(.rating-hidden)){width:1.25rem;height:1.25rem}.sm\:rating.rating-md :where(:not(.rating-hidden)){width:1.5rem;height:1.5rem}.sm\:rating.rating-lg :where(:not(.rating-hidden)){width:1.75rem;height:1.75rem}.sm\:rating.rating-xl :where(:not(.rating-hidden)){width:2rem;height:2rem}.sm\:rating-half :where(:not(.rating-hidden)){width:.75rem}.sm\:rating-half.rating-xs :not(.rating-hidden){width:.5rem}.sm\:rating-half.rating-sm :not(.rating-hidden){width:.625rem}.sm\:rating-half.rating-md :not(.rating-hidden){width:.75rem}.sm\:rating-half.rating-lg :not(.rating-hidden){width:.875rem}.sm\:rating-half.rating-xl :not(.rating-hidden){width:1rem}}@media (min-width:768px){.md\:rating{vertical-align:middle;display:inline-flex;position:relative}.md\:rating input{appearance:none;border:none}.md\:rating :where(*){background-color:var(--color-base-content);opacity:.2;border-radius:0;width:1.5rem;height:1.5rem;animation:.25s ease-out rating}.md\:rating :where(*):is(input){cursor:pointer}.md\:rating .rating-hidden{background-color:transparent;width:.5rem}.md\:rating input[type=radio]:checked{background-image:none}.md\:rating *:checked{opacity:1}.md\:rating *[aria-checked=true]{opacity:1}.md\:rating *[aria-current=true]{opacity:1}.md\:rating *:has(~:checked,~[aria-checked=true],~[aria-current=true]){opacity:1}.md\:rating *:focus-visible{transition:scale .2s ease-out;scale:1.1}.md\:rating :active:focus{animation:none;scale:1.1}.md\:rating.rating-xs :where(:not(.rating-hidden)){width:1rem;height:1rem}.md\:rating.rating-sm :where(:not(.rating-hidden)){width:1.25rem;height:1.25rem}.md\:rating.rating-md :where(:not(.rating-hidden)){width:1.5rem;height:1.5rem}.md\:rating.rating-lg :where(:not(.rating-hidden)){width:1.75rem;height:1.75rem}.md\:rating.rating-xl :where(:not(.rating-hidden)){width:2rem;height:2rem}.md\:rating-half :where(:not(.rating-hidden)){width:.75rem}.md\:rating-half.rating-xs :not(.rating-hidden){width:.5rem}.md\:rating-half.rating-sm :not(.rating-hidden){width:.625rem}.md\:rating-half.rating-md :not(.rating-hidden){width:.75rem}.md\:rating-half.rating-lg :not(.rating-hidden){width:.875rem}.md\:rating-half.rating-xl :not(.rating-hidden){width:1rem}}@media (min-width:1024px){.lg\:rating{vertical-align:middle;display:inline-flex;position:relative}.lg\:rating input{appearance:none;border:none}.lg\:rating :where(*){background-color:var(--color-base-content);opacity:.2;border-radius:0;width:1.5rem;height:1.5rem;animation:.25s ease-out rating}.lg\:rating :where(*):is(input){cursor:pointer}.lg\:rating .rating-hidden{background-color:transparent;width:.5rem}.lg\:rating input[type=radio]:checked{background-image:none}.lg\:rating *:checked{opacity:1}.lg\:rating *[aria-checked=true]{opacity:1}.lg\:rating *[aria-current=true]{opacity:1}.lg\:rating *:has(~:checked,~[aria-checked=true],~[aria-current=true]){opacity:1}.lg\:rating *:focus-visible{transition:scale .2s ease-out;scale:1.1}.lg\:rating :active:focus{animation:none;scale:1.1}.lg\:rating.rating-xs :where(:not(.rating-hidden)){width:1rem;height:1rem}.lg\:rating.rating-sm :where(:not(.rating-hidden)){width:1.25rem;height:1.25rem}.lg\:rating.rating-md :where(:not(.rating-hidden)){width:1.5rem;height:1.5rem}.lg\:rating.rating-lg :where(:not(.rating-hidden)){width:1.75rem;height:1.75rem}.lg\:rating.rating-xl :where(:not(.rating-hidden)){width:2rem;height:2rem}.lg\:rating-half :where(:not(.rating-hidden)){width:.75rem}.lg\:rating-half.rating-xs :not(.rating-hidden){width:.5rem}.lg\:rating-half.rating-sm :not(.rating-hidden){width:.625rem}.lg\:rating-half.rating-md :not(.rating-hidden){width:.75rem}.lg\:rating-half.rating-lg :not(.rating-hidden){width:.875rem}.lg\:rating-half.rating-xl :not(.rating-hidden){width:1rem}}@media (min-width:1280px){.xl\:rating{vertical-align:middle;display:inline-flex;position:relative}.xl\:rating input{appearance:none;border:none}.xl\:rating :where(*){background-color:var(--color-base-content);opacity:.2;border-radius:0;width:1.5rem;height:1.5rem;animation:.25s ease-out rating}.xl\:rating :where(*):is(input){cursor:pointer}.xl\:rating .rating-hidden{background-color:transparent;width:.5rem}.xl\:rating input[type=radio]:checked{background-image:none}.xl\:rating *:checked{opacity:1}.xl\:rating *[aria-checked=true]{opacity:1}.xl\:rating *[aria-current=true]{opacity:1}.xl\:rating *:has(~:checked,~[aria-checked=true],~[aria-current=true]){opacity:1}.xl\:rating *:focus-visible{transition:scale .2s ease-out;scale:1.1}.xl\:rating :active:focus{animation:none;scale:1.1}.xl\:rating.rating-xs :where(:not(.rating-hidden)){width:1rem;height:1rem}.xl\:rating.rating-sm :where(:not(.rating-hidden)){width:1.25rem;height:1.25rem}.xl\:rating.rating-md :where(:not(.rating-hidden)){width:1.5rem;height:1.5rem}.xl\:rating.rating-lg :where(:not(.rating-hidden)){width:1.75rem;height:1.75rem}.xl\:rating.rating-xl :where(:not(.rating-hidden)){width:2rem;height:2rem}.xl\:rating-half :where(:not(.rating-hidden)){width:.75rem}.xl\:rating-half.rating-xs :not(.rating-hidden){width:.5rem}.xl\:rating-half.rating-sm :not(.rating-hidden){width:.625rem}.xl\:rating-half.rating-md :not(.rating-hidden){width:.75rem}.xl\:rating-half.rating-lg :not(.rating-hidden){width:.875rem}.xl\:rating-half.rating-xl :not(.rating-hidden){width:1rem}}@media (min-width:1536px){.\32 xl\:rating{vertical-align:middle;display:inline-flex;position:relative}.\32 xl\:rating input{appearance:none;border:none}.\32 xl\:rating :where(*){background-color:var(--color-base-content);opacity:.2;border-radius:0;width:1.5rem;height:1.5rem;animation:.25s ease-out rating}.\32 xl\:rating :where(*):is(input){cursor:pointer}.\32 xl\:rating .rating-hidden{background-color:transparent;width:.5rem}.\32 xl\:rating input[type=radio]:checked{background-image:none}.\32 xl\:rating *:checked{opacity:1}.\32 xl\:rating *[aria-checked=true]{opacity:1}.\32 xl\:rating *[aria-current=true]{opacity:1}.\32 xl\:rating *:has(~:checked,~[aria-checked=true],~[aria-current=true]){opacity:1}.\32 xl\:rating *:focus-visible{transition:scale .2s ease-out;scale:1.1}.\32 xl\:rating :active:focus{animation:none;scale:1.1}.\32 xl\:rating.rating-xs :where(:not(.rating-hidden)){width:1rem;height:1rem}.\32 xl\:rating.rating-sm :where(:not(.rating-hidden)){width:1.25rem;height:1.25rem}.\32 xl\:rating.rating-md :where(:not(.rating-hidden)){width:1.5rem;height:1.5rem}.\32 xl\:rating.rating-lg :where(:not(.rating-hidden)){width:1.75rem;height:1.75rem}.\32 xl\:rating.rating-xl :where(:not(.rating-hidden)){width:2rem;height:2rem}.\32 xl\:rating-half :where(:not(.rating-hidden)){width:.75rem}.\32 xl\:rating-half.rating-xs :not(.rating-hidden){width:.5rem}.\32 xl\:rating-half.rating-sm :not(.rating-hidden){width:.625rem}.\32 xl\:rating-half.rating-md :not(.rating-hidden){width:.75rem}.\32 xl\:rating-half.rating-lg :not(.rating-hidden){width:.875rem}.\32 xl\:rating-half.rating-xl :not(.rating-hidden){width:1rem}}.timeline{display:flex;position:relative}.timeline>li{grid-template-rows:var(--timeline-row-start,minmax(0,1fr))auto var(--timeline-row-end,minmax(0,1fr));grid-template-columns:var(--timeline-col-start,minmax(0,1fr))auto var(--timeline-col-end,minmax(0,1fr));flex-shrink:0;align-items:center;display:grid;position:relative}.timeline>li>hr{border:none;width:100%}.timeline>li>hr:first-child{grid-row-start:2;grid-column-start:1}.timeline>li>hr:last-child{grid-area:2/3/auto/none}@media print{.timeline>li>hr{border:.1px solid var(--color-base-300)}}.timeline :where(hr){background-color:var(--color-base-300);height:.25rem}.timeline:has(.timeline-middle hr):first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.timeline:has(.timeline-middle hr):last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.timeline:not(:has(.timeline-middle)) :first-child hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.timeline:not(:has(.timeline-middle)) :last-child hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.timeline-box{border:var(--border)solid;border-radius:var(--radius-box);border-color:var(--color-base-300);background-color:var(--color-base-100);padding-block:.5rem;padding-inline:1rem;font-size:.75rem;box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px lab(0% 0 0/.05)}.timeline-start{grid-area:1/1/2/4;place-self:flex-end center;margin:.25rem}.timeline-middle{grid-row-start:2;grid-column-start:2}.timeline-end{grid-area:3/1/4/4;place-self:flex-start center;margin:.25rem}.timeline-compact{--timeline-row-start:0}.timeline-compact .timeline-start{grid-area:3/1/4/4;place-self:flex-start center}.timeline-compact li:has(.timeline-start) .timeline-end{grid-row-start:auto;grid-column-start:none}.timeline-compact.timeline-vertical>li{--timeline-col-start:0}.timeline-compact.timeline-vertical .timeline-start{grid-area:1/3/4/4;place-self:center flex-start}.timeline-compact.timeline-vertical li:has(.timeline-start) .timeline-end{grid-row-start:none;grid-column-start:auto}.timeline-snap-icon>li{--timeline-col-start:.5rem;--timeline-row-start:minmax(0,1fr)}.timeline-vertical{flex-direction:column}.timeline-vertical>li{--timeline-row-start:minmax(0,1fr);--timeline-row-end:minmax(0,1fr);justify-items:center}.timeline-vertical>li>hr{width:.25rem;height:100%}.timeline-vertical>li>hr:first-child{grid-row-start:1;grid-column-start:2}.timeline-vertical>li>hr:last-child{grid-area:3/2/none}.timeline-vertical .timeline-start{grid-area:1/1/4/2;place-self:center flex-end}.timeline-vertical .timeline-end{grid-area:1/3/4/4;place-self:center flex-start}.timeline-vertical:has(.timeline-middle)>li>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.timeline-vertical:has(.timeline-middle)>li>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.timeline-vertical:not(:has(.timeline-middle)) :first-child>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.timeline-vertical:not(:has(.timeline-middle)) :last-child>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.timeline-vertical.timeline-snap-icon>li{--timeline-col-start:minmax(0,1fr);--timeline-row-start:.5rem}.timeline-horizontal{flex-direction:row}.timeline-horizontal>li{align-items:center}.timeline-horizontal>li>hr{width:100%;height:.25rem}.timeline-horizontal>li>hr:first-child{grid-row-start:2;grid-column-start:1}.timeline-horizontal>li>hr:last-child{grid-area:2/3/auto/none}.timeline-horizontal .timeline-start{grid-area:1/1/2/4;place-self:flex-end center}.timeline-horizontal .timeline-end{grid-area:3/1/4/4;place-self:flex-start center}.timeline-horizontal:has(.timeline-middle)>li>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.timeline-horizontal:has(.timeline-middle)>li>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.timeline-horizontal:not(:has(.timeline-middle)) :first-child>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.timeline-horizontal:not(:has(.timeline-middle)) :last-child>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}@media (min-width:640px){.sm\:timeline{display:flex;position:relative}.sm\:timeline>li{grid-template-rows:var(--timeline-row-start,minmax(0,1fr))auto var(--timeline-row-end,minmax(0,1fr));grid-template-columns:var(--timeline-col-start,minmax(0,1fr))auto var(--timeline-col-end,minmax(0,1fr));flex-shrink:0;align-items:center;display:grid;position:relative}.sm\:timeline>li>hr{border:none;width:100%}.sm\:timeline>li>hr:first-child{grid-row-start:2;grid-column-start:1}.sm\:timeline>li>hr:last-child{grid-area:2/3/auto/none}@media print{.sm\:timeline>li>hr{border:.1px solid var(--color-base-300)}}.sm\:timeline :where(hr){background-color:var(--color-base-300);height:.25rem}.sm\:timeline:has(.timeline-middle hr):first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.sm\:timeline:has(.timeline-middle hr):last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.sm\:timeline:not(:has(.timeline-middle)) :first-child hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.sm\:timeline:not(:has(.timeline-middle)) :last-child hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.sm\:timeline-box{border:var(--border)solid;border-radius:var(--radius-box);border-color:var(--color-base-300);background-color:var(--color-base-100);padding-block:.5rem;padding-inline:1rem;font-size:.75rem;box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px lab(0% 0 0/.05)}.sm\:timeline-start{grid-area:1/1/2/4;place-self:flex-end center;margin:.25rem}.sm\:timeline-middle{grid-row-start:2;grid-column-start:2}.sm\:timeline-end{grid-area:3/1/4/4;place-self:flex-start center;margin:.25rem}.sm\:timeline-compact{--timeline-row-start:0}.sm\:timeline-compact .timeline-start{grid-area:3/1/4/4;place-self:flex-start center}.sm\:timeline-compact li:has(.timeline-start) .timeline-end{grid-row-start:auto;grid-column-start:none}.sm\:timeline-compact.timeline-vertical>li{--timeline-col-start:0}.sm\:timeline-compact.timeline-vertical .timeline-start{grid-area:1/3/4/4;place-self:center flex-start}.sm\:timeline-compact.timeline-vertical li:has(.timeline-start) .timeline-end{grid-row-start:none;grid-column-start:auto}.sm\:timeline-snap-icon>li{--timeline-col-start:.5rem;--timeline-row-start:minmax(0,1fr)}.sm\:timeline-vertical{flex-direction:column}.sm\:timeline-vertical>li{--timeline-row-start:minmax(0,1fr);--timeline-row-end:minmax(0,1fr);justify-items:center}.sm\:timeline-vertical>li>hr{width:.25rem;height:100%}.sm\:timeline-vertical>li>hr:first-child{grid-row-start:1;grid-column-start:2}.sm\:timeline-vertical>li>hr:last-child{grid-area:3/2/none}.sm\:timeline-vertical .timeline-start{grid-area:1/1/4/2;place-self:center flex-end}.sm\:timeline-vertical .timeline-end{grid-area:1/3/4/4;place-self:center flex-start}.sm\:timeline-vertical:has(.timeline-middle)>li>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.sm\:timeline-vertical:has(.timeline-middle)>li>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.sm\:timeline-vertical:not(:has(.timeline-middle)) :first-child>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.sm\:timeline-vertical:not(:has(.timeline-middle)) :last-child>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.sm\:timeline-vertical.timeline-snap-icon>li{--timeline-col-start:minmax(0,1fr);--timeline-row-start:.5rem}.sm\:timeline-horizontal{flex-direction:row}.sm\:timeline-horizontal>li{align-items:center}.sm\:timeline-horizontal>li>hr{width:100%;height:.25rem}.sm\:timeline-horizontal>li>hr:first-child{grid-row-start:2;grid-column-start:1}.sm\:timeline-horizontal>li>hr:last-child{grid-area:2/3/auto/none}.sm\:timeline-horizontal .timeline-start{grid-area:1/1/2/4;place-self:flex-end center}.sm\:timeline-horizontal .timeline-end{grid-area:3/1/4/4;place-self:flex-start center}.sm\:timeline-horizontal:has(.timeline-middle)>li>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.sm\:timeline-horizontal:has(.timeline-middle)>li>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.sm\:timeline-horizontal:not(:has(.timeline-middle)) :first-child>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.sm\:timeline-horizontal:not(:has(.timeline-middle)) :last-child>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}}@media (min-width:768px){.md\:timeline{display:flex;position:relative}.md\:timeline>li{grid-template-rows:var(--timeline-row-start,minmax(0,1fr))auto var(--timeline-row-end,minmax(0,1fr));grid-template-columns:var(--timeline-col-start,minmax(0,1fr))auto var(--timeline-col-end,minmax(0,1fr));flex-shrink:0;align-items:center;display:grid;position:relative}.md\:timeline>li>hr{border:none;width:100%}.md\:timeline>li>hr:first-child{grid-row-start:2;grid-column-start:1}.md\:timeline>li>hr:last-child{grid-area:2/3/auto/none}@media print{.md\:timeline>li>hr{border:.1px solid var(--color-base-300)}}.md\:timeline :where(hr){background-color:var(--color-base-300);height:.25rem}.md\:timeline:has(.timeline-middle hr):first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.md\:timeline:has(.timeline-middle hr):last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.md\:timeline:not(:has(.timeline-middle)) :first-child hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.md\:timeline:not(:has(.timeline-middle)) :last-child hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.md\:timeline-box{border:var(--border)solid;border-radius:var(--radius-box);border-color:var(--color-base-300);background-color:var(--color-base-100);padding-block:.5rem;padding-inline:1rem;font-size:.75rem;box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px lab(0% 0 0/.05)}.md\:timeline-start{grid-area:1/1/2/4;place-self:flex-end center;margin:.25rem}.md\:timeline-middle{grid-row-start:2;grid-column-start:2}.md\:timeline-end{grid-area:3/1/4/4;place-self:flex-start center;margin:.25rem}.md\:timeline-compact{--timeline-row-start:0}.md\:timeline-compact .timeline-start{grid-area:3/1/4/4;place-self:flex-start center}.md\:timeline-compact li:has(.timeline-start) .timeline-end{grid-row-start:auto;grid-column-start:none}.md\:timeline-compact.timeline-vertical>li{--timeline-col-start:0}.md\:timeline-compact.timeline-vertical .timeline-start{grid-area:1/3/4/4;place-self:center flex-start}.md\:timeline-compact.timeline-vertical li:has(.timeline-start) .timeline-end{grid-row-start:none;grid-column-start:auto}.md\:timeline-snap-icon>li{--timeline-col-start:.5rem;--timeline-row-start:minmax(0,1fr)}.md\:timeline-vertical{flex-direction:column}.md\:timeline-vertical>li{--timeline-row-start:minmax(0,1fr);--timeline-row-end:minmax(0,1fr);justify-items:center}.md\:timeline-vertical>li>hr{width:.25rem;height:100%}.md\:timeline-vertical>li>hr:first-child{grid-row-start:1;grid-column-start:2}.md\:timeline-vertical>li>hr:last-child{grid-area:3/2/none}.md\:timeline-vertical .timeline-start{grid-area:1/1/4/2;place-self:center flex-end}.md\:timeline-vertical .timeline-end{grid-area:1/3/4/4;place-self:center flex-start}.md\:timeline-vertical:has(.timeline-middle)>li>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.md\:timeline-vertical:has(.timeline-middle)>li>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.md\:timeline-vertical:not(:has(.timeline-middle)) :first-child>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.md\:timeline-vertical:not(:has(.timeline-middle)) :last-child>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.md\:timeline-vertical.timeline-snap-icon>li{--timeline-col-start:minmax(0,1fr);--timeline-row-start:.5rem}.md\:timeline-horizontal{flex-direction:row}.md\:timeline-horizontal>li{align-items:center}.md\:timeline-horizontal>li>hr{width:100%;height:.25rem}.md\:timeline-horizontal>li>hr:first-child{grid-row-start:2;grid-column-start:1}.md\:timeline-horizontal>li>hr:last-child{grid-area:2/3/auto/none}.md\:timeline-horizontal .timeline-start{grid-area:1/1/2/4;place-self:flex-end center}.md\:timeline-horizontal .timeline-end{grid-area:3/1/4/4;place-self:flex-start center}.md\:timeline-horizontal:has(.timeline-middle)>li>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.md\:timeline-horizontal:has(.timeline-middle)>li>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.md\:timeline-horizontal:not(:has(.timeline-middle)) :first-child>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.md\:timeline-horizontal:not(:has(.timeline-middle)) :last-child>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}}@media (min-width:1024px){.lg\:timeline{display:flex;position:relative}.lg\:timeline>li{grid-template-rows:var(--timeline-row-start,minmax(0,1fr))auto var(--timeline-row-end,minmax(0,1fr));grid-template-columns:var(--timeline-col-start,minmax(0,1fr))auto var(--timeline-col-end,minmax(0,1fr));flex-shrink:0;align-items:center;display:grid;position:relative}.lg\:timeline>li>hr{border:none;width:100%}.lg\:timeline>li>hr:first-child{grid-row-start:2;grid-column-start:1}.lg\:timeline>li>hr:last-child{grid-area:2/3/auto/none}@media print{.lg\:timeline>li>hr{border:.1px solid var(--color-base-300)}}.lg\:timeline :where(hr){background-color:var(--color-base-300);height:.25rem}.lg\:timeline:has(.timeline-middle hr):first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.lg\:timeline:has(.timeline-middle hr):last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.lg\:timeline:not(:has(.timeline-middle)) :first-child hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.lg\:timeline:not(:has(.timeline-middle)) :last-child hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.lg\:timeline-box{border:var(--border)solid;border-radius:var(--radius-box);border-color:var(--color-base-300);background-color:var(--color-base-100);padding-block:.5rem;padding-inline:1rem;font-size:.75rem;box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px lab(0% 0 0/.05)}.lg\:timeline-start{grid-area:1/1/2/4;place-self:flex-end center;margin:.25rem}.lg\:timeline-middle{grid-row-start:2;grid-column-start:2}.lg\:timeline-end{grid-area:3/1/4/4;place-self:flex-start center;margin:.25rem}.lg\:timeline-compact{--timeline-row-start:0}.lg\:timeline-compact .timeline-start{grid-area:3/1/4/4;place-self:flex-start center}.lg\:timeline-compact li:has(.timeline-start) .timeline-end{grid-row-start:auto;grid-column-start:none}.lg\:timeline-compact.timeline-vertical>li{--timeline-col-start:0}.lg\:timeline-compact.timeline-vertical .timeline-start{grid-area:1/3/4/4;place-self:center flex-start}.lg\:timeline-compact.timeline-vertical li:has(.timeline-start) .timeline-end{grid-row-start:none;grid-column-start:auto}.lg\:timeline-snap-icon>li{--timeline-col-start:.5rem;--timeline-row-start:minmax(0,1fr)}.lg\:timeline-vertical{flex-direction:column}.lg\:timeline-vertical>li{--timeline-row-start:minmax(0,1fr);--timeline-row-end:minmax(0,1fr);justify-items:center}.lg\:timeline-vertical>li>hr{width:.25rem;height:100%}.lg\:timeline-vertical>li>hr:first-child{grid-row-start:1;grid-column-start:2}.lg\:timeline-vertical>li>hr:last-child{grid-area:3/2/none}.lg\:timeline-vertical .timeline-start{grid-area:1/1/4/2;place-self:center flex-end}.lg\:timeline-vertical .timeline-end{grid-area:1/3/4/4;place-self:center flex-start}.lg\:timeline-vertical:has(.timeline-middle)>li>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.lg\:timeline-vertical:has(.timeline-middle)>li>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.lg\:timeline-vertical:not(:has(.timeline-middle)) :first-child>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.lg\:timeline-vertical:not(:has(.timeline-middle)) :last-child>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.lg\:timeline-vertical.timeline-snap-icon>li{--timeline-col-start:minmax(0,1fr);--timeline-row-start:.5rem}.lg\:timeline-horizontal{flex-direction:row}.lg\:timeline-horizontal>li{align-items:center}.lg\:timeline-horizontal>li>hr{width:100%;height:.25rem}.lg\:timeline-horizontal>li>hr:first-child{grid-row-start:2;grid-column-start:1}.lg\:timeline-horizontal>li>hr:last-child{grid-area:2/3/auto/none}.lg\:timeline-horizontal .timeline-start{grid-area:1/1/2/4;place-self:flex-end center}.lg\:timeline-horizontal .timeline-end{grid-area:3/1/4/4;place-self:flex-start center}.lg\:timeline-horizontal:has(.timeline-middle)>li>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.lg\:timeline-horizontal:has(.timeline-middle)>li>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.lg\:timeline-horizontal:not(:has(.timeline-middle)) :first-child>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.lg\:timeline-horizontal:not(:has(.timeline-middle)) :last-child>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}}@media (min-width:1280px){.xl\:timeline{display:flex;position:relative}.xl\:timeline>li{grid-template-rows:var(--timeline-row-start,minmax(0,1fr))auto var(--timeline-row-end,minmax(0,1fr));grid-template-columns:var(--timeline-col-start,minmax(0,1fr))auto var(--timeline-col-end,minmax(0,1fr));flex-shrink:0;align-items:center;display:grid;position:relative}.xl\:timeline>li>hr{border:none;width:100%}.xl\:timeline>li>hr:first-child{grid-row-start:2;grid-column-start:1}.xl\:timeline>li>hr:last-child{grid-area:2/3/auto/none}@media print{.xl\:timeline>li>hr{border:.1px solid var(--color-base-300)}}.xl\:timeline :where(hr){background-color:var(--color-base-300);height:.25rem}.xl\:timeline:has(.timeline-middle hr):first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.xl\:timeline:has(.timeline-middle hr):last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.xl\:timeline:not(:has(.timeline-middle)) :first-child hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.xl\:timeline:not(:has(.timeline-middle)) :last-child hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.xl\:timeline-box{border:var(--border)solid;border-radius:var(--radius-box);border-color:var(--color-base-300);background-color:var(--color-base-100);padding-block:.5rem;padding-inline:1rem;font-size:.75rem;box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px lab(0% 0 0/.05)}.xl\:timeline-start{grid-area:1/1/2/4;place-self:flex-end center;margin:.25rem}.xl\:timeline-middle{grid-row-start:2;grid-column-start:2}.xl\:timeline-end{grid-area:3/1/4/4;place-self:flex-start center;margin:.25rem}.xl\:timeline-compact{--timeline-row-start:0}.xl\:timeline-compact .timeline-start{grid-area:3/1/4/4;place-self:flex-start center}.xl\:timeline-compact li:has(.timeline-start) .timeline-end{grid-row-start:auto;grid-column-start:none}.xl\:timeline-compact.timeline-vertical>li{--timeline-col-start:0}.xl\:timeline-compact.timeline-vertical .timeline-start{grid-area:1/3/4/4;place-self:center flex-start}.xl\:timeline-compact.timeline-vertical li:has(.timeline-start) .timeline-end{grid-row-start:none;grid-column-start:auto}.xl\:timeline-snap-icon>li{--timeline-col-start:.5rem;--timeline-row-start:minmax(0,1fr)}.xl\:timeline-vertical{flex-direction:column}.xl\:timeline-vertical>li{--timeline-row-start:minmax(0,1fr);--timeline-row-end:minmax(0,1fr);justify-items:center}.xl\:timeline-vertical>li>hr{width:.25rem;height:100%}.xl\:timeline-vertical>li>hr:first-child{grid-row-start:1;grid-column-start:2}.xl\:timeline-vertical>li>hr:last-child{grid-area:3/2/none}.xl\:timeline-vertical .timeline-start{grid-area:1/1/4/2;place-self:center flex-end}.xl\:timeline-vertical .timeline-end{grid-area:1/3/4/4;place-self:center flex-start}.xl\:timeline-vertical:has(.timeline-middle)>li>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.xl\:timeline-vertical:has(.timeline-middle)>li>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.xl\:timeline-vertical:not(:has(.timeline-middle)) :first-child>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.xl\:timeline-vertical:not(:has(.timeline-middle)) :last-child>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.xl\:timeline-vertical.timeline-snap-icon>li{--timeline-col-start:minmax(0,1fr);--timeline-row-start:.5rem}.xl\:timeline-horizontal{flex-direction:row}.xl\:timeline-horizontal>li{align-items:center}.xl\:timeline-horizontal>li>hr{width:100%;height:.25rem}.xl\:timeline-horizontal>li>hr:first-child{grid-row-start:2;grid-column-start:1}.xl\:timeline-horizontal>li>hr:last-child{grid-area:2/3/auto/none}.xl\:timeline-horizontal .timeline-start{grid-area:1/1/2/4;place-self:flex-end center}.xl\:timeline-horizontal .timeline-end{grid-area:3/1/4/4;place-self:flex-start center}.xl\:timeline-horizontal:has(.timeline-middle)>li>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.xl\:timeline-horizontal:has(.timeline-middle)>li>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.xl\:timeline-horizontal:not(:has(.timeline-middle)) :first-child>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.xl\:timeline-horizontal:not(:has(.timeline-middle)) :last-child>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}}@media (min-width:1536px){.\32 xl\:timeline{display:flex;position:relative}.\32 xl\:timeline>li{grid-template-rows:var(--timeline-row-start,minmax(0,1fr))auto var(--timeline-row-end,minmax(0,1fr));grid-template-columns:var(--timeline-col-start,minmax(0,1fr))auto var(--timeline-col-end,minmax(0,1fr));flex-shrink:0;align-items:center;display:grid;position:relative}.\32 xl\:timeline>li>hr{border:none;width:100%}.\32 xl\:timeline>li>hr:first-child{grid-row-start:2;grid-column-start:1}.\32 xl\:timeline>li>hr:last-child{grid-area:2/3/auto/none}@media print{.\32 xl\:timeline>li>hr{border:.1px solid var(--color-base-300)}}.\32 xl\:timeline :where(hr){background-color:var(--color-base-300);height:.25rem}.\32 xl\:timeline:has(.timeline-middle hr):first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.\32 xl\:timeline:has(.timeline-middle hr):last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.\32 xl\:timeline:not(:has(.timeline-middle)) :first-child hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.\32 xl\:timeline:not(:has(.timeline-middle)) :last-child hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.\32 xl\:timeline-box{border:var(--border)solid;border-radius:var(--radius-box);border-color:var(--color-base-300);background-color:var(--color-base-100);padding-block:.5rem;padding-inline:1rem;font-size:.75rem;box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px lab(0% 0 0/.05)}.\32 xl\:timeline-start{grid-area:1/1/2/4;place-self:flex-end center;margin:.25rem}.\32 xl\:timeline-middle{grid-row-start:2;grid-column-start:2}.\32 xl\:timeline-end{grid-area:3/1/4/4;place-self:flex-start center;margin:.25rem}.\32 xl\:timeline-compact{--timeline-row-start:0}.\32 xl\:timeline-compact .timeline-start{grid-area:3/1/4/4;place-self:flex-start center}.\32 xl\:timeline-compact li:has(.timeline-start) .timeline-end{grid-row-start:auto;grid-column-start:none}.\32 xl\:timeline-compact.timeline-vertical>li{--timeline-col-start:0}.\32 xl\:timeline-compact.timeline-vertical .timeline-start{grid-area:1/3/4/4;place-self:center flex-start}.\32 xl\:timeline-compact.timeline-vertical li:has(.timeline-start) .timeline-end{grid-row-start:none;grid-column-start:auto}.\32 xl\:timeline-snap-icon>li{--timeline-col-start:.5rem;--timeline-row-start:minmax(0,1fr)}.\32 xl\:timeline-vertical{flex-direction:column}.\32 xl\:timeline-vertical>li{--timeline-row-start:minmax(0,1fr);--timeline-row-end:minmax(0,1fr);justify-items:center}.\32 xl\:timeline-vertical>li>hr{width:.25rem;height:100%}.\32 xl\:timeline-vertical>li>hr:first-child{grid-row-start:1;grid-column-start:2}.\32 xl\:timeline-vertical>li>hr:last-child{grid-area:3/2/none}.\32 xl\:timeline-vertical .timeline-start{grid-area:1/1/4/2;place-self:center flex-end}.\32 xl\:timeline-vertical .timeline-end{grid-area:1/3/4/4;place-self:center flex-start}.\32 xl\:timeline-vertical:has(.timeline-middle)>li>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.\32 xl\:timeline-vertical:has(.timeline-middle)>li>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.\32 xl\:timeline-vertical:not(:has(.timeline-middle)) :first-child>hr:last-child{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector);border-bottom-right-radius:0;border-bottom-left-radius:0}.\32 xl\:timeline-vertical:not(:has(.timeline-middle)) :last-child>hr:first-child{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.\32 xl\:timeline-vertical.timeline-snap-icon>li{--timeline-col-start:minmax(0,1fr);--timeline-row-start:.5rem}.\32 xl\:timeline-horizontal{flex-direction:row}.\32 xl\:timeline-horizontal>li{align-items:center}.\32 xl\:timeline-horizontal>li>hr{width:100%;height:.25rem}.\32 xl\:timeline-horizontal>li>hr:first-child{grid-row-start:2;grid-column-start:1}.\32 xl\:timeline-horizontal>li>hr:last-child{grid-area:2/3/auto/none}.\32 xl\:timeline-horizontal .timeline-start{grid-area:1/1/2/4;place-self:flex-end center}.\32 xl\:timeline-horizontal .timeline-end{grid-area:3/1/4/4;place-self:flex-start center}.\32 xl\:timeline-horizontal:has(.timeline-middle)>li>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.\32 xl\:timeline-horizontal:has(.timeline-middle)>li>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.\32 xl\:timeline-horizontal:not(:has(.timeline-middle)) :first-child>hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.\32 xl\:timeline-horizontal:not(:has(.timeline-middle)) :last-child>hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}}.mockup-code{border-radius:var(--radius-box);background-color:var(--color-neutral);color:var(--color-neutral-content);direction:ltr;padding-block:1.25rem;font-size:.875rem;position:relative;overflow:auto hidden}.mockup-code:before{content:"";opacity:.3;border-radius:3.40282e38px;width:.75rem;height:.75rem;margin-bottom:1rem;display:block;box-shadow:1.4em 0,2.8em 0,4.2em 0}.mockup-code pre{padding-right:1.25rem}.mockup-code pre:before{content:"";margin-right:2ch}.mockup-code pre[data-prefix]:before{content:attr(data-prefix);text-align:right;opacity:.5;width:2rem;display:inline-block}.mockup-window{border-radius:var(--radius-box);flex-direction:column;padding-top:1.25rem;display:flex;position:relative;overflow:auto hidden}.mockup-window:before{content:"";aspect-ratio:1;opacity:.3;border-radius:3.40282e38px;flex-shrink:0;align-self:flex-start;height:.75rem;margin-bottom:1rem;display:block;box-shadow:1.4em 0,2.8em 0,4.2em 0}[dir=rtl] .mockup-window:before{align-self:flex-end}.mockup-window pre[data-prefix]:before{content:attr(data-prefix);text-align:right;display:inline-block}.mockup-browser{border-radius:var(--radius-box);position:relative;overflow:auto hidden}.mockup-browser pre[data-prefix]:before{content:attr(data-prefix);text-align:right;display:inline-block}.mockup-browser .mockup-browser-toolbar{align-items:center;width:100%;margin-block:.75rem;padding-right:1.4em;display:inline-flex}.mockup-browser .mockup-browser-toolbar:where(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)),[dir=rtl],[dir=rtl] *){flex-direction:row-reverse}.mockup-browser .mockup-browser-toolbar:before{content:"";aspect-ratio:1;opacity:.3;border-radius:3.40282e38px;height:.75rem;margin-right:4.8rem;display:inline-block;box-shadow:1.4em 0,2.8em 0,4.2em 0}.mockup-browser .mockup-browser-toolbar .input{background-color:var(--color-base-200);text-overflow:ellipsis;white-space:nowrap;direction:ltr;align-items:center;gap:.5rem;height:100%;margin-inline:auto;font-size:.75rem;display:flex;overflow:hidden}.mockup-browser .mockup-browser-toolbar .input:before{content:"";opacity:.3;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='currentColor' class='size-4'%3E%3Cpath fill-rule='evenodd' d='M9.965 11.026a5 5 0 1 1 1.06-1.06l2.755 2.754a.75.75 0 1 1-1.06 1.06l-2.755-2.754ZM10.5 7a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Z' clip-rule='evenodd' /%3E%3C/svg%3E%0A");width:1rem;height:1rem}.mockup-phone{background-color:#000;border:6px solid #6b6b6b;border-radius:65px;justify-items:center;padding:11px;display:inline-grid;overflow:hidden}.mockup-phone-camera{z-index:1;background:#000;border-radius:17px;grid-area:1/1/1/1;width:126px;height:32px;margin-top:6px}.mockup-phone-display{border-radius:49px;grid-area:1/1/1/1;width:390px;height:845px;overflow:hidden}.fieldset{grid-template-columns:1fr;grid-auto-rows:max-content;gap:.375rem;padding-block:.25rem;font-size:.75rem;display:grid}.fieldset-legend{color:var(--color-base-content);justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:-.25rem;padding-block:.5rem;font-weight:600;display:flex}.fieldset-label{color:color-mix(in oklab,var(--color-base-content)60%,transparent);align-items:center;gap:.375rem;display:flex}.fieldset-label:has(input){cursor:pointer}@media (min-width:640px){.sm\:fieldset{grid-template-columns:1fr;grid-auto-rows:max-content;gap:.375rem;padding-block:.25rem;font-size:.75rem;display:grid}.sm\:fieldset-legend{color:var(--color-base-content);justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:-.25rem;padding-block:.5rem;font-weight:600;display:flex}.sm\:fieldset-label{color:color-mix(in oklab,var(--color-base-content)60%,transparent);align-items:center;gap:.375rem;display:flex}.sm\:fieldset-label:has(input){cursor:pointer}}@media (min-width:768px){.md\:fieldset{grid-template-columns:1fr;grid-auto-rows:max-content;gap:.375rem;padding-block:.25rem;font-size:.75rem;display:grid}.md\:fieldset-legend{color:var(--color-base-content);justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:-.25rem;padding-block:.5rem;font-weight:600;display:flex}.md\:fieldset-label{color:color-mix(in oklab,var(--color-base-content)60%,transparent);align-items:center;gap:.375rem;display:flex}.md\:fieldset-label:has(input){cursor:pointer}}@media (min-width:1024px){.lg\:fieldset{grid-template-columns:1fr;grid-auto-rows:max-content;gap:.375rem;padding-block:.25rem;font-size:.75rem;display:grid}.lg\:fieldset-legend{color:var(--color-base-content);justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:-.25rem;padding-block:.5rem;font-weight:600;display:flex}.lg\:fieldset-label{color:color-mix(in oklab,var(--color-base-content)60%,transparent);align-items:center;gap:.375rem;display:flex}.lg\:fieldset-label:has(input){cursor:pointer}}@media (min-width:1280px){.xl\:fieldset{grid-template-columns:1fr;grid-auto-rows:max-content;gap:.375rem;padding-block:.25rem;font-size:.75rem;display:grid}.xl\:fieldset-legend{color:var(--color-base-content);justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:-.25rem;padding-block:.5rem;font-weight:600;display:flex}.xl\:fieldset-label{color:color-mix(in oklab,var(--color-base-content)60%,transparent);align-items:center;gap:.375rem;display:flex}.xl\:fieldset-label:has(input){cursor:pointer}}@media (min-width:1536px){.\32 xl\:fieldset{grid-template-columns:1fr;grid-auto-rows:max-content;gap:.375rem;padding-block:.25rem;font-size:.75rem;display:grid}.\32 xl\:fieldset-legend{color:var(--color-base-content);justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:-.25rem;padding-block:.5rem;font-weight:600;display:flex}.\32 xl\:fieldset-label{color:color-mix(in oklab,var(--color-base-content)60%,transparent);align-items:center;gap:.375rem;display:flex}.\32 xl\:fieldset-label:has(input){cursor:pointer}}.progress{appearance:none;border-radius:var(--radius-box);background-color:color-mix(in oklab,currentColor 20%,transparent);width:100%;height:.5rem;color:var(--color-base-content);position:relative;overflow:hidden}.progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}@supports ((-moz-appearance:none)){.progress:indeterminate::-moz-progress-bar{background-color:transparent;background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}}@supports ((-moz-appearance:none)){.progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:transparent}.progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.progress-primary{color:var(--color-primary)}.progress-secondary{color:var(--color-secondary)}.progress-accent{color:var(--color-accent)}.progress-neutral{color:var(--color-neutral)}.progress-info{color:var(--color-info)}.progress-success{color:var(--color-success)}.progress-warning{color:var(--color-warning)}.progress-error{color:var(--color-error)}@keyframes progress{50%{background-position-x:-115%}}@media (min-width:640px){.sm\:progress{appearance:none;border-radius:var(--radius-box);background-color:color-mix(in oklab,currentColor 20%,transparent);width:100%;height:.5rem;color:var(--color-base-content);position:relative;overflow:hidden}.sm\:progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}@supports ((-moz-appearance:none)){.sm\:progress:indeterminate::-moz-progress-bar{background-color:transparent;background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}}@supports ((-moz-appearance:none)){.sm\:progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.sm\:progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:transparent}.sm\:progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.sm\:progress-primary{color:var(--color-primary)}.sm\:progress-secondary{color:var(--color-secondary)}.sm\:progress-accent{color:var(--color-accent)}.sm\:progress-neutral{color:var(--color-neutral)}.sm\:progress-info{color:var(--color-info)}.sm\:progress-success{color:var(--color-success)}.sm\:progress-warning{color:var(--color-warning)}.sm\:progress-error{color:var(--color-error)}}@media (min-width:768px){.md\:progress{appearance:none;border-radius:var(--radius-box);background-color:color-mix(in oklab,currentColor 20%,transparent);width:100%;height:.5rem;color:var(--color-base-content);position:relative;overflow:hidden}.md\:progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}@supports ((-moz-appearance:none)){.md\:progress:indeterminate::-moz-progress-bar{background-color:transparent;background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}}@supports ((-moz-appearance:none)){.md\:progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.md\:progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:transparent}.md\:progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.md\:progress-primary{color:var(--color-primary)}.md\:progress-secondary{color:var(--color-secondary)}.md\:progress-accent{color:var(--color-accent)}.md\:progress-neutral{color:var(--color-neutral)}.md\:progress-info{color:var(--color-info)}.md\:progress-success{color:var(--color-success)}.md\:progress-warning{color:var(--color-warning)}.md\:progress-error{color:var(--color-error)}}@media (min-width:1024px){.lg\:progress{appearance:none;border-radius:var(--radius-box);background-color:color-mix(in oklab,currentColor 20%,transparent);width:100%;height:.5rem;color:var(--color-base-content);position:relative;overflow:hidden}.lg\:progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}@supports ((-moz-appearance:none)){.lg\:progress:indeterminate::-moz-progress-bar{background-color:transparent;background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}}@supports ((-moz-appearance:none)){.lg\:progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.lg\:progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:transparent}.lg\:progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.lg\:progress-primary{color:var(--color-primary)}.lg\:progress-secondary{color:var(--color-secondary)}.lg\:progress-accent{color:var(--color-accent)}.lg\:progress-neutral{color:var(--color-neutral)}.lg\:progress-info{color:var(--color-info)}.lg\:progress-success{color:var(--color-success)}.lg\:progress-warning{color:var(--color-warning)}.lg\:progress-error{color:var(--color-error)}}@media (min-width:1280px){.xl\:progress{appearance:none;border-radius:var(--radius-box);background-color:color-mix(in oklab,currentColor 20%,transparent);width:100%;height:.5rem;color:var(--color-base-content);position:relative;overflow:hidden}.xl\:progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}@supports ((-moz-appearance:none)){.xl\:progress:indeterminate::-moz-progress-bar{background-color:transparent;background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}}@supports ((-moz-appearance:none)){.xl\:progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.xl\:progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:transparent}.xl\:progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.xl\:progress-primary{color:var(--color-primary)}.xl\:progress-secondary{color:var(--color-secondary)}.xl\:progress-accent{color:var(--color-accent)}.xl\:progress-neutral{color:var(--color-neutral)}.xl\:progress-info{color:var(--color-info)}.xl\:progress-success{color:var(--color-success)}.xl\:progress-warning{color:var(--color-warning)}.xl\:progress-error{color:var(--color-error)}}@media (min-width:1536px){.\32 xl\:progress{appearance:none;border-radius:var(--radius-box);background-color:color-mix(in oklab,currentColor 20%,transparent);width:100%;height:.5rem;color:var(--color-base-content);position:relative;overflow:hidden}.\32 xl\:progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}@supports ((-moz-appearance:none)){.\32 xl\:progress:indeterminate::-moz-progress-bar{background-color:transparent;background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,transparent 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}}@supports ((-moz-appearance:none)){.\32 xl\:progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.\32 xl\:progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:transparent}.\32 xl\:progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.\32 xl\:progress-primary{color:var(--color-primary)}.\32 xl\:progress-secondary{color:var(--color-secondary)}.\32 xl\:progress-accent{color:var(--color-accent)}.\32 xl\:progress-neutral{color:var(--color-neutral)}.\32 xl\:progress-info{color:var(--color-info)}.\32 xl\:progress-success{color:var(--color-success)}.\32 xl\:progress-warning{color:var(--color-warning)}.\32 xl\:progress-error{color:var(--color-error)}}.breadcrumbs{max-width:100%;padding-block:.5rem;overflow-x:auto}.breadcrumbs>menu{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.breadcrumbs>menu>li{align-items:center;display:flex}.breadcrumbs>menu>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.breadcrumbs>menu>li>*:hover{text-decoration-line:underline}}.breadcrumbs>menu>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.breadcrumbs>menu>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.breadcrumbs>menu>li>*:focus-visible{outline-offset:2px;outline:2px solid}.breadcrumbs>menu>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.breadcrumbs>menu>li)+:before{rotate:-135deg}.breadcrumbs>ul{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.breadcrumbs>ul>li{align-items:center;display:flex}.breadcrumbs>ul>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.breadcrumbs>ul>li>*:hover{text-decoration-line:underline}}.breadcrumbs>ul>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.breadcrumbs>ul>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.breadcrumbs>ul>li>*:focus-visible{outline-offset:2px;outline:2px solid}.breadcrumbs>ul>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.breadcrumbs>ul>li)+:before{rotate:-135deg}.breadcrumbs>ol{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.breadcrumbs>ol>li{align-items:center;display:flex}.breadcrumbs>ol>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.breadcrumbs>ol>li>*:hover{text-decoration-line:underline}}.breadcrumbs>ol>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.breadcrumbs>ol>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.breadcrumbs>ol>li>*:focus-visible{outline-offset:2px;outline:2px solid}.breadcrumbs>ol>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.breadcrumbs>ol>li)+:before{rotate:-135deg}@media (min-width:640px){.sm\:breadcrumbs{max-width:100%;padding-block:.5rem;overflow-x:auto}.sm\:breadcrumbs>menu{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.sm\:breadcrumbs>menu>li{align-items:center;display:flex}.sm\:breadcrumbs>menu>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.sm\:breadcrumbs>menu>li>*:hover{text-decoration-line:underline}}.sm\:breadcrumbs>menu>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:breadcrumbs>menu>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.sm\:breadcrumbs>menu>li>*:focus-visible{outline-offset:2px;outline:2px solid}.sm\:breadcrumbs>menu>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.sm\:breadcrumbs>menu>li)+:before{rotate:-135deg}.sm\:breadcrumbs>ul{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.sm\:breadcrumbs>ul>li{align-items:center;display:flex}.sm\:breadcrumbs>ul>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.sm\:breadcrumbs>ul>li>*:hover{text-decoration-line:underline}}.sm\:breadcrumbs>ul>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:breadcrumbs>ul>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.sm\:breadcrumbs>ul>li>*:focus-visible{outline-offset:2px;outline:2px solid}.sm\:breadcrumbs>ul>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.sm\:breadcrumbs>ul>li)+:before{rotate:-135deg}.sm\:breadcrumbs>ol{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.sm\:breadcrumbs>ol>li{align-items:center;display:flex}.sm\:breadcrumbs>ol>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.sm\:breadcrumbs>ol>li>*:hover{text-decoration-line:underline}}.sm\:breadcrumbs>ol>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:breadcrumbs>ol>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.sm\:breadcrumbs>ol>li>*:focus-visible{outline-offset:2px;outline:2px solid}.sm\:breadcrumbs>ol>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.sm\:breadcrumbs>ol>li)+:before{rotate:-135deg}}@media (min-width:768px){.md\:breadcrumbs{max-width:100%;padding-block:.5rem;overflow-x:auto}.md\:breadcrumbs>menu{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.md\:breadcrumbs>menu>li{align-items:center;display:flex}.md\:breadcrumbs>menu>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.md\:breadcrumbs>menu>li>*:hover{text-decoration-line:underline}}.md\:breadcrumbs>menu>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:breadcrumbs>menu>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.md\:breadcrumbs>menu>li>*:focus-visible{outline-offset:2px;outline:2px solid}.md\:breadcrumbs>menu>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.md\:breadcrumbs>menu>li)+:before{rotate:-135deg}.md\:breadcrumbs>ul{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.md\:breadcrumbs>ul>li{align-items:center;display:flex}.md\:breadcrumbs>ul>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.md\:breadcrumbs>ul>li>*:hover{text-decoration-line:underline}}.md\:breadcrumbs>ul>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:breadcrumbs>ul>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.md\:breadcrumbs>ul>li>*:focus-visible{outline-offset:2px;outline:2px solid}.md\:breadcrumbs>ul>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.md\:breadcrumbs>ul>li)+:before{rotate:-135deg}.md\:breadcrumbs>ol{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.md\:breadcrumbs>ol>li{align-items:center;display:flex}.md\:breadcrumbs>ol>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.md\:breadcrumbs>ol>li>*:hover{text-decoration-line:underline}}.md\:breadcrumbs>ol>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:breadcrumbs>ol>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.md\:breadcrumbs>ol>li>*:focus-visible{outline-offset:2px;outline:2px solid}.md\:breadcrumbs>ol>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.md\:breadcrumbs>ol>li)+:before{rotate:-135deg}}@media (min-width:1024px){.lg\:breadcrumbs{max-width:100%;padding-block:.5rem;overflow-x:auto}.lg\:breadcrumbs>menu{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.lg\:breadcrumbs>menu>li{align-items:center;display:flex}.lg\:breadcrumbs>menu>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.lg\:breadcrumbs>menu>li>*:hover{text-decoration-line:underline}}.lg\:breadcrumbs>menu>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:breadcrumbs>menu>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.lg\:breadcrumbs>menu>li>*:focus-visible{outline-offset:2px;outline:2px solid}.lg\:breadcrumbs>menu>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.lg\:breadcrumbs>menu>li)+:before{rotate:-135deg}.lg\:breadcrumbs>ul{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.lg\:breadcrumbs>ul>li{align-items:center;display:flex}.lg\:breadcrumbs>ul>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.lg\:breadcrumbs>ul>li>*:hover{text-decoration-line:underline}}.lg\:breadcrumbs>ul>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:breadcrumbs>ul>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.lg\:breadcrumbs>ul>li>*:focus-visible{outline-offset:2px;outline:2px solid}.lg\:breadcrumbs>ul>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.lg\:breadcrumbs>ul>li)+:before{rotate:-135deg}.lg\:breadcrumbs>ol{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.lg\:breadcrumbs>ol>li{align-items:center;display:flex}.lg\:breadcrumbs>ol>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.lg\:breadcrumbs>ol>li>*:hover{text-decoration-line:underline}}.lg\:breadcrumbs>ol>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:breadcrumbs>ol>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.lg\:breadcrumbs>ol>li>*:focus-visible{outline-offset:2px;outline:2px solid}.lg\:breadcrumbs>ol>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.lg\:breadcrumbs>ol>li)+:before{rotate:-135deg}}@media (min-width:1280px){.xl\:breadcrumbs{max-width:100%;padding-block:.5rem;overflow-x:auto}.xl\:breadcrumbs>menu{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.xl\:breadcrumbs>menu>li{align-items:center;display:flex}.xl\:breadcrumbs>menu>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.xl\:breadcrumbs>menu>li>*:hover{text-decoration-line:underline}}.xl\:breadcrumbs>menu>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:breadcrumbs>menu>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.xl\:breadcrumbs>menu>li>*:focus-visible{outline-offset:2px;outline:2px solid}.xl\:breadcrumbs>menu>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.xl\:breadcrumbs>menu>li)+:before{rotate:-135deg}.xl\:breadcrumbs>ul{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.xl\:breadcrumbs>ul>li{align-items:center;display:flex}.xl\:breadcrumbs>ul>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.xl\:breadcrumbs>ul>li>*:hover{text-decoration-line:underline}}.xl\:breadcrumbs>ul>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:breadcrumbs>ul>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.xl\:breadcrumbs>ul>li>*:focus-visible{outline-offset:2px;outline:2px solid}.xl\:breadcrumbs>ul>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.xl\:breadcrumbs>ul>li)+:before{rotate:-135deg}.xl\:breadcrumbs>ol{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.xl\:breadcrumbs>ol>li{align-items:center;display:flex}.xl\:breadcrumbs>ol>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.xl\:breadcrumbs>ol>li>*:hover{text-decoration-line:underline}}.xl\:breadcrumbs>ol>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:breadcrumbs>ol>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.xl\:breadcrumbs>ol>li>*:focus-visible{outline-offset:2px;outline:2px solid}.xl\:breadcrumbs>ol>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.xl\:breadcrumbs>ol>li)+:before{rotate:-135deg}}@media (min-width:1536px){.\32 xl\:breadcrumbs{max-width:100%;padding-block:.5rem;overflow-x:auto}.\32 xl\:breadcrumbs>menu{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.\32 xl\:breadcrumbs>menu>li{align-items:center;display:flex}.\32 xl\:breadcrumbs>menu>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.\32 xl\:breadcrumbs>menu>li>*:hover{text-decoration-line:underline}}.\32 xl\:breadcrumbs>menu>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:breadcrumbs>menu>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:breadcrumbs>menu>li>*:focus-visible{outline-offset:2px;outline:2px solid}.\32 xl\:breadcrumbs>menu>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.\32 xl\:breadcrumbs>menu>li)+:before{rotate:-135deg}.\32 xl\:breadcrumbs>ul{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.\32 xl\:breadcrumbs>ul>li{align-items:center;display:flex}.\32 xl\:breadcrumbs>ul>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.\32 xl\:breadcrumbs>ul>li>*:hover{text-decoration-line:underline}}.\32 xl\:breadcrumbs>ul>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:breadcrumbs>ul>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:breadcrumbs>ul>li>*:focus-visible{outline-offset:2px;outline:2px solid}.\32 xl\:breadcrumbs>ul>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.\32 xl\:breadcrumbs>ul>li)+:before{rotate:-135deg}.\32 xl\:breadcrumbs>ol{white-space:nowrap;align-items:center;min-height:min-content;display:flex}.\32 xl\:breadcrumbs>ol>li{align-items:center;display:flex}.\32 xl\:breadcrumbs>ol>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){.\32 xl\:breadcrumbs>ol>li>*:hover{text-decoration-line:underline}}.\32 xl\:breadcrumbs>ol>li>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:breadcrumbs>ol>li>*:focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:breadcrumbs>ol>li>*:focus-visible{outline-offset:2px;outline:2px solid}.\32 xl\:breadcrumbs>ol>li+:before{content:"";opacity:.4;background-color:transparent;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(.\32 xl\:breadcrumbs>ol>li)+:before{rotate:-135deg}}.validator:user-valid{--input-color:var(--color-success)}.validator:user-valid:focus{--input-color:var(--color-success)}.validator:user-valid:checked{--input-color:var(--color-success)}.validator:user-valid[aria-checked=true]{--input-color:var(--color-success)}.validator:user-valid:focus-within{--input-color:var(--color-success)}.validator:has(:user-valid){--input-color:var(--color-success)}.validator:has(:user-valid):focus{--input-color:var(--color-success)}.validator:has(:user-valid):checked{--input-color:var(--color-success)}.validator:has(:user-valid)[aria-checked=true]{--input-color:var(--color-success)}.validator:has(:user-valid):focus-within{--input-color:var(--color-success)}.validator:user-invalid{--input-color:var(--color-error)}.validator:user-invalid:focus{--input-color:var(--color-error)}.validator:user-invalid:checked{--input-color:var(--color-error)}.validator:user-invalid[aria-checked=true]{--input-color:var(--color-error)}.validator:user-invalid:focus-within{--input-color:var(--color-error)}.validator:user-invalid~.validator-hint{visibility:visible;color:var(--color-error);display:block}.validator:has(:user-invalid){--input-color:var(--color-error)}.validator:has(:user-invalid):focus{--input-color:var(--color-error)}.validator:has(:user-invalid):checked{--input-color:var(--color-error)}.validator:has(:user-invalid)[aria-checked=true]{--input-color:var(--color-error)}.validator:has(:user-invalid):focus-within{--input-color:var(--color-error)}.validator:has(:user-invalid)~.validator-hint{visibility:visible;color:var(--color-error);display:block}.validator~.validator-hint{visibility:hidden}.validator-hint{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));margin-top:.5rem}.tooltip{--tt-bg:var(--color-neutral);--tt-off:calc(100% + .5rem);--tt-tail:calc(100% + 1px + .25rem);display:inline-block;position:relative}.tooltip>:where(.tooltip-content){border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.tooltip[data-tip]:before{border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.tooltip:after{opacity:0;background-color:var(--tt-bg);content:"";pointer-events:none;--mask-tooltip:url("data:image/svg+xml,%3Csvg width='10' height='4' viewBox='0 0 8 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0.500009 1C3.5 1 3.00001 4 5.00001 4C7 4 6.5 1 9.5 1C10 1 10 0.499897 10 0H0C-1.99338e-08 0.5 0 1 0.500009 1Z' fill='black'/%3E%3C/svg%3E%0A");width:.625rem;height:.25rem;-webkit-mask-position:-1px 0;mask-position:-1px 0;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-tooltip);mask-image:var(--mask-tooltip);transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;display:block;position:absolute}:is(.tooltip,.tooltip-top)>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}:is(.tooltip,.tooltip-top)[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}.tooltip-bottom>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.tooltip-bottom[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.tooltip-left>.tooltip-content{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.tooltip-left[data-tip]:before{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.tooltip-right>.tooltip-content{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.tooltip-right[data-tip]:before{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.tooltip.tooltip-open>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip.tooltip-open[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip.tooltip-open:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip[data-tip]:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip[data-tip]:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip[data-tip]:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip:has(:focus-visible)>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip:has(:focus-visible)[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tooltip:has(:focus-visible):after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}:is(.tooltip,.tooltip-top):after{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-tail)50%}.tooltip-bottom:after{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem))rotate(180deg);inset:var(--tt-tail)auto auto 50%}.tooltip-left:after{transform:translateX(var(--tt-pos,.25rem))translateY(-50%)rotate(-90deg);inset:50% calc(var(--tt-tail) + 1px)auto auto}.tooltip-right:after{transform:translateX(var(--tt-pos,-.25rem))translateY(-50%)rotate(90deg);inset:50% auto auto calc(var(--tt-tail) + 1px)}.tooltip-primary{--tt-bg:var(--color-primary)}.tooltip-primary>.tooltip-content{color:var(--color-primary-content)}.tooltip-primary[data-tip]:before{color:var(--color-primary-content)}.tooltip-secondary{--tt-bg:var(--color-secondary)}.tooltip-secondary>.tooltip-content{color:var(--color-secondary-content)}.tooltip-secondary[data-tip]:before{color:var(--color-secondary-content)}.tooltip-accent{--tt-bg:var(--color-accent)}.tooltip-accent>.tooltip-content{color:var(--color-accent-content)}.tooltip-accent[data-tip]:before{color:var(--color-accent-content)}.tooltip-info{--tt-bg:var(--color-info)}.tooltip-info>.tooltip-content{color:var(--color-info-content)}.tooltip-info[data-tip]:before{color:var(--color-info-content)}.tooltip-success{--tt-bg:var(--color-success)}.tooltip-success>.tooltip-content{color:var(--color-success-content)}.tooltip-success[data-tip]:before{color:var(--color-success-content)}.tooltip-warning{--tt-bg:var(--color-warning)}.tooltip-warning>.tooltip-content{color:var(--color-warning-content)}.tooltip-warning[data-tip]:before{color:var(--color-warning-content)}.tooltip-error{--tt-bg:var(--color-error)}.tooltip-error>.tooltip-content{color:var(--color-error-content)}.tooltip-error[data-tip]:before{color:var(--color-error-content)}@media (min-width:640px){.sm\:tooltip{--tt-bg:var(--color-neutral);--tt-off:calc(100% + .5rem);--tt-tail:calc(100% + 1px + .25rem);display:inline-block;position:relative}.sm\:tooltip>:where(.tooltip-content){border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.sm\:tooltip[data-tip]:before{border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.sm\:tooltip:after{opacity:0;background-color:var(--tt-bg);content:"";pointer-events:none;--mask-tooltip:url("data:image/svg+xml,%3Csvg width='10' height='4' viewBox='0 0 8 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0.500009 1C3.5 1 3.00001 4 5.00001 4C7 4 6.5 1 9.5 1C10 1 10 0.499897 10 0H0C-1.99338e-08 0.5 0 1 0.500009 1Z' fill='black'/%3E%3C/svg%3E%0A");width:.625rem;height:.25rem;-webkit-mask-position:-1px 0;mask-position:-1px 0;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-tooltip);mask-image:var(--mask-tooltip);transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;display:block;position:absolute}:is(.sm\:tooltip,.sm\:tooltip-top)>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}:is(.sm\:tooltip,.sm\:tooltip-top)[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}.sm\:tooltip-bottom>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.sm\:tooltip-bottom[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.sm\:tooltip-left>.tooltip-content{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.sm\:tooltip-left[data-tip]:before{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.sm\:tooltip-right>.tooltip-content{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.sm\:tooltip-right[data-tip]:before{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.sm\:tooltip.tooltip-open>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip.tooltip-open[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip.tooltip-open:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip[data-tip]:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip[data-tip]:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip[data-tip]:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip:has(:focus-visible)>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip:has(:focus-visible)[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.sm\:tooltip:has(:focus-visible):after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}:is(.sm\:tooltip,.sm\:tooltip-top):after{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-tail)50%}.sm\:tooltip-bottom:after{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem))rotate(180deg);inset:var(--tt-tail)auto auto 50%}.sm\:tooltip-left:after{transform:translateX(var(--tt-pos,.25rem))translateY(-50%)rotate(-90deg);inset:50% calc(var(--tt-tail) + 1px)auto auto}.sm\:tooltip-right:after{transform:translateX(var(--tt-pos,-.25rem))translateY(-50%)rotate(90deg);inset:50% auto auto calc(var(--tt-tail) + 1px)}.sm\:tooltip-primary{--tt-bg:var(--color-primary)}.sm\:tooltip-primary>.tooltip-content{color:var(--color-primary-content)}.sm\:tooltip-primary[data-tip]:before{color:var(--color-primary-content)}.sm\:tooltip-secondary{--tt-bg:var(--color-secondary)}.sm\:tooltip-secondary>.tooltip-content{color:var(--color-secondary-content)}.sm\:tooltip-secondary[data-tip]:before{color:var(--color-secondary-content)}.sm\:tooltip-accent{--tt-bg:var(--color-accent)}.sm\:tooltip-accent>.tooltip-content{color:var(--color-accent-content)}.sm\:tooltip-accent[data-tip]:before{color:var(--color-accent-content)}.sm\:tooltip-info{--tt-bg:var(--color-info)}.sm\:tooltip-info>.tooltip-content{color:var(--color-info-content)}.sm\:tooltip-info[data-tip]:before{color:var(--color-info-content)}.sm\:tooltip-success{--tt-bg:var(--color-success)}.sm\:tooltip-success>.tooltip-content{color:var(--color-success-content)}.sm\:tooltip-success[data-tip]:before{color:var(--color-success-content)}.sm\:tooltip-warning{--tt-bg:var(--color-warning)}.sm\:tooltip-warning>.tooltip-content{color:var(--color-warning-content)}.sm\:tooltip-warning[data-tip]:before{color:var(--color-warning-content)}.sm\:tooltip-error{--tt-bg:var(--color-error)}.sm\:tooltip-error>.tooltip-content{color:var(--color-error-content)}.sm\:tooltip-error[data-tip]:before{color:var(--color-error-content)}}@media (min-width:768px){.md\:tooltip{--tt-bg:var(--color-neutral);--tt-off:calc(100% + .5rem);--tt-tail:calc(100% + 1px + .25rem);display:inline-block;position:relative}.md\:tooltip>:where(.tooltip-content){border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.md\:tooltip[data-tip]:before{border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.md\:tooltip:after{opacity:0;background-color:var(--tt-bg);content:"";pointer-events:none;--mask-tooltip:url("data:image/svg+xml,%3Csvg width='10' height='4' viewBox='0 0 8 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0.500009 1C3.5 1 3.00001 4 5.00001 4C7 4 6.5 1 9.5 1C10 1 10 0.499897 10 0H0C-1.99338e-08 0.5 0 1 0.500009 1Z' fill='black'/%3E%3C/svg%3E%0A");width:.625rem;height:.25rem;-webkit-mask-position:-1px 0;mask-position:-1px 0;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-tooltip);mask-image:var(--mask-tooltip);transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;display:block;position:absolute}:is(.md\:tooltip,.md\:tooltip-top)>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}:is(.md\:tooltip,.md\:tooltip-top)[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}.md\:tooltip-bottom>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.md\:tooltip-bottom[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.md\:tooltip-left>.tooltip-content{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.md\:tooltip-left[data-tip]:before{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.md\:tooltip-right>.tooltip-content{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.md\:tooltip-right[data-tip]:before{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.md\:tooltip.tooltip-open>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip.tooltip-open[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip.tooltip-open:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip[data-tip]:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip[data-tip]:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip[data-tip]:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip:has(:focus-visible)>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip:has(:focus-visible)[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.md\:tooltip:has(:focus-visible):after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}:is(.md\:tooltip,.md\:tooltip-top):after{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-tail)50%}.md\:tooltip-bottom:after{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem))rotate(180deg);inset:var(--tt-tail)auto auto 50%}.md\:tooltip-left:after{transform:translateX(var(--tt-pos,.25rem))translateY(-50%)rotate(-90deg);inset:50% calc(var(--tt-tail) + 1px)auto auto}.md\:tooltip-right:after{transform:translateX(var(--tt-pos,-.25rem))translateY(-50%)rotate(90deg);inset:50% auto auto calc(var(--tt-tail) + 1px)}.md\:tooltip-primary{--tt-bg:var(--color-primary)}.md\:tooltip-primary>.tooltip-content{color:var(--color-primary-content)}.md\:tooltip-primary[data-tip]:before{color:var(--color-primary-content)}.md\:tooltip-secondary{--tt-bg:var(--color-secondary)}.md\:tooltip-secondary>.tooltip-content{color:var(--color-secondary-content)}.md\:tooltip-secondary[data-tip]:before{color:var(--color-secondary-content)}.md\:tooltip-accent{--tt-bg:var(--color-accent)}.md\:tooltip-accent>.tooltip-content{color:var(--color-accent-content)}.md\:tooltip-accent[data-tip]:before{color:var(--color-accent-content)}.md\:tooltip-info{--tt-bg:var(--color-info)}.md\:tooltip-info>.tooltip-content{color:var(--color-info-content)}.md\:tooltip-info[data-tip]:before{color:var(--color-info-content)}.md\:tooltip-success{--tt-bg:var(--color-success)}.md\:tooltip-success>.tooltip-content{color:var(--color-success-content)}.md\:tooltip-success[data-tip]:before{color:var(--color-success-content)}.md\:tooltip-warning{--tt-bg:var(--color-warning)}.md\:tooltip-warning>.tooltip-content{color:var(--color-warning-content)}.md\:tooltip-warning[data-tip]:before{color:var(--color-warning-content)}.md\:tooltip-error{--tt-bg:var(--color-error)}.md\:tooltip-error>.tooltip-content{color:var(--color-error-content)}.md\:tooltip-error[data-tip]:before{color:var(--color-error-content)}}@media (min-width:1024px){.lg\:tooltip{--tt-bg:var(--color-neutral);--tt-off:calc(100% + .5rem);--tt-tail:calc(100% + 1px + .25rem);display:inline-block;position:relative}.lg\:tooltip>:where(.tooltip-content){border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.lg\:tooltip[data-tip]:before{border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.lg\:tooltip:after{opacity:0;background-color:var(--tt-bg);content:"";pointer-events:none;--mask-tooltip:url("data:image/svg+xml,%3Csvg width='10' height='4' viewBox='0 0 8 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0.500009 1C3.5 1 3.00001 4 5.00001 4C7 4 6.5 1 9.5 1C10 1 10 0.499897 10 0H0C-1.99338e-08 0.5 0 1 0.500009 1Z' fill='black'/%3E%3C/svg%3E%0A");width:.625rem;height:.25rem;-webkit-mask-position:-1px 0;mask-position:-1px 0;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-tooltip);mask-image:var(--mask-tooltip);transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;display:block;position:absolute}:is(.lg\:tooltip,.lg\:tooltip-top)>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}:is(.lg\:tooltip,.lg\:tooltip-top)[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}.lg\:tooltip-bottom>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.lg\:tooltip-bottom[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.lg\:tooltip-left>.tooltip-content{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.lg\:tooltip-left[data-tip]:before{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.lg\:tooltip-right>.tooltip-content{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.lg\:tooltip-right[data-tip]:before{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.lg\:tooltip.tooltip-open>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip.tooltip-open[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip.tooltip-open:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip[data-tip]:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip[data-tip]:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip[data-tip]:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip:has(:focus-visible)>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip:has(:focus-visible)[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.lg\:tooltip:has(:focus-visible):after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}:is(.lg\:tooltip,.lg\:tooltip-top):after{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-tail)50%}.lg\:tooltip-bottom:after{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem))rotate(180deg);inset:var(--tt-tail)auto auto 50%}.lg\:tooltip-left:after{transform:translateX(var(--tt-pos,.25rem))translateY(-50%)rotate(-90deg);inset:50% calc(var(--tt-tail) + 1px)auto auto}.lg\:tooltip-right:after{transform:translateX(var(--tt-pos,-.25rem))translateY(-50%)rotate(90deg);inset:50% auto auto calc(var(--tt-tail) + 1px)}.lg\:tooltip-primary{--tt-bg:var(--color-primary)}.lg\:tooltip-primary>.tooltip-content{color:var(--color-primary-content)}.lg\:tooltip-primary[data-tip]:before{color:var(--color-primary-content)}.lg\:tooltip-secondary{--tt-bg:var(--color-secondary)}.lg\:tooltip-secondary>.tooltip-content{color:var(--color-secondary-content)}.lg\:tooltip-secondary[data-tip]:before{color:var(--color-secondary-content)}.lg\:tooltip-accent{--tt-bg:var(--color-accent)}.lg\:tooltip-accent>.tooltip-content{color:var(--color-accent-content)}.lg\:tooltip-accent[data-tip]:before{color:var(--color-accent-content)}.lg\:tooltip-info{--tt-bg:var(--color-info)}.lg\:tooltip-info>.tooltip-content{color:var(--color-info-content)}.lg\:tooltip-info[data-tip]:before{color:var(--color-info-content)}.lg\:tooltip-success{--tt-bg:var(--color-success)}.lg\:tooltip-success>.tooltip-content{color:var(--color-success-content)}.lg\:tooltip-success[data-tip]:before{color:var(--color-success-content)}.lg\:tooltip-warning{--tt-bg:var(--color-warning)}.lg\:tooltip-warning>.tooltip-content{color:var(--color-warning-content)}.lg\:tooltip-warning[data-tip]:before{color:var(--color-warning-content)}.lg\:tooltip-error{--tt-bg:var(--color-error)}.lg\:tooltip-error>.tooltip-content{color:var(--color-error-content)}.lg\:tooltip-error[data-tip]:before{color:var(--color-error-content)}}@media (min-width:1280px){.xl\:tooltip{--tt-bg:var(--color-neutral);--tt-off:calc(100% + .5rem);--tt-tail:calc(100% + 1px + .25rem);display:inline-block;position:relative}.xl\:tooltip>:where(.tooltip-content){border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.xl\:tooltip[data-tip]:before{border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.xl\:tooltip:after{opacity:0;background-color:var(--tt-bg);content:"";pointer-events:none;--mask-tooltip:url("data:image/svg+xml,%3Csvg width='10' height='4' viewBox='0 0 8 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0.500009 1C3.5 1 3.00001 4 5.00001 4C7 4 6.5 1 9.5 1C10 1 10 0.499897 10 0H0C-1.99338e-08 0.5 0 1 0.500009 1Z' fill='black'/%3E%3C/svg%3E%0A");width:.625rem;height:.25rem;-webkit-mask-position:-1px 0;mask-position:-1px 0;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-tooltip);mask-image:var(--mask-tooltip);transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;display:block;position:absolute}:is(.xl\:tooltip,.xl\:tooltip-top)>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}:is(.xl\:tooltip,.xl\:tooltip-top)[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}.xl\:tooltip-bottom>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.xl\:tooltip-bottom[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.xl\:tooltip-left>.tooltip-content{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.xl\:tooltip-left[data-tip]:before{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.xl\:tooltip-right>.tooltip-content{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.xl\:tooltip-right[data-tip]:before{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.xl\:tooltip.tooltip-open>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip.tooltip-open[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip.tooltip-open:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip[data-tip]:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip[data-tip]:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip[data-tip]:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip:has(:focus-visible)>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip:has(:focus-visible)[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.xl\:tooltip:has(:focus-visible):after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}:is(.xl\:tooltip,.xl\:tooltip-top):after{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-tail)50%}.xl\:tooltip-bottom:after{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem))rotate(180deg);inset:var(--tt-tail)auto auto 50%}.xl\:tooltip-left:after{transform:translateX(var(--tt-pos,.25rem))translateY(-50%)rotate(-90deg);inset:50% calc(var(--tt-tail) + 1px)auto auto}.xl\:tooltip-right:after{transform:translateX(var(--tt-pos,-.25rem))translateY(-50%)rotate(90deg);inset:50% auto auto calc(var(--tt-tail) + 1px)}.xl\:tooltip-primary{--tt-bg:var(--color-primary)}.xl\:tooltip-primary>.tooltip-content{color:var(--color-primary-content)}.xl\:tooltip-primary[data-tip]:before{color:var(--color-primary-content)}.xl\:tooltip-secondary{--tt-bg:var(--color-secondary)}.xl\:tooltip-secondary>.tooltip-content{color:var(--color-secondary-content)}.xl\:tooltip-secondary[data-tip]:before{color:var(--color-secondary-content)}.xl\:tooltip-accent{--tt-bg:var(--color-accent)}.xl\:tooltip-accent>.tooltip-content{color:var(--color-accent-content)}.xl\:tooltip-accent[data-tip]:before{color:var(--color-accent-content)}.xl\:tooltip-info{--tt-bg:var(--color-info)}.xl\:tooltip-info>.tooltip-content{color:var(--color-info-content)}.xl\:tooltip-info[data-tip]:before{color:var(--color-info-content)}.xl\:tooltip-success{--tt-bg:var(--color-success)}.xl\:tooltip-success>.tooltip-content{color:var(--color-success-content)}.xl\:tooltip-success[data-tip]:before{color:var(--color-success-content)}.xl\:tooltip-warning{--tt-bg:var(--color-warning)}.xl\:tooltip-warning>.tooltip-content{color:var(--color-warning-content)}.xl\:tooltip-warning[data-tip]:before{color:var(--color-warning-content)}.xl\:tooltip-error{--tt-bg:var(--color-error)}.xl\:tooltip-error>.tooltip-content{color:var(--color-error-content)}.xl\:tooltip-error[data-tip]:before{color:var(--color-error-content)}}@media (min-width:1536px){.\32 xl\:tooltip{--tt-bg:var(--color-neutral);--tt-off:calc(100% + .5rem);--tt-tail:calc(100% + 1px + .25rem);display:inline-block;position:relative}.\32 xl\:tooltip>:where(.tooltip-content){border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.\32 xl\:tooltip[data-tip]:before{border-radius:var(--radius-field);text-align:center;white-space:normal;max-width:20rem;color:var(--color-neutral-content);opacity:0;background-color:var(--tt-bg);pointer-events:none;z-index:1;--tw-content:attr(data-tip);content:var(--tw-content);width:max-content;padding-block:.25rem;padding-inline:.5rem;font-size:.875rem;line-height:1.25em;transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;position:absolute}.\32 xl\:tooltip:after{opacity:0;background-color:var(--tt-bg);content:"";pointer-events:none;--mask-tooltip:url("data:image/svg+xml,%3Csvg width='10' height='4' viewBox='0 0 8 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0.500009 1C3.5 1 3.00001 4 5.00001 4C7 4 6.5 1 9.5 1C10 1 10 0.499897 10 0H0C-1.99338e-08 0.5 0 1 0.500009 1Z' fill='black'/%3E%3C/svg%3E%0A");width:.625rem;height:.25rem;-webkit-mask-position:-1px 0;mask-position:-1px 0;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-tooltip);mask-image:var(--mask-tooltip);transition:opacity .2s cubic-bezier(.4,0,.2,1) 75ms,transform .2s cubic-bezier(.4,0,.2,1) 75ms;display:block;position:absolute}:is(.\32 xl\:tooltip,.\32 xl\:tooltip-top)>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}:is(.\32 xl\:tooltip,.\32 xl\:tooltip-top)[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-off)50%}.\32 xl\:tooltip-bottom>.tooltip-content{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.\32 xl\:tooltip-bottom[data-tip]:before{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem));inset:var(--tt-off)auto auto 50%}.\32 xl\:tooltip-left>.tooltip-content{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.\32 xl\:tooltip-left[data-tip]:before{transform:translateX(calc(var(--tt-pos,.25rem) - .25rem))translateY(-50%);inset:50% var(--tt-off)auto auto}.\32 xl\:tooltip-right>.tooltip-content{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.\32 xl\:tooltip-right[data-tip]:before{transform:translateX(calc(var(--tt-pos,-.25rem) + .25rem))translateY(-50%);inset:50% auto auto var(--tt-off)}.\32 xl\:tooltip.tooltip-open>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip.tooltip-open[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip.tooltip-open:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip[data-tip]:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip[data-tip]:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip[data-tip]:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip:hover>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip:hover[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip:hover:after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip:has(:focus-visible)>.tooltip-content{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip:has(:focus-visible)[data-tip]:before{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.\32 xl\:tooltip:has(:focus-visible):after{opacity:1;--tt-pos:0rem;transition:opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}:is(.\32 xl\:tooltip,.\32 xl\:tooltip-top):after{transform:translateX(-50%)translateY(var(--tt-pos,.25rem));inset:auto auto var(--tt-tail)50%}.\32 xl\:tooltip-bottom:after{transform:translateX(-50%)translateY(var(--tt-pos,-.25rem))rotate(180deg);inset:var(--tt-tail)auto auto 50%}.\32 xl\:tooltip-left:after{transform:translateX(var(--tt-pos,.25rem))translateY(-50%)rotate(-90deg);inset:50% calc(var(--tt-tail) + 1px)auto auto}.\32 xl\:tooltip-right:after{transform:translateX(var(--tt-pos,-.25rem))translateY(-50%)rotate(90deg);inset:50% auto auto calc(var(--tt-tail) + 1px)}.\32 xl\:tooltip-primary{--tt-bg:var(--color-primary)}.\32 xl\:tooltip-primary>.tooltip-content{color:var(--color-primary-content)}.\32 xl\:tooltip-primary[data-tip]:before{color:var(--color-primary-content)}.\32 xl\:tooltip-secondary{--tt-bg:var(--color-secondary)}.\32 xl\:tooltip-secondary>.tooltip-content{color:var(--color-secondary-content)}.\32 xl\:tooltip-secondary[data-tip]:before{color:var(--color-secondary-content)}.\32 xl\:tooltip-accent{--tt-bg:var(--color-accent)}.\32 xl\:tooltip-accent>.tooltip-content{color:var(--color-accent-content)}.\32 xl\:tooltip-accent[data-tip]:before{color:var(--color-accent-content)}.\32 xl\:tooltip-info{--tt-bg:var(--color-info)}.\32 xl\:tooltip-info>.tooltip-content{color:var(--color-info-content)}.\32 xl\:tooltip-info[data-tip]:before{color:var(--color-info-content)}.\32 xl\:tooltip-success{--tt-bg:var(--color-success)}.\32 xl\:tooltip-success>.tooltip-content{color:var(--color-success-content)}.\32 xl\:tooltip-success[data-tip]:before{color:var(--color-success-content)}.\32 xl\:tooltip-warning{--tt-bg:var(--color-warning)}.\32 xl\:tooltip-warning>.tooltip-content{color:var(--color-warning-content)}.\32 xl\:tooltip-warning[data-tip]:before{color:var(--color-warning-content)}.\32 xl\:tooltip-error{--tt-bg:var(--color-error)}.\32 xl\:tooltip-error>.tooltip-content{color:var(--color-error-content)}.\32 xl\:tooltip-error[data-tip]:before{color:var(--color-error-content)}}.textarea{border:var(--border)solid transparent;appearance:none;border-radius:var(--radius-field);background-color:var(--color-base-100);vertical-align:middle;border-color:var(--input-color);width:clamp(3rem,20rem,100%);min-height:5rem;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);flex-shrink:1;padding-block:.5rem;padding-inline:.75rem;font-size:.875rem}.textarea textarea{appearance:none;background-color:transparent;border:none}.textarea textarea:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.textarea textarea:focus{outline-offset:2px;outline:2px solid transparent}}.textarea textarea:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.textarea textarea:focus-within{outline-offset:2px;outline:2px solid transparent}}.textarea:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.textarea:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.textarea:has(>textarea[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.textarea:has(>textarea[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.textarea:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.textarea:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.textarea:has(>textarea[disabled])>textarea[disabled]{cursor:not-allowed}.textarea-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.textarea-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.textarea-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.textarea-neutral{--input-color:var(--color-neutral)}.textarea-neutral:focus{--input-color:var(--color-neutral)}.textarea-neutral:focus-within{--input-color:var(--color-neutral)}.textarea-primary{--input-color:var(--color-primary)}.textarea-primary:focus{--input-color:var(--color-primary)}.textarea-primary:focus-within{--input-color:var(--color-primary)}.textarea-secondary{--input-color:var(--color-secondary)}.textarea-secondary:focus{--input-color:var(--color-secondary)}.textarea-secondary:focus-within{--input-color:var(--color-secondary)}.textarea-accent{--input-color:var(--color-accent)}.textarea-accent:focus{--input-color:var(--color-accent)}.textarea-accent:focus-within{--input-color:var(--color-accent)}.textarea-info{--input-color:var(--color-info)}.textarea-info:focus{--input-color:var(--color-info)}.textarea-info:focus-within{--input-color:var(--color-info)}.textarea-success{--input-color:var(--color-success)}.textarea-success:focus{--input-color:var(--color-success)}.textarea-success:focus-within{--input-color:var(--color-success)}.textarea-warning{--input-color:var(--color-warning)}.textarea-warning:focus{--input-color:var(--color-warning)}.textarea-warning:focus-within{--input-color:var(--color-warning)}.textarea-error{--input-color:var(--color-error)}.textarea-error:focus{--input-color:var(--color-error)}.textarea-error:focus-within{--input-color:var(--color-error)}.textarea-xs{font-size:.6875rem}.textarea-sm{font-size:.75rem}.textarea-md{font-size:.875rem}.textarea-lg{font-size:1.125rem}.textarea-xl{font-size:1.375rem}@media (min-width:640px){.sm\:textarea{border:var(--border)solid transparent;appearance:none;border-radius:var(--radius-field);background-color:var(--color-base-100);vertical-align:middle;border-color:var(--input-color);width:clamp(3rem,20rem,100%);min-height:5rem;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);flex-shrink:1;padding-block:.5rem;padding-inline:.75rem;font-size:.875rem}.sm\:textarea textarea{appearance:none;background-color:transparent;border:none}.sm\:textarea textarea:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:textarea textarea:focus{outline-offset:2px;outline:2px solid transparent}}.sm\:textarea textarea:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:textarea textarea:focus-within{outline-offset:2px;outline:2px solid transparent}}.sm\:textarea:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.sm\:textarea:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.sm\:textarea:has(>textarea[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.sm\:textarea:has(>textarea[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.sm\:textarea:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.sm\:textarea:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.sm\:textarea:has(>textarea[disabled])>textarea[disabled]{cursor:not-allowed}.sm\:textarea-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.sm\:textarea-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.sm\:textarea-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.sm\:textarea-neutral{--input-color:var(--color-neutral)}.sm\:textarea-neutral:focus{--input-color:var(--color-neutral)}.sm\:textarea-neutral:focus-within{--input-color:var(--color-neutral)}.sm\:textarea-primary{--input-color:var(--color-primary)}.sm\:textarea-primary:focus{--input-color:var(--color-primary)}.sm\:textarea-primary:focus-within{--input-color:var(--color-primary)}.sm\:textarea-secondary{--input-color:var(--color-secondary)}.sm\:textarea-secondary:focus{--input-color:var(--color-secondary)}.sm\:textarea-secondary:focus-within{--input-color:var(--color-secondary)}.sm\:textarea-accent{--input-color:var(--color-accent)}.sm\:textarea-accent:focus{--input-color:var(--color-accent)}.sm\:textarea-accent:focus-within{--input-color:var(--color-accent)}.sm\:textarea-info{--input-color:var(--color-info)}.sm\:textarea-info:focus{--input-color:var(--color-info)}.sm\:textarea-info:focus-within{--input-color:var(--color-info)}.sm\:textarea-success{--input-color:var(--color-success)}.sm\:textarea-success:focus{--input-color:var(--color-success)}.sm\:textarea-success:focus-within{--input-color:var(--color-success)}.sm\:textarea-warning{--input-color:var(--color-warning)}.sm\:textarea-warning:focus{--input-color:var(--color-warning)}.sm\:textarea-warning:focus-within{--input-color:var(--color-warning)}.sm\:textarea-error{--input-color:var(--color-error)}.sm\:textarea-error:focus{--input-color:var(--color-error)}.sm\:textarea-error:focus-within{--input-color:var(--color-error)}.sm\:textarea-xs{font-size:.6875rem}.sm\:textarea-sm{font-size:.75rem}.sm\:textarea-md{font-size:.875rem}.sm\:textarea-lg{font-size:1.125rem}.sm\:textarea-xl{font-size:1.375rem}}@media (min-width:768px){.md\:textarea{border:var(--border)solid transparent;appearance:none;border-radius:var(--radius-field);background-color:var(--color-base-100);vertical-align:middle;border-color:var(--input-color);width:clamp(3rem,20rem,100%);min-height:5rem;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);flex-shrink:1;padding-block:.5rem;padding-inline:.75rem;font-size:.875rem}.md\:textarea textarea{appearance:none;background-color:transparent;border:none}.md\:textarea textarea:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:textarea textarea:focus{outline-offset:2px;outline:2px solid transparent}}.md\:textarea textarea:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:textarea textarea:focus-within{outline-offset:2px;outline:2px solid transparent}}.md\:textarea:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.md\:textarea:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.md\:textarea:has(>textarea[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.md\:textarea:has(>textarea[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.md\:textarea:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.md\:textarea:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.md\:textarea:has(>textarea[disabled])>textarea[disabled]{cursor:not-allowed}.md\:textarea-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.md\:textarea-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.md\:textarea-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.md\:textarea-neutral{--input-color:var(--color-neutral)}.md\:textarea-neutral:focus{--input-color:var(--color-neutral)}.md\:textarea-neutral:focus-within{--input-color:var(--color-neutral)}.md\:textarea-primary{--input-color:var(--color-primary)}.md\:textarea-primary:focus{--input-color:var(--color-primary)}.md\:textarea-primary:focus-within{--input-color:var(--color-primary)}.md\:textarea-secondary{--input-color:var(--color-secondary)}.md\:textarea-secondary:focus{--input-color:var(--color-secondary)}.md\:textarea-secondary:focus-within{--input-color:var(--color-secondary)}.md\:textarea-accent{--input-color:var(--color-accent)}.md\:textarea-accent:focus{--input-color:var(--color-accent)}.md\:textarea-accent:focus-within{--input-color:var(--color-accent)}.md\:textarea-info{--input-color:var(--color-info)}.md\:textarea-info:focus{--input-color:var(--color-info)}.md\:textarea-info:focus-within{--input-color:var(--color-info)}.md\:textarea-success{--input-color:var(--color-success)}.md\:textarea-success:focus{--input-color:var(--color-success)}.md\:textarea-success:focus-within{--input-color:var(--color-success)}.md\:textarea-warning{--input-color:var(--color-warning)}.md\:textarea-warning:focus{--input-color:var(--color-warning)}.md\:textarea-warning:focus-within{--input-color:var(--color-warning)}.md\:textarea-error{--input-color:var(--color-error)}.md\:textarea-error:focus{--input-color:var(--color-error)}.md\:textarea-error:focus-within{--input-color:var(--color-error)}.md\:textarea-xs{font-size:.6875rem}.md\:textarea-sm{font-size:.75rem}.md\:textarea-md{font-size:.875rem}.md\:textarea-lg{font-size:1.125rem}.md\:textarea-xl{font-size:1.375rem}}@media (min-width:1024px){.lg\:textarea{border:var(--border)solid transparent;appearance:none;border-radius:var(--radius-field);background-color:var(--color-base-100);vertical-align:middle;border-color:var(--input-color);width:clamp(3rem,20rem,100%);min-height:5rem;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);flex-shrink:1;padding-block:.5rem;padding-inline:.75rem;font-size:.875rem}.lg\:textarea textarea{appearance:none;background-color:transparent;border:none}.lg\:textarea textarea:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:textarea textarea:focus{outline-offset:2px;outline:2px solid transparent}}.lg\:textarea textarea:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:textarea textarea:focus-within{outline-offset:2px;outline:2px solid transparent}}.lg\:textarea:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.lg\:textarea:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.lg\:textarea:has(>textarea[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.lg\:textarea:has(>textarea[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.lg\:textarea:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.lg\:textarea:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.lg\:textarea:has(>textarea[disabled])>textarea[disabled]{cursor:not-allowed}.lg\:textarea-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.lg\:textarea-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.lg\:textarea-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.lg\:textarea-neutral{--input-color:var(--color-neutral)}.lg\:textarea-neutral:focus{--input-color:var(--color-neutral)}.lg\:textarea-neutral:focus-within{--input-color:var(--color-neutral)}.lg\:textarea-primary{--input-color:var(--color-primary)}.lg\:textarea-primary:focus{--input-color:var(--color-primary)}.lg\:textarea-primary:focus-within{--input-color:var(--color-primary)}.lg\:textarea-secondary{--input-color:var(--color-secondary)}.lg\:textarea-secondary:focus{--input-color:var(--color-secondary)}.lg\:textarea-secondary:focus-within{--input-color:var(--color-secondary)}.lg\:textarea-accent{--input-color:var(--color-accent)}.lg\:textarea-accent:focus{--input-color:var(--color-accent)}.lg\:textarea-accent:focus-within{--input-color:var(--color-accent)}.lg\:textarea-info{--input-color:var(--color-info)}.lg\:textarea-info:focus{--input-color:var(--color-info)}.lg\:textarea-info:focus-within{--input-color:var(--color-info)}.lg\:textarea-success{--input-color:var(--color-success)}.lg\:textarea-success:focus{--input-color:var(--color-success)}.lg\:textarea-success:focus-within{--input-color:var(--color-success)}.lg\:textarea-warning{--input-color:var(--color-warning)}.lg\:textarea-warning:focus{--input-color:var(--color-warning)}.lg\:textarea-warning:focus-within{--input-color:var(--color-warning)}.lg\:textarea-error{--input-color:var(--color-error)}.lg\:textarea-error:focus{--input-color:var(--color-error)}.lg\:textarea-error:focus-within{--input-color:var(--color-error)}.lg\:textarea-xs{font-size:.6875rem}.lg\:textarea-sm{font-size:.75rem}.lg\:textarea-md{font-size:.875rem}.lg\:textarea-lg{font-size:1.125rem}.lg\:textarea-xl{font-size:1.375rem}}@media (min-width:1280px){.xl\:textarea{border:var(--border)solid transparent;appearance:none;border-radius:var(--radius-field);background-color:var(--color-base-100);vertical-align:middle;border-color:var(--input-color);width:clamp(3rem,20rem,100%);min-height:5rem;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);flex-shrink:1;padding-block:.5rem;padding-inline:.75rem;font-size:.875rem}.xl\:textarea textarea{appearance:none;background-color:transparent;border:none}.xl\:textarea textarea:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:textarea textarea:focus{outline-offset:2px;outline:2px solid transparent}}.xl\:textarea textarea:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:textarea textarea:focus-within{outline-offset:2px;outline:2px solid transparent}}.xl\:textarea:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.xl\:textarea:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.xl\:textarea:has(>textarea[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.xl\:textarea:has(>textarea[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.xl\:textarea:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.xl\:textarea:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.xl\:textarea:has(>textarea[disabled])>textarea[disabled]{cursor:not-allowed}.xl\:textarea-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.xl\:textarea-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.xl\:textarea-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.xl\:textarea-neutral{--input-color:var(--color-neutral)}.xl\:textarea-neutral:focus{--input-color:var(--color-neutral)}.xl\:textarea-neutral:focus-within{--input-color:var(--color-neutral)}.xl\:textarea-primary{--input-color:var(--color-primary)}.xl\:textarea-primary:focus{--input-color:var(--color-primary)}.xl\:textarea-primary:focus-within{--input-color:var(--color-primary)}.xl\:textarea-secondary{--input-color:var(--color-secondary)}.xl\:textarea-secondary:focus{--input-color:var(--color-secondary)}.xl\:textarea-secondary:focus-within{--input-color:var(--color-secondary)}.xl\:textarea-accent{--input-color:var(--color-accent)}.xl\:textarea-accent:focus{--input-color:var(--color-accent)}.xl\:textarea-accent:focus-within{--input-color:var(--color-accent)}.xl\:textarea-info{--input-color:var(--color-info)}.xl\:textarea-info:focus{--input-color:var(--color-info)}.xl\:textarea-info:focus-within{--input-color:var(--color-info)}.xl\:textarea-success{--input-color:var(--color-success)}.xl\:textarea-success:focus{--input-color:var(--color-success)}.xl\:textarea-success:focus-within{--input-color:var(--color-success)}.xl\:textarea-warning{--input-color:var(--color-warning)}.xl\:textarea-warning:focus{--input-color:var(--color-warning)}.xl\:textarea-warning:focus-within{--input-color:var(--color-warning)}.xl\:textarea-error{--input-color:var(--color-error)}.xl\:textarea-error:focus{--input-color:var(--color-error)}.xl\:textarea-error:focus-within{--input-color:var(--color-error)}.xl\:textarea-xs{font-size:.6875rem}.xl\:textarea-sm{font-size:.75rem}.xl\:textarea-md{font-size:.875rem}.xl\:textarea-lg{font-size:1.125rem}.xl\:textarea-xl{font-size:1.375rem}}@media (min-width:1536px){.\32 xl\:textarea{border:var(--border)solid transparent;appearance:none;border-radius:var(--radius-field);background-color:var(--color-base-100);vertical-align:middle;border-color:var(--input-color);width:clamp(3rem,20rem,100%);min-height:5rem;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);flex-shrink:1;padding-block:.5rem;padding-inline:.75rem;font-size:.875rem}.\32 xl\:textarea textarea{appearance:none;background-color:transparent;border:none}.\32 xl\:textarea textarea:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:textarea textarea:focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:textarea textarea:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:textarea textarea:focus-within{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:textarea:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.\32 xl\:textarea:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.\32 xl\:textarea:has(>textarea[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.\32 xl\:textarea:has(>textarea[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.\32 xl\:textarea:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent);box-shadow:none}.\32 xl\:textarea:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.\32 xl\:textarea:has(>textarea[disabled])>textarea[disabled]{cursor:not-allowed}.\32 xl\:textarea-ghost{box-shadow:none;background-color:transparent;border-color:transparent}.\32 xl\:textarea-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.\32 xl\:textarea-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.\32 xl\:textarea-neutral{--input-color:var(--color-neutral)}.\32 xl\:textarea-neutral:focus{--input-color:var(--color-neutral)}.\32 xl\:textarea-neutral:focus-within{--input-color:var(--color-neutral)}.\32 xl\:textarea-primary{--input-color:var(--color-primary)}.\32 xl\:textarea-primary:focus{--input-color:var(--color-primary)}.\32 xl\:textarea-primary:focus-within{--input-color:var(--color-primary)}.\32 xl\:textarea-secondary{--input-color:var(--color-secondary)}.\32 xl\:textarea-secondary:focus{--input-color:var(--color-secondary)}.\32 xl\:textarea-secondary:focus-within{--input-color:var(--color-secondary)}.\32 xl\:textarea-accent{--input-color:var(--color-accent)}.\32 xl\:textarea-accent:focus{--input-color:var(--color-accent)}.\32 xl\:textarea-accent:focus-within{--input-color:var(--color-accent)}.\32 xl\:textarea-info{--input-color:var(--color-info)}.\32 xl\:textarea-info:focus{--input-color:var(--color-info)}.\32 xl\:textarea-info:focus-within{--input-color:var(--color-info)}.\32 xl\:textarea-success{--input-color:var(--color-success)}.\32 xl\:textarea-success:focus{--input-color:var(--color-success)}.\32 xl\:textarea-success:focus-within{--input-color:var(--color-success)}.\32 xl\:textarea-warning{--input-color:var(--color-warning)}.\32 xl\:textarea-warning:focus{--input-color:var(--color-warning)}.\32 xl\:textarea-warning:focus-within{--input-color:var(--color-warning)}.\32 xl\:textarea-error{--input-color:var(--color-error)}.\32 xl\:textarea-error:focus{--input-color:var(--color-error)}.\32 xl\:textarea-error:focus-within{--input-color:var(--color-error)}.\32 xl\:textarea-xs{font-size:.6875rem}.\32 xl\:textarea-sm{font-size:.75rem}.\32 xl\:textarea-md{font-size:.875rem}.\32 xl\:textarea-lg{font-size:1.125rem}.\32 xl\:textarea-xl{font-size:1.375rem}}.alert{border-radius:var(--radius-box);color:var(--color-base-content);background-color:var(--alert-color,var(--color-base-200));text-align:start;border:var(--border)solid var(--color-base-200);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);box-shadow:0 3px 0 -2px oklch(100% 0 0/calc(var(--depth)*.08))inset,0 1px color-mix(in oklab,color-mix(in oklab,#000 20%,var(--alert-color,var(--color-base-200)))calc(var(--depth)*20%),transparent),0 4px 3px -2px oklch(0% 0 0/calc(var(--depth)*.08));grid-template-columns:auto;grid-auto-flow:column;justify-content:start;place-items:center start;gap:1rem;padding-block:.75rem;padding-inline:1rem;font-size:.875rem;line-height:1.25rem;display:grid}.alert:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}.alert.alert-outline{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none}.alert.alert-dash{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none;border-style:dashed}.alert.alert-soft{color:var(--alert-color,var(--color-base-content));background:color-mix(in oklab,var(--alert-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--alert-color,var(--color-base-content))10%,var(--color-base-100));box-shadow:none;background-image:none}.alert-info{border-color:var(--color-info);color:var(--color-info-content);--alert-color:var(--color-info)}.alert-success{border-color:var(--color-success);color:var(--color-success-content);--alert-color:var(--color-success)}.alert-warning{border-color:var(--color-warning);color:var(--color-warning-content);--alert-color:var(--color-warning)}.alert-error{border-color:var(--color-error);color:var(--color-error-content);--alert-color:var(--color-error)}.alert-vertical{text-align:center;grid-template-columns:auto;grid-auto-flow:row;justify-content:center;justify-items:center}.alert-vertical:has(:nth-child(2)){grid-template-columns:auto}.alert-horizontal{text-align:start;grid-template-columns:auto;grid-auto-flow:column;justify-content:start;justify-items:start}.alert-horizontal:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}@media (min-width:640px){.sm\:alert{border-radius:var(--radius-box);color:var(--color-base-content);background-color:var(--alert-color,var(--color-base-200));text-align:start;border:var(--border)solid var(--color-base-200);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);box-shadow:0 3px 0 -2px oklch(100% 0 0/calc(var(--depth)*.08))inset,0 1px color-mix(in oklab,color-mix(in oklab,#000 20%,var(--alert-color,var(--color-base-200)))calc(var(--depth)*20%),transparent),0 4px 3px -2px oklch(0% 0 0/calc(var(--depth)*.08));grid-template-columns:auto;grid-auto-flow:column;justify-content:start;place-items:center start;gap:1rem;padding-block:.75rem;padding-inline:1rem;font-size:.875rem;line-height:1.25rem;display:grid}.sm\:alert:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}.sm\:alert.alert-outline{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none}.sm\:alert.alert-dash{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none;border-style:dashed}.sm\:alert.alert-soft{color:var(--alert-color,var(--color-base-content));background:color-mix(in oklab,var(--alert-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--alert-color,var(--color-base-content))10%,var(--color-base-100));box-shadow:none;background-image:none}.sm\:alert-info{border-color:var(--color-info);color:var(--color-info-content);--alert-color:var(--color-info)}.sm\:alert-success{border-color:var(--color-success);color:var(--color-success-content);--alert-color:var(--color-success)}.sm\:alert-warning{border-color:var(--color-warning);color:var(--color-warning-content);--alert-color:var(--color-warning)}.sm\:alert-error{border-color:var(--color-error);color:var(--color-error-content);--alert-color:var(--color-error)}.sm\:alert-vertical{text-align:center;grid-template-columns:auto;grid-auto-flow:row;justify-content:center;justify-items:center}.sm\:alert-vertical:has(:nth-child(2)){grid-template-columns:auto}.sm\:alert-horizontal{text-align:start;grid-template-columns:auto;grid-auto-flow:column;justify-content:start;justify-items:start}.sm\:alert-horizontal:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}}@media (min-width:768px){.md\:alert{border-radius:var(--radius-box);color:var(--color-base-content);background-color:var(--alert-color,var(--color-base-200));text-align:start;border:var(--border)solid var(--color-base-200);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);box-shadow:0 3px 0 -2px oklch(100% 0 0/calc(var(--depth)*.08))inset,0 1px color-mix(in oklab,color-mix(in oklab,#000 20%,var(--alert-color,var(--color-base-200)))calc(var(--depth)*20%),transparent),0 4px 3px -2px oklch(0% 0 0/calc(var(--depth)*.08));grid-template-columns:auto;grid-auto-flow:column;justify-content:start;place-items:center start;gap:1rem;padding-block:.75rem;padding-inline:1rem;font-size:.875rem;line-height:1.25rem;display:grid}.md\:alert:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}.md\:alert.alert-outline{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none}.md\:alert.alert-dash{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none;border-style:dashed}.md\:alert.alert-soft{color:var(--alert-color,var(--color-base-content));background:color-mix(in oklab,var(--alert-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--alert-color,var(--color-base-content))10%,var(--color-base-100));box-shadow:none;background-image:none}.md\:alert-info{border-color:var(--color-info);color:var(--color-info-content);--alert-color:var(--color-info)}.md\:alert-success{border-color:var(--color-success);color:var(--color-success-content);--alert-color:var(--color-success)}.md\:alert-warning{border-color:var(--color-warning);color:var(--color-warning-content);--alert-color:var(--color-warning)}.md\:alert-error{border-color:var(--color-error);color:var(--color-error-content);--alert-color:var(--color-error)}.md\:alert-vertical{text-align:center;grid-template-columns:auto;grid-auto-flow:row;justify-content:center;justify-items:center}.md\:alert-vertical:has(:nth-child(2)){grid-template-columns:auto}.md\:alert-horizontal{text-align:start;grid-template-columns:auto;grid-auto-flow:column;justify-content:start;justify-items:start}.md\:alert-horizontal:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}}@media (min-width:1024px){.lg\:alert{border-radius:var(--radius-box);color:var(--color-base-content);background-color:var(--alert-color,var(--color-base-200));text-align:start;border:var(--border)solid var(--color-base-200);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);box-shadow:0 3px 0 -2px oklch(100% 0 0/calc(var(--depth)*.08))inset,0 1px color-mix(in oklab,color-mix(in oklab,#000 20%,var(--alert-color,var(--color-base-200)))calc(var(--depth)*20%),transparent),0 4px 3px -2px oklch(0% 0 0/calc(var(--depth)*.08));grid-template-columns:auto;grid-auto-flow:column;justify-content:start;place-items:center start;gap:1rem;padding-block:.75rem;padding-inline:1rem;font-size:.875rem;line-height:1.25rem;display:grid}.lg\:alert:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}.lg\:alert.alert-outline{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none}.lg\:alert.alert-dash{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none;border-style:dashed}.lg\:alert.alert-soft{color:var(--alert-color,var(--color-base-content));background:color-mix(in oklab,var(--alert-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--alert-color,var(--color-base-content))10%,var(--color-base-100));box-shadow:none;background-image:none}.lg\:alert-info{border-color:var(--color-info);color:var(--color-info-content);--alert-color:var(--color-info)}.lg\:alert-success{border-color:var(--color-success);color:var(--color-success-content);--alert-color:var(--color-success)}.lg\:alert-warning{border-color:var(--color-warning);color:var(--color-warning-content);--alert-color:var(--color-warning)}.lg\:alert-error{border-color:var(--color-error);color:var(--color-error-content);--alert-color:var(--color-error)}.lg\:alert-vertical{text-align:center;grid-template-columns:auto;grid-auto-flow:row;justify-content:center;justify-items:center}.lg\:alert-vertical:has(:nth-child(2)){grid-template-columns:auto}.lg\:alert-horizontal{text-align:start;grid-template-columns:auto;grid-auto-flow:column;justify-content:start;justify-items:start}.lg\:alert-horizontal:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}}@media (min-width:1280px){.xl\:alert{border-radius:var(--radius-box);color:var(--color-base-content);background-color:var(--alert-color,var(--color-base-200));text-align:start;border:var(--border)solid var(--color-base-200);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);box-shadow:0 3px 0 -2px oklch(100% 0 0/calc(var(--depth)*.08))inset,0 1px color-mix(in oklab,color-mix(in oklab,#000 20%,var(--alert-color,var(--color-base-200)))calc(var(--depth)*20%),transparent),0 4px 3px -2px oklch(0% 0 0/calc(var(--depth)*.08));grid-template-columns:auto;grid-auto-flow:column;justify-content:start;place-items:center start;gap:1rem;padding-block:.75rem;padding-inline:1rem;font-size:.875rem;line-height:1.25rem;display:grid}.xl\:alert:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}.xl\:alert.alert-outline{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none}.xl\:alert.alert-dash{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none;border-style:dashed}.xl\:alert.alert-soft{color:var(--alert-color,var(--color-base-content));background:color-mix(in oklab,var(--alert-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--alert-color,var(--color-base-content))10%,var(--color-base-100));box-shadow:none;background-image:none}.xl\:alert-info{border-color:var(--color-info);color:var(--color-info-content);--alert-color:var(--color-info)}.xl\:alert-success{border-color:var(--color-success);color:var(--color-success-content);--alert-color:var(--color-success)}.xl\:alert-warning{border-color:var(--color-warning);color:var(--color-warning-content);--alert-color:var(--color-warning)}.xl\:alert-error{border-color:var(--color-error);color:var(--color-error-content);--alert-color:var(--color-error)}.xl\:alert-vertical{text-align:center;grid-template-columns:auto;grid-auto-flow:row;justify-content:center;justify-items:center}.xl\:alert-vertical:has(:nth-child(2)){grid-template-columns:auto}.xl\:alert-horizontal{text-align:start;grid-template-columns:auto;grid-auto-flow:column;justify-content:start;justify-items:start}.xl\:alert-horizontal:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}}@media (min-width:1536px){.\32 xl\:alert{border-radius:var(--radius-box);color:var(--color-base-content);background-color:var(--alert-color,var(--color-base-200));text-align:start;border:var(--border)solid var(--color-base-200);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);box-shadow:0 3px 0 -2px oklch(100% 0 0/calc(var(--depth)*.08))inset,0 1px color-mix(in oklab,color-mix(in oklab,#000 20%,var(--alert-color,var(--color-base-200)))calc(var(--depth)*20%),transparent),0 4px 3px -2px oklch(0% 0 0/calc(var(--depth)*.08));grid-template-columns:auto;grid-auto-flow:column;justify-content:start;place-items:center start;gap:1rem;padding-block:.75rem;padding-inline:1rem;font-size:.875rem;line-height:1.25rem;display:grid}.\32 xl\:alert:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}.\32 xl\:alert.alert-outline{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none}.\32 xl\:alert.alert-dash{color:var(--alert-color);box-shadow:none;background-color:transparent;background-image:none;border-style:dashed}.\32 xl\:alert.alert-soft{color:var(--alert-color,var(--color-base-content));background:color-mix(in oklab,var(--alert-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--alert-color,var(--color-base-content))10%,var(--color-base-100));box-shadow:none;background-image:none}.\32 xl\:alert-info{border-color:var(--color-info);color:var(--color-info-content);--alert-color:var(--color-info)}.\32 xl\:alert-success{border-color:var(--color-success);color:var(--color-success-content);--alert-color:var(--color-success)}.\32 xl\:alert-warning{border-color:var(--color-warning);color:var(--color-warning-content);--alert-color:var(--color-warning)}.\32 xl\:alert-error{border-color:var(--color-error);color:var(--color-error-content);--alert-color:var(--color-error)}.\32 xl\:alert-vertical{text-align:center;grid-template-columns:auto;grid-auto-flow:row;justify-content:center;justify-items:center}.\32 xl\:alert-vertical:has(:nth-child(2)){grid-template-columns:auto}.\32 xl\:alert-horizontal{text-align:start;grid-template-columns:auto;grid-auto-flow:column;justify-content:start;justify-items:start}.\32 xl\:alert-horizontal:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}}.countdown{display:inline-flex}.countdown.countdown{line-height:1em}.countdown>*{height:1em;display:inline-block;overflow-y:hidden}.countdown>*:before{content:"00\a 01\a 02\a 03\a 04\a 05\a 06\a 07\a 08\a 09\a 10\a 11\a 12\a 13\a 14\a 15\a 16\a 17\a 18\a 19\a 20\a 21\a 22\a 23\a 24\a 25\a 26\a 27\a 28\a 29\a 30\a 31\a 32\a 33\a 34\a 35\a 36\a 37\a 38\a 39\a 40\a 41\a 42\a 43\a 44\a 45\a 46\a 47\a 48\a 49\a 50\a 51\a 52\a 53\a 54\a 55\a 56\a 57\a 58\a 59\a 60\a 61\a 62\a 63\a 64\a 65\a 66\a 67\a 68\a 69\a 70\a 71\a 72\a 73\a 74\a 75\a 76\a 77\a 78\a 79\a 80\a 81\a 82\a 83\a 84\a 85\a 86\a 87\a 88\a 89\a 90\a 91\a 92\a 93\a 94\a 95\a 96\a 97\a 98\a 99\a ";white-space:pre;top:calc(var(--value)*-1em);text-align:center;transition:all 1s cubic-bezier(1,0,0,1);position:relative}.menu{--menu-active-fg:var(--color-neutral-content);--menu-active-bg:var(--color-neutral);flex-flow:column wrap;width:fit-content;padding:.5rem;font-size:.875rem;display:flex}.menu :where(li ul){white-space:nowrap;margin-inline-start:1rem;padding-inline-start:.5rem;position:relative}.menu :where(li ul):before{background-color:var(--color-base-content);opacity:.1;width:var(--border);content:"";inset-inline-start:0;position:absolute;top:.75rem;bottom:.75rem}.menu :where(li>.menu-dropdown:not(.menu-dropdown-show)){display:none}.menu :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title,.btn))){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.menu :where(li>details>summary){--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.menu :where(li>details>summary){outline-offset:2px;outline:2px solid transparent}}.menu :where(li>details>summary)::-webkit-details-marker{display:none}.menu :where(li>details>summary):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.menu :where(li>.menu-dropdown-toggle):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.menu :where(li>details[open]>summary):after{translate:0 1px;rotate:45deg}.menu :where(li>.menu-dropdown-toggle.menu-dropdown-show):after{translate:0 1px;rotate:45deg}.menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{outline-offset:2px;outline:2px solid transparent}}.menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{outline-offset:2px;outline:2px solid transparent}}.menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);--tw-outline-style:none;outline-style:none;box-shadow:inset 0 1px rgba(0,0,0,.01),inset 0 -1px rgba(255,255,255,.01);box-shadow:inset 0 1px lab(0% 0 0/.01),inset 0 -1px lab(100% 0 0/.01)}@media (forced-colors:active){.menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){outline-offset:2px;outline:2px solid transparent}}.menu :where(li:empty){background-color:var(--color-base-content);opacity:.1;height:1px;margin:.5rem 1rem}.menu :where(li){flex-flow:column wrap;flex-shrink:0;align-items:stretch;display:flex;position:relative}.menu :where(li) .badge{justify-self:flex-end}.menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{outline-offset:2px;outline:2px solid transparent}}.menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:not(.menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{outline-offset:2px;outline:2px solid transparent}}.menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:not(.menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.menu :where(li)>details>summary:active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.menu :where(li)>details>summary:active{outline-offset:2px;outline:2px solid transparent}}.menu :where(li)>details>summary:active:not(.menu :where(li)>details>summary:active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.menu :where(li).menu-disabled{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.menu .dropdown:focus-within .menu-dropdown-toggle:after{translate:0 1px;rotate:45deg}.menu .dropdown-content{margin-top:.5rem;padding:.5rem}.menu .dropdown-content:before{display:none}.menu-title{color:color-mix(in oklab,var(--color-base-content)40%,transparent);padding-block:.5rem;padding-inline:.75rem;font-size:.875rem;font-weight:600}.menu-horizontal{flex-direction:row;display:inline-flex}.menu-horizontal>li:not(.menu-title)>details>ul{margin-inline-start:0;margin-top:1rem;padding-block:.5rem;padding-inline-end:.5rem;position:absolute}.menu-horizontal>li>details>ul:before{content:none}:where(.menu-horizontal>li:not(.menu-title)>details>ul){border-radius:var(--radius-box);background-color:var(--color-base-100);box-shadow:0 1px 3px rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);box-shadow:0 1px 3px lab(0% 0 0/.1),0 1px 2px -1px lab(0% 0 0/.1)}.menu-vertical{flex-direction:column;display:inline-flex}.menu-vertical>li:not(.menu-title)>details>ul{margin-inline-start:1rem;margin-top:0;padding-block:0;padding-inline-end:0;position:relative}.menu-xs :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.menu-xs :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.menu-xs .menu-title{padding-block:.25rem;padding-inline:.5rem}.menu-sm :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.menu-sm :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.menu-sm .menu-title{padding-block:.5rem;padding-inline:.75rem}.menu-md :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.menu-md :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.menu-md .menu-title{padding-block:.5rem;padding-inline:.75rem}.menu-lg :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.menu-lg :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.menu-lg .menu-title{padding-block:.75rem;padding-inline:1.5rem}.menu-xl :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.menu-xl :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.menu-xl .menu-title{padding-block:.75rem;padding-inline:1.5rem}@media (min-width:640px){.sm\:menu{--menu-active-fg:var(--color-neutral-content);--menu-active-bg:var(--color-neutral);flex-flow:column wrap;width:fit-content;padding:.5rem;font-size:.875rem;display:flex}.sm\:menu :where(li ul){white-space:nowrap;margin-inline-start:1rem;padding-inline-start:.5rem;position:relative}.sm\:menu :where(li ul):before{background-color:var(--color-base-content);opacity:.1;width:var(--border);content:"";inset-inline-start:0;position:absolute;top:.75rem;bottom:.75rem}.sm\:menu :where(li>.menu-dropdown:not(.menu-dropdown-show)){display:none}.sm\:menu :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title,.btn))){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.sm\:menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.sm\:menu :where(li>details>summary){--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:menu :where(li>details>summary){outline-offset:2px;outline:2px solid transparent}}.sm\:menu :where(li>details>summary)::-webkit-details-marker{display:none}.sm\:menu :where(li>details>summary):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.sm\:menu :where(li>.menu-dropdown-toggle):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.sm\:menu :where(li>details[open]>summary):after{translate:0 1px;rotate:45deg}.sm\:menu :where(li>.menu-dropdown-toggle.menu-dropdown-show):after{translate:0 1px;rotate:45deg}.sm\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{outline-offset:2px;outline:2px solid transparent}}.sm\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{outline-offset:2px;outline:2px solid transparent}}.sm\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);--tw-outline-style:none;outline-style:none;box-shadow:inset 0 1px rgba(0,0,0,.01),inset 0 -1px rgba(255,255,255,.01);box-shadow:inset 0 1px lab(0% 0 0/.01),inset 0 -1px lab(100% 0 0/.01)}@media (forced-colors:active){.sm\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){outline-offset:2px;outline:2px solid transparent}}.sm\:menu :where(li:empty){background-color:var(--color-base-content);opacity:.1;height:1px;margin:.5rem 1rem}.sm\:menu :where(li){flex-flow:column wrap;flex-shrink:0;align-items:stretch;display:flex;position:relative}.sm\:menu :where(li) .badge{justify-self:flex-end}.sm\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.sm\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{outline-offset:2px;outline:2px solid transparent}}.sm\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:not(.sm\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.sm\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.sm\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{outline-offset:2px;outline:2px solid transparent}}.sm\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:not(.sm\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.sm\:menu :where(li)>details>summary:active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.sm\:menu :where(li)>details>summary:active{outline-offset:2px;outline:2px solid transparent}}.sm\:menu :where(li)>details>summary:active:not(.sm\:menu :where(li)>details>summary:active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.sm\:menu :where(li).menu-disabled{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.sm\:menu .dropdown:focus-within .menu-dropdown-toggle:after{translate:0 1px;rotate:45deg}.sm\:menu .dropdown-content{margin-top:.5rem;padding:.5rem}.sm\:menu .dropdown-content:before{display:none}.sm\:menu-title{color:color-mix(in oklab,var(--color-base-content)40%,transparent);padding-block:.5rem;padding-inline:.75rem;font-size:.875rem;font-weight:600}.sm\:menu-horizontal{flex-direction:row;display:inline-flex}.sm\:menu-horizontal>li:not(.menu-title)>details>ul{margin-inline-start:0;margin-top:1rem;padding-block:.5rem;padding-inline-end:.5rem;position:absolute}.sm\:menu-horizontal>li>details>ul:before{content:none}:where(.sm\:menu-horizontal>li:not(.menu-title)>details>ul){border-radius:var(--radius-box);background-color:var(--color-base-100);box-shadow:0 1px 3px rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);box-shadow:0 1px 3px lab(0% 0 0/.1),0 1px 2px -1px lab(0% 0 0/.1)}.sm\:menu-vertical{flex-direction:column;display:inline-flex}.sm\:menu-vertical>li:not(.menu-title)>details>ul{margin-inline-start:1rem;margin-top:0;padding-block:0;padding-inline-end:0;position:relative}.sm\:menu-xs :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.sm\:menu-xs :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.sm\:menu-xs .menu-title{padding-block:.25rem;padding-inline:.5rem}.sm\:menu-sm :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.sm\:menu-sm :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.sm\:menu-sm .menu-title{padding-block:.5rem;padding-inline:.75rem}.sm\:menu-md :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.sm\:menu-md :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.sm\:menu-md .menu-title{padding-block:.5rem;padding-inline:.75rem}.sm\:menu-lg :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.sm\:menu-lg :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.sm\:menu-lg .menu-title{padding-block:.75rem;padding-inline:1.5rem}.sm\:menu-xl :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.sm\:menu-xl :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.sm\:menu-xl .menu-title{padding-block:.75rem;padding-inline:1.5rem}}@media (min-width:768px){.md\:menu{--menu-active-fg:var(--color-neutral-content);--menu-active-bg:var(--color-neutral);flex-flow:column wrap;width:fit-content;padding:.5rem;font-size:.875rem;display:flex}.md\:menu :where(li ul){white-space:nowrap;margin-inline-start:1rem;padding-inline-start:.5rem;position:relative}.md\:menu :where(li ul):before{background-color:var(--color-base-content);opacity:.1;width:var(--border);content:"";inset-inline-start:0;position:absolute;top:.75rem;bottom:.75rem}.md\:menu :where(li>.menu-dropdown:not(.menu-dropdown-show)){display:none}.md\:menu :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title,.btn))){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.md\:menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.md\:menu :where(li>details>summary){--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:menu :where(li>details>summary){outline-offset:2px;outline:2px solid transparent}}.md\:menu :where(li>details>summary)::-webkit-details-marker{display:none}.md\:menu :where(li>details>summary):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.md\:menu :where(li>.menu-dropdown-toggle):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.md\:menu :where(li>details[open]>summary):after{translate:0 1px;rotate:45deg}.md\:menu :where(li>.menu-dropdown-toggle.menu-dropdown-show):after{translate:0 1px;rotate:45deg}.md\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{outline-offset:2px;outline:2px solid transparent}}.md\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{outline-offset:2px;outline:2px solid transparent}}.md\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);--tw-outline-style:none;outline-style:none;box-shadow:inset 0 1px rgba(0,0,0,.01),inset 0 -1px rgba(255,255,255,.01);box-shadow:inset 0 1px lab(0% 0 0/.01),inset 0 -1px lab(100% 0 0/.01)}@media (forced-colors:active){.md\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){outline-offset:2px;outline:2px solid transparent}}.md\:menu :where(li:empty){background-color:var(--color-base-content);opacity:.1;height:1px;margin:.5rem 1rem}.md\:menu :where(li){flex-flow:column wrap;flex-shrink:0;align-items:stretch;display:flex;position:relative}.md\:menu :where(li) .badge{justify-self:flex-end}.md\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.md\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{outline-offset:2px;outline:2px solid transparent}}.md\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:not(.md\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.md\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.md\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{outline-offset:2px;outline:2px solid transparent}}.md\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:not(.md\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.md\:menu :where(li)>details>summary:active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.md\:menu :where(li)>details>summary:active{outline-offset:2px;outline:2px solid transparent}}.md\:menu :where(li)>details>summary:active:not(.md\:menu :where(li)>details>summary:active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.md\:menu :where(li).menu-disabled{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.md\:menu .dropdown:focus-within .menu-dropdown-toggle:after{translate:0 1px;rotate:45deg}.md\:menu .dropdown-content{margin-top:.5rem;padding:.5rem}.md\:menu .dropdown-content:before{display:none}.md\:menu-title{color:color-mix(in oklab,var(--color-base-content)40%,transparent);padding-block:.5rem;padding-inline:.75rem;font-size:.875rem;font-weight:600}.md\:menu-horizontal{flex-direction:row;display:inline-flex}.md\:menu-horizontal>li:not(.menu-title)>details>ul{margin-inline-start:0;margin-top:1rem;padding-block:.5rem;padding-inline-end:.5rem;position:absolute}.md\:menu-horizontal>li>details>ul:before{content:none}:where(.md\:menu-horizontal>li:not(.menu-title)>details>ul){border-radius:var(--radius-box);background-color:var(--color-base-100);box-shadow:0 1px 3px rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);box-shadow:0 1px 3px lab(0% 0 0/.1),0 1px 2px -1px lab(0% 0 0/.1)}.md\:menu-vertical{flex-direction:column;display:inline-flex}.md\:menu-vertical>li:not(.menu-title)>details>ul{margin-inline-start:1rem;margin-top:0;padding-block:0;padding-inline-end:0;position:relative}.md\:menu-xs :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.md\:menu-xs :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.md\:menu-xs .menu-title{padding-block:.25rem;padding-inline:.5rem}.md\:menu-sm :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.md\:menu-sm :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.md\:menu-sm .menu-title{padding-block:.5rem;padding-inline:.75rem}.md\:menu-md :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.md\:menu-md :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.md\:menu-md .menu-title{padding-block:.5rem;padding-inline:.75rem}.md\:menu-lg :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.md\:menu-lg :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.md\:menu-lg .menu-title{padding-block:.75rem;padding-inline:1.5rem}.md\:menu-xl :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.md\:menu-xl :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.md\:menu-xl .menu-title{padding-block:.75rem;padding-inline:1.5rem}}@media (min-width:1024px){.lg\:menu{--menu-active-fg:var(--color-neutral-content);--menu-active-bg:var(--color-neutral);flex-flow:column wrap;width:fit-content;padding:.5rem;font-size:.875rem;display:flex}.lg\:menu :where(li ul){white-space:nowrap;margin-inline-start:1rem;padding-inline-start:.5rem;position:relative}.lg\:menu :where(li ul):before{background-color:var(--color-base-content);opacity:.1;width:var(--border);content:"";inset-inline-start:0;position:absolute;top:.75rem;bottom:.75rem}.lg\:menu :where(li>.menu-dropdown:not(.menu-dropdown-show)){display:none}.lg\:menu :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title,.btn))){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.lg\:menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.lg\:menu :where(li>details>summary){--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:menu :where(li>details>summary){outline-offset:2px;outline:2px solid transparent}}.lg\:menu :where(li>details>summary)::-webkit-details-marker{display:none}.lg\:menu :where(li>details>summary):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.lg\:menu :where(li>.menu-dropdown-toggle):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.lg\:menu :where(li>details[open]>summary):after{translate:0 1px;rotate:45deg}.lg\:menu :where(li>.menu-dropdown-toggle.menu-dropdown-show):after{translate:0 1px;rotate:45deg}.lg\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{outline-offset:2px;outline:2px solid transparent}}.lg\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{outline-offset:2px;outline:2px solid transparent}}.lg\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);--tw-outline-style:none;outline-style:none;box-shadow:inset 0 1px rgba(0,0,0,.01),inset 0 -1px rgba(255,255,255,.01);box-shadow:inset 0 1px lab(0% 0 0/.01),inset 0 -1px lab(100% 0 0/.01)}@media (forced-colors:active){.lg\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){outline-offset:2px;outline:2px solid transparent}}.lg\:menu :where(li:empty){background-color:var(--color-base-content);opacity:.1;height:1px;margin:.5rem 1rem}.lg\:menu :where(li){flex-flow:column wrap;flex-shrink:0;align-items:stretch;display:flex;position:relative}.lg\:menu :where(li) .badge{justify-self:flex-end}.lg\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.lg\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{outline-offset:2px;outline:2px solid transparent}}.lg\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:not(.lg\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.lg\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.lg\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{outline-offset:2px;outline:2px solid transparent}}.lg\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:not(.lg\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.lg\:menu :where(li)>details>summary:active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.lg\:menu :where(li)>details>summary:active{outline-offset:2px;outline:2px solid transparent}}.lg\:menu :where(li)>details>summary:active:not(.lg\:menu :where(li)>details>summary:active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.lg\:menu :where(li).menu-disabled{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.lg\:menu .dropdown:focus-within .menu-dropdown-toggle:after{translate:0 1px;rotate:45deg}.lg\:menu .dropdown-content{margin-top:.5rem;padding:.5rem}.lg\:menu .dropdown-content:before{display:none}.lg\:menu-title{color:color-mix(in oklab,var(--color-base-content)40%,transparent);padding-block:.5rem;padding-inline:.75rem;font-size:.875rem;font-weight:600}.lg\:menu-horizontal{flex-direction:row;display:inline-flex}.lg\:menu-horizontal>li:not(.menu-title)>details>ul{margin-inline-start:0;margin-top:1rem;padding-block:.5rem;padding-inline-end:.5rem;position:absolute}.lg\:menu-horizontal>li>details>ul:before{content:none}:where(.lg\:menu-horizontal>li:not(.menu-title)>details>ul){border-radius:var(--radius-box);background-color:var(--color-base-100);box-shadow:0 1px 3px rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);box-shadow:0 1px 3px lab(0% 0 0/.1),0 1px 2px -1px lab(0% 0 0/.1)}.lg\:menu-vertical{flex-direction:column;display:inline-flex}.lg\:menu-vertical>li:not(.menu-title)>details>ul{margin-inline-start:1rem;margin-top:0;padding-block:0;padding-inline-end:0;position:relative}.lg\:menu-xs :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.lg\:menu-xs :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.lg\:menu-xs .menu-title{padding-block:.25rem;padding-inline:.5rem}.lg\:menu-sm :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.lg\:menu-sm :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.lg\:menu-sm .menu-title{padding-block:.5rem;padding-inline:.75rem}.lg\:menu-md :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.lg\:menu-md :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.lg\:menu-md .menu-title{padding-block:.5rem;padding-inline:.75rem}.lg\:menu-lg :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.lg\:menu-lg :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.lg\:menu-lg .menu-title{padding-block:.75rem;padding-inline:1.5rem}.lg\:menu-xl :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.lg\:menu-xl :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.lg\:menu-xl .menu-title{padding-block:.75rem;padding-inline:1.5rem}}@media (min-width:1280px){.xl\:menu{--menu-active-fg:var(--color-neutral-content);--menu-active-bg:var(--color-neutral);flex-flow:column wrap;width:fit-content;padding:.5rem;font-size:.875rem;display:flex}.xl\:menu :where(li ul){white-space:nowrap;margin-inline-start:1rem;padding-inline-start:.5rem;position:relative}.xl\:menu :where(li ul):before{background-color:var(--color-base-content);opacity:.1;width:var(--border);content:"";inset-inline-start:0;position:absolute;top:.75rem;bottom:.75rem}.xl\:menu :where(li>.menu-dropdown:not(.menu-dropdown-show)){display:none}.xl\:menu :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title,.btn))){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.xl\:menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.xl\:menu :where(li>details>summary){--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:menu :where(li>details>summary){outline-offset:2px;outline:2px solid transparent}}.xl\:menu :where(li>details>summary)::-webkit-details-marker{display:none}.xl\:menu :where(li>details>summary):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.xl\:menu :where(li>.menu-dropdown-toggle):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.xl\:menu :where(li>details[open]>summary):after{translate:0 1px;rotate:45deg}.xl\:menu :where(li>.menu-dropdown-toggle.menu-dropdown-show):after{translate:0 1px;rotate:45deg}.xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{outline-offset:2px;outline:2px solid transparent}}.xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{outline-offset:2px;outline:2px solid transparent}}.xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);--tw-outline-style:none;outline-style:none;box-shadow:inset 0 1px rgba(0,0,0,.01),inset 0 -1px rgba(255,255,255,.01);box-shadow:inset 0 1px lab(0% 0 0/.01),inset 0 -1px lab(100% 0 0/.01)}@media (forced-colors:active){.xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){outline-offset:2px;outline:2px solid transparent}}.xl\:menu :where(li:empty){background-color:var(--color-base-content);opacity:.1;height:1px;margin:.5rem 1rem}.xl\:menu :where(li){flex-flow:column wrap;flex-shrink:0;align-items:stretch;display:flex;position:relative}.xl\:menu :where(li) .badge{justify-self:flex-end}.xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{outline-offset:2px;outline:2px solid transparent}}.xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:not(.xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{outline-offset:2px;outline:2px solid transparent}}.xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:not(.xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.xl\:menu :where(li)>details>summary:active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.xl\:menu :where(li)>details>summary:active{outline-offset:2px;outline:2px solid transparent}}.xl\:menu :where(li)>details>summary:active:not(.xl\:menu :where(li)>details>summary:active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.xl\:menu :where(li).menu-disabled{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.xl\:menu .dropdown:focus-within .menu-dropdown-toggle:after{translate:0 1px;rotate:45deg}.xl\:menu .dropdown-content{margin-top:.5rem;padding:.5rem}.xl\:menu .dropdown-content:before{display:none}.xl\:menu-title{color:color-mix(in oklab,var(--color-base-content)40%,transparent);padding-block:.5rem;padding-inline:.75rem;font-size:.875rem;font-weight:600}.xl\:menu-horizontal{flex-direction:row;display:inline-flex}.xl\:menu-horizontal>li:not(.menu-title)>details>ul{margin-inline-start:0;margin-top:1rem;padding-block:.5rem;padding-inline-end:.5rem;position:absolute}.xl\:menu-horizontal>li>details>ul:before{content:none}:where(.xl\:menu-horizontal>li:not(.menu-title)>details>ul){border-radius:var(--radius-box);background-color:var(--color-base-100);box-shadow:0 1px 3px rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);box-shadow:0 1px 3px lab(0% 0 0/.1),0 1px 2px -1px lab(0% 0 0/.1)}.xl\:menu-vertical{flex-direction:column;display:inline-flex}.xl\:menu-vertical>li:not(.menu-title)>details>ul{margin-inline-start:1rem;margin-top:0;padding-block:0;padding-inline-end:0;position:relative}.xl\:menu-xs :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.xl\:menu-xs :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.xl\:menu-xs .menu-title{padding-block:.25rem;padding-inline:.5rem}.xl\:menu-sm :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.xl\:menu-sm :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.xl\:menu-sm .menu-title{padding-block:.5rem;padding-inline:.75rem}.xl\:menu-md :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.xl\:menu-md :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.xl\:menu-md .menu-title{padding-block:.5rem;padding-inline:.75rem}.xl\:menu-lg :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.xl\:menu-lg :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.xl\:menu-lg .menu-title{padding-block:.75rem;padding-inline:1.5rem}.xl\:menu-xl :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.xl\:menu-xl :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.xl\:menu-xl .menu-title{padding-block:.75rem;padding-inline:1.5rem}}@media (min-width:1536px){.\32 xl\:menu{--menu-active-fg:var(--color-neutral-content);--menu-active-bg:var(--color-neutral);flex-flow:column wrap;width:fit-content;padding:.5rem;font-size:.875rem;display:flex}.\32 xl\:menu :where(li ul){white-space:nowrap;margin-inline-start:1rem;padding-inline-start:.5rem;position:relative}.\32 xl\:menu :where(li ul):before{background-color:var(--color-base-content);opacity:.1;width:var(--border);content:"";inset-inline-start:0;position:absolute;top:.75rem;bottom:.75rem}.\32 xl\:menu :where(li>.menu-dropdown:not(.menu-dropdown-show)){display:none}.\32 xl\:menu :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title,.btn))){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.\32 xl\:menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);text-align:start;text-wrap:balance;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.\32 xl\:menu :where(li>details>summary){--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:menu :where(li>details>summary){outline-offset:2px;outline:2px solid transparent}}.\32 xl\:menu :where(li>details>summary)::-webkit-details-marker{display:none}.\32 xl\:menu :where(li>details>summary):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.\32 xl\:menu :where(li>.menu-dropdown-toggle):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.\32 xl\:menu :where(li>details[open]>summary):after{translate:0 1px;rotate:45deg}.\32 xl\:menu :where(li>.menu-dropdown-toggle.menu-dropdown-show):after{translate:0 1px;rotate:45deg}.\32 xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)).menu-focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)),li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title)):not(:is(.menu-active,:active,.btn)):focus-visible{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){cursor:pointer;background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);--tw-outline-style:none;outline-style:none;box-shadow:inset 0 1px rgba(0,0,0,.01),inset 0 -1px rgba(255,255,255,.01);box-shadow:inset 0 1px lab(0% 0 0/.01),inset 0 -1px lab(100% 0 0/.01)}@media (forced-colors:active){.\32 xl\:menu :where(li:not(:is(.menu-title,.disabled))>:not(:is(ul,details,.menu-title)):not(:is(.menu-active,:active,.btn)):hover,li:not(:is(.menu-title,.disabled))>details>summary:not(.menu-title):not(:is(.menu-active,:active,.btn)):hover){outline-offset:2px;outline:2px solid transparent}}.\32 xl\:menu :where(li:empty){background-color:var(--color-base-content);opacity:.1;height:1px;margin:.5rem 1rem}.\32 xl\:menu :where(li){flex-flow:column wrap;flex-shrink:0;align-items:stretch;display:flex;position:relative}.\32 xl\:menu :where(li) .badge{justify-self:flex-end}.\32 xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.\32 xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:not(.\32 xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)):active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.\32 xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.\32 xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:not(.\32 xl\:menu :where(li)>:not(:is(ul,.menu-title,details,.btn)).menu-active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.\32 xl\:menu :where(li)>details>summary:active{--tw-outline-style:none;color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);outline-style:none}@media (forced-colors:active){.\32 xl\:menu :where(li)>details>summary:active{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:menu :where(li)>details>summary:active:not(.\32 xl\:menu :where(li)>details>summary:active:active){box-shadow:0 2px calc(var(--depth)*3px)-2px var(--menu-active-bg)}.\32 xl\:menu :where(li).menu-disabled{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.\32 xl\:menu .dropdown:focus-within .menu-dropdown-toggle:after{translate:0 1px;rotate:45deg}.\32 xl\:menu .dropdown-content{margin-top:.5rem;padding:.5rem}.\32 xl\:menu .dropdown-content:before{display:none}.\32 xl\:menu-title{color:color-mix(in oklab,var(--color-base-content)40%,transparent);padding-block:.5rem;padding-inline:.75rem;font-size:.875rem;font-weight:600}.\32 xl\:menu-horizontal{flex-direction:row;display:inline-flex}.\32 xl\:menu-horizontal>li:not(.menu-title)>details>ul{margin-inline-start:0;margin-top:1rem;padding-block:.5rem;padding-inline-end:.5rem;position:absolute}.\32 xl\:menu-horizontal>li>details>ul:before{content:none}:where(.\32 xl\:menu-horizontal>li:not(.menu-title)>details>ul){border-radius:var(--radius-box);background-color:var(--color-base-100);box-shadow:0 1px 3px rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);box-shadow:0 1px 3px lab(0% 0 0/.1),0 1px 2px -1px lab(0% 0 0/.1)}.\32 xl\:menu-vertical{flex-direction:column;display:inline-flex}.\32 xl\:menu-vertical>li:not(.menu-title)>details>ul{margin-inline-start:1rem;margin-top:0;padding-block:0;padding-inline-end:0;position:relative}.\32 xl\:menu-xs :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.\32 xl\:menu-xs :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.5rem;font-size:.6875rem}.\32 xl\:menu-xs .menu-title{padding-block:.25rem;padding-inline:.5rem}.\32 xl\:menu-sm :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.\32 xl\:menu-sm :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.\32 xl\:menu-sm .menu-title{padding-block:.5rem;padding-inline:.75rem}.\32 xl\:menu-md :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.\32 xl\:menu-md :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:.75rem;font-size:.875rem}.\32 xl\:menu-md .menu-title{padding-block:.5rem;padding-inline:.75rem}.\32 xl\:menu-lg :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.\32 xl\:menu-lg :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1rem;font-size:1.125rem}.\32 xl\:menu-lg .menu-title{padding-block:.75rem;padding-inline:1.5rem}.\32 xl\:menu-xl :where(li:not(.menu-title)>:not(:is(ul,details,.menu-title))){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.\32 xl\:menu-xl :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.375rem;padding-inline:1.25rem;font-size:1.375rem}.\32 xl\:menu-xl .menu-title{padding-block:.75rem;padding-inline:1.5rem}}.hero{background-position:50%;background-size:cover;place-items:center;width:100%;display:grid}.hero>*{grid-row-start:1;grid-column-start:1}.hero-overlay{background-color:color-mix(in oklab,var(--color-neutral)50%,transparent);grid-row-start:1;grid-column-start:1;width:100%;height:100%}.hero-content{isolation:isolate;justify-content:center;align-items:center;gap:1rem;max-width:80rem;padding:1rem;display:flex}@media (min-width:640px){.sm\:hero{background-position:50%;background-size:cover;place-items:center;width:100%;display:grid}.sm\:hero>*{grid-row-start:1;grid-column-start:1}.sm\:hero-overlay{background-color:color-mix(in oklab,var(--color-neutral)50%,transparent);grid-row-start:1;grid-column-start:1;width:100%;height:100%}.sm\:hero-content{isolation:isolate;justify-content:center;align-items:center;gap:1rem;max-width:80rem;padding:1rem;display:flex}}@media (min-width:768px){.md\:hero{background-position:50%;background-size:cover;place-items:center;width:100%;display:grid}.md\:hero>*{grid-row-start:1;grid-column-start:1}.md\:hero-overlay{background-color:color-mix(in oklab,var(--color-neutral)50%,transparent);grid-row-start:1;grid-column-start:1;width:100%;height:100%}.md\:hero-content{isolation:isolate;justify-content:center;align-items:center;gap:1rem;max-width:80rem;padding:1rem;display:flex}}@media (min-width:1024px){.lg\:hero{background-position:50%;background-size:cover;place-items:center;width:100%;display:grid}.lg\:hero>*{grid-row-start:1;grid-column-start:1}.lg\:hero-overlay{background-color:color-mix(in oklab,var(--color-neutral)50%,transparent);grid-row-start:1;grid-column-start:1;width:100%;height:100%}.lg\:hero-content{isolation:isolate;justify-content:center;align-items:center;gap:1rem;max-width:80rem;padding:1rem;display:flex}}@media (min-width:1280px){.xl\:hero{background-position:50%;background-size:cover;place-items:center;width:100%;display:grid}.xl\:hero>*{grid-row-start:1;grid-column-start:1}.xl\:hero-overlay{background-color:color-mix(in oklab,var(--color-neutral)50%,transparent);grid-row-start:1;grid-column-start:1;width:100%;height:100%}.xl\:hero-content{isolation:isolate;justify-content:center;align-items:center;gap:1rem;max-width:80rem;padding:1rem;display:flex}}@media (min-width:1536px){.\32 xl\:hero{background-position:50%;background-size:cover;place-items:center;width:100%;display:grid}.\32 xl\:hero>*{grid-row-start:1;grid-column-start:1}.\32 xl\:hero-overlay{background-color:color-mix(in oklab,var(--color-neutral)50%,transparent);grid-row-start:1;grid-column-start:1;width:100%;height:100%}.\32 xl\:hero-content{isolation:isolate;justify-content:center;align-items:center;gap:1rem;max-width:80rem;padding:1rem;display:flex}}.dropdown{position-area:var(--anchor-v,bottom)var(--anchor-h,span-right);display:inline-block;position:relative}.dropdown>:not(summary):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.dropdown>:not(summary):focus{outline-offset:2px;outline:2px solid transparent}}.dropdown .dropdown-content{position:absolute}.dropdown:not(:is(details,.dropdown-open,.dropdown-hover:hover,:focus-within)) .dropdown-content{transform-origin:top;opacity:0;display:none;scale:95%}.dropdown[popover]{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}.dropdown .dropdown-content{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}@starting-style{.dropdown[popover]{opacity:0;scale:95%}.dropdown .dropdown-content{opacity:0;scale:95%}}.dropdown.dropdown-open>[tabindex]:first-child{pointer-events:none}.dropdown.dropdown-open .dropdown-content{opacity:1}.dropdown:not(.dropdown-hover):focus>[tabindex]:first-child{pointer-events:none}.dropdown:not(.dropdown-hover):focus .dropdown-content{opacity:1}.dropdown:focus-within>[tabindex]:first-child{pointer-events:none}.dropdown:focus-within .dropdown-content{opacity:1}.dropdown.dropdown-hover:hover .dropdown-content{opacity:1;scale:100%}.dropdown:is(details) summary::-webkit-details-marker{display:none}.dropdown.dropdown-open .dropdown-content{scale:100%}.dropdown:focus .dropdown-content{scale:100%}.dropdown:focus-within .dropdown-content{scale:100%}.dropdown:where([popover]){background:0 0}.dropdown[popover]{color:inherit;position:fixed}@supports not (position-area:bottom){.dropdown[popover]{margin:auto}.dropdown[popover].dropdown-open:not(:popover-open){transform-origin:top;opacity:0;display:none;scale:95%}.dropdown[popover]::backdrop{background-color:rgba(0,0,0,.3);background-color:lab(0% 0 0/.3)}}.dropdown[popover]:not(:is(.dropdown-open,:popover-open)){transform-origin:top;opacity:0;display:none;scale:95%}.dropdown-start{--anchor-h:span-right}.dropdown-start :where(.dropdown-content){inset-inline-end:auto}.dropdown-start.dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.dropdown-start.dropdown-left .dropdown-content{top:0;bottom:auto}.dropdown-start.dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.dropdown-start.dropdown-right .dropdown-content{top:0;bottom:auto}.dropdown-center{--anchor-h:center}.dropdown-center :where(.dropdown-content){inset-inline-end:50%;translate:50%}.dropdown-center.dropdown-left{--anchor-h:left;--anchor-v:center}.dropdown-center.dropdown-left .dropdown-content{top:auto;bottom:50%;translate:0 50%}.dropdown-center.dropdown-right{--anchor-h:right;--anchor-v:center}.dropdown-center.dropdown-right .dropdown-content{top:auto;bottom:50%;translate:0 50%}.dropdown-end{--anchor-h:span-left}.dropdown-end :where(.dropdown-content){inset-inline-end:0;translate:0}.dropdown-end.dropdown-left{--anchor-h:left;--anchor-v:span-top}.dropdown-end.dropdown-left .dropdown-content{top:auto;bottom:0}.dropdown-end.dropdown-right{--anchor-h:right;--anchor-v:span-top}.dropdown-end.dropdown-right .dropdown-content{top:auto;bottom:0}.dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.dropdown-left .dropdown-content{transform-origin:100%;inset-inline-end:100%;top:0;bottom:auto}.dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.dropdown-right .dropdown-content{transform-origin:0;inset-inline-start:100%;top:0;bottom:auto}.dropdown-bottom{--anchor-v:bottom}.dropdown-bottom .dropdown-content{transform-origin:top;top:100%;bottom:auto}.dropdown-top{--anchor-v:top}.dropdown-top .dropdown-content{transform-origin:bottom;top:auto;bottom:100%}@keyframes dropdown{0%{opacity:0}}@media (min-width:640px){.sm\:dropdown{position-area:var(--anchor-v,bottom)var(--anchor-h,span-right);display:inline-block;position:relative}.sm\:dropdown>:not(summary):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:dropdown>:not(summary):focus{outline-offset:2px;outline:2px solid transparent}}.sm\:dropdown .dropdown-content{position:absolute}.sm\:dropdown:not(:is(details,.dropdown-open,.dropdown-hover:hover,:focus-within)) .dropdown-content{transform-origin:top;opacity:0;display:none;scale:95%}.sm\:dropdown[popover]{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}.sm\:dropdown .dropdown-content{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}@starting-style{.sm\:dropdown[popover]{opacity:0;scale:95%}.sm\:dropdown .dropdown-content{opacity:0;scale:95%}}.sm\:dropdown.dropdown-open>[tabindex]:first-child{pointer-events:none}.sm\:dropdown.dropdown-open .dropdown-content{opacity:1}.sm\:dropdown:not(.dropdown-hover):focus>[tabindex]:first-child{pointer-events:none}.sm\:dropdown:not(.dropdown-hover):focus .dropdown-content{opacity:1}.sm\:dropdown:focus-within>[tabindex]:first-child{pointer-events:none}.sm\:dropdown:focus-within .dropdown-content{opacity:1}.sm\:dropdown.dropdown-hover:hover .dropdown-content{opacity:1;scale:100%}.sm\:dropdown:is(details) summary::-webkit-details-marker{display:none}.sm\:dropdown.dropdown-open .dropdown-content{scale:100%}.sm\:dropdown:focus .dropdown-content{scale:100%}.sm\:dropdown:focus-within .dropdown-content{scale:100%}.sm\:dropdown:where([popover]){background:0 0}.sm\:dropdown[popover]{color:inherit;position:fixed}@supports not (position-area:bottom){.sm\:dropdown[popover]{margin:auto}.sm\:dropdown[popover].dropdown-open:not(:popover-open){transform-origin:top;opacity:0;display:none;scale:95%}.sm\:dropdown[popover]::backdrop{background-color:rgba(0,0,0,.3);background-color:lab(0% 0 0/.3)}}.sm\:dropdown[popover]:not(:is(.dropdown-open,:popover-open)){transform-origin:top;opacity:0;display:none;scale:95%}.sm\:dropdown-start{--anchor-h:span-right}.sm\:dropdown-start :where(.dropdown-content){inset-inline-end:auto}.sm\:dropdown-start.dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.sm\:dropdown-start.dropdown-left .dropdown-content{top:0;bottom:auto}.sm\:dropdown-start.dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.sm\:dropdown-start.dropdown-right .dropdown-content{top:0;bottom:auto}.sm\:dropdown-center{--anchor-h:center}.sm\:dropdown-center :where(.dropdown-content){inset-inline-end:50%;translate:50%}.sm\:dropdown-center.dropdown-left{--anchor-h:left;--anchor-v:center}.sm\:dropdown-center.dropdown-left .dropdown-content{top:auto;bottom:50%;translate:0 50%}.sm\:dropdown-center.dropdown-right{--anchor-h:right;--anchor-v:center}.sm\:dropdown-center.dropdown-right .dropdown-content{top:auto;bottom:50%;translate:0 50%}.sm\:dropdown-end{--anchor-h:span-left}.sm\:dropdown-end :where(.dropdown-content){inset-inline-end:0;translate:0}.sm\:dropdown-end.dropdown-left{--anchor-h:left;--anchor-v:span-top}.sm\:dropdown-end.dropdown-left .dropdown-content{top:auto;bottom:0}.sm\:dropdown-end.dropdown-right{--anchor-h:right;--anchor-v:span-top}.sm\:dropdown-end.dropdown-right .dropdown-content{top:auto;bottom:0}.sm\:dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.sm\:dropdown-left .dropdown-content{transform-origin:100%;inset-inline-end:100%;top:0;bottom:auto}.sm\:dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.sm\:dropdown-right .dropdown-content{transform-origin:0;inset-inline-start:100%;top:0;bottom:auto}.sm\:dropdown-bottom{--anchor-v:bottom}.sm\:dropdown-bottom .dropdown-content{transform-origin:top;top:100%;bottom:auto}.sm\:dropdown-top{--anchor-v:top}.sm\:dropdown-top .dropdown-content{transform-origin:bottom;top:auto;bottom:100%}}@media (min-width:768px){.md\:dropdown{position-area:var(--anchor-v,bottom)var(--anchor-h,span-right);display:inline-block;position:relative}.md\:dropdown>:not(summary):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:dropdown>:not(summary):focus{outline-offset:2px;outline:2px solid transparent}}.md\:dropdown .dropdown-content{position:absolute}.md\:dropdown:not(:is(details,.dropdown-open,.dropdown-hover:hover,:focus-within)) .dropdown-content{transform-origin:top;opacity:0;display:none;scale:95%}.md\:dropdown[popover]{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}.md\:dropdown .dropdown-content{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}@starting-style{.md\:dropdown[popover]{opacity:0;scale:95%}.md\:dropdown .dropdown-content{opacity:0;scale:95%}}.md\:dropdown.dropdown-open>[tabindex]:first-child{pointer-events:none}.md\:dropdown.dropdown-open .dropdown-content{opacity:1}.md\:dropdown:not(.dropdown-hover):focus>[tabindex]:first-child{pointer-events:none}.md\:dropdown:not(.dropdown-hover):focus .dropdown-content{opacity:1}.md\:dropdown:focus-within>[tabindex]:first-child{pointer-events:none}.md\:dropdown:focus-within .dropdown-content{opacity:1}.md\:dropdown.dropdown-hover:hover .dropdown-content{opacity:1;scale:100%}.md\:dropdown:is(details) summary::-webkit-details-marker{display:none}.md\:dropdown.dropdown-open .dropdown-content{scale:100%}.md\:dropdown:focus .dropdown-content{scale:100%}.md\:dropdown:focus-within .dropdown-content{scale:100%}.md\:dropdown:where([popover]){background:0 0}.md\:dropdown[popover]{color:inherit;position:fixed}@supports not (position-area:bottom){.md\:dropdown[popover]{margin:auto}.md\:dropdown[popover].dropdown-open:not(:popover-open){transform-origin:top;opacity:0;display:none;scale:95%}.md\:dropdown[popover]::backdrop{background-color:rgba(0,0,0,.3);background-color:lab(0% 0 0/.3)}}.md\:dropdown[popover]:not(:is(.dropdown-open,:popover-open)){transform-origin:top;opacity:0;display:none;scale:95%}.md\:dropdown-start{--anchor-h:span-right}.md\:dropdown-start :where(.dropdown-content){inset-inline-end:auto}.md\:dropdown-start.dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.md\:dropdown-start.dropdown-left .dropdown-content{top:0;bottom:auto}.md\:dropdown-start.dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.md\:dropdown-start.dropdown-right .dropdown-content{top:0;bottom:auto}.md\:dropdown-center{--anchor-h:center}.md\:dropdown-center :where(.dropdown-content){inset-inline-end:50%;translate:50%}.md\:dropdown-center.dropdown-left{--anchor-h:left;--anchor-v:center}.md\:dropdown-center.dropdown-left .dropdown-content{top:auto;bottom:50%;translate:0 50%}.md\:dropdown-center.dropdown-right{--anchor-h:right;--anchor-v:center}.md\:dropdown-center.dropdown-right .dropdown-content{top:auto;bottom:50%;translate:0 50%}.md\:dropdown-end{--anchor-h:span-left}.md\:dropdown-end :where(.dropdown-content){inset-inline-end:0;translate:0}.md\:dropdown-end.dropdown-left{--anchor-h:left;--anchor-v:span-top}.md\:dropdown-end.dropdown-left .dropdown-content{top:auto;bottom:0}.md\:dropdown-end.dropdown-right{--anchor-h:right;--anchor-v:span-top}.md\:dropdown-end.dropdown-right .dropdown-content{top:auto;bottom:0}.md\:dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.md\:dropdown-left .dropdown-content{transform-origin:100%;inset-inline-end:100%;top:0;bottom:auto}.md\:dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.md\:dropdown-right .dropdown-content{transform-origin:0;inset-inline-start:100%;top:0;bottom:auto}.md\:dropdown-bottom{--anchor-v:bottom}.md\:dropdown-bottom .dropdown-content{transform-origin:top;top:100%;bottom:auto}.md\:dropdown-top{--anchor-v:top}.md\:dropdown-top .dropdown-content{transform-origin:bottom;top:auto;bottom:100%}}@media (min-width:1024px){.lg\:dropdown{position-area:var(--anchor-v,bottom)var(--anchor-h,span-right);display:inline-block;position:relative}.lg\:dropdown>:not(summary):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:dropdown>:not(summary):focus{outline-offset:2px;outline:2px solid transparent}}.lg\:dropdown .dropdown-content{position:absolute}.lg\:dropdown:not(:is(details,.dropdown-open,.dropdown-hover:hover,:focus-within)) .dropdown-content{transform-origin:top;opacity:0;display:none;scale:95%}.lg\:dropdown[popover]{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}.lg\:dropdown .dropdown-content{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}@starting-style{.lg\:dropdown[popover]{opacity:0;scale:95%}.lg\:dropdown .dropdown-content{opacity:0;scale:95%}}.lg\:dropdown.dropdown-open>[tabindex]:first-child{pointer-events:none}.lg\:dropdown.dropdown-open .dropdown-content{opacity:1}.lg\:dropdown:not(.dropdown-hover):focus>[tabindex]:first-child{pointer-events:none}.lg\:dropdown:not(.dropdown-hover):focus .dropdown-content{opacity:1}.lg\:dropdown:focus-within>[tabindex]:first-child{pointer-events:none}.lg\:dropdown:focus-within .dropdown-content{opacity:1}.lg\:dropdown.dropdown-hover:hover .dropdown-content{opacity:1;scale:100%}.lg\:dropdown:is(details) summary::-webkit-details-marker{display:none}.lg\:dropdown.dropdown-open .dropdown-content{scale:100%}.lg\:dropdown:focus .dropdown-content{scale:100%}.lg\:dropdown:focus-within .dropdown-content{scale:100%}.lg\:dropdown:where([popover]){background:0 0}.lg\:dropdown[popover]{color:inherit;position:fixed}@supports not (position-area:bottom){.lg\:dropdown[popover]{margin:auto}.lg\:dropdown[popover].dropdown-open:not(:popover-open){transform-origin:top;opacity:0;display:none;scale:95%}.lg\:dropdown[popover]::backdrop{background-color:rgba(0,0,0,.3);background-color:lab(0% 0 0/.3)}}.lg\:dropdown[popover]:not(:is(.dropdown-open,:popover-open)){transform-origin:top;opacity:0;display:none;scale:95%}.lg\:dropdown-start{--anchor-h:span-right}.lg\:dropdown-start :where(.dropdown-content){inset-inline-end:auto}.lg\:dropdown-start.dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.lg\:dropdown-start.dropdown-left .dropdown-content{top:0;bottom:auto}.lg\:dropdown-start.dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.lg\:dropdown-start.dropdown-right .dropdown-content{top:0;bottom:auto}.lg\:dropdown-center{--anchor-h:center}.lg\:dropdown-center :where(.dropdown-content){inset-inline-end:50%;translate:50%}.lg\:dropdown-center.dropdown-left{--anchor-h:left;--anchor-v:center}.lg\:dropdown-center.dropdown-left .dropdown-content{top:auto;bottom:50%;translate:0 50%}.lg\:dropdown-center.dropdown-right{--anchor-h:right;--anchor-v:center}.lg\:dropdown-center.dropdown-right .dropdown-content{top:auto;bottom:50%;translate:0 50%}.lg\:dropdown-end{--anchor-h:span-left}.lg\:dropdown-end :where(.dropdown-content){inset-inline-end:0;translate:0}.lg\:dropdown-end.dropdown-left{--anchor-h:left;--anchor-v:span-top}.lg\:dropdown-end.dropdown-left .dropdown-content{top:auto;bottom:0}.lg\:dropdown-end.dropdown-right{--anchor-h:right;--anchor-v:span-top}.lg\:dropdown-end.dropdown-right .dropdown-content{top:auto;bottom:0}.lg\:dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.lg\:dropdown-left .dropdown-content{transform-origin:100%;inset-inline-end:100%;top:0;bottom:auto}.lg\:dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.lg\:dropdown-right .dropdown-content{transform-origin:0;inset-inline-start:100%;top:0;bottom:auto}.lg\:dropdown-bottom{--anchor-v:bottom}.lg\:dropdown-bottom .dropdown-content{transform-origin:top;top:100%;bottom:auto}.lg\:dropdown-top{--anchor-v:top}.lg\:dropdown-top .dropdown-content{transform-origin:bottom;top:auto;bottom:100%}}@media (min-width:1280px){.xl\:dropdown{position-area:var(--anchor-v,bottom)var(--anchor-h,span-right);display:inline-block;position:relative}.xl\:dropdown>:not(summary):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:dropdown>:not(summary):focus{outline-offset:2px;outline:2px solid transparent}}.xl\:dropdown .dropdown-content{position:absolute}.xl\:dropdown:not(:is(details,.dropdown-open,.dropdown-hover:hover,:focus-within)) .dropdown-content{transform-origin:top;opacity:0;display:none;scale:95%}.xl\:dropdown[popover]{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}.xl\:dropdown .dropdown-content{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}@starting-style{.xl\:dropdown[popover]{opacity:0;scale:95%}.xl\:dropdown .dropdown-content{opacity:0;scale:95%}}.xl\:dropdown.dropdown-open>[tabindex]:first-child{pointer-events:none}.xl\:dropdown.dropdown-open .dropdown-content{opacity:1}.xl\:dropdown:not(.dropdown-hover):focus>[tabindex]:first-child{pointer-events:none}.xl\:dropdown:not(.dropdown-hover):focus .dropdown-content{opacity:1}.xl\:dropdown:focus-within>[tabindex]:first-child{pointer-events:none}.xl\:dropdown:focus-within .dropdown-content{opacity:1}.xl\:dropdown.dropdown-hover:hover .dropdown-content{opacity:1;scale:100%}.xl\:dropdown:is(details) summary::-webkit-details-marker{display:none}.xl\:dropdown.dropdown-open .dropdown-content{scale:100%}.xl\:dropdown:focus .dropdown-content{scale:100%}.xl\:dropdown:focus-within .dropdown-content{scale:100%}.xl\:dropdown:where([popover]){background:0 0}.xl\:dropdown[popover]{color:inherit;position:fixed}@supports not (position-area:bottom){.xl\:dropdown[popover]{margin:auto}.xl\:dropdown[popover].dropdown-open:not(:popover-open){transform-origin:top;opacity:0;display:none;scale:95%}.xl\:dropdown[popover]::backdrop{background-color:rgba(0,0,0,.3);background-color:lab(0% 0 0/.3)}}.xl\:dropdown[popover]:not(:is(.dropdown-open,:popover-open)){transform-origin:top;opacity:0;display:none;scale:95%}.xl\:dropdown-start{--anchor-h:span-right}.xl\:dropdown-start :where(.dropdown-content){inset-inline-end:auto}.xl\:dropdown-start.dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.xl\:dropdown-start.dropdown-left .dropdown-content{top:0;bottom:auto}.xl\:dropdown-start.dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.xl\:dropdown-start.dropdown-right .dropdown-content{top:0;bottom:auto}.xl\:dropdown-center{--anchor-h:center}.xl\:dropdown-center :where(.dropdown-content){inset-inline-end:50%;translate:50%}.xl\:dropdown-center.dropdown-left{--anchor-h:left;--anchor-v:center}.xl\:dropdown-center.dropdown-left .dropdown-content{top:auto;bottom:50%;translate:0 50%}.xl\:dropdown-center.dropdown-right{--anchor-h:right;--anchor-v:center}.xl\:dropdown-center.dropdown-right .dropdown-content{top:auto;bottom:50%;translate:0 50%}.xl\:dropdown-end{--anchor-h:span-left}.xl\:dropdown-end :where(.dropdown-content){inset-inline-end:0;translate:0}.xl\:dropdown-end.dropdown-left{--anchor-h:left;--anchor-v:span-top}.xl\:dropdown-end.dropdown-left .dropdown-content{top:auto;bottom:0}.xl\:dropdown-end.dropdown-right{--anchor-h:right;--anchor-v:span-top}.xl\:dropdown-end.dropdown-right .dropdown-content{top:auto;bottom:0}.xl\:dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.xl\:dropdown-left .dropdown-content{transform-origin:100%;inset-inline-end:100%;top:0;bottom:auto}.xl\:dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.xl\:dropdown-right .dropdown-content{transform-origin:0;inset-inline-start:100%;top:0;bottom:auto}.xl\:dropdown-bottom{--anchor-v:bottom}.xl\:dropdown-bottom .dropdown-content{transform-origin:top;top:100%;bottom:auto}.xl\:dropdown-top{--anchor-v:top}.xl\:dropdown-top .dropdown-content{transform-origin:bottom;top:auto;bottom:100%}}@media (min-width:1536px){.\32 xl\:dropdown{position-area:var(--anchor-v,bottom)var(--anchor-h,span-right);display:inline-block;position:relative}.\32 xl\:dropdown>:not(summary):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:dropdown>:not(summary):focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:dropdown .dropdown-content{position:absolute}.\32 xl\:dropdown:not(:is(details,.dropdown-open,.dropdown-hover:hover,:focus-within)) .dropdown-content{transform-origin:top;opacity:0;display:none;scale:95%}.\32 xl\:dropdown[popover]{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}.\32 xl\:dropdown .dropdown-content{z-index:999;transition-behavior:allow-discrete;transition-property:opacity,scale,display;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}@starting-style{.\32 xl\:dropdown[popover]{opacity:0;scale:95%}.\32 xl\:dropdown .dropdown-content{opacity:0;scale:95%}}.\32 xl\:dropdown.dropdown-open>[tabindex]:first-child{pointer-events:none}.\32 xl\:dropdown.dropdown-open .dropdown-content{opacity:1}.\32 xl\:dropdown:not(.dropdown-hover):focus>[tabindex]:first-child{pointer-events:none}.\32 xl\:dropdown:not(.dropdown-hover):focus .dropdown-content{opacity:1}.\32 xl\:dropdown:focus-within>[tabindex]:first-child{pointer-events:none}.\32 xl\:dropdown:focus-within .dropdown-content{opacity:1}.\32 xl\:dropdown.dropdown-hover:hover .dropdown-content{opacity:1;scale:100%}.\32 xl\:dropdown:is(details) summary::-webkit-details-marker{display:none}.\32 xl\:dropdown.dropdown-open .dropdown-content{scale:100%}.\32 xl\:dropdown:focus .dropdown-content{scale:100%}.\32 xl\:dropdown:focus-within .dropdown-content{scale:100%}.\32 xl\:dropdown:where([popover]){background:0 0}.\32 xl\:dropdown[popover]{color:inherit;position:fixed}@supports not (position-area:bottom){.\32 xl\:dropdown[popover]{margin:auto}.\32 xl\:dropdown[popover].dropdown-open:not(:popover-open){transform-origin:top;opacity:0;display:none;scale:95%}.\32 xl\:dropdown[popover]::backdrop{background-color:rgba(0,0,0,.3);background-color:lab(0% 0 0/.3)}}.\32 xl\:dropdown[popover]:not(:is(.dropdown-open,:popover-open)){transform-origin:top;opacity:0;display:none;scale:95%}.\32 xl\:dropdown-start{--anchor-h:span-right}.\32 xl\:dropdown-start :where(.dropdown-content){inset-inline-end:auto}.\32 xl\:dropdown-start.dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.\32 xl\:dropdown-start.dropdown-left .dropdown-content{top:0;bottom:auto}.\32 xl\:dropdown-start.dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.\32 xl\:dropdown-start.dropdown-right .dropdown-content{top:0;bottom:auto}.\32 xl\:dropdown-center{--anchor-h:center}.\32 xl\:dropdown-center :where(.dropdown-content){inset-inline-end:50%;translate:50%}.\32 xl\:dropdown-center.dropdown-left{--anchor-h:left;--anchor-v:center}.\32 xl\:dropdown-center.dropdown-left .dropdown-content{top:auto;bottom:50%;translate:0 50%}.\32 xl\:dropdown-center.dropdown-right{--anchor-h:right;--anchor-v:center}.\32 xl\:dropdown-center.dropdown-right .dropdown-content{top:auto;bottom:50%;translate:0 50%}.\32 xl\:dropdown-end{--anchor-h:span-left}.\32 xl\:dropdown-end :where(.dropdown-content){inset-inline-end:0;translate:0}.\32 xl\:dropdown-end.dropdown-left{--anchor-h:left;--anchor-v:span-top}.\32 xl\:dropdown-end.dropdown-left .dropdown-content{top:auto;bottom:0}.\32 xl\:dropdown-end.dropdown-right{--anchor-h:right;--anchor-v:span-top}.\32 xl\:dropdown-end.dropdown-right .dropdown-content{top:auto;bottom:0}.\32 xl\:dropdown-left{--anchor-h:left;--anchor-v:span-bottom}.\32 xl\:dropdown-left .dropdown-content{transform-origin:100%;inset-inline-end:100%;top:0;bottom:auto}.\32 xl\:dropdown-right{--anchor-h:right;--anchor-v:span-bottom}.\32 xl\:dropdown-right .dropdown-content{transform-origin:0;inset-inline-start:100%;top:0;bottom:auto}.\32 xl\:dropdown-bottom{--anchor-v:bottom}.\32 xl\:dropdown-bottom .dropdown-content{transform-origin:top;top:100%;bottom:auto}.\32 xl\:dropdown-top{--anchor-v:top}.\32 xl\:dropdown-top .dropdown-content{transform-origin:bottom;top:auto;bottom:100%}}.cally{font-size:.7rem}.cally::part(container){-webkit-user-select:none;user-select:none;padding:.5rem 1rem}.cally ::part(th){block-size:auto;font-weight:400}.cally::part(header){direction:ltr}.cally ::part(head){opacity:.5;font-size:.7rem}.cally::part(button){border-radius:var(--radius-field);background:0 0;border:none;padding:.5rem}.cally::part(button):hover{background:var(--color-base-200)}.cally ::part(day){border-radius:var(--radius-field);font-size:.7rem}.cally ::part(button day today){background:var(--color-primary);color:var(--color-primary-content)}.cally ::part(selected){color:var(--color-base-100);background:var(--color-base-content);border-radius:var(--radius-field)}.cally ::part(range-inner){border-radius:0}.cally ::part(range-start){border-start-end-radius:0;border-end-end-radius:0}.cally ::part(range-end){border-start-start-radius:0;border-end-start-radius:0}.cally ::part(range-start range-end){border-radius:var(--radius-field)}.cally calendar-month{width:100%}.react-day-picker{-webkit-user-select:none;user-select:none;background-color:var(--color-base-100);border-radius:var(--radius-box);border:var(--border)solid var(--color-base-200);font-size:.75rem;display:inline-block;position:relative;overflow:clip}.react-day-picker[dir=rtl] .rdp-nav .rdp-chevron{transform-origin:50%;transform:rotate(180deg)}.react-day-picker *{box-sizing:border-box}.react-day-picker .rdp-day{text-align:center;width:2.25rem;height:2.25rem}.react-day-picker .rdp-day_button{cursor:pointer;font:inherit;color:inherit;border-radius:var(--radius-field);background:0 0;border:2px solid transparent;justify-content:center;align-items:center;width:2.25rem;height:2.25rem;margin:0;padding:0;display:flex}.react-day-picker .rdp-day_button:disabled{cursor:revert}.react-day-picker .rdp-day_button:hover{background-color:var(--color-base-200)}.react-day-picker .rdp-caption_label{z-index:1;white-space:nowrap;border:0;align-items:center;display:inline-flex;position:relative}.react-day-picker .rdp-button_next{border-radius:var(--radius-field)}.react-day-picker .rdp-button_next:hover{background-color:var(--color-base-200)}.react-day-picker .rdp-button_previous{border-radius:var(--radius-field)}.react-day-picker .rdp-button_previous:hover{background-color:var(--color-base-200)}.react-day-picker .rdp-button_next{cursor:pointer;font:inherit;color:inherit;appearance:none;background:0 0;border:none;justify-content:center;align-items:center;width:2.25rem;height:2.25rem;margin:0;padding:0;display:inline-flex;position:relative}.react-day-picker .rdp-button_next:disabled{cursor:revert;opacity:.5}.react-day-picker .rdp-button_previous{cursor:pointer;font:inherit;color:inherit;appearance:none;background:0 0;border:none;justify-content:center;align-items:center;width:2.25rem;height:2.25rem;margin:0;padding:0;display:inline-flex;position:relative}.react-day-picker .rdp-button_previous:disabled{cursor:revert;opacity:.5}.react-day-picker .rdp-chevron{fill:var(--color-base-content);width:1rem;height:1rem;display:inline-block}.react-day-picker .rdp-dropdowns{align-items:center;gap:.5rem;display:inline-flex;position:relative}.react-day-picker .rdp-dropdown{z-index:2;opacity:0;appearance:none;cursor:inherit;line-height:inherit;border:none;width:100%;margin:0;padding:0;position:absolute;inset-block:0;inset-inline-start:0}.react-day-picker .rdp-dropdown:focus-visible~.rdp-caption_label{outline:5px auto highlight;outline:5px auto -webkit-focus-ring-color}.react-day-picker .rdp-dropdown_root{align-items:center;display:inline-flex;position:relative}.react-day-picker .rdp-dropdown_root[data-disabled=true] .rdp-chevron{opacity:.5}.react-day-picker .rdp-month_caption{height:2.75rem;font-size:.75rem;font-weight:inherit;place-content:center;display:flex}.react-day-picker .rdp-months{flex-wrap:wrap;gap:2rem;max-width:fit-content;padding:.5rem;display:flex;position:relative}.react-day-picker .rdp-month_grid{border-collapse:collapse}.react-day-picker .rdp-nav{inset-block-start:0;inset-inline-end:0;justify-content:space-between;align-items:center;width:100%;height:2.75rem;padding-inline:.5rem;display:flex;position:absolute;top:.25rem}.react-day-picker .rdp-weekday{opacity:.6;text-align:center;padding:.5rem 0;font-size:smaller;font-weight:500}.react-day-picker .rdp-week_number{opacity:.6;text-align:center;border:none;border-radius:100%;width:2.25rem;height:2.25rem;font-size:small;font-weight:400}.react-day-picker .rdp-today:not(.rdp-outside) .rdp-day_button{background:var(--color-primary);color:var(--color-primary-content)}.react-day-picker .rdp-selected{font-weight:inherit;font-size:.75rem}.react-day-picker .rdp-selected .rdp-day_button{color:var(--color-base-100);background-color:var(--color-base-content);border-radius:var(--radius-field);border:none}.react-day-picker .rdp-selected .rdp-day_button:hover{background-color:var(--color-base-content)}.react-day-picker .rdp-outside{opacity:.75}.react-day-picker .rdp-disabled{opacity:.5}.react-day-picker .rdp-hidden{visibility:hidden;color:var(--color-base-content)}.react-day-picker .rdp-range_start .rdp-day_button{border-radius:var(--radius-field)0 0 var(--radius-field)}.react-day-picker .rdp-range_start .rdp-day_button{background-color:var(--color-base-content);color:var(--color-base-content)}.react-day-picker .rdp-range_middle{background-color:var(--color-base-200)}.react-day-picker .rdp-range_middle .rdp-day_button{border:unset;border-radius:unset;color:inherit}.react-day-picker .rdp-range_end{color:var(--color-base-content)}.react-day-picker .rdp-range_end .rdp-day_button{border-radius:0 var(--radius-field)var(--radius-field)0}.react-day-picker .rdp-range_end .rdp-day_button{color:var(--color-base-content);background-color:var(--color-base-content)}.react-day-picker .rdp-range_start.rdp-range_end{background:revert}.react-day-picker .rdp-focusable{cursor:pointer}.react-day-picker .rdp-footer{border-top:var(--border)solid var(--color-base-200);padding:.5rem}.pika-single:is(div){-webkit-user-select:none;user-select:none;z-index:999;color:var(--color-base-content);background-color:var(--color-base-100);border-radius:var(--radius-box);border:var(--border)solid var(--color-base-200);padding:.5rem;font-size:.75rem;display:inline-block;position:relative}.pika-single:is(div):before{content:"";display:table}.pika-single:is(div):after{content:"";display:table}.pika-single:is(div):after{clear:both}.pika-single:is(div).is-hidden{display:none}.pika-single:is(div).is-bound{position:absolute}.pika-single:is(div) .pika-lendar{float:left}.pika-single:is(div) .pika-title{text-align:center;position:relative}.pika-single:is(div) .pika-label{z-index:999;background-color:var(--color-base-100);margin:0;padding:5px 3px;display:inline-block;position:relative;overflow:hidden}.pika-single:is(div) .pika-title select{cursor:pointer;z-index:999;opacity:0;margin:0;position:absolute;top:5px;left:0}.pika-single:is(div) .pika-prev{cursor:pointer;color:transparent;border-radius:var(--radius-field);border:0;outline:none;width:2.25rem;height:2.25rem;font-size:1.2em;display:block;position:absolute;top:0}.pika-single:is(div) .pika-prev:hover{background-color:var(--color-base-200)}.pika-single:is(div) .pika-prev.is-disabled{cursor:default;opacity:.2}.pika-single:is(div) .pika-prev:before{width:2.25rem;height:2.25rem;color:var(--color-base-content);line-height:2.25;display:inline-block}.pika-single:is(div) .pika-next{cursor:pointer;color:transparent;border-radius:var(--radius-field);border:0;outline:none;width:2.25rem;height:2.25rem;font-size:1.2em;display:block;position:absolute;top:0}.pika-single:is(div) .pika-next:hover{background-color:var(--color-base-200)}.pika-single:is(div) .pika-next.is-disabled{cursor:default;opacity:.2}.pika-single:is(div) .pika-next:before{width:2.25rem;height:2.25rem;color:var(--color-base-content);line-height:2.25;display:inline-block}.pika-single:is(div) .pika-prev{left:0}.pika-single:is(div) .pika-prev:before{content:"‹"}.pika-single:is(div) .pika-next{right:0}.pika-single:is(div) .pika-next:before{content:"›"}.pika-single:is(div) .pika-select{display:inline-block}.pika-single:is(div) .pika-table{border-collapse:collapse;border-spacing:0;border:0;width:100%}.pika-single:is(div) .pika-table th{padding:0}.pika-single:is(div) .pika-table td{padding:0}.pika-single:is(div) .pika-table th{opacity:.6;text-align:center;width:2.25rem;height:2.25rem}.pika-single:is(div) .pika-button{cursor:pointer;text-align:right;text-align:center;border:0;outline:none;width:2.25rem;height:2.25rem;margin:0;padding:5px;display:block}.pika-single:is(div) .pika-week{color:var(--color-base-content)}.pika-single:is(div) .is-today .pika-button{background:var(--color-primary);color:var(--color-primary-content)}.pika-single:is(div) .is-selected .pika-button{color:var(--color-base-100);background-color:var(--color-base-content);border-radius:var(--radius-field)}.pika-single:is(div) .is-selected .pika-button:hover{color:var(--color-base-100);background-color:var(--color-base-content);border-radius:var(--radius-field)}.pika-single:is(div) .has-event .pika-button{color:var(--color-base-100);background-color:var(--color-base-content);border-radius:var(--radius-field)}.pika-single:is(div) .has-event .pika-button:hover{color:var(--color-base-100);background-color:var(--color-base-content);border-radius:var(--radius-field)}.pika-single:is(div) .has-event .pika-button{background:var(--color-base-primary)}.pika-single:is(div) .is-disabled .pika-button{background:var(--color-base-primary)}.pika-single:is(div) .is-inrange .pika-button{background:var(--color-base-primary)}.pika-single:is(div) .is-startrange .pika-button{color:var(--color-base-100);background:var(--color-base-content);border-radius:var(--radius-field)}.pika-single:is(div) .is-endrange .pika-button{color:var(--color-base-100);background:var(--color-base-content);border-radius:var(--radius-field)}.pika-single:is(div) .is-disabled .pika-button{pointer-events:none;cursor:default;color:var(--color-base-content);opacity:.3}.pika-single:is(div) .is-outside-current-month .pika-button{color:var(--color-base-content);opacity:.3}.pika-single:is(div) .is-selection-disabled{pointer-events:none;cursor:default}.pika-single:is(div) .pika-button:hover{color:var(--color-base-content);background-color:var(--color-base-200);border-radius:var(--radius-field)}.pika-single:is(div) .pika-row.pick-whole-week:hover .pika-button{color:var(--color-base-content);background-color:var(--color-base-200);border-radius:var(--radius-field)}.pika-single:is(div) .pika-table abbr{font-weight:400;text-decoration:none}.card{border-radius:var(--radius-box);outline-offset:2px;outline:0 solid transparent;flex-direction:column;transition:outline .2s ease-in-out;display:flex;position:relative}.card:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.card:focus{outline-offset:2px;outline:2px solid transparent}}.card:focus-visible{outline-color:currentColor}.card :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-end-radius:unset;border-end-start-radius:unset;overflow:hidden}.card :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:unset;border-end-end-radius:inherit;border-end-start-radius:inherit;overflow:hidden}.card:where(.card-border){border:var(--border)solid var(--color-base-200)}.card:where(.card-dash){border:var(--border)dashed var(--color-base-200)}.card.image-full{display:grid}.card.image-full>*{grid-row-start:1;grid-column-start:1}.card.image-full>.card-body{color:var(--color-neutral-content);position:relative}.card.image-full :where(figure){border-radius:inherit;overflow:hidden}.card.image-full>figure img{object-fit:cover;filter:brightness(28%);height:100%}.card figure{justify-content:center;align-items:center;display:flex}.card:has(>input:is(input[type=checkbox],input[type=radio])){cursor:pointer;-webkit-user-select:none;user-select:none}.card:has(>:checked){outline:2px solid}.card-title{font-size:var(--cardtitle-fs,1.125rem);align-items:center;gap:.5rem;font-weight:600;display:flex}.card-body{padding:var(--card-p,1.5rem);font-size:var(--card-fs,.875rem);flex-direction:column;flex:auto;gap:.5rem;display:flex}.card-body :where(p){flex-grow:1}.card-actions{flex-wrap:wrap;align-items:flex-start;gap:.5rem;display:flex}.card-xs .card-body{--card-p:.5rem;--card-fs:.6875rem}.card-xs .card-title{--cardtitle-fs:.875rem}.card-sm .card-body{--card-p:1rem;--card-fs:.75rem}.card-sm .card-title{--cardtitle-fs:1rem}.card-md .card-body{--card-p:1.5rem;--card-fs:.875rem}.card-md .card-title{--cardtitle-fs:1.125rem}.card-lg .card-body{--card-p:2rem;--card-fs:1rem}.card-lg .card-title{--cardtitle-fs:1.25rem}.card-xl .card-body{--card-p:2.5rem;--card-fs:1.125rem}.card-xl .card-title{--cardtitle-fs:1.375rem}.card-side{flex-direction:row;align-items:stretch}.card-side :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:unset;border-end-end-radius:unset;border-end-start-radius:inherit;overflow:hidden}.card-side :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:inherit;border-end-end-radius:inherit;border-end-start-radius:unset;overflow:hidden}.card-side figure>*{max-width:unset}.card-side :where(figure>*){object-fit:cover;width:100%;height:100%}@media (min-width:640px){.sm\:card{border-radius:var(--radius-box);outline-offset:2px;outline:0 solid transparent;flex-direction:column;transition:outline .2s ease-in-out;display:flex;position:relative}.sm\:card:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:card:focus{outline-offset:2px;outline:2px solid transparent}}.sm\:card:focus-visible{outline-color:currentColor}.sm\:card :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-end-radius:unset;border-end-start-radius:unset;overflow:hidden}.sm\:card :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:unset;border-end-end-radius:inherit;border-end-start-radius:inherit;overflow:hidden}.sm\:card:where(.card-border){border:var(--border)solid var(--color-base-200)}.sm\:card:where(.card-dash){border:var(--border)dashed var(--color-base-200)}.sm\:card.image-full{display:grid}.sm\:card.image-full>*{grid-row-start:1;grid-column-start:1}.sm\:card.image-full>.card-body{color:var(--color-neutral-content);position:relative}.sm\:card.image-full :where(figure){border-radius:inherit;overflow:hidden}.sm\:card.image-full>figure img{object-fit:cover;filter:brightness(28%);height:100%}.sm\:card figure{justify-content:center;align-items:center;display:flex}.sm\:card:has(>input:is(input[type=checkbox],input[type=radio])){cursor:pointer;-webkit-user-select:none;user-select:none}.sm\:card:has(>:checked){outline:2px solid}.sm\:card-title{font-size:var(--cardtitle-fs,1.125rem);align-items:center;gap:.5rem;font-weight:600;display:flex}.sm\:card-body{padding:var(--card-p,1.5rem);font-size:var(--card-fs,.875rem);flex-direction:column;flex:auto;gap:.5rem;display:flex}.sm\:card-body :where(p){flex-grow:1}.sm\:card-actions{flex-wrap:wrap;align-items:flex-start;gap:.5rem;display:flex}.sm\:card-xs .card-body{--card-p:.5rem;--card-fs:.6875rem}.sm\:card-xs .card-title{--cardtitle-fs:.875rem}.sm\:card-sm .card-body{--card-p:1rem;--card-fs:.75rem}.sm\:card-sm .card-title{--cardtitle-fs:1rem}.sm\:card-md .card-body{--card-p:1.5rem;--card-fs:.875rem}.sm\:card-md .card-title{--cardtitle-fs:1.125rem}.sm\:card-lg .card-body{--card-p:2rem;--card-fs:1rem}.sm\:card-lg .card-title{--cardtitle-fs:1.25rem}.sm\:card-xl .card-body{--card-p:2.5rem;--card-fs:1.125rem}.sm\:card-xl .card-title{--cardtitle-fs:1.375rem}.sm\:card-side{flex-direction:row;align-items:stretch}.sm\:card-side :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:unset;border-end-end-radius:unset;border-end-start-radius:inherit;overflow:hidden}.sm\:card-side :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:inherit;border-end-end-radius:inherit;border-end-start-radius:unset;overflow:hidden}.sm\:card-side figure>*{max-width:unset}.sm\:card-side :where(figure>*){object-fit:cover;width:100%;height:100%}}@media (min-width:768px){.md\:card{border-radius:var(--radius-box);outline-offset:2px;outline:0 solid transparent;flex-direction:column;transition:outline .2s ease-in-out;display:flex;position:relative}.md\:card:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:card:focus{outline-offset:2px;outline:2px solid transparent}}.md\:card:focus-visible{outline-color:currentColor}.md\:card :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-end-radius:unset;border-end-start-radius:unset;overflow:hidden}.md\:card :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:unset;border-end-end-radius:inherit;border-end-start-radius:inherit;overflow:hidden}.md\:card:where(.card-border){border:var(--border)solid var(--color-base-200)}.md\:card:where(.card-dash){border:var(--border)dashed var(--color-base-200)}.md\:card.image-full{display:grid}.md\:card.image-full>*{grid-row-start:1;grid-column-start:1}.md\:card.image-full>.card-body{color:var(--color-neutral-content);position:relative}.md\:card.image-full :where(figure){border-radius:inherit;overflow:hidden}.md\:card.image-full>figure img{object-fit:cover;filter:brightness(28%);height:100%}.md\:card figure{justify-content:center;align-items:center;display:flex}.md\:card:has(>input:is(input[type=checkbox],input[type=radio])){cursor:pointer;-webkit-user-select:none;user-select:none}.md\:card:has(>:checked){outline:2px solid}.md\:card-title{font-size:var(--cardtitle-fs,1.125rem);align-items:center;gap:.5rem;font-weight:600;display:flex}.md\:card-body{padding:var(--card-p,1.5rem);font-size:var(--card-fs,.875rem);flex-direction:column;flex:auto;gap:.5rem;display:flex}.md\:card-body :where(p){flex-grow:1}.md\:card-actions{flex-wrap:wrap;align-items:flex-start;gap:.5rem;display:flex}.md\:card-xs .card-body{--card-p:.5rem;--card-fs:.6875rem}.md\:card-xs .card-title{--cardtitle-fs:.875rem}.md\:card-sm .card-body{--card-p:1rem;--card-fs:.75rem}.md\:card-sm .card-title{--cardtitle-fs:1rem}.md\:card-md .card-body{--card-p:1.5rem;--card-fs:.875rem}.md\:card-md .card-title{--cardtitle-fs:1.125rem}.md\:card-lg .card-body{--card-p:2rem;--card-fs:1rem}.md\:card-lg .card-title{--cardtitle-fs:1.25rem}.md\:card-xl .card-body{--card-p:2.5rem;--card-fs:1.125rem}.md\:card-xl .card-title{--cardtitle-fs:1.375rem}.md\:card-side{flex-direction:row;align-items:stretch}.md\:card-side :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:unset;border-end-end-radius:unset;border-end-start-radius:inherit;overflow:hidden}.md\:card-side :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:inherit;border-end-end-radius:inherit;border-end-start-radius:unset;overflow:hidden}.md\:card-side figure>*{max-width:unset}.md\:card-side :where(figure>*){object-fit:cover;width:100%;height:100%}}@media (min-width:1024px){.lg\:card{border-radius:var(--radius-box);outline-offset:2px;outline:0 solid transparent;flex-direction:column;transition:outline .2s ease-in-out;display:flex;position:relative}.lg\:card:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:card:focus{outline-offset:2px;outline:2px solid transparent}}.lg\:card:focus-visible{outline-color:currentColor}.lg\:card :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-end-radius:unset;border-end-start-radius:unset;overflow:hidden}.lg\:card :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:unset;border-end-end-radius:inherit;border-end-start-radius:inherit;overflow:hidden}.lg\:card:where(.card-border){border:var(--border)solid var(--color-base-200)}.lg\:card:where(.card-dash){border:var(--border)dashed var(--color-base-200)}.lg\:card.image-full{display:grid}.lg\:card.image-full>*{grid-row-start:1;grid-column-start:1}.lg\:card.image-full>.card-body{color:var(--color-neutral-content);position:relative}.lg\:card.image-full :where(figure){border-radius:inherit;overflow:hidden}.lg\:card.image-full>figure img{object-fit:cover;filter:brightness(28%);height:100%}.lg\:card figure{justify-content:center;align-items:center;display:flex}.lg\:card:has(>input:is(input[type=checkbox],input[type=radio])){cursor:pointer;-webkit-user-select:none;user-select:none}.lg\:card:has(>:checked){outline:2px solid}.lg\:card-title{font-size:var(--cardtitle-fs,1.125rem);align-items:center;gap:.5rem;font-weight:600;display:flex}.lg\:card-body{padding:var(--card-p,1.5rem);font-size:var(--card-fs,.875rem);flex-direction:column;flex:auto;gap:.5rem;display:flex}.lg\:card-body :where(p){flex-grow:1}.lg\:card-actions{flex-wrap:wrap;align-items:flex-start;gap:.5rem;display:flex}.lg\:card-xs .card-body{--card-p:.5rem;--card-fs:.6875rem}.lg\:card-xs .card-title{--cardtitle-fs:.875rem}.lg\:card-sm .card-body{--card-p:1rem;--card-fs:.75rem}.lg\:card-sm .card-title{--cardtitle-fs:1rem}.lg\:card-md .card-body{--card-p:1.5rem;--card-fs:.875rem}.lg\:card-md .card-title{--cardtitle-fs:1.125rem}.lg\:card-lg .card-body{--card-p:2rem;--card-fs:1rem}.lg\:card-lg .card-title{--cardtitle-fs:1.25rem}.lg\:card-xl .card-body{--card-p:2.5rem;--card-fs:1.125rem}.lg\:card-xl .card-title{--cardtitle-fs:1.375rem}.lg\:card-side{flex-direction:row;align-items:stretch}.lg\:card-side :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:unset;border-end-end-radius:unset;border-end-start-radius:inherit;overflow:hidden}.lg\:card-side :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:inherit;border-end-end-radius:inherit;border-end-start-radius:unset;overflow:hidden}.lg\:card-side figure>*{max-width:unset}.lg\:card-side :where(figure>*){object-fit:cover;width:100%;height:100%}}@media (min-width:1280px){.xl\:card{border-radius:var(--radius-box);outline-offset:2px;outline:0 solid transparent;flex-direction:column;transition:outline .2s ease-in-out;display:flex;position:relative}.xl\:card:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:card:focus{outline-offset:2px;outline:2px solid transparent}}.xl\:card:focus-visible{outline-color:currentColor}.xl\:card :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-end-radius:unset;border-end-start-radius:unset;overflow:hidden}.xl\:card :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:unset;border-end-end-radius:inherit;border-end-start-radius:inherit;overflow:hidden}.xl\:card:where(.card-border){border:var(--border)solid var(--color-base-200)}.xl\:card:where(.card-dash){border:var(--border)dashed var(--color-base-200)}.xl\:card.image-full{display:grid}.xl\:card.image-full>*{grid-row-start:1;grid-column-start:1}.xl\:card.image-full>.card-body{color:var(--color-neutral-content);position:relative}.xl\:card.image-full :where(figure){border-radius:inherit;overflow:hidden}.xl\:card.image-full>figure img{object-fit:cover;filter:brightness(28%);height:100%}.xl\:card figure{justify-content:center;align-items:center;display:flex}.xl\:card:has(>input:is(input[type=checkbox],input[type=radio])){cursor:pointer;-webkit-user-select:none;user-select:none}.xl\:card:has(>:checked){outline:2px solid}.xl\:card-title{font-size:var(--cardtitle-fs,1.125rem);align-items:center;gap:.5rem;font-weight:600;display:flex}.xl\:card-body{padding:var(--card-p,1.5rem);font-size:var(--card-fs,.875rem);flex-direction:column;flex:auto;gap:.5rem;display:flex}.xl\:card-body :where(p){flex-grow:1}.xl\:card-actions{flex-wrap:wrap;align-items:flex-start;gap:.5rem;display:flex}.xl\:card-xs .card-body{--card-p:.5rem;--card-fs:.6875rem}.xl\:card-xs .card-title{--cardtitle-fs:.875rem}.xl\:card-sm .card-body{--card-p:1rem;--card-fs:.75rem}.xl\:card-sm .card-title{--cardtitle-fs:1rem}.xl\:card-md .card-body{--card-p:1.5rem;--card-fs:.875rem}.xl\:card-md .card-title{--cardtitle-fs:1.125rem}.xl\:card-lg .card-body{--card-p:2rem;--card-fs:1rem}.xl\:card-lg .card-title{--cardtitle-fs:1.25rem}.xl\:card-xl .card-body{--card-p:2.5rem;--card-fs:1.125rem}.xl\:card-xl .card-title{--cardtitle-fs:1.375rem}.xl\:card-side{flex-direction:row;align-items:stretch}.xl\:card-side :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:unset;border-end-end-radius:unset;border-end-start-radius:inherit;overflow:hidden}.xl\:card-side :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:inherit;border-end-end-radius:inherit;border-end-start-radius:unset;overflow:hidden}.xl\:card-side figure>*{max-width:unset}.xl\:card-side :where(figure>*){object-fit:cover;width:100%;height:100%}}@media (min-width:1536px){.\32 xl\:card{border-radius:var(--radius-box);outline-offset:2px;outline:0 solid transparent;flex-direction:column;transition:outline .2s ease-in-out;display:flex;position:relative}.\32 xl\:card:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:card:focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:card:focus-visible{outline-color:currentColor}.\32 xl\:card :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-end-radius:unset;border-end-start-radius:unset;overflow:hidden}.\32 xl\:card :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:unset;border-end-end-radius:inherit;border-end-start-radius:inherit;overflow:hidden}.\32 xl\:card:where(.card-border){border:var(--border)solid var(--color-base-200)}.\32 xl\:card:where(.card-dash){border:var(--border)dashed var(--color-base-200)}.\32 xl\:card.image-full{display:grid}.\32 xl\:card.image-full>*{grid-row-start:1;grid-column-start:1}.\32 xl\:card.image-full>.card-body{color:var(--color-neutral-content);position:relative}.\32 xl\:card.image-full :where(figure){border-radius:inherit;overflow:hidden}.\32 xl\:card.image-full>figure img{object-fit:cover;filter:brightness(28%);height:100%}.\32 xl\:card figure{justify-content:center;align-items:center;display:flex}.\32 xl\:card:has(>input:is(input[type=checkbox],input[type=radio])){cursor:pointer;-webkit-user-select:none;user-select:none}.\32 xl\:card:has(>:checked){outline:2px solid}.\32 xl\:card-title{font-size:var(--cardtitle-fs,1.125rem);align-items:center;gap:.5rem;font-weight:600;display:flex}.\32 xl\:card-body{padding:var(--card-p,1.5rem);font-size:var(--card-fs,.875rem);flex-direction:column;flex:auto;gap:.5rem;display:flex}.\32 xl\:card-body :where(p){flex-grow:1}.\32 xl\:card-actions{flex-wrap:wrap;align-items:flex-start;gap:.5rem;display:flex}.\32 xl\:card-xs .card-body{--card-p:.5rem;--card-fs:.6875rem}.\32 xl\:card-xs .card-title{--cardtitle-fs:.875rem}.\32 xl\:card-sm .card-body{--card-p:1rem;--card-fs:.75rem}.\32 xl\:card-sm .card-title{--cardtitle-fs:1rem}.\32 xl\:card-md .card-body{--card-p:1.5rem;--card-fs:.875rem}.\32 xl\:card-md .card-title{--cardtitle-fs:1.125rem}.\32 xl\:card-lg .card-body{--card-p:2rem;--card-fs:1rem}.\32 xl\:card-lg .card-title{--cardtitle-fs:1.25rem}.\32 xl\:card-xl .card-body{--card-p:2.5rem;--card-fs:1.125rem}.\32 xl\:card-xl .card-title{--cardtitle-fs:1.375rem}.\32 xl\:card-side{flex-direction:row;align-items:stretch}.\32 xl\:card-side :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:unset;border-end-end-radius:unset;border-end-start-radius:inherit;overflow:hidden}.\32 xl\:card-side :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:inherit;border-end-end-radius:inherit;border-end-start-radius:unset;overflow:hidden}.\32 xl\:card-side figure>*{max-width:unset}.\32 xl\:card-side :where(figure>*){object-fit:cover;width:100%;height:100%}}.indicator{width:max-content;display:inline-flex;position:relative}.indicator :where(.indicator-item){z-index:1;white-space:nowrap;top:var(--inidicator-t,0);bottom:var(--inidicator-b,auto);left:var(--inidicator-s,auto);right:var(--inidicator-e,0);translate:var(--inidicator-x,50%)var(--indicator-y,-50%);position:absolute}.indicator-start{--inidicator-s:0;--inidicator-e:auto;--inidicator-x:-50%}.indicator-center{--inidicator-s:50%;--inidicator-e:50%;--inidicator-x:-50%}[dir=rtl] .indicator-center{--inidicator-x:50%}.indicator-end{--inidicator-s:auto;--inidicator-e:0;--inidicator-x:50%}.indicator-bottom{--inidicator-t:auto;--inidicator-b:0;--indicator-y:50%}.indicator-middle{--inidicator-t:50%;--inidicator-b:50%;--indicator-y:-50%}.indicator-top{--inidicator-t:0;--inidicator-b:auto;--indicator-y:-50%}@media (min-width:640px){.sm\:indicator{width:max-content;display:inline-flex;position:relative}.sm\:indicator :where(.indicator-item){z-index:1;white-space:nowrap;top:var(--inidicator-t,0);bottom:var(--inidicator-b,auto);left:var(--inidicator-s,auto);right:var(--inidicator-e,0);translate:var(--inidicator-x,50%)var(--indicator-y,-50%);position:absolute}.sm\:indicator-start{--inidicator-s:0;--inidicator-e:auto;--inidicator-x:-50%}.sm\:indicator-center{--inidicator-s:50%;--inidicator-e:50%;--inidicator-x:-50%}[dir=rtl] .sm\:indicator-center{--inidicator-x:50%}.sm\:indicator-end{--inidicator-s:auto;--inidicator-e:0;--inidicator-x:50%}.sm\:indicator-bottom{--inidicator-t:auto;--inidicator-b:0;--indicator-y:50%}.sm\:indicator-middle{--inidicator-t:50%;--inidicator-b:50%;--indicator-y:-50%}.sm\:indicator-top{--inidicator-t:0;--inidicator-b:auto;--indicator-y:-50%}}@media (min-width:768px){.md\:indicator{width:max-content;display:inline-flex;position:relative}.md\:indicator :where(.indicator-item){z-index:1;white-space:nowrap;top:var(--inidicator-t,0);bottom:var(--inidicator-b,auto);left:var(--inidicator-s,auto);right:var(--inidicator-e,0);translate:var(--inidicator-x,50%)var(--indicator-y,-50%);position:absolute}.md\:indicator-start{--inidicator-s:0;--inidicator-e:auto;--inidicator-x:-50%}.md\:indicator-center{--inidicator-s:50%;--inidicator-e:50%;--inidicator-x:-50%}[dir=rtl] .md\:indicator-center{--inidicator-x:50%}.md\:indicator-end{--inidicator-s:auto;--inidicator-e:0;--inidicator-x:50%}.md\:indicator-bottom{--inidicator-t:auto;--inidicator-b:0;--indicator-y:50%}.md\:indicator-middle{--inidicator-t:50%;--inidicator-b:50%;--indicator-y:-50%}.md\:indicator-top{--inidicator-t:0;--inidicator-b:auto;--indicator-y:-50%}}@media (min-width:1024px){.lg\:indicator{width:max-content;display:inline-flex;position:relative}.lg\:indicator :where(.indicator-item){z-index:1;white-space:nowrap;top:var(--inidicator-t,0);bottom:var(--inidicator-b,auto);left:var(--inidicator-s,auto);right:var(--inidicator-e,0);translate:var(--inidicator-x,50%)var(--indicator-y,-50%);position:absolute}.lg\:indicator-start{--inidicator-s:0;--inidicator-e:auto;--inidicator-x:-50%}.lg\:indicator-center{--inidicator-s:50%;--inidicator-e:50%;--inidicator-x:-50%}[dir=rtl] .lg\:indicator-center{--inidicator-x:50%}.lg\:indicator-end{--inidicator-s:auto;--inidicator-e:0;--inidicator-x:50%}.lg\:indicator-bottom{--inidicator-t:auto;--inidicator-b:0;--indicator-y:50%}.lg\:indicator-middle{--inidicator-t:50%;--inidicator-b:50%;--indicator-y:-50%}.lg\:indicator-top{--inidicator-t:0;--inidicator-b:auto;--indicator-y:-50%}}@media (min-width:1280px){.xl\:indicator{width:max-content;display:inline-flex;position:relative}.xl\:indicator :where(.indicator-item){z-index:1;white-space:nowrap;top:var(--inidicator-t,0);bottom:var(--inidicator-b,auto);left:var(--inidicator-s,auto);right:var(--inidicator-e,0);translate:var(--inidicator-x,50%)var(--indicator-y,-50%);position:absolute}.xl\:indicator-start{--inidicator-s:0;--inidicator-e:auto;--inidicator-x:-50%}.xl\:indicator-center{--inidicator-s:50%;--inidicator-e:50%;--inidicator-x:-50%}[dir=rtl] .xl\:indicator-center{--inidicator-x:50%}.xl\:indicator-end{--inidicator-s:auto;--inidicator-e:0;--inidicator-x:50%}.xl\:indicator-bottom{--inidicator-t:auto;--inidicator-b:0;--indicator-y:50%}.xl\:indicator-middle{--inidicator-t:50%;--inidicator-b:50%;--indicator-y:-50%}.xl\:indicator-top{--inidicator-t:0;--inidicator-b:auto;--indicator-y:-50%}}@media (min-width:1536px){.\32 xl\:indicator{width:max-content;display:inline-flex;position:relative}.\32 xl\:indicator :where(.indicator-item){z-index:1;white-space:nowrap;top:var(--inidicator-t,0);bottom:var(--inidicator-b,auto);left:var(--inidicator-s,auto);right:var(--inidicator-e,0);translate:var(--inidicator-x,50%)var(--indicator-y,-50%);position:absolute}.\32 xl\:indicator-start{--inidicator-s:0;--inidicator-e:auto;--inidicator-x:-50%}.\32 xl\:indicator-center{--inidicator-s:50%;--inidicator-e:50%;--inidicator-x:-50%}[dir=rtl] .\32 xl\:indicator-center{--inidicator-x:50%}.\32 xl\:indicator-end{--inidicator-s:auto;--inidicator-e:0;--inidicator-x:50%}.\32 xl\:indicator-bottom{--inidicator-t:auto;--inidicator-b:0;--indicator-y:50%}.\32 xl\:indicator-middle{--inidicator-t:50%;--inidicator-b:50%;--indicator-y:-50%}.\32 xl\:indicator-top{--inidicator-t:0;--inidicator-b:auto;--indicator-y:-50%}}.stack{grid-template-rows:3px 4px 1fr 4px 3px;grid-template-columns:3px 4px 1fr 4px 3px;display:inline-grid}.stack>*{width:100%;height:100%}.stack>*:nth-child(n+2){opacity:.7;width:100%}.stack>*:nth-child(2){z-index:2;opacity:.9}.stack>*:first-child{z-index:3;width:100%}.stack>*{grid-area:3/3/6/4}.stack>*:nth-child(2){grid-area:2/2/5/5}.stack>*:first-child{grid-area:1/1/4/6}.stack.stack-bottom>*{grid-area:3/3/6/4}.stack.stack-bottom>*:nth-child(2){grid-area:2/2/5/5}.stack.stack-bottom>*:first-child{grid-area:1/1/4/6}.stack.stack-top>*{grid-area:1/3/4/4}.stack.stack-top>*:nth-child(2){grid-area:2/2/5/5}.stack.stack-top>*:first-child{grid-area:3/1/6/6}.stack.stack-start>*{grid-area:3/1/4/4}.stack.stack-start>*:nth-child(2){grid-area:2/2/5/5}.stack.stack-start>*:first-child{grid-area:1/3/6/6}.stack.stack-end>*{grid-area:3/3/4/6}.stack.stack-end>*:nth-child(2){grid-area:2/2/5/5}.stack.stack-end>*:first-child{grid-area:1/1/6/4}@media (min-width:640px){.sm\:stack{grid-template-rows:3px 4px 1fr 4px 3px;grid-template-columns:3px 4px 1fr 4px 3px;display:inline-grid}.sm\:stack>*{width:100%;height:100%}.sm\:stack>*:nth-child(n+2){opacity:.7;width:100%}.sm\:stack>*:nth-child(2){z-index:2;opacity:.9}.sm\:stack>*:first-child{z-index:3;width:100%}.sm\:stack>*{grid-area:3/3/6/4}.sm\:stack>*:nth-child(2){grid-area:2/2/5/5}.sm\:stack>*:first-child{grid-area:1/1/4/6}.sm\:stack.stack-bottom>*{grid-area:3/3/6/4}.sm\:stack.stack-bottom>*:nth-child(2){grid-area:2/2/5/5}.sm\:stack.stack-bottom>*:first-child{grid-area:1/1/4/6}.sm\:stack.stack-top>*{grid-area:1/3/4/4}.sm\:stack.stack-top>*:nth-child(2){grid-area:2/2/5/5}.sm\:stack.stack-top>*:first-child{grid-area:3/1/6/6}.sm\:stack.stack-start>*{grid-area:3/1/4/4}.sm\:stack.stack-start>*:nth-child(2){grid-area:2/2/5/5}.sm\:stack.stack-start>*:first-child{grid-area:1/3/6/6}.sm\:stack.stack-end>*{grid-area:3/3/4/6}.sm\:stack.stack-end>*:nth-child(2){grid-area:2/2/5/5}.sm\:stack.stack-end>*:first-child{grid-area:1/1/6/4}}@media (min-width:768px){.md\:stack{grid-template-rows:3px 4px 1fr 4px 3px;grid-template-columns:3px 4px 1fr 4px 3px;display:inline-grid}.md\:stack>*{width:100%;height:100%}.md\:stack>*:nth-child(n+2){opacity:.7;width:100%}.md\:stack>*:nth-child(2){z-index:2;opacity:.9}.md\:stack>*:first-child{z-index:3;width:100%}.md\:stack>*{grid-area:3/3/6/4}.md\:stack>*:nth-child(2){grid-area:2/2/5/5}.md\:stack>*:first-child{grid-area:1/1/4/6}.md\:stack.stack-bottom>*{grid-area:3/3/6/4}.md\:stack.stack-bottom>*:nth-child(2){grid-area:2/2/5/5}.md\:stack.stack-bottom>*:first-child{grid-area:1/1/4/6}.md\:stack.stack-top>*{grid-area:1/3/4/4}.md\:stack.stack-top>*:nth-child(2){grid-area:2/2/5/5}.md\:stack.stack-top>*:first-child{grid-area:3/1/6/6}.md\:stack.stack-start>*{grid-area:3/1/4/4}.md\:stack.stack-start>*:nth-child(2){grid-area:2/2/5/5}.md\:stack.stack-start>*:first-child{grid-area:1/3/6/6}.md\:stack.stack-end>*{grid-area:3/3/4/6}.md\:stack.stack-end>*:nth-child(2){grid-area:2/2/5/5}.md\:stack.stack-end>*:first-child{grid-area:1/1/6/4}}@media (min-width:1024px){.lg\:stack{grid-template-rows:3px 4px 1fr 4px 3px;grid-template-columns:3px 4px 1fr 4px 3px;display:inline-grid}.lg\:stack>*{width:100%;height:100%}.lg\:stack>*:nth-child(n+2){opacity:.7;width:100%}.lg\:stack>*:nth-child(2){z-index:2;opacity:.9}.lg\:stack>*:first-child{z-index:3;width:100%}.lg\:stack>*{grid-area:3/3/6/4}.lg\:stack>*:nth-child(2){grid-area:2/2/5/5}.lg\:stack>*:first-child{grid-area:1/1/4/6}.lg\:stack.stack-bottom>*{grid-area:3/3/6/4}.lg\:stack.stack-bottom>*:nth-child(2){grid-area:2/2/5/5}.lg\:stack.stack-bottom>*:first-child{grid-area:1/1/4/6}.lg\:stack.stack-top>*{grid-area:1/3/4/4}.lg\:stack.stack-top>*:nth-child(2){grid-area:2/2/5/5}.lg\:stack.stack-top>*:first-child{grid-area:3/1/6/6}.lg\:stack.stack-start>*{grid-area:3/1/4/4}.lg\:stack.stack-start>*:nth-child(2){grid-area:2/2/5/5}.lg\:stack.stack-start>*:first-child{grid-area:1/3/6/6}.lg\:stack.stack-end>*{grid-area:3/3/4/6}.lg\:stack.stack-end>*:nth-child(2){grid-area:2/2/5/5}.lg\:stack.stack-end>*:first-child{grid-area:1/1/6/4}}@media (min-width:1280px){.xl\:stack{grid-template-rows:3px 4px 1fr 4px 3px;grid-template-columns:3px 4px 1fr 4px 3px;display:inline-grid}.xl\:stack>*{width:100%;height:100%}.xl\:stack>*:nth-child(n+2){opacity:.7;width:100%}.xl\:stack>*:nth-child(2){z-index:2;opacity:.9}.xl\:stack>*:first-child{z-index:3;width:100%}.xl\:stack>*{grid-area:3/3/6/4}.xl\:stack>*:nth-child(2){grid-area:2/2/5/5}.xl\:stack>*:first-child{grid-area:1/1/4/6}.xl\:stack.stack-bottom>*{grid-area:3/3/6/4}.xl\:stack.stack-bottom>*:nth-child(2){grid-area:2/2/5/5}.xl\:stack.stack-bottom>*:first-child{grid-area:1/1/4/6}.xl\:stack.stack-top>*{grid-area:1/3/4/4}.xl\:stack.stack-top>*:nth-child(2){grid-area:2/2/5/5}.xl\:stack.stack-top>*:first-child{grid-area:3/1/6/6}.xl\:stack.stack-start>*{grid-area:3/1/4/4}.xl\:stack.stack-start>*:nth-child(2){grid-area:2/2/5/5}.xl\:stack.stack-start>*:first-child{grid-area:1/3/6/6}.xl\:stack.stack-end>*{grid-area:3/3/4/6}.xl\:stack.stack-end>*:nth-child(2){grid-area:2/2/5/5}.xl\:stack.stack-end>*:first-child{grid-area:1/1/6/4}}@media (min-width:1536px){.\32 xl\:stack{grid-template-rows:3px 4px 1fr 4px 3px;grid-template-columns:3px 4px 1fr 4px 3px;display:inline-grid}.\32 xl\:stack>*{width:100%;height:100%}.\32 xl\:stack>*:nth-child(n+2){opacity:.7;width:100%}.\32 xl\:stack>*:nth-child(2){z-index:2;opacity:.9}.\32 xl\:stack>*:first-child{z-index:3;width:100%}.\32 xl\:stack>*{grid-area:3/3/6/4}.\32 xl\:stack>*:nth-child(2){grid-area:2/2/5/5}.\32 xl\:stack>*:first-child{grid-area:1/1/4/6}.\32 xl\:stack.stack-bottom>*{grid-area:3/3/6/4}.\32 xl\:stack.stack-bottom>*:nth-child(2){grid-area:2/2/5/5}.\32 xl\:stack.stack-bottom>*:first-child{grid-area:1/1/4/6}.\32 xl\:stack.stack-top>*{grid-area:1/3/4/4}.\32 xl\:stack.stack-top>*:nth-child(2){grid-area:2/2/5/5}.\32 xl\:stack.stack-top>*:first-child{grid-area:3/1/6/6}.\32 xl\:stack.stack-start>*{grid-area:3/1/4/4}.\32 xl\:stack.stack-start>*:nth-child(2){grid-area:2/2/5/5}.\32 xl\:stack.stack-start>*:first-child{grid-area:1/3/6/6}.\32 xl\:stack.stack-end>*{grid-area:3/3/4/6}.\32 xl\:stack.stack-end>*:nth-child(2){grid-area:2/2/5/5}.\32 xl\:stack.stack-end>*:first-child{grid-area:1/1/6/4}}.carousel{scroll-snap-type:x mandatory;scroll-behavior:smooth;scrollbar-width:none;display:inline-flex;overflow-x:scroll}.carousel::-webkit-scrollbar{display:none}.carousel-vertical{scroll-snap-type:y mandatory;flex-direction:column;overflow-y:scroll}.carousel-horizontal{scroll-snap-type:x mandatory;flex-direction:row;overflow-x:scroll}.carousel-item{box-sizing:content-box;scroll-snap-align:start;flex:none;display:flex}.carousel-start .carousel-item{scroll-snap-align:start}.carousel-center .carousel-item{scroll-snap-align:center}.carousel-end .carousel-item{scroll-snap-align:end}@media (min-width:640px){.sm\:carousel{scroll-snap-type:x mandatory;scroll-behavior:smooth;scrollbar-width:none;display:inline-flex;overflow-x:scroll}.sm\:carousel::-webkit-scrollbar{display:none}.sm\:carousel-vertical{scroll-snap-type:y mandatory;flex-direction:column;overflow-y:scroll}.sm\:carousel-horizontal{scroll-snap-type:x mandatory;flex-direction:row;overflow-x:scroll}.sm\:carousel-item{box-sizing:content-box;scroll-snap-align:start;flex:none;display:flex}.sm\:carousel-start .carousel-item{scroll-snap-align:start}.sm\:carousel-center .carousel-item{scroll-snap-align:center}.sm\:carousel-end .carousel-item{scroll-snap-align:end}}@media (min-width:768px){.md\:carousel{scroll-snap-type:x mandatory;scroll-behavior:smooth;scrollbar-width:none;display:inline-flex;overflow-x:scroll}.md\:carousel::-webkit-scrollbar{display:none}.md\:carousel-vertical{scroll-snap-type:y mandatory;flex-direction:column;overflow-y:scroll}.md\:carousel-horizontal{scroll-snap-type:x mandatory;flex-direction:row;overflow-x:scroll}.md\:carousel-item{box-sizing:content-box;scroll-snap-align:start;flex:none;display:flex}.md\:carousel-start .carousel-item{scroll-snap-align:start}.md\:carousel-center .carousel-item{scroll-snap-align:center}.md\:carousel-end .carousel-item{scroll-snap-align:end}}@media (min-width:1024px){.lg\:carousel{scroll-snap-type:x mandatory;scroll-behavior:smooth;scrollbar-width:none;display:inline-flex;overflow-x:scroll}.lg\:carousel::-webkit-scrollbar{display:none}.lg\:carousel-vertical{scroll-snap-type:y mandatory;flex-direction:column;overflow-y:scroll}.lg\:carousel-horizontal{scroll-snap-type:x mandatory;flex-direction:row;overflow-x:scroll}.lg\:carousel-item{box-sizing:content-box;scroll-snap-align:start;flex:none;display:flex}.lg\:carousel-start .carousel-item{scroll-snap-align:start}.lg\:carousel-center .carousel-item{scroll-snap-align:center}.lg\:carousel-end .carousel-item{scroll-snap-align:end}}@media (min-width:1280px){.xl\:carousel{scroll-snap-type:x mandatory;scroll-behavior:smooth;scrollbar-width:none;display:inline-flex;overflow-x:scroll}.xl\:carousel::-webkit-scrollbar{display:none}.xl\:carousel-vertical{scroll-snap-type:y mandatory;flex-direction:column;overflow-y:scroll}.xl\:carousel-horizontal{scroll-snap-type:x mandatory;flex-direction:row;overflow-x:scroll}.xl\:carousel-item{box-sizing:content-box;scroll-snap-align:start;flex:none;display:flex}.xl\:carousel-start .carousel-item{scroll-snap-align:start}.xl\:carousel-center .carousel-item{scroll-snap-align:center}.xl\:carousel-end .carousel-item{scroll-snap-align:end}}@media (min-width:1536px){.\32 xl\:carousel{scroll-snap-type:x mandatory;scroll-behavior:smooth;scrollbar-width:none;display:inline-flex;overflow-x:scroll}.\32 xl\:carousel::-webkit-scrollbar{display:none}.\32 xl\:carousel-vertical{scroll-snap-type:y mandatory;flex-direction:column;overflow-y:scroll}.\32 xl\:carousel-horizontal{scroll-snap-type:x mandatory;flex-direction:row;overflow-x:scroll}.\32 xl\:carousel-item{box-sizing:content-box;scroll-snap-align:start;flex:none;display:flex}.\32 xl\:carousel-start .carousel-item{scroll-snap-align:start}.\32 xl\:carousel-center .carousel-item{scroll-snap-align:center}.\32 xl\:carousel-end .carousel-item{scroll-snap-align:end}}.link{cursor:pointer;text-decoration-line:underline}.link:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.link:focus{outline-offset:2px;outline:2px solid transparent}}.link:focus-visible{outline-offset:2px;outline:2px solid}.link-hover{text-decoration-line:none}@media (hover:hover){.link-hover:hover{text-decoration-line:underline}}.link-primary{color:var(--color-primary)}@media (hover:hover){.link-primary:hover{color:color-mix(in oklab,var(--color-primary)80%,#000)}}.link-secondary{color:var(--color-secondary)}@media (hover:hover){.link-secondary:hover{color:color-mix(in oklab,var(--color-secondary)80%,#000)}}.link-accent{color:var(--color-accent)}@media (hover:hover){.link-accent:hover{color:color-mix(in oklab,var(--color-accent)80%,#000)}}.link-neutral{color:var(--color-neutral)}@media (hover:hover){.link-neutral:hover{color:color-mix(in oklab,var(--color-neutral)80%,#000)}}.link-success{color:var(--color-success)}@media (hover:hover){.link-success:hover{color:color-mix(in oklab,var(--color-success)80%,#000)}}.link-info{color:var(--color-info)}@media (hover:hover){.link-info:hover{color:color-mix(in oklab,var(--color-info)80%,#000)}}.link-warning{color:var(--color-warning)}@media (hover:hover){.link-warning:hover{color:color-mix(in oklab,var(--color-warning)80%,#000)}}.link-error{color:var(--color-error)}@media (hover:hover){.link-error:hover{color:color-mix(in oklab,var(--color-error)80%,#000)}}@media (min-width:640px){.sm\:link{cursor:pointer;text-decoration-line:underline}.sm\:link:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:link:focus{outline-offset:2px;outline:2px solid transparent}}.sm\:link:focus-visible{outline-offset:2px;outline:2px solid}.sm\:link-hover{text-decoration-line:none}@media (hover:hover){.sm\:link-hover:hover{text-decoration-line:underline}}.sm\:link-primary{color:var(--color-primary)}@media (hover:hover){.sm\:link-primary:hover{color:color-mix(in oklab,var(--color-primary)80%,#000)}}.sm\:link-secondary{color:var(--color-secondary)}@media (hover:hover){.sm\:link-secondary:hover{color:color-mix(in oklab,var(--color-secondary)80%,#000)}}.sm\:link-accent{color:var(--color-accent)}@media (hover:hover){.sm\:link-accent:hover{color:color-mix(in oklab,var(--color-accent)80%,#000)}}.sm\:link-neutral{color:var(--color-neutral)}@media (hover:hover){.sm\:link-neutral:hover{color:color-mix(in oklab,var(--color-neutral)80%,#000)}}.sm\:link-success{color:var(--color-success)}@media (hover:hover){.sm\:link-success:hover{color:color-mix(in oklab,var(--color-success)80%,#000)}}.sm\:link-info{color:var(--color-info)}@media (hover:hover){.sm\:link-info:hover{color:color-mix(in oklab,var(--color-info)80%,#000)}}.sm\:link-warning{color:var(--color-warning)}@media (hover:hover){.sm\:link-warning:hover{color:color-mix(in oklab,var(--color-warning)80%,#000)}}.sm\:link-error{color:var(--color-error)}@media (hover:hover){.sm\:link-error:hover{color:color-mix(in oklab,var(--color-error)80%,#000)}}}@media (min-width:768px){.md\:link{cursor:pointer;text-decoration-line:underline}.md\:link:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:link:focus{outline-offset:2px;outline:2px solid transparent}}.md\:link:focus-visible{outline-offset:2px;outline:2px solid}.md\:link-hover{text-decoration-line:none}@media (hover:hover){.md\:link-hover:hover{text-decoration-line:underline}}.md\:link-primary{color:var(--color-primary)}@media (hover:hover){.md\:link-primary:hover{color:color-mix(in oklab,var(--color-primary)80%,#000)}}.md\:link-secondary{color:var(--color-secondary)}@media (hover:hover){.md\:link-secondary:hover{color:color-mix(in oklab,var(--color-secondary)80%,#000)}}.md\:link-accent{color:var(--color-accent)}@media (hover:hover){.md\:link-accent:hover{color:color-mix(in oklab,var(--color-accent)80%,#000)}}.md\:link-neutral{color:var(--color-neutral)}@media (hover:hover){.md\:link-neutral:hover{color:color-mix(in oklab,var(--color-neutral)80%,#000)}}.md\:link-success{color:var(--color-success)}@media (hover:hover){.md\:link-success:hover{color:color-mix(in oklab,var(--color-success)80%,#000)}}.md\:link-info{color:var(--color-info)}@media (hover:hover){.md\:link-info:hover{color:color-mix(in oklab,var(--color-info)80%,#000)}}.md\:link-warning{color:var(--color-warning)}@media (hover:hover){.md\:link-warning:hover{color:color-mix(in oklab,var(--color-warning)80%,#000)}}.md\:link-error{color:var(--color-error)}@media (hover:hover){.md\:link-error:hover{color:color-mix(in oklab,var(--color-error)80%,#000)}}}@media (min-width:1024px){.lg\:link{cursor:pointer;text-decoration-line:underline}.lg\:link:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:link:focus{outline-offset:2px;outline:2px solid transparent}}.lg\:link:focus-visible{outline-offset:2px;outline:2px solid}.lg\:link-hover{text-decoration-line:none}@media (hover:hover){.lg\:link-hover:hover{text-decoration-line:underline}}.lg\:link-primary{color:var(--color-primary)}@media (hover:hover){.lg\:link-primary:hover{color:color-mix(in oklab,var(--color-primary)80%,#000)}}.lg\:link-secondary{color:var(--color-secondary)}@media (hover:hover){.lg\:link-secondary:hover{color:color-mix(in oklab,var(--color-secondary)80%,#000)}}.lg\:link-accent{color:var(--color-accent)}@media (hover:hover){.lg\:link-accent:hover{color:color-mix(in oklab,var(--color-accent)80%,#000)}}.lg\:link-neutral{color:var(--color-neutral)}@media (hover:hover){.lg\:link-neutral:hover{color:color-mix(in oklab,var(--color-neutral)80%,#000)}}.lg\:link-success{color:var(--color-success)}@media (hover:hover){.lg\:link-success:hover{color:color-mix(in oklab,var(--color-success)80%,#000)}}.lg\:link-info{color:var(--color-info)}@media (hover:hover){.lg\:link-info:hover{color:color-mix(in oklab,var(--color-info)80%,#000)}}.lg\:link-warning{color:var(--color-warning)}@media (hover:hover){.lg\:link-warning:hover{color:color-mix(in oklab,var(--color-warning)80%,#000)}}.lg\:link-error{color:var(--color-error)}@media (hover:hover){.lg\:link-error:hover{color:color-mix(in oklab,var(--color-error)80%,#000)}}}@media (min-width:1280px){.xl\:link{cursor:pointer;text-decoration-line:underline}.xl\:link:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:link:focus{outline-offset:2px;outline:2px solid transparent}}.xl\:link:focus-visible{outline-offset:2px;outline:2px solid}.xl\:link-hover{text-decoration-line:none}@media (hover:hover){.xl\:link-hover:hover{text-decoration-line:underline}}.xl\:link-primary{color:var(--color-primary)}@media (hover:hover){.xl\:link-primary:hover{color:color-mix(in oklab,var(--color-primary)80%,#000)}}.xl\:link-secondary{color:var(--color-secondary)}@media (hover:hover){.xl\:link-secondary:hover{color:color-mix(in oklab,var(--color-secondary)80%,#000)}}.xl\:link-accent{color:var(--color-accent)}@media (hover:hover){.xl\:link-accent:hover{color:color-mix(in oklab,var(--color-accent)80%,#000)}}.xl\:link-neutral{color:var(--color-neutral)}@media (hover:hover){.xl\:link-neutral:hover{color:color-mix(in oklab,var(--color-neutral)80%,#000)}}.xl\:link-success{color:var(--color-success)}@media (hover:hover){.xl\:link-success:hover{color:color-mix(in oklab,var(--color-success)80%,#000)}}.xl\:link-info{color:var(--color-info)}@media (hover:hover){.xl\:link-info:hover{color:color-mix(in oklab,var(--color-info)80%,#000)}}.xl\:link-warning{color:var(--color-warning)}@media (hover:hover){.xl\:link-warning:hover{color:color-mix(in oklab,var(--color-warning)80%,#000)}}.xl\:link-error{color:var(--color-error)}@media (hover:hover){.xl\:link-error:hover{color:color-mix(in oklab,var(--color-error)80%,#000)}}}@media (min-width:1536px){.\32 xl\:link{cursor:pointer;text-decoration-line:underline}.\32 xl\:link:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:link:focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:link:focus-visible{outline-offset:2px;outline:2px solid}.\32 xl\:link-hover{text-decoration-line:none}@media (hover:hover){.\32 xl\:link-hover:hover{text-decoration-line:underline}}.\32 xl\:link-primary{color:var(--color-primary)}@media (hover:hover){.\32 xl\:link-primary:hover{color:color-mix(in oklab,var(--color-primary)80%,#000)}}.\32 xl\:link-secondary{color:var(--color-secondary)}@media (hover:hover){.\32 xl\:link-secondary:hover{color:color-mix(in oklab,var(--color-secondary)80%,#000)}}.\32 xl\:link-accent{color:var(--color-accent)}@media (hover:hover){.\32 xl\:link-accent:hover{color:color-mix(in oklab,var(--color-accent)80%,#000)}}.\32 xl\:link-neutral{color:var(--color-neutral)}@media (hover:hover){.\32 xl\:link-neutral:hover{color:color-mix(in oklab,var(--color-neutral)80%,#000)}}.\32 xl\:link-success{color:var(--color-success)}@media (hover:hover){.\32 xl\:link-success:hover{color:color-mix(in oklab,var(--color-success)80%,#000)}}.\32 xl\:link-info{color:var(--color-info)}@media (hover:hover){.\32 xl\:link-info:hover{color:color-mix(in oklab,var(--color-info)80%,#000)}}.\32 xl\:link-warning{color:var(--color-warning)}@media (hover:hover){.\32 xl\:link-warning:hover{color:color-mix(in oklab,var(--color-warning)80%,#000)}}.\32 xl\:link-error{color:var(--color-error)}@media (hover:hover){.\32 xl\:link-error:hover{color:color-mix(in oklab,var(--color-error)80%,#000)}}}.stats{border-radius:var(--radius-box);grid-auto-flow:column;display:inline-grid;position:relative;overflow-x:auto}.stat{grid-template-columns:repeat(1,1fr);column-gap:1rem;width:100%;padding-block:1rem;padding-inline:1.5rem;display:inline-grid}.stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.stat-figure{grid-row:1/span 3;grid-column-start:2;place-self:center flex-end}.stat-title{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.stat-value{white-space:nowrap;grid-column-start:1;font-size:2rem;font-weight:800}.stat-desc{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.stat-actions{white-space:nowrap;grid-column-start:1}.stats-horizontal{grid-auto-flow:column;overflow-x:auto}.stats-horizontal .stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.stats-vertical{grid-auto-flow:row;overflow-y:auto}.stats-vertical .stat:not(:last-child){border-inline-end:none;border-block-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent)}@media (min-width:640px){.sm\:stats{border-radius:var(--radius-box);grid-auto-flow:column;display:inline-grid;position:relative;overflow-x:auto}.sm\:stat{grid-template-columns:repeat(1,1fr);column-gap:1rem;width:100%;padding-block:1rem;padding-inline:1.5rem;display:inline-grid}.sm\:stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.sm\:stat-figure{grid-row:1/span 3;grid-column-start:2;place-self:center flex-end}.sm\:stat-title{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.sm\:stat-value{white-space:nowrap;grid-column-start:1;font-size:2rem;font-weight:800}.sm\:stat-desc{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.sm\:stat-actions{white-space:nowrap;grid-column-start:1}.sm\:stats-horizontal{grid-auto-flow:column;overflow-x:auto}.sm\:stats-horizontal .stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.sm\:stats-vertical{grid-auto-flow:row;overflow-y:auto}.sm\:stats-vertical .stat:not(:last-child){border-inline-end:none;border-block-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent)}}@media (min-width:768px){.md\:stats{border-radius:var(--radius-box);grid-auto-flow:column;display:inline-grid;position:relative;overflow-x:auto}.md\:stat{grid-template-columns:repeat(1,1fr);column-gap:1rem;width:100%;padding-block:1rem;padding-inline:1.5rem;display:inline-grid}.md\:stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.md\:stat-figure{grid-row:1/span 3;grid-column-start:2;place-self:center flex-end}.md\:stat-title{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.md\:stat-value{white-space:nowrap;grid-column-start:1;font-size:2rem;font-weight:800}.md\:stat-desc{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.md\:stat-actions{white-space:nowrap;grid-column-start:1}.md\:stats-horizontal{grid-auto-flow:column;overflow-x:auto}.md\:stats-horizontal .stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.md\:stats-vertical{grid-auto-flow:row;overflow-y:auto}.md\:stats-vertical .stat:not(:last-child){border-inline-end:none;border-block-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent)}}@media (min-width:1024px){.lg\:stats{border-radius:var(--radius-box);grid-auto-flow:column;display:inline-grid;position:relative;overflow-x:auto}.lg\:stat{grid-template-columns:repeat(1,1fr);column-gap:1rem;width:100%;padding-block:1rem;padding-inline:1.5rem;display:inline-grid}.lg\:stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.lg\:stat-figure{grid-row:1/span 3;grid-column-start:2;place-self:center flex-end}.lg\:stat-title{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.lg\:stat-value{white-space:nowrap;grid-column-start:1;font-size:2rem;font-weight:800}.lg\:stat-desc{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.lg\:stat-actions{white-space:nowrap;grid-column-start:1}.lg\:stats-horizontal{grid-auto-flow:column;overflow-x:auto}.lg\:stats-horizontal .stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.lg\:stats-vertical{grid-auto-flow:row;overflow-y:auto}.lg\:stats-vertical .stat:not(:last-child){border-inline-end:none;border-block-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent)}}@media (min-width:1280px){.xl\:stats{border-radius:var(--radius-box);grid-auto-flow:column;display:inline-grid;position:relative;overflow-x:auto}.xl\:stat{grid-template-columns:repeat(1,1fr);column-gap:1rem;width:100%;padding-block:1rem;padding-inline:1.5rem;display:inline-grid}.xl\:stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.xl\:stat-figure{grid-row:1/span 3;grid-column-start:2;place-self:center flex-end}.xl\:stat-title{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.xl\:stat-value{white-space:nowrap;grid-column-start:1;font-size:2rem;font-weight:800}.xl\:stat-desc{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.xl\:stat-actions{white-space:nowrap;grid-column-start:1}.xl\:stats-horizontal{grid-auto-flow:column;overflow-x:auto}.xl\:stats-horizontal .stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.xl\:stats-vertical{grid-auto-flow:row;overflow-y:auto}.xl\:stats-vertical .stat:not(:last-child){border-inline-end:none;border-block-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent)}}@media (min-width:1536px){.\32 xl\:stats{border-radius:var(--radius-box);grid-auto-flow:column;display:inline-grid;position:relative;overflow-x:auto}.\32 xl\:stat{grid-template-columns:repeat(1,1fr);column-gap:1rem;width:100%;padding-block:1rem;padding-inline:1.5rem;display:inline-grid}.\32 xl\:stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.\32 xl\:stat-figure{grid-row:1/span 3;grid-column-start:2;place-self:center flex-end}.\32 xl\:stat-title{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.\32 xl\:stat-value{white-space:nowrap;grid-column-start:1;font-size:2rem;font-weight:800}.\32 xl\:stat-desc{white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);grid-column-start:1;font-size:.75rem}.\32 xl\:stat-actions{white-space:nowrap;grid-column-start:1}.\32 xl\:stats-horizontal{grid-auto-flow:column;overflow-x:auto}.\32 xl\:stats-horizontal .stat:not(:last-child){border-inline-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent);border-block-end:none}.\32 xl\:stats-vertical{grid-auto-flow:row;overflow-y:auto}.\32 xl\:stats-vertical .stat:not(:last-child){border-inline-end:none;border-block-end:var(--border)dashed color-mix(in oklab,currentColor 10%,transparent)}}.modal{pointer-events:none;visibility:hidden;width:100%;max-width:none;height:100%;max-height:none;color:inherit;transition:transform .3s ease-out,visibility .3s allow-discrete,background-color .3s ease-out,opacity .1s ease-out;overscroll-behavior:contain;z-index:999;background-color:transparent;place-items:center;margin:0;padding:0;display:grid;position:fixed;inset:0;overflow:hidden}.modal::backdrop{display:none}.modal.modal-open{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.modal[open]{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.modal:target{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.modal.modal-open{pointer-events:auto;visibility:visible;opacity:1}.modal.modal-open .modal-box{opacity:1;translate:0;scale:1}.modal[open]{pointer-events:auto;visibility:visible;opacity:1}.modal[open] .modal-box{opacity:1;translate:0;scale:1}.modal:target{pointer-events:auto;visibility:visible;opacity:1}.modal:target .modal-box{opacity:1;translate:0;scale:1}@starting-style{.modal.modal-open{visibility:hidden;opacity:0}.modal[open]{visibility:hidden;opacity:0}.modal:target{visibility:hidden;opacity:0}}.modal-action{justify-content:flex-end;gap:.5rem;margin-top:1.5rem;display:flex}.modal-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.modal-toggle:checked+.modal{pointer-events:auto;visibility:visible;opacity:1;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4)}.modal-toggle:checked+.modal .modal-box{opacity:1;translate:0;scale:1}@starting-style{.modal-toggle:checked+.modal{visibility:hidden;opacity:0}}.modal-backdrop{color:transparent;z-index:-1;grid-row-start:1;grid-column-start:1;place-self:stretch stretch;display:grid}.modal-backdrop button{cursor:pointer}.modal-box{background-color:var(--color-base-100);border-top-left-radius:var(--modal-tl,var(--radius-box));border-top-right-radius:var(--modal-tr,var(--radius-box));border-bottom-left-radius:var(--modal-bl,var(--radius-box));border-bottom-right-radius:var(--modal-br,var(--radius-box));opacity:0;overscroll-behavior:contain;grid-row-start:1;grid-column-start:1;width:91.6667%;max-width:32rem;max-height:100vh;padding:1.5rem;transition:translate .3s ease-out,scale .3s ease-out,opacity .2s ease-out 50ms,box-shadow .3s ease-out;overflow-y:auto;scale:95%;box-shadow:0 25px 50px -12px rgba(0,0,0,.25);box-shadow:0 25px 50px -12px lab(0% 0 0/.25)}.modal-top{place-items:start}.modal-top :where(.modal-box){--modal-tl:0;--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 -100%;scale:1}.modal-middle{place-items:center}.modal-middle :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:91.6667%;max-width:32rem;height:auto;max-height:calc(100vh - 5em);translate:0 2%;scale:98%}.modal-bottom{place-items:end}.modal-bottom :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:0;width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 100%;scale:1}.modal-start{place-items:start}.modal-start :where(.modal-box){--modal-tl:0;--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:var(--radius-box);width:auto;max-width:none;height:100vh;max-height:none;translate:-100%;scale:1}.modal-end{place-items:end}.modal-end :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:0;width:auto;max-width:none;height:100vh;max-height:none;translate:100%;scale:1}@media (min-width:640px){.sm\:modal{pointer-events:none;visibility:hidden;width:100%;max-width:none;height:100%;max-height:none;color:inherit;transition:transform .3s ease-out,visibility .3s allow-discrete,background-color .3s ease-out,opacity .1s ease-out;overscroll-behavior:contain;z-index:999;background-color:transparent;place-items:center;margin:0;padding:0;display:grid;position:fixed;inset:0;overflow:hidden}.sm\:modal::backdrop{display:none}.sm\:modal.modal-open{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.sm\:modal[open]{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.sm\:modal:target{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.sm\:modal.modal-open{pointer-events:auto;visibility:visible;opacity:1}.sm\:modal.modal-open .modal-box{opacity:1;translate:0;scale:1}.sm\:modal[open]{pointer-events:auto;visibility:visible;opacity:1}.sm\:modal[open] .modal-box{opacity:1;translate:0;scale:1}.sm\:modal:target{pointer-events:auto;visibility:visible;opacity:1}.sm\:modal:target .modal-box{opacity:1;translate:0;scale:1}@starting-style{.sm\:modal.modal-open{visibility:hidden;opacity:0}.sm\:modal[open]{visibility:hidden;opacity:0}.sm\:modal:target{visibility:hidden;opacity:0}}.sm\:modal-action{justify-content:flex-end;gap:.5rem;margin-top:1.5rem;display:flex}.sm\:modal-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.sm\:modal-toggle:checked+.modal{pointer-events:auto;visibility:visible;opacity:1;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4)}.sm\:modal-toggle:checked+.modal .modal-box{opacity:1;translate:0;scale:1}@starting-style{.sm\:modal-toggle:checked+.modal{visibility:hidden;opacity:0}}.sm\:modal-backdrop{color:transparent;z-index:-1;grid-row-start:1;grid-column-start:1;place-self:stretch stretch;display:grid}.sm\:modal-backdrop button{cursor:pointer}.sm\:modal-box{background-color:var(--color-base-100);border-top-left-radius:var(--modal-tl,var(--radius-box));border-top-right-radius:var(--modal-tr,var(--radius-box));border-bottom-left-radius:var(--modal-bl,var(--radius-box));border-bottom-right-radius:var(--modal-br,var(--radius-box));opacity:0;overscroll-behavior:contain;grid-row-start:1;grid-column-start:1;width:91.6667%;max-width:32rem;max-height:100vh;padding:1.5rem;transition:translate .3s ease-out,scale .3s ease-out,opacity .2s ease-out 50ms,box-shadow .3s ease-out;overflow-y:auto;scale:95%;box-shadow:0 25px 50px -12px rgba(0,0,0,.25);box-shadow:0 25px 50px -12px lab(0% 0 0/.25)}.sm\:modal-top{place-items:start}.sm\:modal-top :where(.modal-box){--modal-tl:0;--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 -100%;scale:1}.sm\:modal-middle{place-items:center}.sm\:modal-middle :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:91.6667%;max-width:32rem;height:auto;max-height:calc(100vh - 5em);translate:0 2%;scale:98%}.sm\:modal-bottom{place-items:end}.sm\:modal-bottom :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:0;width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 100%;scale:1}.sm\:modal-start{place-items:start}.sm\:modal-start :where(.modal-box){--modal-tl:0;--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:var(--radius-box);width:auto;max-width:none;height:100vh;max-height:none;translate:-100%;scale:1}.sm\:modal-end{place-items:end}.sm\:modal-end :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:0;width:auto;max-width:none;height:100vh;max-height:none;translate:100%;scale:1}}@media (min-width:768px){.md\:modal{pointer-events:none;visibility:hidden;width:100%;max-width:none;height:100%;max-height:none;color:inherit;transition:transform .3s ease-out,visibility .3s allow-discrete,background-color .3s ease-out,opacity .1s ease-out;overscroll-behavior:contain;z-index:999;background-color:transparent;place-items:center;margin:0;padding:0;display:grid;position:fixed;inset:0;overflow:hidden}.md\:modal::backdrop{display:none}.md\:modal.modal-open{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.md\:modal[open]{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.md\:modal:target{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.md\:modal.modal-open{pointer-events:auto;visibility:visible;opacity:1}.md\:modal.modal-open .modal-box{opacity:1;translate:0;scale:1}.md\:modal[open]{pointer-events:auto;visibility:visible;opacity:1}.md\:modal[open] .modal-box{opacity:1;translate:0;scale:1}.md\:modal:target{pointer-events:auto;visibility:visible;opacity:1}.md\:modal:target .modal-box{opacity:1;translate:0;scale:1}@starting-style{.md\:modal.modal-open{visibility:hidden;opacity:0}.md\:modal[open]{visibility:hidden;opacity:0}.md\:modal:target{visibility:hidden;opacity:0}}.md\:modal-action{justify-content:flex-end;gap:.5rem;margin-top:1.5rem;display:flex}.md\:modal-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.md\:modal-toggle:checked+.modal{pointer-events:auto;visibility:visible;opacity:1;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4)}.md\:modal-toggle:checked+.modal .modal-box{opacity:1;translate:0;scale:1}@starting-style{.md\:modal-toggle:checked+.modal{visibility:hidden;opacity:0}}.md\:modal-backdrop{color:transparent;z-index:-1;grid-row-start:1;grid-column-start:1;place-self:stretch stretch;display:grid}.md\:modal-backdrop button{cursor:pointer}.md\:modal-box{background-color:var(--color-base-100);border-top-left-radius:var(--modal-tl,var(--radius-box));border-top-right-radius:var(--modal-tr,var(--radius-box));border-bottom-left-radius:var(--modal-bl,var(--radius-box));border-bottom-right-radius:var(--modal-br,var(--radius-box));opacity:0;overscroll-behavior:contain;grid-row-start:1;grid-column-start:1;width:91.6667%;max-width:32rem;max-height:100vh;padding:1.5rem;transition:translate .3s ease-out,scale .3s ease-out,opacity .2s ease-out 50ms,box-shadow .3s ease-out;overflow-y:auto;scale:95%;box-shadow:0 25px 50px -12px rgba(0,0,0,.25);box-shadow:0 25px 50px -12px lab(0% 0 0/.25)}.md\:modal-top{place-items:start}.md\:modal-top :where(.modal-box){--modal-tl:0;--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 -100%;scale:1}.md\:modal-middle{place-items:center}.md\:modal-middle :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:91.6667%;max-width:32rem;height:auto;max-height:calc(100vh - 5em);translate:0 2%;scale:98%}.md\:modal-bottom{place-items:end}.md\:modal-bottom :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:0;width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 100%;scale:1}.md\:modal-start{place-items:start}.md\:modal-start :where(.modal-box){--modal-tl:0;--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:var(--radius-box);width:auto;max-width:none;height:100vh;max-height:none;translate:-100%;scale:1}.md\:modal-end{place-items:end}.md\:modal-end :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:0;width:auto;max-width:none;height:100vh;max-height:none;translate:100%;scale:1}}@media (min-width:1024px){.lg\:modal{pointer-events:none;visibility:hidden;width:100%;max-width:none;height:100%;max-height:none;color:inherit;transition:transform .3s ease-out,visibility .3s allow-discrete,background-color .3s ease-out,opacity .1s ease-out;overscroll-behavior:contain;z-index:999;background-color:transparent;place-items:center;margin:0;padding:0;display:grid;position:fixed;inset:0;overflow:hidden}.lg\:modal::backdrop{display:none}.lg\:modal.modal-open{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.lg\:modal[open]{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.lg\:modal:target{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.lg\:modal.modal-open{pointer-events:auto;visibility:visible;opacity:1}.lg\:modal.modal-open .modal-box{opacity:1;translate:0;scale:1}.lg\:modal[open]{pointer-events:auto;visibility:visible;opacity:1}.lg\:modal[open] .modal-box{opacity:1;translate:0;scale:1}.lg\:modal:target{pointer-events:auto;visibility:visible;opacity:1}.lg\:modal:target .modal-box{opacity:1;translate:0;scale:1}@starting-style{.lg\:modal.modal-open{visibility:hidden;opacity:0}.lg\:modal[open]{visibility:hidden;opacity:0}.lg\:modal:target{visibility:hidden;opacity:0}}.lg\:modal-action{justify-content:flex-end;gap:.5rem;margin-top:1.5rem;display:flex}.lg\:modal-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.lg\:modal-toggle:checked+.modal{pointer-events:auto;visibility:visible;opacity:1;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4)}.lg\:modal-toggle:checked+.modal .modal-box{opacity:1;translate:0;scale:1}@starting-style{.lg\:modal-toggle:checked+.modal{visibility:hidden;opacity:0}}.lg\:modal-backdrop{color:transparent;z-index:-1;grid-row-start:1;grid-column-start:1;place-self:stretch stretch;display:grid}.lg\:modal-backdrop button{cursor:pointer}.lg\:modal-box{background-color:var(--color-base-100);border-top-left-radius:var(--modal-tl,var(--radius-box));border-top-right-radius:var(--modal-tr,var(--radius-box));border-bottom-left-radius:var(--modal-bl,var(--radius-box));border-bottom-right-radius:var(--modal-br,var(--radius-box));opacity:0;overscroll-behavior:contain;grid-row-start:1;grid-column-start:1;width:91.6667%;max-width:32rem;max-height:100vh;padding:1.5rem;transition:translate .3s ease-out,scale .3s ease-out,opacity .2s ease-out 50ms,box-shadow .3s ease-out;overflow-y:auto;scale:95%;box-shadow:0 25px 50px -12px rgba(0,0,0,.25);box-shadow:0 25px 50px -12px lab(0% 0 0/.25)}.lg\:modal-top{place-items:start}.lg\:modal-top :where(.modal-box){--modal-tl:0;--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 -100%;scale:1}.lg\:modal-middle{place-items:center}.lg\:modal-middle :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:91.6667%;max-width:32rem;height:auto;max-height:calc(100vh - 5em);translate:0 2%;scale:98%}.lg\:modal-bottom{place-items:end}.lg\:modal-bottom :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:0;width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 100%;scale:1}.lg\:modal-start{place-items:start}.lg\:modal-start :where(.modal-box){--modal-tl:0;--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:var(--radius-box);width:auto;max-width:none;height:100vh;max-height:none;translate:-100%;scale:1}.lg\:modal-end{place-items:end}.lg\:modal-end :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:0;width:auto;max-width:none;height:100vh;max-height:none;translate:100%;scale:1}}@media (min-width:1280px){.xl\:modal{pointer-events:none;visibility:hidden;width:100%;max-width:none;height:100%;max-height:none;color:inherit;transition:transform .3s ease-out,visibility .3s allow-discrete,background-color .3s ease-out,opacity .1s ease-out;overscroll-behavior:contain;z-index:999;background-color:transparent;place-items:center;margin:0;padding:0;display:grid;position:fixed;inset:0;overflow:hidden}.xl\:modal::backdrop{display:none}.xl\:modal.modal-open{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.xl\:modal[open]{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.xl\:modal:target{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.xl\:modal.modal-open{pointer-events:auto;visibility:visible;opacity:1}.xl\:modal.modal-open .modal-box{opacity:1;translate:0;scale:1}.xl\:modal[open]{pointer-events:auto;visibility:visible;opacity:1}.xl\:modal[open] .modal-box{opacity:1;translate:0;scale:1}.xl\:modal:target{pointer-events:auto;visibility:visible;opacity:1}.xl\:modal:target .modal-box{opacity:1;translate:0;scale:1}@starting-style{.xl\:modal.modal-open{visibility:hidden;opacity:0}.xl\:modal[open]{visibility:hidden;opacity:0}.xl\:modal:target{visibility:hidden;opacity:0}}.xl\:modal-action{justify-content:flex-end;gap:.5rem;margin-top:1.5rem;display:flex}.xl\:modal-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.xl\:modal-toggle:checked+.modal{pointer-events:auto;visibility:visible;opacity:1;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4)}.xl\:modal-toggle:checked+.modal .modal-box{opacity:1;translate:0;scale:1}@starting-style{.xl\:modal-toggle:checked+.modal{visibility:hidden;opacity:0}}.xl\:modal-backdrop{color:transparent;z-index:-1;grid-row-start:1;grid-column-start:1;place-self:stretch stretch;display:grid}.xl\:modal-backdrop button{cursor:pointer}.xl\:modal-box{background-color:var(--color-base-100);border-top-left-radius:var(--modal-tl,var(--radius-box));border-top-right-radius:var(--modal-tr,var(--radius-box));border-bottom-left-radius:var(--modal-bl,var(--radius-box));border-bottom-right-radius:var(--modal-br,var(--radius-box));opacity:0;overscroll-behavior:contain;grid-row-start:1;grid-column-start:1;width:91.6667%;max-width:32rem;max-height:100vh;padding:1.5rem;transition:translate .3s ease-out,scale .3s ease-out,opacity .2s ease-out 50ms,box-shadow .3s ease-out;overflow-y:auto;scale:95%;box-shadow:0 25px 50px -12px rgba(0,0,0,.25);box-shadow:0 25px 50px -12px lab(0% 0 0/.25)}.xl\:modal-top{place-items:start}.xl\:modal-top :where(.modal-box){--modal-tl:0;--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 -100%;scale:1}.xl\:modal-middle{place-items:center}.xl\:modal-middle :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:91.6667%;max-width:32rem;height:auto;max-height:calc(100vh - 5em);translate:0 2%;scale:98%}.xl\:modal-bottom{place-items:end}.xl\:modal-bottom :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:0;width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 100%;scale:1}.xl\:modal-start{place-items:start}.xl\:modal-start :where(.modal-box){--modal-tl:0;--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:var(--radius-box);width:auto;max-width:none;height:100vh;max-height:none;translate:-100%;scale:1}.xl\:modal-end{place-items:end}.xl\:modal-end :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:0;width:auto;max-width:none;height:100vh;max-height:none;translate:100%;scale:1}}@media (min-width:1536px){.\32 xl\:modal{pointer-events:none;visibility:hidden;width:100%;max-width:none;height:100%;max-height:none;color:inherit;transition:transform .3s ease-out,visibility .3s allow-discrete,background-color .3s ease-out,opacity .1s ease-out;overscroll-behavior:contain;z-index:999;background-color:transparent;place-items:center;margin:0;padding:0;display:grid;position:fixed;inset:0;overflow:hidden}.\32 xl\:modal::backdrop{display:none}.\32 xl\:modal.modal-open{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.\32 xl\:modal[open]{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.\32 xl\:modal:target{background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);transition:transform .3s ease-out,background-color .3s ease-out,opacity .1s ease-out}.\32 xl\:modal.modal-open{pointer-events:auto;visibility:visible;opacity:1}.\32 xl\:modal.modal-open .modal-box{opacity:1;translate:0;scale:1}.\32 xl\:modal[open]{pointer-events:auto;visibility:visible;opacity:1}.\32 xl\:modal[open] .modal-box{opacity:1;translate:0;scale:1}.\32 xl\:modal:target{pointer-events:auto;visibility:visible;opacity:1}.\32 xl\:modal:target .modal-box{opacity:1;translate:0;scale:1}@starting-style{.\32 xl\:modal.modal-open{visibility:hidden;opacity:0}.\32 xl\:modal[open]{visibility:hidden;opacity:0}.\32 xl\:modal:target{visibility:hidden;opacity:0}}.\32 xl\:modal-action{justify-content:flex-end;gap:.5rem;margin-top:1.5rem;display:flex}.\32 xl\:modal-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.\32 xl\:modal-toggle:checked+.modal{pointer-events:auto;visibility:visible;opacity:1;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4)}.\32 xl\:modal-toggle:checked+.modal .modal-box{opacity:1;translate:0;scale:1}@starting-style{.\32 xl\:modal-toggle:checked+.modal{visibility:hidden;opacity:0}}.\32 xl\:modal-backdrop{color:transparent;z-index:-1;grid-row-start:1;grid-column-start:1;place-self:stretch stretch;display:grid}.\32 xl\:modal-backdrop button{cursor:pointer}.\32 xl\:modal-box{background-color:var(--color-base-100);border-top-left-radius:var(--modal-tl,var(--radius-box));border-top-right-radius:var(--modal-tr,var(--radius-box));border-bottom-left-radius:var(--modal-bl,var(--radius-box));border-bottom-right-radius:var(--modal-br,var(--radius-box));opacity:0;overscroll-behavior:contain;grid-row-start:1;grid-column-start:1;width:91.6667%;max-width:32rem;max-height:100vh;padding:1.5rem;transition:translate .3s ease-out,scale .3s ease-out,opacity .2s ease-out 50ms,box-shadow .3s ease-out;overflow-y:auto;scale:95%;box-shadow:0 25px 50px -12px rgba(0,0,0,.25);box-shadow:0 25px 50px -12px lab(0% 0 0/.25)}.\32 xl\:modal-top{place-items:start}.\32 xl\:modal-top :where(.modal-box){--modal-tl:0;--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 -100%;scale:1}.\32 xl\:modal-middle{place-items:center}.\32 xl\:modal-middle :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:var(--radius-box);--modal-br:var(--radius-box);width:91.6667%;max-width:32rem;height:auto;max-height:calc(100vh - 5em);translate:0 2%;scale:98%}.\32 xl\:modal-bottom{place-items:end}.\32 xl\:modal-bottom :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:0;width:100%;max-width:none;height:auto;max-height:calc(100vh - 5em);translate:0 100%;scale:1}.\32 xl\:modal-start{place-items:start}.\32 xl\:modal-start :where(.modal-box){--modal-tl:0;--modal-tr:var(--radius-box);--modal-bl:0;--modal-br:var(--radius-box);width:auto;max-width:none;height:100vh;max-height:none;translate:-100%;scale:1}.\32 xl\:modal-end{place-items:end}.\32 xl\:modal-end :where(.modal-box){--modal-tl:var(--radius-box);--modal-tr:0;--modal-bl:var(--radius-box);--modal-br:0;width:auto;max-width:none;height:100vh;max-height:none;translate:100%;scale:1}}.chat{column-gap:.75rem;padding-block:.25rem;display:grid}.chat-bubble{border-radius:var(--radius-field);background-color:var(--color-base-300);width:fit-content;color:var(--color-base-content);grid-row-end:3;min-width:2.5rem;max-width:90%;min-height:2rem;padding-block:.5rem;padding-inline:1rem;display:block;position:relative}.chat-bubble:before{background-color:inherit;content:"";width:.75rem;height:.75rem;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-chat);mask-image:var(--mask-chat);position:absolute;bottom:0;-webkit-mask-position:0 -1px;mask-position:0 -1px;-webkit-mask-size:13px;mask-size:13px}.chat-bubble-primary{background-color:var(--color-primary);color:var(--color-primary-content)}.chat-bubble-secondary{background-color:var(--color-secondary);color:var(--color-secondary-content)}.chat-bubble-accent{background-color:var(--color-accent);color:var(--color-accent-content)}.chat-bubble-neutral{background-color:var(--color-neutral);color:var(--color-neutral-content)}.chat-bubble-info{background-color:var(--color-info);color:var(--color-info-content)}.chat-bubble-success{background-color:var(--color-success);color:var(--color-success-content)}.chat-bubble-warning{background-color:var(--color-warning);color:var(--color-warning-content)}.chat-bubble-error{background-color:var(--color-error);color:var(--color-error-content)}.chat-image{grid-row:span 2/span 2;align-self:flex-end}.chat-header{grid-row-start:1;gap:.25rem;font-size:.6875rem;display:flex}.chat-footer{grid-row-start:3;gap:.25rem;font-size:.6875rem;display:flex}.chat-start{grid-template-columns:auto 1fr;place-items:start}.chat-start .chat-header{grid-column-start:2}.chat-start .chat-footer{grid-column-start:2}.chat-start .chat-image{grid-column-start:1}.chat-start .chat-bubble{border-end-start-radius:0;grid-column-start:2}.chat-start .chat-bubble:before{inset-inline-start:-.75rem;transform:rotateY(0)}[dir=rtl] :is(.chat-start .chat-bubble):before{transform:rotateY(180deg)}.chat-end{grid-template-columns:1fr auto;place-items:end}.chat-end .chat-header{grid-column-start:1}.chat-end .chat-footer{grid-column-start:1}.chat-end .chat-image{grid-column-start:2}.chat-end .chat-bubble{border-end-end-radius:0;grid-column-start:1}.chat-end .chat-bubble:before{inset-inline-start:100%;transform:rotateY(180deg)}[dir=rtl] :is(.chat-end .chat-bubble):before{transform:rotateY(0)}@media (min-width:640px){.sm\:chat{column-gap:.75rem;padding-block:.25rem;display:grid}.sm\:chat-bubble{border-radius:var(--radius-field);background-color:var(--color-base-300);width:fit-content;color:var(--color-base-content);grid-row-end:3;min-width:2.5rem;max-width:90%;min-height:2rem;padding-block:.5rem;padding-inline:1rem;display:block;position:relative}.sm\:chat-bubble:before{background-color:inherit;content:"";width:.75rem;height:.75rem;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-chat);mask-image:var(--mask-chat);position:absolute;bottom:0;-webkit-mask-position:0 -1px;mask-position:0 -1px;-webkit-mask-size:13px;mask-size:13px}.sm\:chat-bubble-primary{background-color:var(--color-primary);color:var(--color-primary-content)}.sm\:chat-bubble-secondary{background-color:var(--color-secondary);color:var(--color-secondary-content)}.sm\:chat-bubble-accent{background-color:var(--color-accent);color:var(--color-accent-content)}.sm\:chat-bubble-neutral{background-color:var(--color-neutral);color:var(--color-neutral-content)}.sm\:chat-bubble-info{background-color:var(--color-info);color:var(--color-info-content)}.sm\:chat-bubble-success{background-color:var(--color-success);color:var(--color-success-content)}.sm\:chat-bubble-warning{background-color:var(--color-warning);color:var(--color-warning-content)}.sm\:chat-bubble-error{background-color:var(--color-error);color:var(--color-error-content)}.sm\:chat-image{grid-row:span 2/span 2;align-self:flex-end}.sm\:chat-header{grid-row-start:1;gap:.25rem;font-size:.6875rem;display:flex}.sm\:chat-footer{grid-row-start:3;gap:.25rem;font-size:.6875rem;display:flex}.sm\:chat-start{grid-template-columns:auto 1fr;place-items:start}.sm\:chat-start .chat-header{grid-column-start:2}.sm\:chat-start .chat-footer{grid-column-start:2}.sm\:chat-start .chat-image{grid-column-start:1}.sm\:chat-start .chat-bubble{border-end-start-radius:0;grid-column-start:2}.sm\:chat-start .chat-bubble:before{inset-inline-start:-.75rem;transform:rotateY(0)}[dir=rtl] :is(.sm\:chat-start .chat-bubble):before{transform:rotateY(180deg)}.sm\:chat-end{grid-template-columns:1fr auto;place-items:end}.sm\:chat-end .chat-header{grid-column-start:1}.sm\:chat-end .chat-footer{grid-column-start:1}.sm\:chat-end .chat-image{grid-column-start:2}.sm\:chat-end .chat-bubble{border-end-end-radius:0;grid-column-start:1}.sm\:chat-end .chat-bubble:before{inset-inline-start:100%;transform:rotateY(180deg)}[dir=rtl] :is(.sm\:chat-end .chat-bubble):before{transform:rotateY(0)}}@media (min-width:768px){.md\:chat{column-gap:.75rem;padding-block:.25rem;display:grid}.md\:chat-bubble{border-radius:var(--radius-field);background-color:var(--color-base-300);width:fit-content;color:var(--color-base-content);grid-row-end:3;min-width:2.5rem;max-width:90%;min-height:2rem;padding-block:.5rem;padding-inline:1rem;display:block;position:relative}.md\:chat-bubble:before{background-color:inherit;content:"";width:.75rem;height:.75rem;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-chat);mask-image:var(--mask-chat);position:absolute;bottom:0;-webkit-mask-position:0 -1px;mask-position:0 -1px;-webkit-mask-size:13px;mask-size:13px}.md\:chat-bubble-primary{background-color:var(--color-primary);color:var(--color-primary-content)}.md\:chat-bubble-secondary{background-color:var(--color-secondary);color:var(--color-secondary-content)}.md\:chat-bubble-accent{background-color:var(--color-accent);color:var(--color-accent-content)}.md\:chat-bubble-neutral{background-color:var(--color-neutral);color:var(--color-neutral-content)}.md\:chat-bubble-info{background-color:var(--color-info);color:var(--color-info-content)}.md\:chat-bubble-success{background-color:var(--color-success);color:var(--color-success-content)}.md\:chat-bubble-warning{background-color:var(--color-warning);color:var(--color-warning-content)}.md\:chat-bubble-error{background-color:var(--color-error);color:var(--color-error-content)}.md\:chat-image{grid-row:span 2/span 2;align-self:flex-end}.md\:chat-header{grid-row-start:1;gap:.25rem;font-size:.6875rem;display:flex}.md\:chat-footer{grid-row-start:3;gap:.25rem;font-size:.6875rem;display:flex}.md\:chat-start{grid-template-columns:auto 1fr;place-items:start}.md\:chat-start .chat-header{grid-column-start:2}.md\:chat-start .chat-footer{grid-column-start:2}.md\:chat-start .chat-image{grid-column-start:1}.md\:chat-start .chat-bubble{border-end-start-radius:0;grid-column-start:2}.md\:chat-start .chat-bubble:before{inset-inline-start:-.75rem;transform:rotateY(0)}[dir=rtl] :is(.md\:chat-start .chat-bubble):before{transform:rotateY(180deg)}.md\:chat-end{grid-template-columns:1fr auto;place-items:end}.md\:chat-end .chat-header{grid-column-start:1}.md\:chat-end .chat-footer{grid-column-start:1}.md\:chat-end .chat-image{grid-column-start:2}.md\:chat-end .chat-bubble{border-end-end-radius:0;grid-column-start:1}.md\:chat-end .chat-bubble:before{inset-inline-start:100%;transform:rotateY(180deg)}[dir=rtl] :is(.md\:chat-end .chat-bubble):before{transform:rotateY(0)}}@media (min-width:1024px){.lg\:chat{column-gap:.75rem;padding-block:.25rem;display:grid}.lg\:chat-bubble{border-radius:var(--radius-field);background-color:var(--color-base-300);width:fit-content;color:var(--color-base-content);grid-row-end:3;min-width:2.5rem;max-width:90%;min-height:2rem;padding-block:.5rem;padding-inline:1rem;display:block;position:relative}.lg\:chat-bubble:before{background-color:inherit;content:"";width:.75rem;height:.75rem;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-chat);mask-image:var(--mask-chat);position:absolute;bottom:0;-webkit-mask-position:0 -1px;mask-position:0 -1px;-webkit-mask-size:13px;mask-size:13px}.lg\:chat-bubble-primary{background-color:var(--color-primary);color:var(--color-primary-content)}.lg\:chat-bubble-secondary{background-color:var(--color-secondary);color:var(--color-secondary-content)}.lg\:chat-bubble-accent{background-color:var(--color-accent);color:var(--color-accent-content)}.lg\:chat-bubble-neutral{background-color:var(--color-neutral);color:var(--color-neutral-content)}.lg\:chat-bubble-info{background-color:var(--color-info);color:var(--color-info-content)}.lg\:chat-bubble-success{background-color:var(--color-success);color:var(--color-success-content)}.lg\:chat-bubble-warning{background-color:var(--color-warning);color:var(--color-warning-content)}.lg\:chat-bubble-error{background-color:var(--color-error);color:var(--color-error-content)}.lg\:chat-image{grid-row:span 2/span 2;align-self:flex-end}.lg\:chat-header{grid-row-start:1;gap:.25rem;font-size:.6875rem;display:flex}.lg\:chat-footer{grid-row-start:3;gap:.25rem;font-size:.6875rem;display:flex}.lg\:chat-start{grid-template-columns:auto 1fr;place-items:start}.lg\:chat-start .chat-header{grid-column-start:2}.lg\:chat-start .chat-footer{grid-column-start:2}.lg\:chat-start .chat-image{grid-column-start:1}.lg\:chat-start .chat-bubble{border-end-start-radius:0;grid-column-start:2}.lg\:chat-start .chat-bubble:before{inset-inline-start:-.75rem;transform:rotateY(0)}[dir=rtl] :is(.lg\:chat-start .chat-bubble):before{transform:rotateY(180deg)}.lg\:chat-end{grid-template-columns:1fr auto;place-items:end}.lg\:chat-end .chat-header{grid-column-start:1}.lg\:chat-end .chat-footer{grid-column-start:1}.lg\:chat-end .chat-image{grid-column-start:2}.lg\:chat-end .chat-bubble{border-end-end-radius:0;grid-column-start:1}.lg\:chat-end .chat-bubble:before{inset-inline-start:100%;transform:rotateY(180deg)}[dir=rtl] :is(.lg\:chat-end .chat-bubble):before{transform:rotateY(0)}}@media (min-width:1280px){.xl\:chat{column-gap:.75rem;padding-block:.25rem;display:grid}.xl\:chat-bubble{border-radius:var(--radius-field);background-color:var(--color-base-300);width:fit-content;color:var(--color-base-content);grid-row-end:3;min-width:2.5rem;max-width:90%;min-height:2rem;padding-block:.5rem;padding-inline:1rem;display:block;position:relative}.xl\:chat-bubble:before{background-color:inherit;content:"";width:.75rem;height:.75rem;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-chat);mask-image:var(--mask-chat);position:absolute;bottom:0;-webkit-mask-position:0 -1px;mask-position:0 -1px;-webkit-mask-size:13px;mask-size:13px}.xl\:chat-bubble-primary{background-color:var(--color-primary);color:var(--color-primary-content)}.xl\:chat-bubble-secondary{background-color:var(--color-secondary);color:var(--color-secondary-content)}.xl\:chat-bubble-accent{background-color:var(--color-accent);color:var(--color-accent-content)}.xl\:chat-bubble-neutral{background-color:var(--color-neutral);color:var(--color-neutral-content)}.xl\:chat-bubble-info{background-color:var(--color-info);color:var(--color-info-content)}.xl\:chat-bubble-success{background-color:var(--color-success);color:var(--color-success-content)}.xl\:chat-bubble-warning{background-color:var(--color-warning);color:var(--color-warning-content)}.xl\:chat-bubble-error{background-color:var(--color-error);color:var(--color-error-content)}.xl\:chat-image{grid-row:span 2/span 2;align-self:flex-end}.xl\:chat-header{grid-row-start:1;gap:.25rem;font-size:.6875rem;display:flex}.xl\:chat-footer{grid-row-start:3;gap:.25rem;font-size:.6875rem;display:flex}.xl\:chat-start{grid-template-columns:auto 1fr;place-items:start}.xl\:chat-start .chat-header{grid-column-start:2}.xl\:chat-start .chat-footer{grid-column-start:2}.xl\:chat-start .chat-image{grid-column-start:1}.xl\:chat-start .chat-bubble{border-end-start-radius:0;grid-column-start:2}.xl\:chat-start .chat-bubble:before{inset-inline-start:-.75rem;transform:rotateY(0)}[dir=rtl] :is(.xl\:chat-start .chat-bubble):before{transform:rotateY(180deg)}.xl\:chat-end{grid-template-columns:1fr auto;place-items:end}.xl\:chat-end .chat-header{grid-column-start:1}.xl\:chat-end .chat-footer{grid-column-start:1}.xl\:chat-end .chat-image{grid-column-start:2}.xl\:chat-end .chat-bubble{border-end-end-radius:0;grid-column-start:1}.xl\:chat-end .chat-bubble:before{inset-inline-start:100%;transform:rotateY(180deg)}[dir=rtl] :is(.xl\:chat-end .chat-bubble):before{transform:rotateY(0)}}@media (min-width:1536px){.\32 xl\:chat{column-gap:.75rem;padding-block:.25rem;display:grid}.\32 xl\:chat-bubble{border-radius:var(--radius-field);background-color:var(--color-base-300);width:fit-content;color:var(--color-base-content);grid-row-end:3;min-width:2.5rem;max-width:90%;min-height:2rem;padding-block:.5rem;padding-inline:1rem;display:block;position:relative}.\32 xl\:chat-bubble:before{background-color:inherit;content:"";width:.75rem;height:.75rem;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-image:var(--mask-chat);mask-image:var(--mask-chat);position:absolute;bottom:0;-webkit-mask-position:0 -1px;mask-position:0 -1px;-webkit-mask-size:13px;mask-size:13px}.\32 xl\:chat-bubble-primary{background-color:var(--color-primary);color:var(--color-primary-content)}.\32 xl\:chat-bubble-secondary{background-color:var(--color-secondary);color:var(--color-secondary-content)}.\32 xl\:chat-bubble-accent{background-color:var(--color-accent);color:var(--color-accent-content)}.\32 xl\:chat-bubble-neutral{background-color:var(--color-neutral);color:var(--color-neutral-content)}.\32 xl\:chat-bubble-info{background-color:var(--color-info);color:var(--color-info-content)}.\32 xl\:chat-bubble-success{background-color:var(--color-success);color:var(--color-success-content)}.\32 xl\:chat-bubble-warning{background-color:var(--color-warning);color:var(--color-warning-content)}.\32 xl\:chat-bubble-error{background-color:var(--color-error);color:var(--color-error-content)}.\32 xl\:chat-image{grid-row:span 2/span 2;align-self:flex-end}.\32 xl\:chat-header{grid-row-start:1;gap:.25rem;font-size:.6875rem;display:flex}.\32 xl\:chat-footer{grid-row-start:3;gap:.25rem;font-size:.6875rem;display:flex}.\32 xl\:chat-start{grid-template-columns:auto 1fr;place-items:start}.\32 xl\:chat-start .chat-header{grid-column-start:2}.\32 xl\:chat-start .chat-footer{grid-column-start:2}.\32 xl\:chat-start .chat-image{grid-column-start:1}.\32 xl\:chat-start .chat-bubble{border-end-start-radius:0;grid-column-start:2}.\32 xl\:chat-start .chat-bubble:before{inset-inline-start:-.75rem;transform:rotateY(0)}[dir=rtl] :is(.\32 xl\:chat-start .chat-bubble):before{transform:rotateY(180deg)}.\32 xl\:chat-end{grid-template-columns:1fr auto;place-items:end}.\32 xl\:chat-end .chat-header{grid-column-start:1}.\32 xl\:chat-end .chat-footer{grid-column-start:1}.\32 xl\:chat-end .chat-image{grid-column-start:2}.\32 xl\:chat-end .chat-bubble{border-end-end-radius:0;grid-column-start:1}.\32 xl\:chat-end .chat-bubble:before{inset-inline-start:100%;transform:rotateY(180deg)}[dir=rtl] :is(.\32 xl\:chat-end .chat-bubble):before{transform:rotateY(0)}}.dock{z-index:1;background-color:var(--color-base-100);color:currentColor;border-top:.5px solid color-mix(in oklab,var(--color-base-content)5%,transparent);width:100%;height:4rem;height:calc(4rem + env(safe-area-inset-bottom));padding:.5rem;padding-bottom:env(safe-area-inset-bottom);flex-direction:row;justify-content:space-around;align-items:center;display:flex;position:fixed;bottom:0;left:0;right:0}.dock>*{cursor:pointer;border-radius:var(--radius-box);background-color:transparent;flex-direction:column;flex-shrink:1;flex-basis:100%;justify-content:center;align-items:center;gap:1px;max-width:8rem;height:100%;margin-bottom:.5rem;transition:opacity .2s ease-out;display:flex;position:relative}.dock>*:where(.dock-active):after{content:"";background-color:currentColor;border-top:3px solid;border-radius:3.40282e38px;width:2.5rem;height:.25rem;position:absolute;bottom:.2rem}@media (hover:hover){.dock>*:hover{opacity:.8}}.dock>*[aria-disabled=true]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.dock>*[aria-disabled=true]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.dock>*[disabled]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.dock>*[disabled]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.dock>* .dock-label{font-size:.6875rem}.dock-xs{height:3rem;height:calc(3rem + env(safe-area-inset-bottom))}.dock-xs .dock-active:after{bottom:-.1rem}.dock-xs .dock-label{font-size:.625rem}.dock-sm{height:3.5rem;height:calc(3.5rem + env(safe-area-inset-bottom))}.dock-sm .dock-active:after{bottom:-.1rem}.dock-sm .dock-label{font-size:.625rem}.dock-md{height:4rem;height:calc(4rem + env(safe-area-inset-bottom))}.dock-md .dock-label{font-size:.6875rem}.dock-lg{height:4.5rem;height:calc(4.5rem + env(safe-area-inset-bottom))}.dock-lg .dock-active:after{bottom:.4rem}.dock-lg .dock-label{font-size:.6875rem}.dock-xl{height:5rem;height:calc(5rem + env(safe-area-inset-bottom))}.dock-xl .dock-active:after{bottom:.4rem}.dock-xl .dock-label{font-size:.75rem}@media (min-width:640px){.sm\:dock{z-index:1;background-color:var(--color-base-100);color:currentColor;border-top:.5px solid color-mix(in oklab,var(--color-base-content)5%,transparent);width:100%;height:4rem;height:calc(4rem + env(safe-area-inset-bottom));padding:.5rem;padding-bottom:env(safe-area-inset-bottom);flex-direction:row;justify-content:space-around;align-items:center;display:flex;position:fixed;bottom:0;left:0;right:0}.sm\:dock>*{cursor:pointer;border-radius:var(--radius-box);background-color:transparent;flex-direction:column;flex-shrink:1;flex-basis:100%;justify-content:center;align-items:center;gap:1px;max-width:8rem;height:100%;margin-bottom:.5rem;transition:opacity .2s ease-out;display:flex;position:relative}.sm\:dock>*:where(.dock-active):after{content:"";background-color:currentColor;border-top:3px solid;border-radius:3.40282e38px;width:2.5rem;height:.25rem;position:absolute;bottom:.2rem}@media (hover:hover){.sm\:dock>*:hover{opacity:.8}}.sm\:dock>*[aria-disabled=true]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.sm\:dock>*[aria-disabled=true]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.sm\:dock>*[disabled]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.sm\:dock>*[disabled]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.sm\:dock>* .dock-label{font-size:.6875rem}.sm\:dock-xs{height:3rem;height:calc(3rem + env(safe-area-inset-bottom))}.sm\:dock-xs .dock-active:after{bottom:-.1rem}.sm\:dock-xs .dock-label{font-size:.625rem}.sm\:dock-sm{height:3.5rem;height:calc(3.5rem + env(safe-area-inset-bottom))}.sm\:dock-sm .dock-active:after{bottom:-.1rem}.sm\:dock-sm .dock-label{font-size:.625rem}.sm\:dock-md{height:4rem;height:calc(4rem + env(safe-area-inset-bottom))}.sm\:dock-md .dock-label{font-size:.6875rem}.sm\:dock-lg{height:4.5rem;height:calc(4.5rem + env(safe-area-inset-bottom))}.sm\:dock-lg .dock-active:after{bottom:.4rem}.sm\:dock-lg .dock-label{font-size:.6875rem}.sm\:dock-xl{height:5rem;height:calc(5rem + env(safe-area-inset-bottom))}.sm\:dock-xl .dock-active:after{bottom:.4rem}.sm\:dock-xl .dock-label{font-size:.75rem}}@media (min-width:768px){.md\:dock{z-index:1;background-color:var(--color-base-100);color:currentColor;border-top:.5px solid color-mix(in oklab,var(--color-base-content)5%,transparent);width:100%;height:4rem;height:calc(4rem + env(safe-area-inset-bottom));padding:.5rem;padding-bottom:env(safe-area-inset-bottom);flex-direction:row;justify-content:space-around;align-items:center;display:flex;position:fixed;bottom:0;left:0;right:0}.md\:dock>*{cursor:pointer;border-radius:var(--radius-box);background-color:transparent;flex-direction:column;flex-shrink:1;flex-basis:100%;justify-content:center;align-items:center;gap:1px;max-width:8rem;height:100%;margin-bottom:.5rem;transition:opacity .2s ease-out;display:flex;position:relative}.md\:dock>*:where(.dock-active):after{content:"";background-color:currentColor;border-top:3px solid;border-radius:3.40282e38px;width:2.5rem;height:.25rem;position:absolute;bottom:.2rem}@media (hover:hover){.md\:dock>*:hover{opacity:.8}}.md\:dock>*[aria-disabled=true]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.md\:dock>*[aria-disabled=true]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.md\:dock>*[disabled]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.md\:dock>*[disabled]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.md\:dock>* .dock-label{font-size:.6875rem}.md\:dock-xs{height:3rem;height:calc(3rem + env(safe-area-inset-bottom))}.md\:dock-xs .dock-active:after{bottom:-.1rem}.md\:dock-xs .dock-label{font-size:.625rem}.md\:dock-sm{height:3.5rem;height:calc(3.5rem + env(safe-area-inset-bottom))}.md\:dock-sm .dock-active:after{bottom:-.1rem}.md\:dock-sm .dock-label{font-size:.625rem}.md\:dock-md{height:4rem;height:calc(4rem + env(safe-area-inset-bottom))}.md\:dock-md .dock-label{font-size:.6875rem}.md\:dock-lg{height:4.5rem;height:calc(4.5rem + env(safe-area-inset-bottom))}.md\:dock-lg .dock-active:after{bottom:.4rem}.md\:dock-lg .dock-label{font-size:.6875rem}.md\:dock-xl{height:5rem;height:calc(5rem + env(safe-area-inset-bottom))}.md\:dock-xl .dock-active:after{bottom:.4rem}.md\:dock-xl .dock-label{font-size:.75rem}}@media (min-width:1024px){.lg\:dock{z-index:1;background-color:var(--color-base-100);color:currentColor;border-top:.5px solid color-mix(in oklab,var(--color-base-content)5%,transparent);width:100%;height:4rem;height:calc(4rem + env(safe-area-inset-bottom));padding:.5rem;padding-bottom:env(safe-area-inset-bottom);flex-direction:row;justify-content:space-around;align-items:center;display:flex;position:fixed;bottom:0;left:0;right:0}.lg\:dock>*{cursor:pointer;border-radius:var(--radius-box);background-color:transparent;flex-direction:column;flex-shrink:1;flex-basis:100%;justify-content:center;align-items:center;gap:1px;max-width:8rem;height:100%;margin-bottom:.5rem;transition:opacity .2s ease-out;display:flex;position:relative}.lg\:dock>*:where(.dock-active):after{content:"";background-color:currentColor;border-top:3px solid;border-radius:3.40282e38px;width:2.5rem;height:.25rem;position:absolute;bottom:.2rem}@media (hover:hover){.lg\:dock>*:hover{opacity:.8}}.lg\:dock>*[aria-disabled=true]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.lg\:dock>*[aria-disabled=true]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.lg\:dock>*[disabled]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.lg\:dock>*[disabled]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.lg\:dock>* .dock-label{font-size:.6875rem}.lg\:dock-xs{height:3rem;height:calc(3rem + env(safe-area-inset-bottom))}.lg\:dock-xs .dock-active:after{bottom:-.1rem}.lg\:dock-xs .dock-label{font-size:.625rem}.lg\:dock-sm{height:3.5rem;height:calc(3.5rem + env(safe-area-inset-bottom))}.lg\:dock-sm .dock-active:after{bottom:-.1rem}.lg\:dock-sm .dock-label{font-size:.625rem}.lg\:dock-md{height:4rem;height:calc(4rem + env(safe-area-inset-bottom))}.lg\:dock-md .dock-label{font-size:.6875rem}.lg\:dock-lg{height:4.5rem;height:calc(4.5rem + env(safe-area-inset-bottom))}.lg\:dock-lg .dock-active:after{bottom:.4rem}.lg\:dock-lg .dock-label{font-size:.6875rem}.lg\:dock-xl{height:5rem;height:calc(5rem + env(safe-area-inset-bottom))}.lg\:dock-xl .dock-active:after{bottom:.4rem}.lg\:dock-xl .dock-label{font-size:.75rem}}@media (min-width:1280px){.xl\:dock{z-index:1;background-color:var(--color-base-100);color:currentColor;border-top:.5px solid color-mix(in oklab,var(--color-base-content)5%,transparent);width:100%;height:4rem;height:calc(4rem + env(safe-area-inset-bottom));padding:.5rem;padding-bottom:env(safe-area-inset-bottom);flex-direction:row;justify-content:space-around;align-items:center;display:flex;position:fixed;bottom:0;left:0;right:0}.xl\:dock>*{cursor:pointer;border-radius:var(--radius-box);background-color:transparent;flex-direction:column;flex-shrink:1;flex-basis:100%;justify-content:center;align-items:center;gap:1px;max-width:8rem;height:100%;margin-bottom:.5rem;transition:opacity .2s ease-out;display:flex;position:relative}.xl\:dock>*:where(.dock-active):after{content:"";background-color:currentColor;border-top:3px solid;border-radius:3.40282e38px;width:2.5rem;height:.25rem;position:absolute;bottom:.2rem}@media (hover:hover){.xl\:dock>*:hover{opacity:.8}}.xl\:dock>*[aria-disabled=true]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.xl\:dock>*[aria-disabled=true]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.xl\:dock>*[disabled]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.xl\:dock>*[disabled]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.xl\:dock>* .dock-label{font-size:.6875rem}.xl\:dock-xs{height:3rem;height:calc(3rem + env(safe-area-inset-bottom))}.xl\:dock-xs .dock-active:after{bottom:-.1rem}.xl\:dock-xs .dock-label{font-size:.625rem}.xl\:dock-sm{height:3.5rem;height:calc(3.5rem + env(safe-area-inset-bottom))}.xl\:dock-sm .dock-active:after{bottom:-.1rem}.xl\:dock-sm .dock-label{font-size:.625rem}.xl\:dock-md{height:4rem;height:calc(4rem + env(safe-area-inset-bottom))}.xl\:dock-md .dock-label{font-size:.6875rem}.xl\:dock-lg{height:4.5rem;height:calc(4.5rem + env(safe-area-inset-bottom))}.xl\:dock-lg .dock-active:after{bottom:.4rem}.xl\:dock-lg .dock-label{font-size:.6875rem}.xl\:dock-xl{height:5rem;height:calc(5rem + env(safe-area-inset-bottom))}.xl\:dock-xl .dock-active:after{bottom:.4rem}.xl\:dock-xl .dock-label{font-size:.75rem}}@media (min-width:1536px){.\32 xl\:dock{z-index:1;background-color:var(--color-base-100);color:currentColor;border-top:.5px solid color-mix(in oklab,var(--color-base-content)5%,transparent);width:100%;height:4rem;height:calc(4rem + env(safe-area-inset-bottom));padding:.5rem;padding-bottom:env(safe-area-inset-bottom);flex-direction:row;justify-content:space-around;align-items:center;display:flex;position:fixed;bottom:0;left:0;right:0}.\32 xl\:dock>*{cursor:pointer;border-radius:var(--radius-box);background-color:transparent;flex-direction:column;flex-shrink:1;flex-basis:100%;justify-content:center;align-items:center;gap:1px;max-width:8rem;height:100%;margin-bottom:.5rem;transition:opacity .2s ease-out;display:flex;position:relative}.\32 xl\:dock>*:where(.dock-active):after{content:"";background-color:currentColor;border-top:3px solid;border-radius:3.40282e38px;width:2.5rem;height:.25rem;position:absolute;bottom:.2rem}@media (hover:hover){.\32 xl\:dock>*:hover{opacity:.8}}.\32 xl\:dock>*[aria-disabled=true]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.\32 xl\:dock>*[aria-disabled=true]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.\32 xl\:dock>*[disabled]{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.\32 xl\:dock>*[disabled]:hover{pointer-events:none;color:color-mix(in oklab,var(--color-base-content)10%,transparent);opacity:1}.\32 xl\:dock>* .dock-label{font-size:.6875rem}.\32 xl\:dock-xs{height:3rem;height:calc(3rem + env(safe-area-inset-bottom))}.\32 xl\:dock-xs .dock-active:after{bottom:-.1rem}.\32 xl\:dock-xs .dock-label{font-size:.625rem}.\32 xl\:dock-sm{height:3.5rem;height:calc(3.5rem + env(safe-area-inset-bottom))}.\32 xl\:dock-sm .dock-active:after{bottom:-.1rem}.\32 xl\:dock-sm .dock-label{font-size:.625rem}.\32 xl\:dock-md{height:4rem;height:calc(4rem + env(safe-area-inset-bottom))}.\32 xl\:dock-md .dock-label{font-size:.6875rem}.\32 xl\:dock-lg{height:4.5rem;height:calc(4.5rem + env(safe-area-inset-bottom))}.\32 xl\:dock-lg .dock-active:after{bottom:.4rem}.\32 xl\:dock-lg .dock-label{font-size:.6875rem}.\32 xl\:dock-xl{height:5rem;height:calc(5rem + env(safe-area-inset-bottom))}.\32 xl\:dock-xl .dock-active:after{bottom:.4rem}.\32 xl\:dock-xl .dock-label{font-size:.75rem}}.drawer{grid-auto-columns:max-content auto;width:100%;display:grid;position:relative}.drawer-content{grid-row-start:1;grid-column-start:2;min-width:0}.drawer-side{pointer-events:none;visibility:hidden;overscroll-behavior:contain;opacity:0;width:100%;transition:opacity .2s ease-out .1s allow-discrete,visibility .3s ease-out .1s allow-discrete;inset-inline-start:0;grid-template-rows:repeat(1,minmax(0,1fr));grid-template-columns:repeat(1,minmax(0,1fr));grid-row-start:1;grid-column-start:1;place-items:flex-start start;height:100dvh;display:grid;position:fixed;top:0;overflow:hidden}.drawer-side>.drawer-overlay{cursor:pointer;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);place-self:stretch stretch;position:sticky;top:0}.drawer-side>*{grid-row-start:1;grid-column-start:1}.drawer-side>:not(.drawer-overlay){will-change:transform;transition:translate .3s ease-out;translate:-100%}[dir=rtl] :is(.drawer-side>:not(.drawer-overlay)){translate:100%}.drawer-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible;opacity:1;overflow-y:auto}.drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.drawer-toggle:focus-visible~.drawer-content label.drawer-button{outline-offset:2px;outline:2px solid}.drawer-end{grid-auto-columns:auto max-content}.drawer-end>.drawer-toggle~.drawer-content{grid-column-start:1}.drawer-end>.drawer-toggle~.drawer-side{grid-column-start:2;justify-items:end}.drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:100%}[dir=rtl] :is(.drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:-100%}.drawer-end>.drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.drawer-open>.drawer-side{overflow-y:auto}.drawer-open>.drawer-toggle{display:none}.drawer-open>.drawer-toggle~.drawer-side{pointer-events:auto;visibility:visible;overscroll-behavior:auto;opacity:1;width:auto;display:block;position:sticky}.drawer-open>.drawer-toggle~.drawer-side>.drawer-overlay{cursor:default;background-color:transparent}.drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:0%}[dir=rtl] :is(.drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:0%}.drawer-open>.drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible}@media (min-width:640px){.sm\:drawer{grid-auto-columns:max-content auto;width:100%;display:grid;position:relative}.sm\:drawer-content{grid-row-start:1;grid-column-start:2;min-width:0}.sm\:drawer-side{pointer-events:none;visibility:hidden;overscroll-behavior:contain;opacity:0;width:100%;transition:opacity .2s ease-out .1s allow-discrete,visibility .3s ease-out .1s allow-discrete;inset-inline-start:0;grid-template-rows:repeat(1,minmax(0,1fr));grid-template-columns:repeat(1,minmax(0,1fr));grid-row-start:1;grid-column-start:1;place-items:flex-start start;height:100dvh;display:grid;position:fixed;top:0;overflow:hidden}.sm\:drawer-side>.drawer-overlay{cursor:pointer;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);place-self:stretch stretch;position:sticky;top:0}.sm\:drawer-side>*{grid-row-start:1;grid-column-start:1}.sm\:drawer-side>:not(.drawer-overlay){will-change:transform;transition:translate .3s ease-out;translate:-100%}[dir=rtl] :is(.sm\:drawer-side>:not(.drawer-overlay)){translate:100%}.sm\:drawer-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.sm\:drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible;opacity:1;overflow-y:auto}.sm\:drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.sm\:drawer-toggle:focus-visible~.drawer-content label.drawer-button{outline-offset:2px;outline:2px solid}.sm\:drawer-end{grid-auto-columns:auto max-content}.sm\:drawer-end>.drawer-toggle~.drawer-content{grid-column-start:1}.sm\:drawer-end>.drawer-toggle~.drawer-side{grid-column-start:2;justify-items:end}.sm\:drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:100%}[dir=rtl] :is(.sm\:drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:-100%}.sm\:drawer-end>.drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.sm\:drawer-open>.drawer-side{overflow-y:auto}.sm\:drawer-open>.drawer-toggle{display:none}.sm\:drawer-open>.drawer-toggle~.drawer-side{pointer-events:auto;visibility:visible;overscroll-behavior:auto;opacity:1;width:auto;display:block;position:sticky}.sm\:drawer-open>.drawer-toggle~.drawer-side>.drawer-overlay{cursor:default;background-color:transparent}.sm\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:0%}[dir=rtl] :is(.sm\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:0%}.sm\:drawer-open>.drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible}}@media (min-width:768px){.md\:drawer{grid-auto-columns:max-content auto;width:100%;display:grid;position:relative}.md\:drawer-content{grid-row-start:1;grid-column-start:2;min-width:0}.md\:drawer-side{pointer-events:none;visibility:hidden;overscroll-behavior:contain;opacity:0;width:100%;transition:opacity .2s ease-out .1s allow-discrete,visibility .3s ease-out .1s allow-discrete;inset-inline-start:0;grid-template-rows:repeat(1,minmax(0,1fr));grid-template-columns:repeat(1,minmax(0,1fr));grid-row-start:1;grid-column-start:1;place-items:flex-start start;height:100dvh;display:grid;position:fixed;top:0;overflow:hidden}.md\:drawer-side>.drawer-overlay{cursor:pointer;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);place-self:stretch stretch;position:sticky;top:0}.md\:drawer-side>*{grid-row-start:1;grid-column-start:1}.md\:drawer-side>:not(.drawer-overlay){will-change:transform;transition:translate .3s ease-out;translate:-100%}[dir=rtl] :is(.md\:drawer-side>:not(.drawer-overlay)){translate:100%}.md\:drawer-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.md\:drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible;opacity:1;overflow-y:auto}.md\:drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.md\:drawer-toggle:focus-visible~.drawer-content label.drawer-button{outline-offset:2px;outline:2px solid}.md\:drawer-end{grid-auto-columns:auto max-content}.md\:drawer-end>.drawer-toggle~.drawer-content{grid-column-start:1}.md\:drawer-end>.drawer-toggle~.drawer-side{grid-column-start:2;justify-items:end}.md\:drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:100%}[dir=rtl] :is(.md\:drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:-100%}.md\:drawer-end>.drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.md\:drawer-open>.drawer-side{overflow-y:auto}.md\:drawer-open>.drawer-toggle{display:none}.md\:drawer-open>.drawer-toggle~.drawer-side{pointer-events:auto;visibility:visible;overscroll-behavior:auto;opacity:1;width:auto;display:block;position:sticky}.md\:drawer-open>.drawer-toggle~.drawer-side>.drawer-overlay{cursor:default;background-color:transparent}.md\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:0%}[dir=rtl] :is(.md\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:0%}.md\:drawer-open>.drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible}}@media (min-width:1024px){.lg\:drawer{grid-auto-columns:max-content auto;width:100%;display:grid;position:relative}.lg\:drawer-content{grid-row-start:1;grid-column-start:2;min-width:0}.lg\:drawer-side{pointer-events:none;visibility:hidden;overscroll-behavior:contain;opacity:0;width:100%;transition:opacity .2s ease-out .1s allow-discrete,visibility .3s ease-out .1s allow-discrete;inset-inline-start:0;grid-template-rows:repeat(1,minmax(0,1fr));grid-template-columns:repeat(1,minmax(0,1fr));grid-row-start:1;grid-column-start:1;place-items:flex-start start;height:100dvh;display:grid;position:fixed;top:0;overflow:hidden}.lg\:drawer-side>.drawer-overlay{cursor:pointer;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);place-self:stretch stretch;position:sticky;top:0}.lg\:drawer-side>*{grid-row-start:1;grid-column-start:1}.lg\:drawer-side>:not(.drawer-overlay){will-change:transform;transition:translate .3s ease-out;translate:-100%}[dir=rtl] :is(.lg\:drawer-side>:not(.drawer-overlay)){translate:100%}.lg\:drawer-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.lg\:drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible;opacity:1;overflow-y:auto}.lg\:drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.lg\:drawer-toggle:focus-visible~.drawer-content label.drawer-button{outline-offset:2px;outline:2px solid}.lg\:drawer-end{grid-auto-columns:auto max-content}.lg\:drawer-end>.drawer-toggle~.drawer-content{grid-column-start:1}.lg\:drawer-end>.drawer-toggle~.drawer-side{grid-column-start:2;justify-items:end}.lg\:drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:100%}[dir=rtl] :is(.lg\:drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:-100%}.lg\:drawer-end>.drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.lg\:drawer-open>.drawer-side{overflow-y:auto}.lg\:drawer-open>.drawer-toggle{display:none}.lg\:drawer-open>.drawer-toggle~.drawer-side{pointer-events:auto;visibility:visible;overscroll-behavior:auto;opacity:1;width:auto;display:block;position:sticky}.lg\:drawer-open>.drawer-toggle~.drawer-side>.drawer-overlay{cursor:default;background-color:transparent}.lg\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:0%}[dir=rtl] :is(.lg\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:0%}.lg\:drawer-open>.drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible}}@media (min-width:1280px){.xl\:drawer{grid-auto-columns:max-content auto;width:100%;display:grid;position:relative}.xl\:drawer-content{grid-row-start:1;grid-column-start:2;min-width:0}.xl\:drawer-side{pointer-events:none;visibility:hidden;overscroll-behavior:contain;opacity:0;width:100%;transition:opacity .2s ease-out .1s allow-discrete,visibility .3s ease-out .1s allow-discrete;inset-inline-start:0;grid-template-rows:repeat(1,minmax(0,1fr));grid-template-columns:repeat(1,minmax(0,1fr));grid-row-start:1;grid-column-start:1;place-items:flex-start start;height:100dvh;display:grid;position:fixed;top:0;overflow:hidden}.xl\:drawer-side>.drawer-overlay{cursor:pointer;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);place-self:stretch stretch;position:sticky;top:0}.xl\:drawer-side>*{grid-row-start:1;grid-column-start:1}.xl\:drawer-side>:not(.drawer-overlay){will-change:transform;transition:translate .3s ease-out;translate:-100%}[dir=rtl] :is(.xl\:drawer-side>:not(.drawer-overlay)){translate:100%}.xl\:drawer-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.xl\:drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible;opacity:1;overflow-y:auto}.xl\:drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.xl\:drawer-toggle:focus-visible~.drawer-content label.drawer-button{outline-offset:2px;outline:2px solid}.xl\:drawer-end{grid-auto-columns:auto max-content}.xl\:drawer-end>.drawer-toggle~.drawer-content{grid-column-start:1}.xl\:drawer-end>.drawer-toggle~.drawer-side{grid-column-start:2;justify-items:end}.xl\:drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:100%}[dir=rtl] :is(.xl\:drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:-100%}.xl\:drawer-end>.drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.xl\:drawer-open>.drawer-side{overflow-y:auto}.xl\:drawer-open>.drawer-toggle{display:none}.xl\:drawer-open>.drawer-toggle~.drawer-side{pointer-events:auto;visibility:visible;overscroll-behavior:auto;opacity:1;width:auto;display:block;position:sticky}.xl\:drawer-open>.drawer-toggle~.drawer-side>.drawer-overlay{cursor:default;background-color:transparent}.xl\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:0%}[dir=rtl] :is(.xl\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:0%}.xl\:drawer-open>.drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible}}@media (min-width:1536px){.\32 xl\:drawer{grid-auto-columns:max-content auto;width:100%;display:grid;position:relative}.\32 xl\:drawer-content{grid-row-start:1;grid-column-start:2;min-width:0}.\32 xl\:drawer-side{pointer-events:none;visibility:hidden;overscroll-behavior:contain;opacity:0;width:100%;transition:opacity .2s ease-out .1s allow-discrete,visibility .3s ease-out .1s allow-discrete;inset-inline-start:0;grid-template-rows:repeat(1,minmax(0,1fr));grid-template-columns:repeat(1,minmax(0,1fr));grid-row-start:1;grid-column-start:1;place-items:flex-start start;height:100dvh;display:grid;position:fixed;top:0;overflow:hidden}.\32 xl\:drawer-side>.drawer-overlay{cursor:pointer;background-color:rgba(0,0,0,.4);background-color:lab(0% 0 0/.4);place-self:stretch stretch;position:sticky;top:0}.\32 xl\:drawer-side>*{grid-row-start:1;grid-column-start:1}.\32 xl\:drawer-side>:not(.drawer-overlay){will-change:transform;transition:translate .3s ease-out;translate:-100%}[dir=rtl] :is(.\32 xl\:drawer-side>:not(.drawer-overlay)){translate:100%}.\32 xl\:drawer-toggle{appearance:none;opacity:0;width:0;height:0;position:fixed}.\32 xl\:drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible;opacity:1;overflow-y:auto}.\32 xl\:drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.\32 xl\:drawer-toggle:focus-visible~.drawer-content label.drawer-button{outline-offset:2px;outline:2px solid}.\32 xl\:drawer-end{grid-auto-columns:auto max-content}.\32 xl\:drawer-end>.drawer-toggle~.drawer-content{grid-column-start:1}.\32 xl\:drawer-end>.drawer-toggle~.drawer-side{grid-column-start:2;justify-items:end}.\32 xl\:drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:100%}[dir=rtl] :is(.\32 xl\:drawer-end>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:-100%}.\32 xl\:drawer-end>.drawer-toggle:checked~.drawer-side>:not(.drawer-overlay){translate:0%}.\32 xl\:drawer-open>.drawer-side{overflow-y:auto}.\32 xl\:drawer-open>.drawer-toggle{display:none}.\32 xl\:drawer-open>.drawer-toggle~.drawer-side{pointer-events:auto;visibility:visible;overscroll-behavior:auto;opacity:1;width:auto;display:block;position:sticky}.\32 xl\:drawer-open>.drawer-toggle~.drawer-side>.drawer-overlay{cursor:default;background-color:transparent}.\32 xl\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay){translate:0%}[dir=rtl] :is(.\32 xl\:drawer-open>.drawer-toggle~.drawer-side>:not(.drawer-overlay)){translate:0%}.\32 xl\:drawer-open>.drawer-toggle:checked~.drawer-side{pointer-events:auto;visibility:visible}}.mask{vertical-align:middle;display:inline-block;-webkit-mask-position:50%;mask-position:50%;-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.mask-half-1{-webkit-mask-position:0;mask-position:0;-webkit-mask-size:200%;mask-size:200%}.mask-half-1:where(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)),[dir=rtl],[dir=rtl] *){-webkit-mask-position:100%;mask-position:100%}.mask-half-2{-webkit-mask-position:100%;mask-position:100%;-webkit-mask-size:200%;mask-size:200%}.mask-half-2:where(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)),[dir=rtl],[dir=rtl] *){-webkit-mask-position:0;mask-position:0}.mask-squircle{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M100 0C20 0 0 20 0 100s20 100 100 100 100-20 100-100S180 0 100 0Z'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M100 0C20 0 0 20 0 100s20 100 100 100 100-20 100-100S180 0 100 0Z'/%3e%3c/svg%3e")}.mask-decagon{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='192' height='200' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m96 0 58.779 19.098 36.327 50v61.804l-36.327 50L96 200l-58.779-19.098-36.327-50V69.098l36.327-50z' fill-rule='evenodd'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='192' height='200' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m96 0 58.779 19.098 36.327 50v61.804l-36.327 50L96 200l-58.779-19.098-36.327-50V69.098l36.327-50z' fill-rule='evenodd'/%3e%3c/svg%3e")}.mask-diamond{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m100 0 100 100-100 100L0 100z' fill-rule='evenodd'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m100 0 100 100-100 100L0 100z' fill-rule='evenodd'/%3e%3c/svg%3e")}.mask-heart{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='200' height='185' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M100 184.606a15.384 15.384 0 0 1-8.653-2.678C53.565 156.28 37.205 138.695 28.182 127.7 8.952 104.264-.254 80.202.005 54.146.308 24.287 24.264 0 53.406 0c21.192 0 35.869 11.937 44.416 21.879a2.884 2.884 0 0 0 4.356 0C110.725 11.927 125.402 0 146.594 0c29.142 0 53.098 24.287 53.4 54.151.26 26.061-8.956 50.122-28.176 73.554-9.023 10.994-25.383 28.58-63.165 54.228a15.384 15.384 0 0 1-8.653 2.673Z' fill='black' fill-rule='nonzero'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='200' height='185' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M100 184.606a15.384 15.384 0 0 1-8.653-2.678C53.565 156.28 37.205 138.695 28.182 127.7 8.952 104.264-.254 80.202.005 54.146.308 24.287 24.264 0 53.406 0c21.192 0 35.869 11.937 44.416 21.879a2.884 2.884 0 0 0 4.356 0C110.725 11.927 125.402 0 146.594 0c29.142 0 53.098 24.287 53.4 54.151.26 26.061-8.956 50.122-28.176 73.554-9.023 10.994-25.383 28.58-63.165 54.228a15.384 15.384 0 0 1-8.653 2.673Z' fill='black' fill-rule='nonzero'/%3e%3c/svg%3e")}.mask-hexagon{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='182' height='201' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M.3 65.486c0-9.196 6.687-20.063 14.211-25.078l61.86-35.946c8.36-5.016 20.899-5.016 29.258 0l61.86 35.946c8.36 5.015 14.211 15.882 14.211 25.078v71.055c0 9.196-6.687 20.063-14.211 25.079l-61.86 35.945c-8.36 4.18-20.899 4.18-29.258 0L14.51 161.62C6.151 157.44.3 145.737.3 136.54V65.486Z' fill='black' fill-rule='nonzero'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='182' height='201' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M.3 65.486c0-9.196 6.687-20.063 14.211-25.078l61.86-35.946c8.36-5.016 20.899-5.016 29.258 0l61.86 35.946c8.36 5.015 14.211 15.882 14.211 25.078v71.055c0 9.196-6.687 20.063-14.211 25.079l-61.86 35.945c-8.36 4.18-20.899 4.18-29.258 0L14.51 161.62C6.151 157.44.3 145.737.3 136.54V65.486Z' fill='black' fill-rule='nonzero'/%3e%3c/svg%3e")}.mask-hexagon-2{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='200' height='182' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M64.786 181.4c-9.196 0-20.063-6.687-25.079-14.21L3.762 105.33c-5.016-8.36-5.016-20.9 0-29.259l35.945-61.86C44.723 5.851 55.59 0 64.786 0h71.055c9.196 0 20.063 6.688 25.079 14.211l35.945 61.86c4.18 8.36 4.18 20.899 0 29.258l-35.945 61.86c-4.18 8.36-15.883 14.211-25.079 14.211H64.786Z' fill='black' fill-rule='nonzero'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='200' height='182' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M64.786 181.4c-9.196 0-20.063-6.687-25.079-14.21L3.762 105.33c-5.016-8.36-5.016-20.9 0-29.259l35.945-61.86C44.723 5.851 55.59 0 64.786 0h71.055c9.196 0 20.063 6.688 25.079 14.211l35.945 61.86c4.18 8.36 4.18 20.899 0 29.258l-35.945 61.86c-4.18 8.36-15.883 14.211-25.079 14.211H64.786Z' fill='black' fill-rule='nonzero'/%3e%3c/svg%3e")}.mask-circle{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle fill='black' cx='100' cy='100' r='100' fill-rule='evenodd'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle fill='black' cx='100' cy='100' r='100' fill-rule='evenodd'/%3e%3c/svg%3e")}.mask-pentagon{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='192' height='181' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m96 0 95.106 69.098-36.327 111.804H37.22L.894 69.098z' fill-rule='evenodd'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='192' height='181' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m96 0 95.106 69.098-36.327 111.804H37.22L.894 69.098z' fill-rule='evenodd'/%3e%3c/svg%3e")}.mask-star{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='192' height='180' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m96 137.263-58.779 42.024 22.163-68.389L.894 68.481l72.476-.243L96 0l22.63 68.238 72.476.243-58.49 42.417 22.163 68.389z' fill-rule='evenodd'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='192' height='180' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m96 137.263-58.779 42.024 22.163-68.389L.894 68.481l72.476-.243L96 0l22.63 68.238 72.476.243-58.49 42.417 22.163 68.389z' fill-rule='evenodd'/%3e%3c/svg%3e")}.mask-star-2{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='192' height='180' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m96 153.044-58.779 26.243 7.02-63.513L.894 68.481l63.117-13.01L96 0l31.989 55.472 63.117 13.01-43.347 47.292 7.02 63.513z' fill-rule='evenodd'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='192' height='180' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m96 153.044-58.779 26.243 7.02-63.513L.894 68.481l63.117-13.01L96 0l31.989 55.472 63.117 13.01-43.347 47.292 7.02 63.513z' fill-rule='evenodd'/%3e%3c/svg%3e")}.mask-triangle{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='174' height='149' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m87 148.476-86.603.185L43.86 74.423 87 0l43.14 74.423 43.463 74.238z' fill-rule='evenodd'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='174' height='149' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m87 148.476-86.603.185L43.86 74.423 87 0l43.14 74.423 43.463 74.238z' fill-rule='evenodd'/%3e%3c/svg%3e")}.mask-triangle-2{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='174' height='150' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m87 .738 86.603-.184-43.463 74.238L87 149.214 43.86 74.792.397.554z' fill-rule='evenodd'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='174' height='150' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m87 .738 86.603-.184-43.463 74.238L87 149.214 43.86 74.792.397.554z' fill-rule='evenodd'/%3e%3c/svg%3e")}.mask-triangle-3{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='150' height='174' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m149.369 87.107.185 86.603-74.239-43.463L.893 87.107l74.422-43.14L149.554.505z' fill-rule='evenodd'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='150' height='174' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m149.369 87.107.185 86.603-74.239-43.463L.893 87.107l74.422-43.14L149.554.505z' fill-rule='evenodd'/%3e%3c/svg%3e")}.mask-triangle-4{-webkit-mask-image:url("data:image/svg+xml,%3csvg width='150' height='174' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='M.631 87.107.446.505l74.239 43.462 74.422 43.14-74.422 43.14L.446 173.71z' fill-rule='evenodd'/%3e%3c/svg%3e");mask-image:url("data:image/svg+xml,%3csvg width='150' height='174' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='M.631 87.107.446.505l74.239 43.462 74.422 43.14-74.422 43.14L.446 173.71z' fill-rule='evenodd'/%3e%3c/svg%3e")}.label{white-space:nowrap;color:color-mix(in oklab,currentColor 60%,transparent);align-items:center;gap:.375rem;display:inline-flex}.label:has(input){cursor:pointer}.label:is(.input>*,.select>*){white-space:nowrap;height:calc(100% - .5rem);font-size:inherit;align-items:center;padding-inline:.75rem;display:flex}.label:is(.input>*,.select>*):first-child{border-inline-end:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:-.75rem .75rem}.label:is(.input>*,.select>*):last-child{border-inline-start:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:.75rem -.75rem}.floating-label{display:block;position:relative}.floating-label input{display:block}.floating-label input::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.floating-label textarea::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.floating-label>span{z-index:1;background-color:var(--color-base-100);opacity:0;inset-inline-start:.75rem;top:calc(var(--size-field,.25rem)*10/2);pointer-events:none;border-radius:2px;padding-inline:.25rem;font-size:.875rem;line-height:1;transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out;position:absolute;translate:0 -50%}.floating-label:focus-within ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.floating-label:focus-within>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown)) ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown))>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.floating-label:has(:disabled,[disabled])>span{opacity:0}.floating-label:has(.input-xs,.select-xs,.textarea-xs) span{top:calc(var(--size-field,.25rem)*6/2);font-size:.6875rem}.floating-label:has(.input-sm,.select-sm,.textarea-sm) span{top:calc(var(--size-field,.25rem)*8/2);font-size:.75rem}.floating-label:has(.input-md,.select-md,.textarea-md) span{top:calc(var(--size-field,.25rem)*10/2);font-size:.875rem}.floating-label:has(.input-lg,.select-lg,.textarea-lg) span{top:calc(var(--size-field,.25rem)*12/2);font-size:1.125rem}.floating-label:has(.input-xl,.select-xl,.textarea-xl) span{top:calc(var(--size-field,.25rem)*14/2);font-size:1.375rem}@media (min-width:640px){.sm\:label{white-space:nowrap;color:color-mix(in oklab,currentColor 60%,transparent);align-items:center;gap:.375rem;display:inline-flex}.sm\:label:has(input){cursor:pointer}.sm\:label:is(.input>*,.select>*){white-space:nowrap;height:calc(100% - .5rem);font-size:inherit;align-items:center;padding-inline:.75rem;display:flex}.sm\:label:is(.input>*,.select>*):first-child{border-inline-end:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:-.75rem .75rem}.sm\:label:is(.input>*,.select>*):last-child{border-inline-start:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:.75rem -.75rem}.sm\:floating-label{display:block;position:relative}.sm\:floating-label input{display:block}.sm\:floating-label input::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.sm\:floating-label textarea::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.sm\:floating-label>span{z-index:1;background-color:var(--color-base-100);opacity:0;inset-inline-start:.75rem;top:calc(var(--size-field,.25rem)*10/2);pointer-events:none;border-radius:2px;padding-inline:.25rem;font-size:.875rem;line-height:1;transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out;position:absolute;translate:0 -50%}.sm\:floating-label:focus-within ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.sm\:floating-label:focus-within>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.sm\:floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown)) ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.sm\:floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown))>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.sm\:floating-label:has(:disabled,[disabled])>span{opacity:0}.sm\:floating-label:has(.input-xs,.select-xs,.textarea-xs) span{top:calc(var(--size-field,.25rem)*6/2);font-size:.6875rem}.sm\:floating-label:has(.input-sm,.select-sm,.textarea-sm) span{top:calc(var(--size-field,.25rem)*8/2);font-size:.75rem}.sm\:floating-label:has(.input-md,.select-md,.textarea-md) span{top:calc(var(--size-field,.25rem)*10/2);font-size:.875rem}.sm\:floating-label:has(.input-lg,.select-lg,.textarea-lg) span{top:calc(var(--size-field,.25rem)*12/2);font-size:1.125rem}.sm\:floating-label:has(.input-xl,.select-xl,.textarea-xl) span{top:calc(var(--size-field,.25rem)*14/2);font-size:1.375rem}}@media (min-width:768px){.md\:label{white-space:nowrap;color:color-mix(in oklab,currentColor 60%,transparent);align-items:center;gap:.375rem;display:inline-flex}.md\:label:has(input){cursor:pointer}.md\:label:is(.input>*,.select>*){white-space:nowrap;height:calc(100% - .5rem);font-size:inherit;align-items:center;padding-inline:.75rem;display:flex}.md\:label:is(.input>*,.select>*):first-child{border-inline-end:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:-.75rem .75rem}.md\:label:is(.input>*,.select>*):last-child{border-inline-start:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:.75rem -.75rem}.md\:floating-label{display:block;position:relative}.md\:floating-label input{display:block}.md\:floating-label input::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.md\:floating-label textarea::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.md\:floating-label>span{z-index:1;background-color:var(--color-base-100);opacity:0;inset-inline-start:.75rem;top:calc(var(--size-field,.25rem)*10/2);pointer-events:none;border-radius:2px;padding-inline:.25rem;font-size:.875rem;line-height:1;transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out;position:absolute;translate:0 -50%}.md\:floating-label:focus-within ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.md\:floating-label:focus-within>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.md\:floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown)) ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.md\:floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown))>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.md\:floating-label:has(:disabled,[disabled])>span{opacity:0}.md\:floating-label:has(.input-xs,.select-xs,.textarea-xs) span{top:calc(var(--size-field,.25rem)*6/2);font-size:.6875rem}.md\:floating-label:has(.input-sm,.select-sm,.textarea-sm) span{top:calc(var(--size-field,.25rem)*8/2);font-size:.75rem}.md\:floating-label:has(.input-md,.select-md,.textarea-md) span{top:calc(var(--size-field,.25rem)*10/2);font-size:.875rem}.md\:floating-label:has(.input-lg,.select-lg,.textarea-lg) span{top:calc(var(--size-field,.25rem)*12/2);font-size:1.125rem}.md\:floating-label:has(.input-xl,.select-xl,.textarea-xl) span{top:calc(var(--size-field,.25rem)*14/2);font-size:1.375rem}}@media (min-width:1024px){.lg\:label{white-space:nowrap;color:color-mix(in oklab,currentColor 60%,transparent);align-items:center;gap:.375rem;display:inline-flex}.lg\:label:has(input){cursor:pointer}.lg\:label:is(.input>*,.select>*){white-space:nowrap;height:calc(100% - .5rem);font-size:inherit;align-items:center;padding-inline:.75rem;display:flex}.lg\:label:is(.input>*,.select>*):first-child{border-inline-end:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:-.75rem .75rem}.lg\:label:is(.input>*,.select>*):last-child{border-inline-start:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:.75rem -.75rem}.lg\:floating-label{display:block;position:relative}.lg\:floating-label input{display:block}.lg\:floating-label input::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.lg\:floating-label textarea::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.lg\:floating-label>span{z-index:1;background-color:var(--color-base-100);opacity:0;inset-inline-start:.75rem;top:calc(var(--size-field,.25rem)*10/2);pointer-events:none;border-radius:2px;padding-inline:.25rem;font-size:.875rem;line-height:1;transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out;position:absolute;translate:0 -50%}.lg\:floating-label:focus-within ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.lg\:floating-label:focus-within>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.lg\:floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown)) ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.lg\:floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown))>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.lg\:floating-label:has(:disabled,[disabled])>span{opacity:0}.lg\:floating-label:has(.input-xs,.select-xs,.textarea-xs) span{top:calc(var(--size-field,.25rem)*6/2);font-size:.6875rem}.lg\:floating-label:has(.input-sm,.select-sm,.textarea-sm) span{top:calc(var(--size-field,.25rem)*8/2);font-size:.75rem}.lg\:floating-label:has(.input-md,.select-md,.textarea-md) span{top:calc(var(--size-field,.25rem)*10/2);font-size:.875rem}.lg\:floating-label:has(.input-lg,.select-lg,.textarea-lg) span{top:calc(var(--size-field,.25rem)*12/2);font-size:1.125rem}.lg\:floating-label:has(.input-xl,.select-xl,.textarea-xl) span{top:calc(var(--size-field,.25rem)*14/2);font-size:1.375rem}}@media (min-width:1280px){.xl\:label{white-space:nowrap;color:color-mix(in oklab,currentColor 60%,transparent);align-items:center;gap:.375rem;display:inline-flex}.xl\:label:has(input){cursor:pointer}.xl\:label:is(.input>*,.select>*){white-space:nowrap;height:calc(100% - .5rem);font-size:inherit;align-items:center;padding-inline:.75rem;display:flex}.xl\:label:is(.input>*,.select>*):first-child{border-inline-end:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:-.75rem .75rem}.xl\:label:is(.input>*,.select>*):last-child{border-inline-start:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:.75rem -.75rem}.xl\:floating-label{display:block;position:relative}.xl\:floating-label input{display:block}.xl\:floating-label input::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.xl\:floating-label textarea::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.xl\:floating-label>span{z-index:1;background-color:var(--color-base-100);opacity:0;inset-inline-start:.75rem;top:calc(var(--size-field,.25rem)*10/2);pointer-events:none;border-radius:2px;padding-inline:.25rem;font-size:.875rem;line-height:1;transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out;position:absolute;translate:0 -50%}.xl\:floating-label:focus-within ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.xl\:floating-label:focus-within>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.xl\:floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown)) ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.xl\:floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown))>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.xl\:floating-label:has(:disabled,[disabled])>span{opacity:0}.xl\:floating-label:has(.input-xs,.select-xs,.textarea-xs) span{top:calc(var(--size-field,.25rem)*6/2);font-size:.6875rem}.xl\:floating-label:has(.input-sm,.select-sm,.textarea-sm) span{top:calc(var(--size-field,.25rem)*8/2);font-size:.75rem}.xl\:floating-label:has(.input-md,.select-md,.textarea-md) span{top:calc(var(--size-field,.25rem)*10/2);font-size:.875rem}.xl\:floating-label:has(.input-lg,.select-lg,.textarea-lg) span{top:calc(var(--size-field,.25rem)*12/2);font-size:1.125rem}.xl\:floating-label:has(.input-xl,.select-xl,.textarea-xl) span{top:calc(var(--size-field,.25rem)*14/2);font-size:1.375rem}}@media (min-width:1536px){.\32 xl\:label{white-space:nowrap;color:color-mix(in oklab,currentColor 60%,transparent);align-items:center;gap:.375rem;display:inline-flex}.\32 xl\:label:has(input){cursor:pointer}.\32 xl\:label:is(.input>*,.select>*){white-space:nowrap;height:calc(100% - .5rem);font-size:inherit;align-items:center;padding-inline:.75rem;display:flex}.\32 xl\:label:is(.input>*,.select>*):first-child{border-inline-end:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:-.75rem .75rem}.\32 xl\:label:is(.input>*,.select>*):last-child{border-inline-start:var(--border)solid color-mix(in oklab,currentColor 10%,transparent);margin-inline:.75rem -.75rem}.\32 xl\:floating-label{display:block;position:relative}.\32 xl\:floating-label input{display:block}.\32 xl\:floating-label input::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.\32 xl\:floating-label textarea::placeholder{transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out}.\32 xl\:floating-label>span{z-index:1;background-color:var(--color-base-100);opacity:0;inset-inline-start:.75rem;top:calc(var(--size-field,.25rem)*10/2);pointer-events:none;border-radius:2px;padding-inline:.25rem;font-size:.875rem;line-height:1;transition:top .1s ease-out,translate .1s ease-out,scale .1s ease-out,opacity .1s ease-out;position:absolute;translate:0 -50%}.\32 xl\:floating-label:focus-within ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.\32 xl\:floating-label:focus-within>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.\32 xl\:floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown)) ::placeholder{opacity:0;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.\32 xl\:floating-label:not(:has(input:placeholder-shown,textarea:placeholder-shown))>span{opacity:1;pointer-events:auto;top:0;translate:-12.5% calc(-50% - .125em);scale:.75}.\32 xl\:floating-label:has(:disabled,[disabled])>span{opacity:0}.\32 xl\:floating-label:has(.input-xs,.select-xs,.textarea-xs) span{top:calc(var(--size-field,.25rem)*6/2);font-size:.6875rem}.\32 xl\:floating-label:has(.input-sm,.select-sm,.textarea-sm) span{top:calc(var(--size-field,.25rem)*8/2);font-size:.75rem}.\32 xl\:floating-label:has(.input-md,.select-md,.textarea-md) span{top:calc(var(--size-field,.25rem)*10/2);font-size:.875rem}.\32 xl\:floating-label:has(.input-lg,.select-lg,.textarea-lg) span{top:calc(var(--size-field,.25rem)*12/2);font-size:1.125rem}.\32 xl\:floating-label:has(.input-xl,.select-xl,.textarea-xl) span{top:calc(var(--size-field,.25rem)*14/2);font-size:1.375rem}}.diff{-webkit-user-select:none;user-select:none;direction:ltr;grid-template-columns:auto 1fr;width:100%;display:grid;position:relative;overflow:hidden;container-type:inline-size}.diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.diff:has(.diff-item-1:focus){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.diff:focus-visible .diff-resizer{min-width:90cqi;max-width:90cqi}.diff:has(.diff-item-2:focus-visible){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px}.diff:has(.diff-item-2:focus-visible) .diff-resizer{min-width:10cqi;max-width:10cqi}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.diff:focus .diff-resizer{min-width:10cqi;max-width:10cqi}.diff:has(.diff-item-1:focus) .diff-resizer{min-width:90cqi;max-width:90cqi}}.diff-resizer{z-index:1;resize:horizontal;opacity:0;cursor:ew-resize;transform-origin:100% 100%;clip-path:inset(calc(100% - .75rem) 0 0 calc(100% - .75rem));grid-row-start:1;grid-column-start:1;width:50cqi;min-width:1rem;max-width:calc(100cqi - 1rem);height:.5rem;transition:min-width .3s ease-out,max-width .3s ease-out;position:relative;top:50%;overflow:hidden;transform:scaleY(3)translate(.35rem,.08rem)}.diff-item-2{grid-row-start:1;grid-column-start:1;position:relative}.diff-item-2:after{pointer-events:none;z-index:2;background-color:color-mix(in oklab,var(--color-base-100)50%,transparent);border:2px solid var(--color-base-100);content:"";outline:1px solid color-mix(in oklab,var(--color-base-content)5%,transparent);outline-offset:-3px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:3.40282e38px;width:1.2rem;height:1.8rem;position:absolute;top:50%;bottom:0;right:1px;translate:50% -50%;box-shadow:0 1px 2px rgba(0,0,0,.1);box-shadow:0 1px 2px lab(0% 0 0/.1)}.diff-item-2>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.diff-item-2:after{content:none}}.diff-item-1{z-index:1;border-right:2px solid var(--color-base-100);grid-row-start:1;grid-column-start:1;position:relative;overflow:hidden}.diff-item-1>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}@media (min-width:640px){.sm\:diff{-webkit-user-select:none;user-select:none;direction:ltr;grid-template-columns:auto 1fr;width:100%;display:grid;position:relative;overflow:hidden;container-type:inline-size}.sm\:diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.sm\:diff:has(.diff-item-1:focus){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.sm\:diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.sm\:diff:focus-visible .diff-resizer{min-width:90cqi;max-width:90cqi}.sm\:diff:has(.diff-item-2:focus-visible){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px}.sm\:diff:has(.diff-item-2:focus-visible) .diff-resizer{min-width:10cqi;max-width:10cqi}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.sm\:diff:focus .diff-resizer{min-width:10cqi;max-width:10cqi}.sm\:diff:has(.diff-item-1:focus) .diff-resizer{min-width:90cqi;max-width:90cqi}}.sm\:diff-resizer{z-index:1;resize:horizontal;opacity:0;cursor:ew-resize;transform-origin:100% 100%;clip-path:inset(calc(100% - .75rem) 0 0 calc(100% - .75rem));grid-row-start:1;grid-column-start:1;width:50cqi;min-width:1rem;max-width:calc(100cqi - 1rem);height:.5rem;transition:min-width .3s ease-out,max-width .3s ease-out;position:relative;top:50%;overflow:hidden;transform:scaleY(3)translate(.35rem,.08rem)}.sm\:diff-item-2{grid-row-start:1;grid-column-start:1;position:relative}.sm\:diff-item-2:after{pointer-events:none;z-index:2;background-color:color-mix(in oklab,var(--color-base-100)50%,transparent);border:2px solid var(--color-base-100);content:"";outline:1px solid color-mix(in oklab,var(--color-base-content)5%,transparent);outline-offset:-3px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:3.40282e38px;width:1.2rem;height:1.8rem;position:absolute;top:50%;bottom:0;right:1px;translate:50% -50%;box-shadow:0 1px 2px rgba(0,0,0,.1);box-shadow:0 1px 2px lab(0% 0 0/.1)}.sm\:diff-item-2>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.sm\:diff-item-2:after{content:none}}.sm\:diff-item-1{z-index:1;border-right:2px solid var(--color-base-100);grid-row-start:1;grid-column-start:1;position:relative;overflow:hidden}.sm\:diff-item-1>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}}@media (min-width:768px){.md\:diff{-webkit-user-select:none;user-select:none;direction:ltr;grid-template-columns:auto 1fr;width:100%;display:grid;position:relative;overflow:hidden;container-type:inline-size}.md\:diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.md\:diff:has(.diff-item-1:focus){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.md\:diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.md\:diff:focus-visible .diff-resizer{min-width:90cqi;max-width:90cqi}.md\:diff:has(.diff-item-2:focus-visible){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px}.md\:diff:has(.diff-item-2:focus-visible) .diff-resizer{min-width:10cqi;max-width:10cqi}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.md\:diff:focus .diff-resizer{min-width:10cqi;max-width:10cqi}.md\:diff:has(.diff-item-1:focus) .diff-resizer{min-width:90cqi;max-width:90cqi}}.md\:diff-resizer{z-index:1;resize:horizontal;opacity:0;cursor:ew-resize;transform-origin:100% 100%;clip-path:inset(calc(100% - .75rem) 0 0 calc(100% - .75rem));grid-row-start:1;grid-column-start:1;width:50cqi;min-width:1rem;max-width:calc(100cqi - 1rem);height:.5rem;transition:min-width .3s ease-out,max-width .3s ease-out;position:relative;top:50%;overflow:hidden;transform:scaleY(3)translate(.35rem,.08rem)}.md\:diff-item-2{grid-row-start:1;grid-column-start:1;position:relative}.md\:diff-item-2:after{pointer-events:none;z-index:2;background-color:color-mix(in oklab,var(--color-base-100)50%,transparent);border:2px solid var(--color-base-100);content:"";outline:1px solid color-mix(in oklab,var(--color-base-content)5%,transparent);outline-offset:-3px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:3.40282e38px;width:1.2rem;height:1.8rem;position:absolute;top:50%;bottom:0;right:1px;translate:50% -50%;box-shadow:0 1px 2px rgba(0,0,0,.1);box-shadow:0 1px 2px lab(0% 0 0/.1)}.md\:diff-item-2>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.md\:diff-item-2:after{content:none}}.md\:diff-item-1{z-index:1;border-right:2px solid var(--color-base-100);grid-row-start:1;grid-column-start:1;position:relative;overflow:hidden}.md\:diff-item-1>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}}@media (min-width:1024px){.lg\:diff{-webkit-user-select:none;user-select:none;direction:ltr;grid-template-columns:auto 1fr;width:100%;display:grid;position:relative;overflow:hidden;container-type:inline-size}.lg\:diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.lg\:diff:has(.diff-item-1:focus){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.lg\:diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.lg\:diff:focus-visible .diff-resizer{min-width:90cqi;max-width:90cqi}.lg\:diff:has(.diff-item-2:focus-visible){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px}.lg\:diff:has(.diff-item-2:focus-visible) .diff-resizer{min-width:10cqi;max-width:10cqi}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.lg\:diff:focus .diff-resizer{min-width:10cqi;max-width:10cqi}.lg\:diff:has(.diff-item-1:focus) .diff-resizer{min-width:90cqi;max-width:90cqi}}.lg\:diff-resizer{z-index:1;resize:horizontal;opacity:0;cursor:ew-resize;transform-origin:100% 100%;clip-path:inset(calc(100% - .75rem) 0 0 calc(100% - .75rem));grid-row-start:1;grid-column-start:1;width:50cqi;min-width:1rem;max-width:calc(100cqi - 1rem);height:.5rem;transition:min-width .3s ease-out,max-width .3s ease-out;position:relative;top:50%;overflow:hidden;transform:scaleY(3)translate(.35rem,.08rem)}.lg\:diff-item-2{grid-row-start:1;grid-column-start:1;position:relative}.lg\:diff-item-2:after{pointer-events:none;z-index:2;background-color:color-mix(in oklab,var(--color-base-100)50%,transparent);border:2px solid var(--color-base-100);content:"";outline:1px solid color-mix(in oklab,var(--color-base-content)5%,transparent);outline-offset:-3px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:3.40282e38px;width:1.2rem;height:1.8rem;position:absolute;top:50%;bottom:0;right:1px;translate:50% -50%;box-shadow:0 1px 2px rgba(0,0,0,.1);box-shadow:0 1px 2px lab(0% 0 0/.1)}.lg\:diff-item-2>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.lg\:diff-item-2:after{content:none}}.lg\:diff-item-1{z-index:1;border-right:2px solid var(--color-base-100);grid-row-start:1;grid-column-start:1;position:relative;overflow:hidden}.lg\:diff-item-1>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}}@media (min-width:1280px){.xl\:diff{-webkit-user-select:none;user-select:none;direction:ltr;grid-template-columns:auto 1fr;width:100%;display:grid;position:relative;overflow:hidden;container-type:inline-size}.xl\:diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.xl\:diff:has(.diff-item-1:focus){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.xl\:diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.xl\:diff:focus-visible .diff-resizer{min-width:90cqi;max-width:90cqi}.xl\:diff:has(.diff-item-2:focus-visible){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px}.xl\:diff:has(.diff-item-2:focus-visible) .diff-resizer{min-width:10cqi;max-width:10cqi}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.xl\:diff:focus .diff-resizer{min-width:10cqi;max-width:10cqi}.xl\:diff:has(.diff-item-1:focus) .diff-resizer{min-width:90cqi;max-width:90cqi}}.xl\:diff-resizer{z-index:1;resize:horizontal;opacity:0;cursor:ew-resize;transform-origin:100% 100%;clip-path:inset(calc(100% - .75rem) 0 0 calc(100% - .75rem));grid-row-start:1;grid-column-start:1;width:50cqi;min-width:1rem;max-width:calc(100cqi - 1rem);height:.5rem;transition:min-width .3s ease-out,max-width .3s ease-out;position:relative;top:50%;overflow:hidden;transform:scaleY(3)translate(.35rem,.08rem)}.xl\:diff-item-2{grid-row-start:1;grid-column-start:1;position:relative}.xl\:diff-item-2:after{pointer-events:none;z-index:2;background-color:color-mix(in oklab,var(--color-base-100)50%,transparent);border:2px solid var(--color-base-100);content:"";outline:1px solid color-mix(in oklab,var(--color-base-content)5%,transparent);outline-offset:-3px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:3.40282e38px;width:1.2rem;height:1.8rem;position:absolute;top:50%;bottom:0;right:1px;translate:50% -50%;box-shadow:0 1px 2px rgba(0,0,0,.1);box-shadow:0 1px 2px lab(0% 0 0/.1)}.xl\:diff-item-2>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.xl\:diff-item-2:after{content:none}}.xl\:diff-item-1{z-index:1;border-right:2px solid var(--color-base-100);grid-row-start:1;grid-column-start:1;position:relative;overflow:hidden}.xl\:diff-item-1>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}}@media (min-width:1536px){.\32 xl\:diff{-webkit-user-select:none;user-select:none;direction:ltr;grid-template-columns:auto 1fr;width:100%;display:grid;position:relative;overflow:hidden;container-type:inline-size}.\32 xl\:diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.\32 xl\:diff:has(.diff-item-1:focus){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.\32 xl\:diff:focus-visible{outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.\32 xl\:diff:focus-visible .diff-resizer{min-width:90cqi;max-width:90cqi}.\32 xl\:diff:has(.diff-item-2:focus-visible){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px}.\32 xl\:diff:has(.diff-item-2:focus-visible) .diff-resizer{min-width:10cqi;max-width:10cqi}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.\32 xl\:diff:focus .diff-resizer{min-width:10cqi;max-width:10cqi}.\32 xl\:diff:has(.diff-item-1:focus) .diff-resizer{min-width:90cqi;max-width:90cqi}}.\32 xl\:diff-resizer{z-index:1;resize:horizontal;opacity:0;cursor:ew-resize;transform-origin:100% 100%;clip-path:inset(calc(100% - .75rem) 0 0 calc(100% - .75rem));grid-row-start:1;grid-column-start:1;width:50cqi;min-width:1rem;max-width:calc(100cqi - 1rem);height:.5rem;transition:min-width .3s ease-out,max-width .3s ease-out;position:relative;top:50%;overflow:hidden;transform:scaleY(3)translate(.35rem,.08rem)}.\32 xl\:diff-item-2{grid-row-start:1;grid-column-start:1;position:relative}.\32 xl\:diff-item-2:after{pointer-events:none;z-index:2;background-color:color-mix(in oklab,var(--color-base-100)50%,transparent);border:2px solid var(--color-base-100);content:"";outline:1px solid color-mix(in oklab,var(--color-base-content)5%,transparent);outline-offset:-3px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:3.40282e38px;width:1.2rem;height:1.8rem;position:absolute;top:50%;bottom:0;right:1px;translate:50% -50%;box-shadow:0 1px 2px rgba(0,0,0,.1);box-shadow:0 1px 2px lab(0% 0 0/.1)}.\32 xl\:diff-item-2>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.\32 xl\:diff-item-2:after{content:none}}.\32 xl\:diff-item-1{z-index:1;border-right:2px solid var(--color-base-100);grid-row-start:1;grid-column-start:1;position:relative;overflow:hidden}.\32 xl\:diff-item-1>*{pointer-events:none;object-fit:cover;object-position:center;width:100cqi;max-width:none;height:100%;position:absolute;top:0;bottom:0;left:0}}.kbd{border-radius:var(--radius-field);background-color:var(--color-base-200);vertical-align:middle;border:var(--border)solid color-mix(in srgb,var(--color-base-content)20%,transparent);border-bottom:calc(var(--border) + 1px)solid color-mix(in srgb,var(--color-base-content)20%,transparent);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);min-width:var(--size);justify-content:center;align-items:center;padding-left:.5em;padding-right:.5em;font-size:.875rem;display:inline-flex}.kbd-xs{--size:calc(var(--size-selector,.25rem)*4);font-size:.625rem}.kbd-sm{--size:calc(var(--size-selector,.25rem)*5);font-size:.75rem}.kbd-md{--size:calc(var(--size-selector,.25rem)*6);font-size:.875rem}.kbd-lg{--size:calc(var(--size-selector,.25rem)*7);font-size:1rem}.kbd-xl{--size:calc(var(--size-selector,.25rem)*8);font-size:1.125rem}@media (min-width:640px){.sm\:kbd{border-radius:var(--radius-field);background-color:var(--color-base-200);vertical-align:middle;border:var(--border)solid color-mix(in srgb,var(--color-base-content)20%,transparent);border-bottom:calc(var(--border) + 1px)solid color-mix(in srgb,var(--color-base-content)20%,transparent);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);min-width:var(--size);justify-content:center;align-items:center;padding-left:.5em;padding-right:.5em;font-size:.875rem;display:inline-flex}.sm\:kbd-xs{--size:calc(var(--size-selector,.25rem)*4);font-size:.625rem}.sm\:kbd-sm{--size:calc(var(--size-selector,.25rem)*5);font-size:.75rem}.sm\:kbd-md{--size:calc(var(--size-selector,.25rem)*6);font-size:.875rem}.sm\:kbd-lg{--size:calc(var(--size-selector,.25rem)*7);font-size:1rem}.sm\:kbd-xl{--size:calc(var(--size-selector,.25rem)*8);font-size:1.125rem}}@media (min-width:768px){.md\:kbd{border-radius:var(--radius-field);background-color:var(--color-base-200);vertical-align:middle;border:var(--border)solid color-mix(in srgb,var(--color-base-content)20%,transparent);border-bottom:calc(var(--border) + 1px)solid color-mix(in srgb,var(--color-base-content)20%,transparent);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);min-width:var(--size);justify-content:center;align-items:center;padding-left:.5em;padding-right:.5em;font-size:.875rem;display:inline-flex}.md\:kbd-xs{--size:calc(var(--size-selector,.25rem)*4);font-size:.625rem}.md\:kbd-sm{--size:calc(var(--size-selector,.25rem)*5);font-size:.75rem}.md\:kbd-md{--size:calc(var(--size-selector,.25rem)*6);font-size:.875rem}.md\:kbd-lg{--size:calc(var(--size-selector,.25rem)*7);font-size:1rem}.md\:kbd-xl{--size:calc(var(--size-selector,.25rem)*8);font-size:1.125rem}}@media (min-width:1024px){.lg\:kbd{border-radius:var(--radius-field);background-color:var(--color-base-200);vertical-align:middle;border:var(--border)solid color-mix(in srgb,var(--color-base-content)20%,transparent);border-bottom:calc(var(--border) + 1px)solid color-mix(in srgb,var(--color-base-content)20%,transparent);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);min-width:var(--size);justify-content:center;align-items:center;padding-left:.5em;padding-right:.5em;font-size:.875rem;display:inline-flex}.lg\:kbd-xs{--size:calc(var(--size-selector,.25rem)*4);font-size:.625rem}.lg\:kbd-sm{--size:calc(var(--size-selector,.25rem)*5);font-size:.75rem}.lg\:kbd-md{--size:calc(var(--size-selector,.25rem)*6);font-size:.875rem}.lg\:kbd-lg{--size:calc(var(--size-selector,.25rem)*7);font-size:1rem}.lg\:kbd-xl{--size:calc(var(--size-selector,.25rem)*8);font-size:1.125rem}}@media (min-width:1280px){.xl\:kbd{border-radius:var(--radius-field);background-color:var(--color-base-200);vertical-align:middle;border:var(--border)solid color-mix(in srgb,var(--color-base-content)20%,transparent);border-bottom:calc(var(--border) + 1px)solid color-mix(in srgb,var(--color-base-content)20%,transparent);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);min-width:var(--size);justify-content:center;align-items:center;padding-left:.5em;padding-right:.5em;font-size:.875rem;display:inline-flex}.xl\:kbd-xs{--size:calc(var(--size-selector,.25rem)*4);font-size:.625rem}.xl\:kbd-sm{--size:calc(var(--size-selector,.25rem)*5);font-size:.75rem}.xl\:kbd-md{--size:calc(var(--size-selector,.25rem)*6);font-size:.875rem}.xl\:kbd-lg{--size:calc(var(--size-selector,.25rem)*7);font-size:1rem}.xl\:kbd-xl{--size:calc(var(--size-selector,.25rem)*8);font-size:1.125rem}}@media (min-width:1536px){.\32 xl\:kbd{border-radius:var(--radius-field);background-color:var(--color-base-200);vertical-align:middle;border:var(--border)solid color-mix(in srgb,var(--color-base-content)20%,transparent);border-bottom:calc(var(--border) + 1px)solid color-mix(in srgb,var(--color-base-content)20%,transparent);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);min-width:var(--size);justify-content:center;align-items:center;padding-left:.5em;padding-right:.5em;font-size:.875rem;display:inline-flex}.\32 xl\:kbd-xs{--size:calc(var(--size-selector,.25rem)*4);font-size:.625rem}.\32 xl\:kbd-sm{--size:calc(var(--size-selector,.25rem)*5);font-size:.75rem}.\32 xl\:kbd-md{--size:calc(var(--size-selector,.25rem)*6);font-size:.875rem}.\32 xl\:kbd-lg{--size:calc(var(--size-selector,.25rem)*7);font-size:1rem}.\32 xl\:kbd-xl{--size:calc(var(--size-selector,.25rem)*8);font-size:1.125rem}}.toast{white-space:nowrap;min-width:fit-content;translate:var(--toast-x,0)var(--toast-y,0);inset-inline:auto 0;background-color:transparent;flex-direction:column;gap:.5rem;margin:1rem;display:flex;position:fixed;top:auto;bottom:0}.toast>*{animation:.25s ease-out toast}.toast:where(.toast-start){--toast-x:0;inset-inline:0 auto}.toast:where(.toast-center){--toast-x:-50%;inset-inline:50%}.toast:where(.toast-end){--toast-x:0;inset-inline:auto 0}.toast:where(.toast-bottom){--toast-y:0;top:auto;bottom:0}.toast:where(.toast-middle){--toast-y:-50%;top:50%;bottom:auto}.toast:where(.toast-top){--toast-y:0;top:0;bottom:auto}@keyframes toast{0%{opacity:0;scale:.9}to{opacity:1;scale:1}}@media (min-width:640px){.sm\:toast{white-space:nowrap;min-width:fit-content;translate:var(--toast-x,0)var(--toast-y,0);inset-inline:auto 0;background-color:transparent;flex-direction:column;gap:.5rem;margin:1rem;display:flex;position:fixed;top:auto;bottom:0}.sm\:toast>*{animation:.25s ease-out toast}.sm\:toast:where(.toast-start){--toast-x:0;inset-inline:0 auto}.sm\:toast:where(.toast-center){--toast-x:-50%;inset-inline:50%}.sm\:toast:where(.toast-end){--toast-x:0;inset-inline:auto 0}.sm\:toast:where(.toast-bottom){--toast-y:0;top:auto;bottom:0}.sm\:toast:where(.toast-middle){--toast-y:-50%;top:50%;bottom:auto}.sm\:toast:where(.toast-top){--toast-y:0;top:0;bottom:auto}}@media (min-width:768px){.md\:toast{white-space:nowrap;min-width:fit-content;translate:var(--toast-x,0)var(--toast-y,0);inset-inline:auto 0;background-color:transparent;flex-direction:column;gap:.5rem;margin:1rem;display:flex;position:fixed;top:auto;bottom:0}.md\:toast>*{animation:.25s ease-out toast}.md\:toast:where(.toast-start){--toast-x:0;inset-inline:0 auto}.md\:toast:where(.toast-center){--toast-x:-50%;inset-inline:50%}.md\:toast:where(.toast-end){--toast-x:0;inset-inline:auto 0}.md\:toast:where(.toast-bottom){--toast-y:0;top:auto;bottom:0}.md\:toast:where(.toast-middle){--toast-y:-50%;top:50%;bottom:auto}.md\:toast:where(.toast-top){--toast-y:0;top:0;bottom:auto}}@media (min-width:1024px){.lg\:toast{white-space:nowrap;min-width:fit-content;translate:var(--toast-x,0)var(--toast-y,0);inset-inline:auto 0;background-color:transparent;flex-direction:column;gap:.5rem;margin:1rem;display:flex;position:fixed;top:auto;bottom:0}.lg\:toast>*{animation:.25s ease-out toast}.lg\:toast:where(.toast-start){--toast-x:0;inset-inline:0 auto}.lg\:toast:where(.toast-center){--toast-x:-50%;inset-inline:50%}.lg\:toast:where(.toast-end){--toast-x:0;inset-inline:auto 0}.lg\:toast:where(.toast-bottom){--toast-y:0;top:auto;bottom:0}.lg\:toast:where(.toast-middle){--toast-y:-50%;top:50%;bottom:auto}.lg\:toast:where(.toast-top){--toast-y:0;top:0;bottom:auto}}@media (min-width:1280px){.xl\:toast{white-space:nowrap;min-width:fit-content;translate:var(--toast-x,0)var(--toast-y,0);inset-inline:auto 0;background-color:transparent;flex-direction:column;gap:.5rem;margin:1rem;display:flex;position:fixed;top:auto;bottom:0}.xl\:toast>*{animation:.25s ease-out toast}.xl\:toast:where(.toast-start){--toast-x:0;inset-inline:0 auto}.xl\:toast:where(.toast-center){--toast-x:-50%;inset-inline:50%}.xl\:toast:where(.toast-end){--toast-x:0;inset-inline:auto 0}.xl\:toast:where(.toast-bottom){--toast-y:0;top:auto;bottom:0}.xl\:toast:where(.toast-middle){--toast-y:-50%;top:50%;bottom:auto}.xl\:toast:where(.toast-top){--toast-y:0;top:0;bottom:auto}}@media (min-width:1536px){.\32 xl\:toast{white-space:nowrap;min-width:fit-content;translate:var(--toast-x,0)var(--toast-y,0);inset-inline:auto 0;background-color:transparent;flex-direction:column;gap:.5rem;margin:1rem;display:flex;position:fixed;top:auto;bottom:0}.\32 xl\:toast>*{animation:.25s ease-out toast}.\32 xl\:toast:where(.toast-start){--toast-x:0;inset-inline:0 auto}.\32 xl\:toast:where(.toast-center){--toast-x:-50%;inset-inline:50%}.\32 xl\:toast:where(.toast-end){--toast-x:0;inset-inline:auto 0}.\32 xl\:toast:where(.toast-bottom){--toast-y:0;top:auto;bottom:0}.\32 xl\:toast:where(.toast-middle){--toast-y:-50%;top:50%;bottom:auto}.\32 xl\:toast:where(.toast-top){--toast-y:0;top:0;bottom:auto}}.navbar{align-items:center;width:100%;min-height:4rem;padding:.5rem;display:flex}.navbar-start{justify-content:flex-start;align-items:center;width:50%;display:inline-flex}.navbar-center{flex-shrink:0;align-items:center;display:inline-flex}.navbar-end{justify-content:flex-end;align-items:center;width:50%;display:inline-flex}@media (min-width:640px){.sm\:navbar{align-items:center;width:100%;min-height:4rem;padding:.5rem;display:flex}.sm\:navbar-start{justify-content:flex-start;align-items:center;width:50%;display:inline-flex}.sm\:navbar-center{flex-shrink:0;align-items:center;display:inline-flex}.sm\:navbar-end{justify-content:flex-end;align-items:center;width:50%;display:inline-flex}}@media (min-width:768px){.md\:navbar{align-items:center;width:100%;min-height:4rem;padding:.5rem;display:flex}.md\:navbar-start{justify-content:flex-start;align-items:center;width:50%;display:inline-flex}.md\:navbar-center{flex-shrink:0;align-items:center;display:inline-flex}.md\:navbar-end{justify-content:flex-end;align-items:center;width:50%;display:inline-flex}}@media (min-width:1024px){.lg\:navbar{align-items:center;width:100%;min-height:4rem;padding:.5rem;display:flex}.lg\:navbar-start{justify-content:flex-start;align-items:center;width:50%;display:inline-flex}.lg\:navbar-center{flex-shrink:0;align-items:center;display:inline-flex}.lg\:navbar-end{justify-content:flex-end;align-items:center;width:50%;display:inline-flex}}@media (min-width:1280px){.xl\:navbar{align-items:center;width:100%;min-height:4rem;padding:.5rem;display:flex}.xl\:navbar-start{justify-content:flex-start;align-items:center;width:50%;display:inline-flex}.xl\:navbar-center{flex-shrink:0;align-items:center;display:inline-flex}.xl\:navbar-end{justify-content:flex-end;align-items:center;width:50%;display:inline-flex}}@media (min-width:1536px){.\32 xl\:navbar{align-items:center;width:100%;min-height:4rem;padding:.5rem;display:flex}.\32 xl\:navbar-start{justify-content:flex-start;align-items:center;width:50%;display:inline-flex}.\32 xl\:navbar-center{flex-shrink:0;align-items:center;display:inline-flex}.\32 xl\:navbar-end{justify-content:flex-end;align-items:center;width:50%;display:inline-flex}}.collapse:not(:is(td,tr,colgroup)){visibility:visible}.collapse{border-radius:var(--radius-box,1rem);grid-template-rows:max-content 0fr;width:100%;transition:grid-template-rows .2s;display:grid;position:relative;overflow:hidden}.collapse>input:is([type=checkbox],[type=radio]){appearance:none;opacity:0;grid-row-start:1;grid-column-start:1}.collapse:is([open],:focus:not(.collapse-close)){grid-template-rows:max-content 1fr}.collapse:not(.collapse-close):has(>input:is([type=checkbox],[type=radio]):checked){grid-template-rows:max-content 1fr}.collapse:is([open],:focus:not(.collapse-close))>.collapse-content{visibility:visible;min-height:fit-content}.collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){visibility:visible;min-height:fit-content}.collapse:focus-visible{outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.collapse:has(>input:is([type=checkbox],[type=radio]):focus-visible){outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.collapse:not(.collapse-close)>input[type=checkbox]{cursor:pointer}.collapse:not(.collapse-close)>input[type=radio]:not(:checked){cursor:pointer}.collapse:not(.collapse-close)>.collapse-title{cursor:pointer}.collapse:focus:not(:is(.collapse-close,.collapse[open]))>.collapse-title{cursor:unset}.collapse:is([open],:focus:not(.collapse-close))>:where(.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.collapse[open].collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.collapse.collapse-open.collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.collapse.collapse-arrow:focus:not(.collapse-close)>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.collapse.collapse-arrow:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.collapse[open].collapse-plus>.collapse-title:after{content:"−"}.collapse.collapse-open.collapse-plus>.collapse-title:after{content:"−"}.collapse.collapse-plus:focus:not(.collapse-close)>.collapse-title:after{content:"−"}.collapse.collapse-plus:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{content:"−"}.collapse>input:is([type=checkbox],[type=radio]){z-index:1;padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out}.collapse-title,.collapse-content{grid-row-start:1;grid-column-start:1}.collapse-content{visibility:hidden;min-height:0;cursor:unset;grid-row-start:2;grid-column-start:1;padding-left:1rem;padding-right:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.collapse:is(details){width:100%}.collapse:is(details) summary{display:block;position:relative}.collapse:is(details) summary::-webkit-details-marker{display:none}.collapse:is(details) summary{outline:none}.collapse-arrow>.collapse-title:after{content:"";transform-origin:75% 75%;pointer-events:none;top:1.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem;transform:translateY(-100%)rotate(45deg);box-shadow:2px 2px}.collapse-plus>.collapse-title:after{content:"+";pointer-events:none;top:.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.3s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem}.collapse-title{padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out;position:relative}.collapse-open{grid-template-rows:max-content 1fr}.collapse-open>.collapse-content{visibility:visible;min-height:fit-content;transition:padding .2sease-out,background-color .2sease-out;padding-bottom:1rem}@media (min-width:640px){.sm\:collapse:not(:is(td,tr,colgroup)){visibility:visible}.sm\:collapse{border-radius:var(--radius-box,1rem);grid-template-rows:max-content 0fr;width:100%;transition:grid-template-rows .2s;display:grid;position:relative;overflow:hidden}.sm\:collapse>input:is([type=checkbox],[type=radio]){appearance:none;opacity:0;grid-row-start:1;grid-column-start:1}.sm\:collapse:is([open],:focus:not(.collapse-close)){grid-template-rows:max-content 1fr}.sm\:collapse:not(.collapse-close):has(>input:is([type=checkbox],[type=radio]):checked){grid-template-rows:max-content 1fr}.sm\:collapse:is([open],:focus:not(.collapse-close))>.collapse-content{visibility:visible;min-height:fit-content}.sm\:collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){visibility:visible;min-height:fit-content}.sm\:collapse:focus-visible{outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.sm\:collapse:has(>input:is([type=checkbox],[type=radio]):focus-visible){outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.sm\:collapse:not(.collapse-close)>input[type=checkbox]{cursor:pointer}.sm\:collapse:not(.collapse-close)>input[type=radio]:not(:checked){cursor:pointer}.sm\:collapse:not(.collapse-close)>.collapse-title{cursor:pointer}.sm\:collapse:focus:not(:is(.collapse-close,.collapse[open]))>.collapse-title{cursor:unset}.sm\:collapse:is([open],:focus:not(.collapse-close))>:where(.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.sm\:collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.sm\:collapse[open].collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.sm\:collapse.collapse-open.collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.sm\:collapse.collapse-arrow:focus:not(.collapse-close)>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.sm\:collapse.collapse-arrow:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.sm\:collapse[open].collapse-plus>.collapse-title:after{content:"−"}.sm\:collapse.collapse-open.collapse-plus>.collapse-title:after{content:"−"}.sm\:collapse.collapse-plus:focus:not(.collapse-close)>.collapse-title:after{content:"−"}.sm\:collapse.collapse-plus:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{content:"−"}.sm\:collapse>input:is([type=checkbox],[type=radio]){z-index:1;padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out}.sm\:collapse-title,.sm\:collapse-content{grid-row-start:1;grid-column-start:1}.sm\:collapse-content{visibility:hidden;min-height:0;cursor:unset;grid-row-start:2;grid-column-start:1;padding-left:1rem;padding-right:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.sm\:collapse:is(details){width:100%}.sm\:collapse:is(details) summary{display:block;position:relative}.sm\:collapse:is(details) summary::-webkit-details-marker{display:none}.sm\:collapse:is(details) summary{outline:none}.sm\:collapse-arrow>.collapse-title:after{content:"";transform-origin:75% 75%;pointer-events:none;top:1.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem;transform:translateY(-100%)rotate(45deg);box-shadow:2px 2px}.sm\:collapse-plus>.collapse-title:after{content:"+";pointer-events:none;top:.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.3s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem}.sm\:collapse-title{padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out;position:relative}.sm\:collapse-open{grid-template-rows:max-content 1fr}.sm\:collapse-open>.collapse-content{visibility:visible;min-height:fit-content;transition:padding .2sease-out,background-color .2sease-out;padding-bottom:1rem}}@media (min-width:768px){.md\:collapse:not(:is(td,tr,colgroup)){visibility:visible}.md\:collapse{border-radius:var(--radius-box,1rem);grid-template-rows:max-content 0fr;width:100%;transition:grid-template-rows .2s;display:grid;position:relative;overflow:hidden}.md\:collapse>input:is([type=checkbox],[type=radio]){appearance:none;opacity:0;grid-row-start:1;grid-column-start:1}.md\:collapse:is([open],:focus:not(.collapse-close)){grid-template-rows:max-content 1fr}.md\:collapse:not(.collapse-close):has(>input:is([type=checkbox],[type=radio]):checked){grid-template-rows:max-content 1fr}.md\:collapse:is([open],:focus:not(.collapse-close))>.collapse-content{visibility:visible;min-height:fit-content}.md\:collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){visibility:visible;min-height:fit-content}.md\:collapse:focus-visible{outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.md\:collapse:has(>input:is([type=checkbox],[type=radio]):focus-visible){outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.md\:collapse:not(.collapse-close)>input[type=checkbox]{cursor:pointer}.md\:collapse:not(.collapse-close)>input[type=radio]:not(:checked){cursor:pointer}.md\:collapse:not(.collapse-close)>.collapse-title{cursor:pointer}.md\:collapse:focus:not(:is(.collapse-close,.collapse[open]))>.collapse-title{cursor:unset}.md\:collapse:is([open],:focus:not(.collapse-close))>:where(.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.md\:collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.md\:collapse[open].collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.md\:collapse.collapse-open.collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.md\:collapse.collapse-arrow:focus:not(.collapse-close)>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.md\:collapse.collapse-arrow:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.md\:collapse[open].collapse-plus>.collapse-title:after{content:"−"}.md\:collapse.collapse-open.collapse-plus>.collapse-title:after{content:"−"}.md\:collapse.collapse-plus:focus:not(.collapse-close)>.collapse-title:after{content:"−"}.md\:collapse.collapse-plus:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{content:"−"}.md\:collapse>input:is([type=checkbox],[type=radio]){z-index:1;padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out}.md\:collapse-title,.md\:collapse-content{grid-row-start:1;grid-column-start:1}.md\:collapse-content{visibility:hidden;min-height:0;cursor:unset;grid-row-start:2;grid-column-start:1;padding-left:1rem;padding-right:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.md\:collapse:is(details){width:100%}.md\:collapse:is(details) summary{display:block;position:relative}.md\:collapse:is(details) summary::-webkit-details-marker{display:none}.md\:collapse:is(details) summary{outline:none}.md\:collapse-arrow>.collapse-title:after{content:"";transform-origin:75% 75%;pointer-events:none;top:1.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem;transform:translateY(-100%)rotate(45deg);box-shadow:2px 2px}.md\:collapse-plus>.collapse-title:after{content:"+";pointer-events:none;top:.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.3s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem}.md\:collapse-title{padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out;position:relative}.md\:collapse-open{grid-template-rows:max-content 1fr}.md\:collapse-open>.collapse-content{visibility:visible;min-height:fit-content;transition:padding .2sease-out,background-color .2sease-out;padding-bottom:1rem}}@media (min-width:1024px){.lg\:collapse:not(:is(td,tr,colgroup)){visibility:visible}.lg\:collapse{border-radius:var(--radius-box,1rem);grid-template-rows:max-content 0fr;width:100%;transition:grid-template-rows .2s;display:grid;position:relative;overflow:hidden}.lg\:collapse>input:is([type=checkbox],[type=radio]){appearance:none;opacity:0;grid-row-start:1;grid-column-start:1}.lg\:collapse:is([open],:focus:not(.collapse-close)){grid-template-rows:max-content 1fr}.lg\:collapse:not(.collapse-close):has(>input:is([type=checkbox],[type=radio]):checked){grid-template-rows:max-content 1fr}.lg\:collapse:is([open],:focus:not(.collapse-close))>.collapse-content{visibility:visible;min-height:fit-content}.lg\:collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){visibility:visible;min-height:fit-content}.lg\:collapse:focus-visible{outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.lg\:collapse:has(>input:is([type=checkbox],[type=radio]):focus-visible){outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.lg\:collapse:not(.collapse-close)>input[type=checkbox]{cursor:pointer}.lg\:collapse:not(.collapse-close)>input[type=radio]:not(:checked){cursor:pointer}.lg\:collapse:not(.collapse-close)>.collapse-title{cursor:pointer}.lg\:collapse:focus:not(:is(.collapse-close,.collapse[open]))>.collapse-title{cursor:unset}.lg\:collapse:is([open],:focus:not(.collapse-close))>:where(.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.lg\:collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.lg\:collapse[open].collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.lg\:collapse.collapse-open.collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.lg\:collapse.collapse-arrow:focus:not(.collapse-close)>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.lg\:collapse.collapse-arrow:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.lg\:collapse[open].collapse-plus>.collapse-title:after{content:"−"}.lg\:collapse.collapse-open.collapse-plus>.collapse-title:after{content:"−"}.lg\:collapse.collapse-plus:focus:not(.collapse-close)>.collapse-title:after{content:"−"}.lg\:collapse.collapse-plus:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{content:"−"}.lg\:collapse>input:is([type=checkbox],[type=radio]){z-index:1;padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out}.lg\:collapse-title,.lg\:collapse-content{grid-row-start:1;grid-column-start:1}.lg\:collapse-content{visibility:hidden;min-height:0;cursor:unset;grid-row-start:2;grid-column-start:1;padding-left:1rem;padding-right:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.lg\:collapse:is(details){width:100%}.lg\:collapse:is(details) summary{display:block;position:relative}.lg\:collapse:is(details) summary::-webkit-details-marker{display:none}.lg\:collapse:is(details) summary{outline:none}.lg\:collapse-arrow>.collapse-title:after{content:"";transform-origin:75% 75%;pointer-events:none;top:1.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem;transform:translateY(-100%)rotate(45deg);box-shadow:2px 2px}.lg\:collapse-plus>.collapse-title:after{content:"+";pointer-events:none;top:.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.3s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem}.lg\:collapse-title{padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out;position:relative}.lg\:collapse-open{grid-template-rows:max-content 1fr}.lg\:collapse-open>.collapse-content{visibility:visible;min-height:fit-content;transition:padding .2sease-out,background-color .2sease-out;padding-bottom:1rem}}@media (min-width:1280px){.xl\:collapse:not(:is(td,tr,colgroup)){visibility:visible}.xl\:collapse{border-radius:var(--radius-box,1rem);grid-template-rows:max-content 0fr;width:100%;transition:grid-template-rows .2s;display:grid;position:relative;overflow:hidden}.xl\:collapse>input:is([type=checkbox],[type=radio]){appearance:none;opacity:0;grid-row-start:1;grid-column-start:1}.xl\:collapse:is([open],:focus:not(.collapse-close)){grid-template-rows:max-content 1fr}.xl\:collapse:not(.collapse-close):has(>input:is([type=checkbox],[type=radio]):checked){grid-template-rows:max-content 1fr}.xl\:collapse:is([open],:focus:not(.collapse-close))>.collapse-content{visibility:visible;min-height:fit-content}.xl\:collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){visibility:visible;min-height:fit-content}.xl\:collapse:focus-visible{outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.xl\:collapse:has(>input:is([type=checkbox],[type=radio]):focus-visible){outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.xl\:collapse:not(.collapse-close)>input[type=checkbox]{cursor:pointer}.xl\:collapse:not(.collapse-close)>input[type=radio]:not(:checked){cursor:pointer}.xl\:collapse:not(.collapse-close)>.collapse-title{cursor:pointer}.xl\:collapse:focus:not(:is(.collapse-close,.collapse[open]))>.collapse-title{cursor:unset}.xl\:collapse:is([open],:focus:not(.collapse-close))>:where(.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.xl\:collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.xl\:collapse[open].collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.xl\:collapse.collapse-open.collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.xl\:collapse.collapse-arrow:focus:not(.collapse-close)>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.xl\:collapse.collapse-arrow:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.xl\:collapse[open].collapse-plus>.collapse-title:after{content:"−"}.xl\:collapse.collapse-open.collapse-plus>.collapse-title:after{content:"−"}.xl\:collapse.collapse-plus:focus:not(.collapse-close)>.collapse-title:after{content:"−"}.xl\:collapse.collapse-plus:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{content:"−"}.xl\:collapse>input:is([type=checkbox],[type=radio]){z-index:1;padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out}.xl\:collapse-title,.xl\:collapse-content{grid-row-start:1;grid-column-start:1}.xl\:collapse-content{visibility:hidden;min-height:0;cursor:unset;grid-row-start:2;grid-column-start:1;padding-left:1rem;padding-right:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.xl\:collapse:is(details){width:100%}.xl\:collapse:is(details) summary{display:block;position:relative}.xl\:collapse:is(details) summary::-webkit-details-marker{display:none}.xl\:collapse:is(details) summary{outline:none}.xl\:collapse-arrow>.collapse-title:after{content:"";transform-origin:75% 75%;pointer-events:none;top:1.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem;transform:translateY(-100%)rotate(45deg);box-shadow:2px 2px}.xl\:collapse-plus>.collapse-title:after{content:"+";pointer-events:none;top:.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.3s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem}.xl\:collapse-title{padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out;position:relative}.xl\:collapse-open{grid-template-rows:max-content 1fr}.xl\:collapse-open>.collapse-content{visibility:visible;min-height:fit-content;transition:padding .2sease-out,background-color .2sease-out;padding-bottom:1rem}}@media (min-width:1536px){.\32 xl\:collapse:not(:is(td,tr,colgroup)){visibility:visible}.\32 xl\:collapse{border-radius:var(--radius-box,1rem);grid-template-rows:max-content 0fr;width:100%;transition:grid-template-rows .2s;display:grid;position:relative;overflow:hidden}.\32 xl\:collapse>input:is([type=checkbox],[type=radio]){appearance:none;opacity:0;grid-row-start:1;grid-column-start:1}.\32 xl\:collapse:is([open],:focus:not(.collapse-close)){grid-template-rows:max-content 1fr}.\32 xl\:collapse:not(.collapse-close):has(>input:is([type=checkbox],[type=radio]):checked){grid-template-rows:max-content 1fr}.\32 xl\:collapse:is([open],:focus:not(.collapse-close))>.collapse-content{visibility:visible;min-height:fit-content}.\32 xl\:collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){visibility:visible;min-height:fit-content}.\32 xl\:collapse:focus-visible{outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.\32 xl\:collapse:has(>input:is([type=checkbox],[type=radio]):focus-visible){outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.\32 xl\:collapse:not(.collapse-close)>input[type=checkbox]{cursor:pointer}.\32 xl\:collapse:not(.collapse-close)>input[type=radio]:not(:checked){cursor:pointer}.\32 xl\:collapse:not(.collapse-close)>.collapse-title{cursor:pointer}.\32 xl\:collapse:focus:not(:is(.collapse-close,.collapse[open]))>.collapse-title{cursor:unset}.\32 xl\:collapse:is([open],:focus:not(.collapse-close))>:where(.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.\32 xl\:collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.\32 xl\:collapse[open].collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.\32 xl\:collapse.collapse-open.collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.\32 xl\:collapse.collapse-arrow:focus:not(.collapse-close)>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.\32 xl\:collapse.collapse-arrow:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.\32 xl\:collapse[open].collapse-plus>.collapse-title:after{content:"−"}.\32 xl\:collapse.collapse-open.collapse-plus>.collapse-title:after{content:"−"}.\32 xl\:collapse.collapse-plus:focus:not(.collapse-close)>.collapse-title:after{content:"−"}.\32 xl\:collapse.collapse-plus:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{content:"−"}.\32 xl\:collapse>input:is([type=checkbox],[type=radio]){z-index:1;padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out}.\32 xl\:collapse-title,.\32 xl\:collapse-content{grid-row-start:1;grid-column-start:1}.\32 xl\:collapse-content{visibility:hidden;min-height:0;cursor:unset;grid-row-start:2;grid-column-start:1;padding-left:1rem;padding-right:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.\32 xl\:collapse:is(details){width:100%}.\32 xl\:collapse:is(details) summary{display:block;position:relative}.\32 xl\:collapse:is(details) summary::-webkit-details-marker{display:none}.\32 xl\:collapse:is(details) summary{outline:none}.\32 xl\:collapse-arrow>.collapse-title:after{content:"";transform-origin:75% 75%;pointer-events:none;top:1.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem;transform:translateY(-100%)rotate(45deg);box-shadow:2px 2px}.\32 xl\:collapse-plus>.collapse-title:after{content:"+";pointer-events:none;top:.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.3s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem}.\32 xl\:collapse-title{padding:1rem;width:100%;min-height:3.75rem;padding-inline-end:3rem;transition:background-color .2s ease-out;position:relative}.\32 xl\:collapse-open{grid-template-rows:max-content 1fr}.\32 xl\:collapse-open>.collapse-content{visibility:visible;min-height:fit-content;transition:padding .2sease-out,background-color .2sease-out;padding-bottom:1rem}}.tabs{--tabs-height:auto;--tabs-direction:row;height:var(--tabs-height);flex-wrap:wrap;flex-direction:var(--tabs-direction);display:flex}.tab{cursor:pointer;appearance:none;text-align:center;-webkit-user-select:none;user-select:none;--tab-p:1rem;--tab-bg:var(--color-base-100);--tab-border-color:var(--color-base-300);--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:0;--tab-radius-ee:0;--tab-order:0;--tab-radius-min:calc(.75rem - var(--border));flex-wrap:wrap;order:var(--tab-order);height:calc(var(--size-field,.25rem)*10);border-color:transparent;justify-content:center;align-items:center;padding-inline-start:var(--tab-p);padding-inline-end:var(--tab-p);font-size:.875rem;display:inline-flex;position:relative}@media (hover:hover){.tab:hover{color:var(--color-base-content)}}.tab:is(input[type=radio]){min-width:fit-content}.tab:is(input[type=radio]):after{content:attr(aria-label)}.tab:is(label){position:relative}.tab:is(label) input{cursor:pointer;appearance:none;opacity:0;position:absolute;inset:0}.tab:checked+.tab-content{height:100%;display:block}.tab:is(label:has(:checked))+.tab-content{height:100%;display:block}.tab:is(.tab-active,[aria-selected=true])+.tab-content{height:100%;display:block}.tab:not(:is(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true])){color:color-mix(in oklab,var(--color-base-content)50%,transparent)}.tab:not(input):empty{cursor:default;flex-grow:1}.tab:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.tab:focus{outline-offset:2px;outline:2px solid transparent}}.tab:focus-visible{outline-offset:-5px;outline:2px solid}.tab:is(label:has(:checked:focus-visible)){outline-offset:-5px;outline:2px solid}.tab[disabled]{pointer-events:none;opacity:.4}.tab-disabled{pointer-events:none;opacity:.4}.tabs-border .tab{--tab-border-color:transparent transparent var(--tab-border-color)transparent;border-radius:var(--radius-field);position:relative}.tabs-border .tab:before{--tw-content:"";content:var(--tw-content);background-color:var(--tab-border-color);border-radius:var(--radius-field);width:80%;height:3px;transition:background-color .2s;position:absolute;bottom:0;left:10%}.tabs-border .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{--tab-border-color:currentColor;border-top:3px solid}.tabs-border .tab:is(input:checked):before{--tab-border-color:currentColor;border-top:3px solid}.tabs-border .tab:is(label:has(:checked)):before{--tab-border-color:currentColor;border-top:3px solid}.tabs-lift{--tabs-height:auto;--tabs-direction:row}.tabs-lift>.tab{--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right;border-width:var(--tab-border);padding:var(--tab-paddings);border-color:var(--tab-border-colors);border-start-start-radius:var(--tab-radius-ss);border-start-end-radius:var(--tab-radius-se);border-end-end-radius:var(--tab-radius-ee);border-end-start-radius:var(--tab-radius-es)}.tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{--radius-start:none}[dir=rtl] .tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{transform:rotateY(180deg)}.tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{--radius-end:none}[dir=rtl] .tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{transform:rotateY(180deg)}.tabs-lift>.tab:is(input:checked,label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.tabs-lift>.tab:is(input:checked,label:has(:checked)):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{--radius-start:none}[dir=rtl] .tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{transform:rotateY(180deg)}.tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{--radius-end:none}[dir=rtl] .tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{transform:rotateY(180deg)}.tabs-lift:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.tabs-lift .tab-content{--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.tabs-lift :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.tabs-lift :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.tabs-lift label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.tabs-lift label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.tabs-top{--tabs-height:auto;--tabs-direction:row}.tabs-top .tab{--tab-order:0;--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.tabs-top .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.tabs-top .tab:is(input:checked){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.tabs-top .tab:is(label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.tabs-top:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.tabs-top .tab-content{--tabcontent-order:1;--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.tabs-top :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.tabs-top :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.tabs-top label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.tabs-top label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.tabs-bottom{--tabs-height:auto;--tabs-direction:row}.tabs-bottom .tab{--tab-order:1;--tab-border:var(--border)0 0 0;--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:min(var(--radius-field),var(--tab-radius-min));--tab-radius-ee:min(var(--radius-field),var(--tab-radius-min));--tab-border-colors:var(--tab-border-color)transparent transparent transparent;--tab-paddings:0 var(--tab-p)var(--border)var(--tab-p);--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.tabs-bottom .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.tabs-bottom .tab:is(input:checked){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.tabs-bottom .tab:is(label:has(:checked)){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.tabs-bottom:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color)}.tabs-bottom .tab-content{--tabcontent-order:0;--tabcontent-margin:0 0 calc(-1*var(--border))0;--tabcontent-radius-ss:var(--radius-box);--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:0;--tabcontent-radius-ee:var(--radius-box)}.tabs-bottom>:checked+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.tabs-bottom>:is(label:has(:checked))+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.tabs-bottom>:is(.tab-active,[aria-selected=true])+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.tabs-box{background-color:var(--color-base-200);border-radius:calc(var(--radius-field) + min(.25rem,calc(var(--radius-field) + var(--radius-field) + var(--radius-field))));box-shadow:0 -.5px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 .5px oklch(0% 0 0/calc(var(--depth)*.05))inset;padding:.25rem}.tabs-box .tab{border-radius:var(--radius-field);border-style:none}.tabs-box .tab:focus-visible{outline-offset:2px}.tabs-box .tab:is(label:has(:checked:focus-visible)){outline-offset:2px}.tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){border:1px solid}}.tabs-box>:is(input:checked){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.tabs-box>:is(input:checked){border:1px solid}}.tabs-box>:is(label:has(:checked)){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.tabs-box>:is(label:has(:checked)){border:1px solid}}.tab-content{--tabcontent-radius-ss:0;--tabcontent-radius-se:0;--tabcontent-radius-es:0;--tabcontent-radius-ee:0;--tabcontent-order:1;width:100%;margin:var(--tabcontent-margin);order:1;order:var(--tabcontent-order);border-color:transparent;border-width:var(--border);border-start-start-radius:var(--tabcontent-radius-ss);border-start-end-radius:var(--tabcontent-radius-se);border-end-end-radius:var(--tabcontent-radius-ee);border-end-start-radius:var(--tabcontent-radius-es);display:none}.tabs-xs :where(.tab){height:calc(var(--size-field,.25rem)*6);--tab-p:.375rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.75rem}.tabs-sm :where(.tab){height:calc(var(--size-field,.25rem)*8);--tab-p:.5rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.875rem}.tabs-md :where(.tab){height:calc(var(--size-field,.25rem)*10);--tab-p:.75rem;--tab-radius-min:calc(.75rem - var(--border));font-size:.875rem}.tabs-lg :where(.tab){height:calc(var(--size-field,.25rem)*12);--tab-p:1rem;--tab-radius-min:calc(1.5rem - var(--border));font-size:1.125rem}.tabs-xl :where(.tab){height:calc(var(--size-field,.25rem)*14);--tab-p:1.25rem;--tab-radius-min:calc(2rem - var(--border));font-size:1.125rem}@media (min-width:640px){.sm\:tabs{--tabs-height:auto;--tabs-direction:row;height:var(--tabs-height);flex-wrap:wrap;flex-direction:var(--tabs-direction);display:flex}.sm\:tab{cursor:pointer;appearance:none;text-align:center;-webkit-user-select:none;user-select:none;--tab-p:1rem;--tab-bg:var(--color-base-100);--tab-border-color:var(--color-base-300);--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:0;--tab-radius-ee:0;--tab-order:0;--tab-radius-min:calc(.75rem - var(--border));flex-wrap:wrap;order:var(--tab-order);height:calc(var(--size-field,.25rem)*10);border-color:transparent;justify-content:center;align-items:center;padding-inline-start:var(--tab-p);padding-inline-end:var(--tab-p);font-size:.875rem;display:inline-flex;position:relative}@media (hover:hover){.sm\:tab:hover{color:var(--color-base-content)}}.sm\:tab:is(input[type=radio]){min-width:fit-content}.sm\:tab:is(input[type=radio]):after{content:attr(aria-label)}.sm\:tab:is(label){position:relative}.sm\:tab:is(label) input{cursor:pointer;appearance:none;opacity:0;position:absolute;inset:0}.sm\:tab:checked+.tab-content{height:100%;display:block}.sm\:tab:is(label:has(:checked))+.tab-content{height:100%;display:block}.sm\:tab:is(.tab-active,[aria-selected=true])+.tab-content{height:100%;display:block}.sm\:tab:not(:is(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true])){color:color-mix(in oklab,var(--color-base-content)50%,transparent)}.sm\:tab:not(input):empty{cursor:default;flex-grow:1}.sm\:tab:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:tab:focus{outline-offset:2px;outline:2px solid transparent}}.sm\:tab:focus-visible{outline-offset:-5px;outline:2px solid}.sm\:tab:is(label:has(:checked:focus-visible)){outline-offset:-5px;outline:2px solid}.sm\:tab[disabled]{pointer-events:none;opacity:.4}.sm\:tab-disabled{pointer-events:none;opacity:.4}.sm\:tabs-border .tab{--tab-border-color:transparent transparent var(--tab-border-color)transparent;border-radius:var(--radius-field);position:relative}.sm\:tabs-border .tab:before{--tw-content:"";content:var(--tw-content);background-color:var(--tab-border-color);border-radius:var(--radius-field);width:80%;height:3px;transition:background-color .2s;position:absolute;bottom:0;left:10%}.sm\:tabs-border .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{--tab-border-color:currentColor;border-top:3px solid}.sm\:tabs-border .tab:is(input:checked):before{--tab-border-color:currentColor;border-top:3px solid}.sm\:tabs-border .tab:is(label:has(:checked)):before{--tab-border-color:currentColor;border-top:3px solid}.sm\:tabs-lift{--tabs-height:auto;--tabs-direction:row}.sm\:tabs-lift>.tab{--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right;border-width:var(--tab-border);padding:var(--tab-paddings);border-color:var(--tab-border-colors);border-start-start-radius:var(--tab-radius-ss);border-start-end-radius:var(--tab-radius-se);border-end-end-radius:var(--tab-radius-ee);border-end-start-radius:var(--tab-radius-es)}.sm\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.sm\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.sm\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{--radius-start:none}[dir=rtl] .sm\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{transform:rotateY(180deg)}.sm\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{--radius-end:none}[dir=rtl] .sm\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{transform:rotateY(180deg)}.sm\:tabs-lift>.tab:is(input:checked,label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.sm\:tabs-lift>.tab:is(input:checked,label:has(:checked)):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.sm\:tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{--radius-start:none}[dir=rtl] .sm\:tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{transform:rotateY(180deg)}.sm\:tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{--radius-end:none}[dir=rtl] .sm\:tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{transform:rotateY(180deg)}.sm\:tabs-lift:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.sm\:tabs-lift .tab-content{--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.sm\:tabs-lift :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-lift :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-lift label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-lift label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-top{--tabs-height:auto;--tabs-direction:row}.sm\:tabs-top .tab{--tab-order:0;--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.sm\:tabs-top .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.sm\:tabs-top .tab:is(input:checked){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.sm\:tabs-top .tab:is(label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.sm\:tabs-top:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.sm\:tabs-top .tab-content{--tabcontent-order:1;--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.sm\:tabs-top :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-top :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-top label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-top label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.sm\:tabs-bottom{--tabs-height:auto;--tabs-direction:row}.sm\:tabs-bottom .tab{--tab-order:1;--tab-border:var(--border)0 0 0;--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:min(var(--radius-field),var(--tab-radius-min));--tab-radius-ee:min(var(--radius-field),var(--tab-radius-min));--tab-border-colors:var(--tab-border-color)transparent transparent transparent;--tab-paddings:0 var(--tab-p)var(--border)var(--tab-p);--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.sm\:tabs-bottom .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.sm\:tabs-bottom .tab:is(input:checked){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.sm\:tabs-bottom .tab:is(label:has(:checked)){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.sm\:tabs-bottom:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color)}.sm\:tabs-bottom .tab-content{--tabcontent-order:0;--tabcontent-margin:0 0 calc(-1*var(--border))0;--tabcontent-radius-ss:var(--radius-box);--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:0;--tabcontent-radius-ee:var(--radius-box)}.sm\:tabs-bottom>:checked+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.sm\:tabs-bottom>:is(label:has(:checked))+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.sm\:tabs-bottom>:is(.tab-active,[aria-selected=true])+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.sm\:tabs-box{background-color:var(--color-base-200);border-radius:calc(var(--radius-field) + min(.25rem,calc(var(--radius-field) + var(--radius-field) + var(--radius-field))));box-shadow:0 -.5px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 .5px oklch(0% 0 0/calc(var(--depth)*.05))inset;padding:.25rem}.sm\:tabs-box .tab{border-radius:var(--radius-field);border-style:none}.sm\:tabs-box .tab:focus-visible{outline-offset:2px}.sm\:tabs-box .tab:is(label:has(:checked:focus-visible)){outline-offset:2px}.sm\:tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.sm\:tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){border:1px solid}}.sm\:tabs-box>:is(input:checked){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.sm\:tabs-box>:is(input:checked){border:1px solid}}.sm\:tabs-box>:is(label:has(:checked)){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.sm\:tabs-box>:is(label:has(:checked)){border:1px solid}}.sm\:tab-content{--tabcontent-radius-ss:0;--tabcontent-radius-se:0;--tabcontent-radius-es:0;--tabcontent-radius-ee:0;--tabcontent-order:1;width:100%;margin:var(--tabcontent-margin);order:1;order:var(--tabcontent-order);border-color:transparent;border-width:var(--border);border-start-start-radius:var(--tabcontent-radius-ss);border-start-end-radius:var(--tabcontent-radius-se);border-end-end-radius:var(--tabcontent-radius-ee);border-end-start-radius:var(--tabcontent-radius-es);display:none}.sm\:tabs-xs :where(.tab){height:calc(var(--size-field,.25rem)*6);--tab-p:.375rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.75rem}.sm\:tabs-sm :where(.tab){height:calc(var(--size-field,.25rem)*8);--tab-p:.5rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.875rem}.sm\:tabs-md :where(.tab){height:calc(var(--size-field,.25rem)*10);--tab-p:.75rem;--tab-radius-min:calc(.75rem - var(--border));font-size:.875rem}.sm\:tabs-lg :where(.tab){height:calc(var(--size-field,.25rem)*12);--tab-p:1rem;--tab-radius-min:calc(1.5rem - var(--border));font-size:1.125rem}.sm\:tabs-xl :where(.tab){height:calc(var(--size-field,.25rem)*14);--tab-p:1.25rem;--tab-radius-min:calc(2rem - var(--border));font-size:1.125rem}}@media (min-width:768px){.md\:tabs{--tabs-height:auto;--tabs-direction:row;height:var(--tabs-height);flex-wrap:wrap;flex-direction:var(--tabs-direction);display:flex}.md\:tab{cursor:pointer;appearance:none;text-align:center;-webkit-user-select:none;user-select:none;--tab-p:1rem;--tab-bg:var(--color-base-100);--tab-border-color:var(--color-base-300);--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:0;--tab-radius-ee:0;--tab-order:0;--tab-radius-min:calc(.75rem - var(--border));flex-wrap:wrap;order:var(--tab-order);height:calc(var(--size-field,.25rem)*10);border-color:transparent;justify-content:center;align-items:center;padding-inline-start:var(--tab-p);padding-inline-end:var(--tab-p);font-size:.875rem;display:inline-flex;position:relative}@media (hover:hover){.md\:tab:hover{color:var(--color-base-content)}}.md\:tab:is(input[type=radio]){min-width:fit-content}.md\:tab:is(input[type=radio]):after{content:attr(aria-label)}.md\:tab:is(label){position:relative}.md\:tab:is(label) input{cursor:pointer;appearance:none;opacity:0;position:absolute;inset:0}.md\:tab:checked+.tab-content{height:100%;display:block}.md\:tab:is(label:has(:checked))+.tab-content{height:100%;display:block}.md\:tab:is(.tab-active,[aria-selected=true])+.tab-content{height:100%;display:block}.md\:tab:not(:is(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true])){color:color-mix(in oklab,var(--color-base-content)50%,transparent)}.md\:tab:not(input):empty{cursor:default;flex-grow:1}.md\:tab:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:tab:focus{outline-offset:2px;outline:2px solid transparent}}.md\:tab:focus-visible{outline-offset:-5px;outline:2px solid}.md\:tab:is(label:has(:checked:focus-visible)){outline-offset:-5px;outline:2px solid}.md\:tab[disabled]{pointer-events:none;opacity:.4}.md\:tab-disabled{pointer-events:none;opacity:.4}.md\:tabs-border .tab{--tab-border-color:transparent transparent var(--tab-border-color)transparent;border-radius:var(--radius-field);position:relative}.md\:tabs-border .tab:before{--tw-content:"";content:var(--tw-content);background-color:var(--tab-border-color);border-radius:var(--radius-field);width:80%;height:3px;transition:background-color .2s;position:absolute;bottom:0;left:10%}.md\:tabs-border .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{--tab-border-color:currentColor;border-top:3px solid}.md\:tabs-border .tab:is(input:checked):before{--tab-border-color:currentColor;border-top:3px solid}.md\:tabs-border .tab:is(label:has(:checked)):before{--tab-border-color:currentColor;border-top:3px solid}.md\:tabs-lift{--tabs-height:auto;--tabs-direction:row}.md\:tabs-lift>.tab{--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right;border-width:var(--tab-border);padding:var(--tab-paddings);border-color:var(--tab-border-colors);border-start-start-radius:var(--tab-radius-ss);border-start-end-radius:var(--tab-radius-se);border-end-end-radius:var(--tab-radius-ee);border-end-start-radius:var(--tab-radius-es)}.md\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.md\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.md\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{--radius-start:none}[dir=rtl] .md\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{transform:rotateY(180deg)}.md\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{--radius-end:none}[dir=rtl] .md\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{transform:rotateY(180deg)}.md\:tabs-lift>.tab:is(input:checked,label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.md\:tabs-lift>.tab:is(input:checked,label:has(:checked)):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.md\:tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{--radius-start:none}[dir=rtl] .md\:tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{transform:rotateY(180deg)}.md\:tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{--radius-end:none}[dir=rtl] .md\:tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{transform:rotateY(180deg)}.md\:tabs-lift:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.md\:tabs-lift .tab-content{--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.md\:tabs-lift :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-lift :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-lift label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-lift label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-top{--tabs-height:auto;--tabs-direction:row}.md\:tabs-top .tab{--tab-order:0;--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.md\:tabs-top .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.md\:tabs-top .tab:is(input:checked){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.md\:tabs-top .tab:is(label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.md\:tabs-top:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.md\:tabs-top .tab-content{--tabcontent-order:1;--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.md\:tabs-top :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-top :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-top label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-top label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.md\:tabs-bottom{--tabs-height:auto;--tabs-direction:row}.md\:tabs-bottom .tab{--tab-order:1;--tab-border:var(--border)0 0 0;--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:min(var(--radius-field),var(--tab-radius-min));--tab-radius-ee:min(var(--radius-field),var(--tab-radius-min));--tab-border-colors:var(--tab-border-color)transparent transparent transparent;--tab-paddings:0 var(--tab-p)var(--border)var(--tab-p);--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.md\:tabs-bottom .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.md\:tabs-bottom .tab:is(input:checked){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.md\:tabs-bottom .tab:is(label:has(:checked)){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.md\:tabs-bottom:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color)}.md\:tabs-bottom .tab-content{--tabcontent-order:0;--tabcontent-margin:0 0 calc(-1*var(--border))0;--tabcontent-radius-ss:var(--radius-box);--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:0;--tabcontent-radius-ee:var(--radius-box)}.md\:tabs-bottom>:checked+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.md\:tabs-bottom>:is(label:has(:checked))+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.md\:tabs-bottom>:is(.tab-active,[aria-selected=true])+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.md\:tabs-box{background-color:var(--color-base-200);border-radius:calc(var(--radius-field) + min(.25rem,calc(var(--radius-field) + var(--radius-field) + var(--radius-field))));box-shadow:0 -.5px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 .5px oklch(0% 0 0/calc(var(--depth)*.05))inset;padding:.25rem}.md\:tabs-box .tab{border-radius:var(--radius-field);border-style:none}.md\:tabs-box .tab:focus-visible{outline-offset:2px}.md\:tabs-box .tab:is(label:has(:checked:focus-visible)){outline-offset:2px}.md\:tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.md\:tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){border:1px solid}}.md\:tabs-box>:is(input:checked){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.md\:tabs-box>:is(input:checked){border:1px solid}}.md\:tabs-box>:is(label:has(:checked)){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.md\:tabs-box>:is(label:has(:checked)){border:1px solid}}.md\:tab-content{--tabcontent-radius-ss:0;--tabcontent-radius-se:0;--tabcontent-radius-es:0;--tabcontent-radius-ee:0;--tabcontent-order:1;width:100%;margin:var(--tabcontent-margin);order:1;order:var(--tabcontent-order);border-color:transparent;border-width:var(--border);border-start-start-radius:var(--tabcontent-radius-ss);border-start-end-radius:var(--tabcontent-radius-se);border-end-end-radius:var(--tabcontent-radius-ee);border-end-start-radius:var(--tabcontent-radius-es);display:none}.md\:tabs-xs :where(.tab){height:calc(var(--size-field,.25rem)*6);--tab-p:.375rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.75rem}.md\:tabs-sm :where(.tab){height:calc(var(--size-field,.25rem)*8);--tab-p:.5rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.875rem}.md\:tabs-md :where(.tab){height:calc(var(--size-field,.25rem)*10);--tab-p:.75rem;--tab-radius-min:calc(.75rem - var(--border));font-size:.875rem}.md\:tabs-lg :where(.tab){height:calc(var(--size-field,.25rem)*12);--tab-p:1rem;--tab-radius-min:calc(1.5rem - var(--border));font-size:1.125rem}.md\:tabs-xl :where(.tab){height:calc(var(--size-field,.25rem)*14);--tab-p:1.25rem;--tab-radius-min:calc(2rem - var(--border));font-size:1.125rem}}@media (min-width:1024px){.lg\:tabs{--tabs-height:auto;--tabs-direction:row;height:var(--tabs-height);flex-wrap:wrap;flex-direction:var(--tabs-direction);display:flex}.lg\:tab{cursor:pointer;appearance:none;text-align:center;-webkit-user-select:none;user-select:none;--tab-p:1rem;--tab-bg:var(--color-base-100);--tab-border-color:var(--color-base-300);--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:0;--tab-radius-ee:0;--tab-order:0;--tab-radius-min:calc(.75rem - var(--border));flex-wrap:wrap;order:var(--tab-order);height:calc(var(--size-field,.25rem)*10);border-color:transparent;justify-content:center;align-items:center;padding-inline-start:var(--tab-p);padding-inline-end:var(--tab-p);font-size:.875rem;display:inline-flex;position:relative}@media (hover:hover){.lg\:tab:hover{color:var(--color-base-content)}}.lg\:tab:is(input[type=radio]){min-width:fit-content}.lg\:tab:is(input[type=radio]):after{content:attr(aria-label)}.lg\:tab:is(label){position:relative}.lg\:tab:is(label) input{cursor:pointer;appearance:none;opacity:0;position:absolute;inset:0}.lg\:tab:checked+.tab-content{height:100%;display:block}.lg\:tab:is(label:has(:checked))+.tab-content{height:100%;display:block}.lg\:tab:is(.tab-active,[aria-selected=true])+.tab-content{height:100%;display:block}.lg\:tab:not(:is(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true])){color:color-mix(in oklab,var(--color-base-content)50%,transparent)}.lg\:tab:not(input):empty{cursor:default;flex-grow:1}.lg\:tab:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:tab:focus{outline-offset:2px;outline:2px solid transparent}}.lg\:tab:focus-visible{outline-offset:-5px;outline:2px solid}.lg\:tab:is(label:has(:checked:focus-visible)){outline-offset:-5px;outline:2px solid}.lg\:tab[disabled]{pointer-events:none;opacity:.4}.lg\:tab-disabled{pointer-events:none;opacity:.4}.lg\:tabs-border .tab{--tab-border-color:transparent transparent var(--tab-border-color)transparent;border-radius:var(--radius-field);position:relative}.lg\:tabs-border .tab:before{--tw-content:"";content:var(--tw-content);background-color:var(--tab-border-color);border-radius:var(--radius-field);width:80%;height:3px;transition:background-color .2s;position:absolute;bottom:0;left:10%}.lg\:tabs-border .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{--tab-border-color:currentColor;border-top:3px solid}.lg\:tabs-border .tab:is(input:checked):before{--tab-border-color:currentColor;border-top:3px solid}.lg\:tabs-border .tab:is(label:has(:checked)):before{--tab-border-color:currentColor;border-top:3px solid}.lg\:tabs-lift{--tabs-height:auto;--tabs-direction:row}.lg\:tabs-lift>.tab{--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right;border-width:var(--tab-border);padding:var(--tab-paddings);border-color:var(--tab-border-colors);border-start-start-radius:var(--tab-radius-ss);border-start-end-radius:var(--tab-radius-se);border-end-end-radius:var(--tab-radius-ee);border-end-start-radius:var(--tab-radius-es)}.lg\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.lg\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.lg\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{--radius-start:none}[dir=rtl] .lg\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{transform:rotateY(180deg)}.lg\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{--radius-end:none}[dir=rtl] .lg\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{transform:rotateY(180deg)}.lg\:tabs-lift>.tab:is(input:checked,label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.lg\:tabs-lift>.tab:is(input:checked,label:has(:checked)):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.lg\:tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{--radius-start:none}[dir=rtl] .lg\:tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{transform:rotateY(180deg)}.lg\:tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{--radius-end:none}[dir=rtl] .lg\:tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{transform:rotateY(180deg)}.lg\:tabs-lift:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.lg\:tabs-lift .tab-content{--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.lg\:tabs-lift :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-lift :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-lift label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-lift label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-top{--tabs-height:auto;--tabs-direction:row}.lg\:tabs-top .tab{--tab-order:0;--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.lg\:tabs-top .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.lg\:tabs-top .tab:is(input:checked){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.lg\:tabs-top .tab:is(label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.lg\:tabs-top:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.lg\:tabs-top .tab-content{--tabcontent-order:1;--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.lg\:tabs-top :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-top :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-top label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-top label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.lg\:tabs-bottom{--tabs-height:auto;--tabs-direction:row}.lg\:tabs-bottom .tab{--tab-order:1;--tab-border:var(--border)0 0 0;--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:min(var(--radius-field),var(--tab-radius-min));--tab-radius-ee:min(var(--radius-field),var(--tab-radius-min));--tab-border-colors:var(--tab-border-color)transparent transparent transparent;--tab-paddings:0 var(--tab-p)var(--border)var(--tab-p);--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.lg\:tabs-bottom .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.lg\:tabs-bottom .tab:is(input:checked){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.lg\:tabs-bottom .tab:is(label:has(:checked)){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.lg\:tabs-bottom:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color)}.lg\:tabs-bottom .tab-content{--tabcontent-order:0;--tabcontent-margin:0 0 calc(-1*var(--border))0;--tabcontent-radius-ss:var(--radius-box);--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:0;--tabcontent-radius-ee:var(--radius-box)}.lg\:tabs-bottom>:checked+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.lg\:tabs-bottom>:is(label:has(:checked))+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.lg\:tabs-bottom>:is(.tab-active,[aria-selected=true])+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.lg\:tabs-box{background-color:var(--color-base-200);border-radius:calc(var(--radius-field) + min(.25rem,calc(var(--radius-field) + var(--radius-field) + var(--radius-field))));box-shadow:0 -.5px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 .5px oklch(0% 0 0/calc(var(--depth)*.05))inset;padding:.25rem}.lg\:tabs-box .tab{border-radius:var(--radius-field);border-style:none}.lg\:tabs-box .tab:focus-visible{outline-offset:2px}.lg\:tabs-box .tab:is(label:has(:checked:focus-visible)){outline-offset:2px}.lg\:tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.lg\:tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){border:1px solid}}.lg\:tabs-box>:is(input:checked){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.lg\:tabs-box>:is(input:checked){border:1px solid}}.lg\:tabs-box>:is(label:has(:checked)){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.lg\:tabs-box>:is(label:has(:checked)){border:1px solid}}.lg\:tab-content{--tabcontent-radius-ss:0;--tabcontent-radius-se:0;--tabcontent-radius-es:0;--tabcontent-radius-ee:0;--tabcontent-order:1;width:100%;margin:var(--tabcontent-margin);order:1;order:var(--tabcontent-order);border-color:transparent;border-width:var(--border);border-start-start-radius:var(--tabcontent-radius-ss);border-start-end-radius:var(--tabcontent-radius-se);border-end-end-radius:var(--tabcontent-radius-ee);border-end-start-radius:var(--tabcontent-radius-es);display:none}.lg\:tabs-xs :where(.tab){height:calc(var(--size-field,.25rem)*6);--tab-p:.375rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.75rem}.lg\:tabs-sm :where(.tab){height:calc(var(--size-field,.25rem)*8);--tab-p:.5rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.875rem}.lg\:tabs-md :where(.tab){height:calc(var(--size-field,.25rem)*10);--tab-p:.75rem;--tab-radius-min:calc(.75rem - var(--border));font-size:.875rem}.lg\:tabs-lg :where(.tab){height:calc(var(--size-field,.25rem)*12);--tab-p:1rem;--tab-radius-min:calc(1.5rem - var(--border));font-size:1.125rem}.lg\:tabs-xl :where(.tab){height:calc(var(--size-field,.25rem)*14);--tab-p:1.25rem;--tab-radius-min:calc(2rem - var(--border));font-size:1.125rem}}@media (min-width:1280px){.xl\:tabs{--tabs-height:auto;--tabs-direction:row;height:var(--tabs-height);flex-wrap:wrap;flex-direction:var(--tabs-direction);display:flex}.xl\:tab{cursor:pointer;appearance:none;text-align:center;-webkit-user-select:none;user-select:none;--tab-p:1rem;--tab-bg:var(--color-base-100);--tab-border-color:var(--color-base-300);--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:0;--tab-radius-ee:0;--tab-order:0;--tab-radius-min:calc(.75rem - var(--border));flex-wrap:wrap;order:var(--tab-order);height:calc(var(--size-field,.25rem)*10);border-color:transparent;justify-content:center;align-items:center;padding-inline-start:var(--tab-p);padding-inline-end:var(--tab-p);font-size:.875rem;display:inline-flex;position:relative}@media (hover:hover){.xl\:tab:hover{color:var(--color-base-content)}}.xl\:tab:is(input[type=radio]){min-width:fit-content}.xl\:tab:is(input[type=radio]):after{content:attr(aria-label)}.xl\:tab:is(label){position:relative}.xl\:tab:is(label) input{cursor:pointer;appearance:none;opacity:0;position:absolute;inset:0}.xl\:tab:checked+.tab-content{height:100%;display:block}.xl\:tab:is(label:has(:checked))+.tab-content{height:100%;display:block}.xl\:tab:is(.tab-active,[aria-selected=true])+.tab-content{height:100%;display:block}.xl\:tab:not(:is(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true])){color:color-mix(in oklab,var(--color-base-content)50%,transparent)}.xl\:tab:not(input):empty{cursor:default;flex-grow:1}.xl\:tab:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:tab:focus{outline-offset:2px;outline:2px solid transparent}}.xl\:tab:focus-visible{outline-offset:-5px;outline:2px solid}.xl\:tab:is(label:has(:checked:focus-visible)){outline-offset:-5px;outline:2px solid}.xl\:tab[disabled]{pointer-events:none;opacity:.4}.xl\:tab-disabled{pointer-events:none;opacity:.4}.xl\:tabs-border .tab{--tab-border-color:transparent transparent var(--tab-border-color)transparent;border-radius:var(--radius-field);position:relative}.xl\:tabs-border .tab:before{--tw-content:"";content:var(--tw-content);background-color:var(--tab-border-color);border-radius:var(--radius-field);width:80%;height:3px;transition:background-color .2s;position:absolute;bottom:0;left:10%}.xl\:tabs-border .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{--tab-border-color:currentColor;border-top:3px solid}.xl\:tabs-border .tab:is(input:checked):before{--tab-border-color:currentColor;border-top:3px solid}.xl\:tabs-border .tab:is(label:has(:checked)):before{--tab-border-color:currentColor;border-top:3px solid}.xl\:tabs-lift{--tabs-height:auto;--tabs-direction:row}.xl\:tabs-lift>.tab{--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right;border-width:var(--tab-border);padding:var(--tab-paddings);border-color:var(--tab-border-colors);border-start-start-radius:var(--tab-radius-ss);border-start-end-radius:var(--tab-radius-se);border-end-end-radius:var(--tab-radius-ee);border-end-start-radius:var(--tab-radius-es)}.xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{--radius-start:none}[dir=rtl] .xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{transform:rotateY(180deg)}.xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{--radius-end:none}[dir=rtl] .xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{transform:rotateY(180deg)}.xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{--radius-start:none}[dir=rtl] .xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{transform:rotateY(180deg)}.xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{--radius-end:none}[dir=rtl] .xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{transform:rotateY(180deg)}.xl\:tabs-lift:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.xl\:tabs-lift .tab-content{--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.xl\:tabs-lift :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-lift :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-lift label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-lift label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-top{--tabs-height:auto;--tabs-direction:row}.xl\:tabs-top .tab{--tab-order:0;--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.xl\:tabs-top .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.xl\:tabs-top .tab:is(input:checked){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.xl\:tabs-top .tab:is(label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.xl\:tabs-top:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.xl\:tabs-top .tab-content{--tabcontent-order:1;--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.xl\:tabs-top :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-top :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-top label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-top label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.xl\:tabs-bottom{--tabs-height:auto;--tabs-direction:row}.xl\:tabs-bottom .tab{--tab-order:1;--tab-border:var(--border)0 0 0;--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:min(var(--radius-field),var(--tab-radius-min));--tab-radius-ee:min(var(--radius-field),var(--tab-radius-min));--tab-border-colors:var(--tab-border-color)transparent transparent transparent;--tab-paddings:0 var(--tab-p)var(--border)var(--tab-p);--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.xl\:tabs-bottom .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.xl\:tabs-bottom .tab:is(input:checked){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.xl\:tabs-bottom .tab:is(label:has(:checked)){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.xl\:tabs-bottom:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color)}.xl\:tabs-bottom .tab-content{--tabcontent-order:0;--tabcontent-margin:0 0 calc(-1*var(--border))0;--tabcontent-radius-ss:var(--radius-box);--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:0;--tabcontent-radius-ee:var(--radius-box)}.xl\:tabs-bottom>:checked+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.xl\:tabs-bottom>:is(label:has(:checked))+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.xl\:tabs-bottom>:is(.tab-active,[aria-selected=true])+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.xl\:tabs-box{background-color:var(--color-base-200);border-radius:calc(var(--radius-field) + min(.25rem,calc(var(--radius-field) + var(--radius-field) + var(--radius-field))));box-shadow:0 -.5px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 .5px oklch(0% 0 0/calc(var(--depth)*.05))inset;padding:.25rem}.xl\:tabs-box .tab{border-radius:var(--radius-field);border-style:none}.xl\:tabs-box .tab:focus-visible{outline-offset:2px}.xl\:tabs-box .tab:is(label:has(:checked:focus-visible)){outline-offset:2px}.xl\:tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.xl\:tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){border:1px solid}}.xl\:tabs-box>:is(input:checked){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.xl\:tabs-box>:is(input:checked){border:1px solid}}.xl\:tabs-box>:is(label:has(:checked)){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.xl\:tabs-box>:is(label:has(:checked)){border:1px solid}}.xl\:tab-content{--tabcontent-radius-ss:0;--tabcontent-radius-se:0;--tabcontent-radius-es:0;--tabcontent-radius-ee:0;--tabcontent-order:1;width:100%;margin:var(--tabcontent-margin);order:1;order:var(--tabcontent-order);border-color:transparent;border-width:var(--border);border-start-start-radius:var(--tabcontent-radius-ss);border-start-end-radius:var(--tabcontent-radius-se);border-end-end-radius:var(--tabcontent-radius-ee);border-end-start-radius:var(--tabcontent-radius-es);display:none}.xl\:tabs-xs :where(.tab){height:calc(var(--size-field,.25rem)*6);--tab-p:.375rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.75rem}.xl\:tabs-sm :where(.tab){height:calc(var(--size-field,.25rem)*8);--tab-p:.5rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.875rem}.xl\:tabs-md :where(.tab){height:calc(var(--size-field,.25rem)*10);--tab-p:.75rem;--tab-radius-min:calc(.75rem - var(--border));font-size:.875rem}.xl\:tabs-lg :where(.tab){height:calc(var(--size-field,.25rem)*12);--tab-p:1rem;--tab-radius-min:calc(1.5rem - var(--border));font-size:1.125rem}.xl\:tabs-xl :where(.tab){height:calc(var(--size-field,.25rem)*14);--tab-p:1.25rem;--tab-radius-min:calc(2rem - var(--border));font-size:1.125rem}}@media (min-width:1536px){.\32 xl\:tabs{--tabs-height:auto;--tabs-direction:row;height:var(--tabs-height);flex-wrap:wrap;flex-direction:var(--tabs-direction);display:flex}.\32 xl\:tab{cursor:pointer;appearance:none;text-align:center;-webkit-user-select:none;user-select:none;--tab-p:1rem;--tab-bg:var(--color-base-100);--tab-border-color:var(--color-base-300);--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:0;--tab-radius-ee:0;--tab-order:0;--tab-radius-min:calc(.75rem - var(--border));flex-wrap:wrap;order:var(--tab-order);height:calc(var(--size-field,.25rem)*10);border-color:transparent;justify-content:center;align-items:center;padding-inline-start:var(--tab-p);padding-inline-end:var(--tab-p);font-size:.875rem;display:inline-flex;position:relative}@media (hover:hover){.\32 xl\:tab:hover{color:var(--color-base-content)}}.\32 xl\:tab:is(input[type=radio]){min-width:fit-content}.\32 xl\:tab:is(input[type=radio]):after{content:attr(aria-label)}.\32 xl\:tab:is(label){position:relative}.\32 xl\:tab:is(label) input{cursor:pointer;appearance:none;opacity:0;position:absolute;inset:0}.\32 xl\:tab:checked+.tab-content{height:100%;display:block}.\32 xl\:tab:is(label:has(:checked))+.tab-content{height:100%;display:block}.\32 xl\:tab:is(.tab-active,[aria-selected=true])+.tab-content{height:100%;display:block}.\32 xl\:tab:not(:is(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true])){color:color-mix(in oklab,var(--color-base-content)50%,transparent)}.\32 xl\:tab:not(input):empty{cursor:default;flex-grow:1}.\32 xl\:tab:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:tab:focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:tab:focus-visible{outline-offset:-5px;outline:2px solid}.\32 xl\:tab:is(label:has(:checked:focus-visible)){outline-offset:-5px;outline:2px solid}.\32 xl\:tab[disabled]{pointer-events:none;opacity:.4}.\32 xl\:tab-disabled{pointer-events:none;opacity:.4}.\32 xl\:tabs-border .tab{--tab-border-color:transparent transparent var(--tab-border-color)transparent;border-radius:var(--radius-field);position:relative}.\32 xl\:tabs-border .tab:before{--tw-content:"";content:var(--tw-content);background-color:var(--tab-border-color);border-radius:var(--radius-field);width:80%;height:3px;transition:background-color .2s;position:absolute;bottom:0;left:10%}.\32 xl\:tabs-border .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{--tab-border-color:currentColor;border-top:3px solid}.\32 xl\:tabs-border .tab:is(input:checked):before{--tab-border-color:currentColor;border-top:3px solid}.\32 xl\:tabs-border .tab:is(label:has(:checked)):before{--tab-border-color:currentColor;border-top:3px solid}.\32 xl\:tabs-lift{--tabs-height:auto;--tabs-direction:row}.\32 xl\:tabs-lift>.tab{--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right;border-width:var(--tab-border);padding:var(--tab-paddings);border-color:var(--tab-border-colors);border-start-start-radius:var(--tab-radius-ss);border-start-end-radius:var(--tab-radius-se);border-end-end-radius:var(--tab-radius-ee);border-end-start-radius:var(--tab-radius-es)}.\32 xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.\32 xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.\32 xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{--radius-start:none}[dir=rtl] .\32 xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):first-child:before{transform:rotateY(180deg)}.\32 xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{--radius-end:none}[dir=rtl] .\32 xl\:tabs-lift>.tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])):last-child:before{transform:rotateY(180deg)}.\32 xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--tab-grad:calc(69% - var(--border));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));background-color:var(--tab-bg)}.\32 xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)):before{z-index:1;content:"";width:var(--tab-corner-width);height:var(--tab-corner-height);background-position:var(--tab-corner-position);background-image:var(--radius-start),var(--radius-end);background-size:min(var(--radius-field),var(--tab-radius-min))min(var(--radius-field),var(--tab-radius-min));inset:var(--tab-inset);background-repeat:no-repeat;display:block;position:absolute}.\32 xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{--radius-start:none}[dir=rtl] .\32 xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)):first-child:before{transform:rotateY(180deg)}.\32 xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{--radius-end:none}[dir=rtl] .\32 xl\:tabs-lift>.tab:is(input:checked,label:has(:checked)):last-child:before{transform:rotateY(180deg)}.\32 xl\:tabs-lift:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.\32 xl\:tabs-lift .tab-content{--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.\32 xl\:tabs-lift :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-lift :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-lift label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-lift label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-lift :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-top{--tabs-height:auto;--tabs-direction:row}.\32 xl\:tabs-top .tab{--tab-order:0;--tab-border:0 0 var(--border)0;--tab-radius-ss:min(var(--radius-field),var(--tab-radius-min));--tab-radius-se:min(var(--radius-field),var(--tab-radius-min));--tab-radius-es:0;--tab-radius-ee:0;--tab-paddings:var(--border)var(--tab-p)0 var(--tab-p);--tab-border-colors:transparent transparent var(--tab-border-color)transparent;--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.\32 xl\:tabs-top .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.\32 xl\:tabs-top .tab:is(input:checked){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.\32 xl\:tabs-top .tab:is(label:has(:checked)){--tab-border:var(--border)var(--border)0 var(--border);--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color);--tab-paddings:0 calc(var(--tab-p) - var(--border))var(--border)calc(var(--tab-p) - var(--border));--tab-inset:auto auto 0 auto;--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.\32 xl\:tabs-top:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:var(--tab-border-color)var(--tab-border-color)transparent var(--tab-border-color)}.\32 xl\:tabs-top .tab-content{--tabcontent-order:1;--tabcontent-margin:calc(-1*var(--border))0 0 0;--tabcontent-radius-ss:0;--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box)}.\32 xl\:tabs-top :checked+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-top :checked+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-top label:has(:checked)+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-top label:has(:checked)+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:first-child{--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-top :is(.tab-active,[aria-selected=true])+.tab-content:nth-child(n+3){--tabcontent-radius-ss:var(--radius-box)}.\32 xl\:tabs-bottom{--tabs-height:auto;--tabs-direction:row}.\32 xl\:tabs-bottom .tab{--tab-order:1;--tab-border:var(--border)0 0 0;--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:min(var(--radius-field),var(--tab-radius-min));--tab-radius-ee:min(var(--radius-field),var(--tab-radius-min));--tab-border-colors:var(--tab-border-color)transparent transparent transparent;--tab-paddings:0 var(--tab-p)var(--border)var(--tab-p);--tab-corner-width:calc(100% + min(var(--radius-field),var(--tab-radius-min))*2);--tab-corner-height:min(var(--radius-field),var(--tab-radius-min));--tab-corner-position:top left,top right}.\32 xl\:tabs-bottom .tab:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.\32 xl\:tabs-bottom .tab:is(input:checked){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.\32 xl\:tabs-bottom .tab:is(label:has(:checked)){--tab-border:0 var(--border)var(--border)var(--border);--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color);--tab-paddings:var(--border)calc(var(--tab-p) - var(--border))0 calc(var(--tab-p) - var(--border));--tab-inset:0 auto auto auto;--radius-start:radial-gradient(circle at bottom left,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px));--radius-end:radial-gradient(circle at bottom right,transparent var(--tab-grad),var(--tab-border-color)calc(var(--tab-grad) + .25px),var(--tab-border-color)calc(var(--tab-grad) + var(--border)),var(--tab-bg)calc(var(--tab-grad) + var(--border) + .25px))}.\32 xl\:tabs-bottom:has(.tab-content)>.tab:first-child:not(:is(.tab-active,[aria-selected=true])){--tab-border-colors:transparent var(--tab-border-color)var(--tab-border-color)var(--tab-border-color)}.\32 xl\:tabs-bottom .tab-content{--tabcontent-order:0;--tabcontent-margin:0 0 calc(-1*var(--border))0;--tabcontent-radius-ss:var(--radius-box);--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:0;--tabcontent-radius-ee:var(--radius-box)}.\32 xl\:tabs-bottom>:checked+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.\32 xl\:tabs-bottom>:is(label:has(:checked))+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.\32 xl\:tabs-bottom>:is(.tab-active,[aria-selected=true])+.tab-content:not(:nth-child(2)){--tabcontent-radius-es:var(--radius-box)}.\32 xl\:tabs-box{background-color:var(--color-base-200);border-radius:calc(var(--radius-field) + min(.25rem,calc(var(--radius-field) + var(--radius-field) + var(--radius-field))));box-shadow:0 -.5px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 .5px oklch(0% 0 0/calc(var(--depth)*.05))inset;padding:.25rem}.\32 xl\:tabs-box .tab{border-radius:var(--radius-field);border-style:none}.\32 xl\:tabs-box .tab:focus-visible{outline-offset:2px}.\32 xl\:tabs-box .tab:is(label:has(:checked:focus-visible)){outline-offset:2px}.\32 xl\:tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.\32 xl\:tabs-box>:is(.tab-active,[aria-selected=true]):not(:is(.tab-disabled,[disabled])){border:1px solid}}.\32 xl\:tabs-box>:is(input:checked){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.\32 xl\:tabs-box>:is(input:checked){border:1px solid}}.\32 xl\:tabs-box>:is(label:has(:checked)){background-color:var(--tab-bg,var(--color-base-100));box-shadow:0 1px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px 1px -1px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*50%),transparent),0 1px 6px -4px color-mix(in oklab,var(--color-neutral)calc(var(--depth)*100%),transparent)}@media (forced-colors:active){.\32 xl\:tabs-box>:is(label:has(:checked)){border:1px solid}}.\32 xl\:tab-content{--tabcontent-radius-ss:0;--tabcontent-radius-se:0;--tabcontent-radius-es:0;--tabcontent-radius-ee:0;--tabcontent-order:1;width:100%;margin:var(--tabcontent-margin);order:1;order:var(--tabcontent-order);border-color:transparent;border-width:var(--border);border-start-start-radius:var(--tabcontent-radius-ss);border-start-end-radius:var(--tabcontent-radius-se);border-end-end-radius:var(--tabcontent-radius-ee);border-end-start-radius:var(--tabcontent-radius-es);display:none}.\32 xl\:tabs-xs :where(.tab){height:calc(var(--size-field,.25rem)*6);--tab-p:.375rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.75rem}.\32 xl\:tabs-sm :where(.tab){height:calc(var(--size-field,.25rem)*8);--tab-p:.5rem;--tab-radius-min:calc(.5rem - var(--border));font-size:.875rem}.\32 xl\:tabs-md :where(.tab){height:calc(var(--size-field,.25rem)*10);--tab-p:.75rem;--tab-radius-min:calc(.75rem - var(--border));font-size:.875rem}.\32 xl\:tabs-lg :where(.tab){height:calc(var(--size-field,.25rem)*12);--tab-p:1rem;--tab-radius-min:calc(1.5rem - var(--border));font-size:1.125rem}.\32 xl\:tabs-xl :where(.tab){height:calc(var(--size-field,.25rem)*14);--tab-p:1.25rem;--tab-radius-min:calc(2rem - var(--border));font-size:1.125rem}}.badge{border-radius:var(--radius-selector);vertical-align:middle;color:var(--badge-fg);border:var(--border)solid var(--badge-color,var(--color-base-200));width:fit-content;padding-inline:calc(.25rem*3 - var(--border));background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);background-color:var(--badge-bg);--badge-bg:var(--badge-color,var(--color-base-100));--badge-fg:var(--color-base-content);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);justify-content:center;align-items:center;gap:.5rem;font-size:.875rem;display:inline-flex}.badge.badge-outline{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none}.badge.badge-dash{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none;border-style:dashed}.badge.badge-soft{color:var(--badge-color,var(--color-base-content));background-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))10%,var(--color-base-100));background-image:none}.badge-primary{--badge-color:var(--color-primary);--badge-fg:var(--color-primary-content)}.badge-secondary{--badge-color:var(--color-secondary);--badge-fg:var(--color-secondary-content)}.badge-accent{--badge-color:var(--color-accent);--badge-fg:var(--color-accent-content)}.badge-neutral{--badge-color:var(--color-neutral);--badge-fg:var(--color-neutral-content)}.badge-info{--badge-color:var(--color-info);--badge-fg:var(--color-info-content)}.badge-success{--badge-color:var(--color-success);--badge-fg:var(--color-success-content)}.badge-warning{--badge-color:var(--color-warning);--badge-fg:var(--color-warning-content)}.badge-error{--badge-color:var(--color-error);--badge-fg:var(--color-error-content)}.badge-ghost{border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content);background-image:none}.badge-xs{--size:calc(var(--size-selector,.25rem)*4);padding-inline:calc(.25rem*2 - var(--border));font-size:.625rem}.badge-sm{--size:calc(var(--size-selector,.25rem)*5);padding-inline:calc(.25rem*2.5 - var(--border));font-size:.75rem}.badge-md{--size:calc(var(--size-selector,.25rem)*6);padding-inline:calc(.25rem*3 - var(--border));font-size:.875rem}.badge-lg{--size:calc(var(--size-selector,.25rem)*7);padding-inline:calc(.25rem*3.5 - var(--border));font-size:1rem}.badge-xl{--size:calc(var(--size-selector,.25rem)*8);padding-inline:calc(.25rem*4 - var(--border));font-size:1.125rem}@media (min-width:640px){.sm\:badge{border-radius:var(--radius-selector);vertical-align:middle;color:var(--badge-fg);border:var(--border)solid var(--badge-color,var(--color-base-200));width:fit-content;padding-inline:calc(.25rem*3 - var(--border));background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);background-color:var(--badge-bg);--badge-bg:var(--badge-color,var(--color-base-100));--badge-fg:var(--color-base-content);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);justify-content:center;align-items:center;gap:.5rem;font-size:.875rem;display:inline-flex}.sm\:badge.badge-outline{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none}.sm\:badge.badge-dash{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none;border-style:dashed}.sm\:badge.badge-soft{color:var(--badge-color,var(--color-base-content));background-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))10%,var(--color-base-100));background-image:none}.sm\:badge-primary{--badge-color:var(--color-primary);--badge-fg:var(--color-primary-content)}.sm\:badge-secondary{--badge-color:var(--color-secondary);--badge-fg:var(--color-secondary-content)}.sm\:badge-accent{--badge-color:var(--color-accent);--badge-fg:var(--color-accent-content)}.sm\:badge-neutral{--badge-color:var(--color-neutral);--badge-fg:var(--color-neutral-content)}.sm\:badge-info{--badge-color:var(--color-info);--badge-fg:var(--color-info-content)}.sm\:badge-success{--badge-color:var(--color-success);--badge-fg:var(--color-success-content)}.sm\:badge-warning{--badge-color:var(--color-warning);--badge-fg:var(--color-warning-content)}.sm\:badge-error{--badge-color:var(--color-error);--badge-fg:var(--color-error-content)}.sm\:badge-ghost{border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content);background-image:none}.sm\:badge-xs{--size:calc(var(--size-selector,.25rem)*4);padding-inline:calc(.25rem*2 - var(--border));font-size:.625rem}.sm\:badge-sm{--size:calc(var(--size-selector,.25rem)*5);padding-inline:calc(.25rem*2.5 - var(--border));font-size:.75rem}.sm\:badge-md{--size:calc(var(--size-selector,.25rem)*6);padding-inline:calc(.25rem*3 - var(--border));font-size:.875rem}.sm\:badge-lg{--size:calc(var(--size-selector,.25rem)*7);padding-inline:calc(.25rem*3.5 - var(--border));font-size:1rem}.sm\:badge-xl{--size:calc(var(--size-selector,.25rem)*8);padding-inline:calc(.25rem*4 - var(--border));font-size:1.125rem}}@media (min-width:768px){.md\:badge{border-radius:var(--radius-selector);vertical-align:middle;color:var(--badge-fg);border:var(--border)solid var(--badge-color,var(--color-base-200));width:fit-content;padding-inline:calc(.25rem*3 - var(--border));background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);background-color:var(--badge-bg);--badge-bg:var(--badge-color,var(--color-base-100));--badge-fg:var(--color-base-content);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);justify-content:center;align-items:center;gap:.5rem;font-size:.875rem;display:inline-flex}.md\:badge.badge-outline{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none}.md\:badge.badge-dash{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none;border-style:dashed}.md\:badge.badge-soft{color:var(--badge-color,var(--color-base-content));background-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))10%,var(--color-base-100));background-image:none}.md\:badge-primary{--badge-color:var(--color-primary);--badge-fg:var(--color-primary-content)}.md\:badge-secondary{--badge-color:var(--color-secondary);--badge-fg:var(--color-secondary-content)}.md\:badge-accent{--badge-color:var(--color-accent);--badge-fg:var(--color-accent-content)}.md\:badge-neutral{--badge-color:var(--color-neutral);--badge-fg:var(--color-neutral-content)}.md\:badge-info{--badge-color:var(--color-info);--badge-fg:var(--color-info-content)}.md\:badge-success{--badge-color:var(--color-success);--badge-fg:var(--color-success-content)}.md\:badge-warning{--badge-color:var(--color-warning);--badge-fg:var(--color-warning-content)}.md\:badge-error{--badge-color:var(--color-error);--badge-fg:var(--color-error-content)}.md\:badge-ghost{border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content);background-image:none}.md\:badge-xs{--size:calc(var(--size-selector,.25rem)*4);padding-inline:calc(.25rem*2 - var(--border));font-size:.625rem}.md\:badge-sm{--size:calc(var(--size-selector,.25rem)*5);padding-inline:calc(.25rem*2.5 - var(--border));font-size:.75rem}.md\:badge-md{--size:calc(var(--size-selector,.25rem)*6);padding-inline:calc(.25rem*3 - var(--border));font-size:.875rem}.md\:badge-lg{--size:calc(var(--size-selector,.25rem)*7);padding-inline:calc(.25rem*3.5 - var(--border));font-size:1rem}.md\:badge-xl{--size:calc(var(--size-selector,.25rem)*8);padding-inline:calc(.25rem*4 - var(--border));font-size:1.125rem}}@media (min-width:1024px){.lg\:badge{border-radius:var(--radius-selector);vertical-align:middle;color:var(--badge-fg);border:var(--border)solid var(--badge-color,var(--color-base-200));width:fit-content;padding-inline:calc(.25rem*3 - var(--border));background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);background-color:var(--badge-bg);--badge-bg:var(--badge-color,var(--color-base-100));--badge-fg:var(--color-base-content);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);justify-content:center;align-items:center;gap:.5rem;font-size:.875rem;display:inline-flex}.lg\:badge.badge-outline{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none}.lg\:badge.badge-dash{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none;border-style:dashed}.lg\:badge.badge-soft{color:var(--badge-color,var(--color-base-content));background-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))10%,var(--color-base-100));background-image:none}.lg\:badge-primary{--badge-color:var(--color-primary);--badge-fg:var(--color-primary-content)}.lg\:badge-secondary{--badge-color:var(--color-secondary);--badge-fg:var(--color-secondary-content)}.lg\:badge-accent{--badge-color:var(--color-accent);--badge-fg:var(--color-accent-content)}.lg\:badge-neutral{--badge-color:var(--color-neutral);--badge-fg:var(--color-neutral-content)}.lg\:badge-info{--badge-color:var(--color-info);--badge-fg:var(--color-info-content)}.lg\:badge-success{--badge-color:var(--color-success);--badge-fg:var(--color-success-content)}.lg\:badge-warning{--badge-color:var(--color-warning);--badge-fg:var(--color-warning-content)}.lg\:badge-error{--badge-color:var(--color-error);--badge-fg:var(--color-error-content)}.lg\:badge-ghost{border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content);background-image:none}.lg\:badge-xs{--size:calc(var(--size-selector,.25rem)*4);padding-inline:calc(.25rem*2 - var(--border));font-size:.625rem}.lg\:badge-sm{--size:calc(var(--size-selector,.25rem)*5);padding-inline:calc(.25rem*2.5 - var(--border));font-size:.75rem}.lg\:badge-md{--size:calc(var(--size-selector,.25rem)*6);padding-inline:calc(.25rem*3 - var(--border));font-size:.875rem}.lg\:badge-lg{--size:calc(var(--size-selector,.25rem)*7);padding-inline:calc(.25rem*3.5 - var(--border));font-size:1rem}.lg\:badge-xl{--size:calc(var(--size-selector,.25rem)*8);padding-inline:calc(.25rem*4 - var(--border));font-size:1.125rem}}@media (min-width:1280px){.xl\:badge{border-radius:var(--radius-selector);vertical-align:middle;color:var(--badge-fg);border:var(--border)solid var(--badge-color,var(--color-base-200));width:fit-content;padding-inline:calc(.25rem*3 - var(--border));background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);background-color:var(--badge-bg);--badge-bg:var(--badge-color,var(--color-base-100));--badge-fg:var(--color-base-content);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);justify-content:center;align-items:center;gap:.5rem;font-size:.875rem;display:inline-flex}.xl\:badge.badge-outline{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none}.xl\:badge.badge-dash{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none;border-style:dashed}.xl\:badge.badge-soft{color:var(--badge-color,var(--color-base-content));background-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))10%,var(--color-base-100));background-image:none}.xl\:badge-primary{--badge-color:var(--color-primary);--badge-fg:var(--color-primary-content)}.xl\:badge-secondary{--badge-color:var(--color-secondary);--badge-fg:var(--color-secondary-content)}.xl\:badge-accent{--badge-color:var(--color-accent);--badge-fg:var(--color-accent-content)}.xl\:badge-neutral{--badge-color:var(--color-neutral);--badge-fg:var(--color-neutral-content)}.xl\:badge-info{--badge-color:var(--color-info);--badge-fg:var(--color-info-content)}.xl\:badge-success{--badge-color:var(--color-success);--badge-fg:var(--color-success-content)}.xl\:badge-warning{--badge-color:var(--color-warning);--badge-fg:var(--color-warning-content)}.xl\:badge-error{--badge-color:var(--color-error);--badge-fg:var(--color-error-content)}.xl\:badge-ghost{border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content);background-image:none}.xl\:badge-xs{--size:calc(var(--size-selector,.25rem)*4);padding-inline:calc(.25rem*2 - var(--border));font-size:.625rem}.xl\:badge-sm{--size:calc(var(--size-selector,.25rem)*5);padding-inline:calc(.25rem*2.5 - var(--border));font-size:.75rem}.xl\:badge-md{--size:calc(var(--size-selector,.25rem)*6);padding-inline:calc(.25rem*3 - var(--border));font-size:.875rem}.xl\:badge-lg{--size:calc(var(--size-selector,.25rem)*7);padding-inline:calc(.25rem*3.5 - var(--border));font-size:1rem}.xl\:badge-xl{--size:calc(var(--size-selector,.25rem)*8);padding-inline:calc(.25rem*4 - var(--border));font-size:1.125rem}}@media (min-width:1536px){.\32 xl\:badge{border-radius:var(--radius-selector);vertical-align:middle;color:var(--badge-fg);border:var(--border)solid var(--badge-color,var(--color-base-200));width:fit-content;padding-inline:calc(.25rem*3 - var(--border));background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);background-color:var(--badge-bg);--badge-bg:var(--badge-color,var(--color-base-100));--badge-fg:var(--color-base-content);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);justify-content:center;align-items:center;gap:.5rem;font-size:.875rem;display:inline-flex}.\32 xl\:badge.badge-outline{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none}.\32 xl\:badge.badge-dash{--badge-fg:var(--badge-color);--badge-bg:transparent;background-image:none;border-style:dashed}.\32 xl\:badge.badge-soft{color:var(--badge-color,var(--color-base-content));background-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))8%,var(--color-base-100));border-color:color-mix(in oklab,var(--badge-color,var(--color-base-content))10%,var(--color-base-100));background-image:none}.\32 xl\:badge-primary{--badge-color:var(--color-primary);--badge-fg:var(--color-primary-content)}.\32 xl\:badge-secondary{--badge-color:var(--color-secondary);--badge-fg:var(--color-secondary-content)}.\32 xl\:badge-accent{--badge-color:var(--color-accent);--badge-fg:var(--color-accent-content)}.\32 xl\:badge-neutral{--badge-color:var(--color-neutral);--badge-fg:var(--color-neutral-content)}.\32 xl\:badge-info{--badge-color:var(--color-info);--badge-fg:var(--color-info-content)}.\32 xl\:badge-success{--badge-color:var(--color-success);--badge-fg:var(--color-success-content)}.\32 xl\:badge-warning{--badge-color:var(--color-warning);--badge-fg:var(--color-warning-content)}.\32 xl\:badge-error{--badge-color:var(--color-error);--badge-fg:var(--color-error-content)}.\32 xl\:badge-ghost{border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content);background-image:none}.\32 xl\:badge-xs{--size:calc(var(--size-selector,.25rem)*4);padding-inline:calc(.25rem*2 - var(--border));font-size:.625rem}.\32 xl\:badge-sm{--size:calc(var(--size-selector,.25rem)*5);padding-inline:calc(.25rem*2.5 - var(--border));font-size:.75rem}.\32 xl\:badge-md{--size:calc(var(--size-selector,.25rem)*6);padding-inline:calc(.25rem*3 - var(--border));font-size:.875rem}.\32 xl\:badge-lg{--size:calc(var(--size-selector,.25rem)*7);padding-inline:calc(.25rem*3.5 - var(--border));font-size:1rem}.\32 xl\:badge-xl{--size:calc(var(--size-selector,.25rem)*8);padding-inline:calc(.25rem*4 - var(--border));font-size:1.125rem}}.list{flex-direction:column;font-size:.875rem;display:flex}.list :where(.list-row){--list-grid-cols:minmax(0,auto)1fr;border-radius:var(--radius-box);word-break:break-word;grid-auto-flow:column;grid-template-columns:var(--list-grid-cols);gap:1rem;padding:1rem;display:grid;position:relative}.list :where(.list-row):has(.list-col-grow:first-child){--list-grid-cols:1fr}.list :where(.list-row):has(.list-col-grow:nth-child(2)){--list-grid-cols:minmax(0,auto)1fr}.list :where(.list-row):has(.list-col-grow:nth-child(3)){--list-grid-cols:minmax(0,auto)minmax(0,auto)1fr}.list :where(.list-row):has(.list-col-grow:nth-child(4)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.list :where(.list-row):has(.list-col-grow:nth-child(5)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.list :where(.list-row):has(.list-col-grow:nth-child(6)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.list :where(.list-row) :not(.list-col-wrap){grid-row-start:1}.list>:not(:last-child).list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.list>:not(:last-child) .list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.list-col-wrap{grid-row-start:2}@media (min-width:640px){.sm\:list{flex-direction:column;font-size:.875rem;display:flex}.sm\:list :where(.list-row){--list-grid-cols:minmax(0,auto)1fr;border-radius:var(--radius-box);word-break:break-word;grid-auto-flow:column;grid-template-columns:var(--list-grid-cols);gap:1rem;padding:1rem;display:grid;position:relative}.sm\:list :where(.list-row):has(.list-col-grow:first-child){--list-grid-cols:1fr}.sm\:list :where(.list-row):has(.list-col-grow:nth-child(2)){--list-grid-cols:minmax(0,auto)1fr}.sm\:list :where(.list-row):has(.list-col-grow:nth-child(3)){--list-grid-cols:minmax(0,auto)minmax(0,auto)1fr}.sm\:list :where(.list-row):has(.list-col-grow:nth-child(4)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.sm\:list :where(.list-row):has(.list-col-grow:nth-child(5)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.sm\:list :where(.list-row):has(.list-col-grow:nth-child(6)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.sm\:list :where(.list-row) :not(.list-col-wrap){grid-row-start:1}.sm\:list>:not(:last-child).list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.sm\:list>:not(:last-child) .list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.sm\:list-col-wrap{grid-row-start:2}}@media (min-width:768px){.md\:list{flex-direction:column;font-size:.875rem;display:flex}.md\:list :where(.list-row){--list-grid-cols:minmax(0,auto)1fr;border-radius:var(--radius-box);word-break:break-word;grid-auto-flow:column;grid-template-columns:var(--list-grid-cols);gap:1rem;padding:1rem;display:grid;position:relative}.md\:list :where(.list-row):has(.list-col-grow:first-child){--list-grid-cols:1fr}.md\:list :where(.list-row):has(.list-col-grow:nth-child(2)){--list-grid-cols:minmax(0,auto)1fr}.md\:list :where(.list-row):has(.list-col-grow:nth-child(3)){--list-grid-cols:minmax(0,auto)minmax(0,auto)1fr}.md\:list :where(.list-row):has(.list-col-grow:nth-child(4)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.md\:list :where(.list-row):has(.list-col-grow:nth-child(5)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.md\:list :where(.list-row):has(.list-col-grow:nth-child(6)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.md\:list :where(.list-row) :not(.list-col-wrap){grid-row-start:1}.md\:list>:not(:last-child).list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.md\:list>:not(:last-child) .list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.md\:list-col-wrap{grid-row-start:2}}@media (min-width:1024px){.lg\:list{flex-direction:column;font-size:.875rem;display:flex}.lg\:list :where(.list-row){--list-grid-cols:minmax(0,auto)1fr;border-radius:var(--radius-box);word-break:break-word;grid-auto-flow:column;grid-template-columns:var(--list-grid-cols);gap:1rem;padding:1rem;display:grid;position:relative}.lg\:list :where(.list-row):has(.list-col-grow:first-child){--list-grid-cols:1fr}.lg\:list :where(.list-row):has(.list-col-grow:nth-child(2)){--list-grid-cols:minmax(0,auto)1fr}.lg\:list :where(.list-row):has(.list-col-grow:nth-child(3)){--list-grid-cols:minmax(0,auto)minmax(0,auto)1fr}.lg\:list :where(.list-row):has(.list-col-grow:nth-child(4)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.lg\:list :where(.list-row):has(.list-col-grow:nth-child(5)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.lg\:list :where(.list-row):has(.list-col-grow:nth-child(6)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.lg\:list :where(.list-row) :not(.list-col-wrap){grid-row-start:1}.lg\:list>:not(:last-child).list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.lg\:list>:not(:last-child) .list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.lg\:list-col-wrap{grid-row-start:2}}@media (min-width:1280px){.xl\:list{flex-direction:column;font-size:.875rem;display:flex}.xl\:list :where(.list-row){--list-grid-cols:minmax(0,auto)1fr;border-radius:var(--radius-box);word-break:break-word;grid-auto-flow:column;grid-template-columns:var(--list-grid-cols);gap:1rem;padding:1rem;display:grid;position:relative}.xl\:list :where(.list-row):has(.list-col-grow:first-child){--list-grid-cols:1fr}.xl\:list :where(.list-row):has(.list-col-grow:nth-child(2)){--list-grid-cols:minmax(0,auto)1fr}.xl\:list :where(.list-row):has(.list-col-grow:nth-child(3)){--list-grid-cols:minmax(0,auto)minmax(0,auto)1fr}.xl\:list :where(.list-row):has(.list-col-grow:nth-child(4)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.xl\:list :where(.list-row):has(.list-col-grow:nth-child(5)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.xl\:list :where(.list-row):has(.list-col-grow:nth-child(6)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.xl\:list :where(.list-row) :not(.list-col-wrap){grid-row-start:1}.xl\:list>:not(:last-child).list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.xl\:list>:not(:last-child) .list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.xl\:list-col-wrap{grid-row-start:2}}@media (min-width:1536px){.\32 xl\:list{flex-direction:column;font-size:.875rem;display:flex}.\32 xl\:list :where(.list-row){--list-grid-cols:minmax(0,auto)1fr;border-radius:var(--radius-box);word-break:break-word;grid-auto-flow:column;grid-template-columns:var(--list-grid-cols);gap:1rem;padding:1rem;display:grid;position:relative}.\32 xl\:list :where(.list-row):has(.list-col-grow:first-child){--list-grid-cols:1fr}.\32 xl\:list :where(.list-row):has(.list-col-grow:nth-child(2)){--list-grid-cols:minmax(0,auto)1fr}.\32 xl\:list :where(.list-row):has(.list-col-grow:nth-child(3)){--list-grid-cols:minmax(0,auto)minmax(0,auto)1fr}.\32 xl\:list :where(.list-row):has(.list-col-grow:nth-child(4)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.\32 xl\:list :where(.list-row):has(.list-col-grow:nth-child(5)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.\32 xl\:list :where(.list-row):has(.list-col-grow:nth-child(6)){--list-grid-cols:minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)minmax(0,auto)1fr}.\32 xl\:list :where(.list-row) :not(.list-col-wrap){grid-row-start:1}.\32 xl\:list>:not(:last-child).list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.\32 xl\:list>:not(:last-child) .list-row:after{content:"";border-bottom:var(--border)solid;inset-inline:var(--radius-box);border-color:color-mix(in oklab,var(--color-base-content)5%,transparent);position:absolute;bottom:0}.\32 xl\:list-col-wrap{grid-row-start:2}}.range{appearance:none;--range-thumb:var(--color-base-100);--range-thumb-size:calc(var(--size-selector,.25rem)*6);--range-progress:currentColor;--range-fill:1;--range-p:.25rem;--range-bg:color-mix(in oklab,currentColor 10%,transparent);cursor:pointer;vertical-align:middle;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));width:clamp(3rem,20rem,100%);height:var(--range-thumb-size);background-color:transparent;border:none;overflow:hidden}[dir=rtl] .range{--range-dir:-1}.range:focus{outline:none}.range:focus-visible{outline-offset:2px;outline:2px solid}.range::-webkit-slider-runnable-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.range::-webkit-slider-runnable-track{border:1px solid}}.range::-webkit-slider-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;appearance:none;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%;transform:translateY(-50%)}.range::-moz-range-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.range::-moz-range-track{border:1px solid}}.range::-moz-range-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%}.range:disabled{cursor:not-allowed;opacity:.3}.range-primary{color:var(--color-primary);--range-thumb:var(--color-primary-content)}.range-secondary{color:var(--color-secondary);--range-thumb:var(--color-secondary-content)}.range-accent{color:var(--color-accent);--range-thumb:var(--color-accent-content)}.range-neutral{color:var(--color-neutral);--range-thumb:var(--color-neutral-content)}.range-success{color:var(--color-success);--range-thumb:var(--color-success-content)}.range-warning{color:var(--color-warning);--range-thumb:var(--color-warning-content)}.range-info{color:var(--color-info);--range-thumb:var(--color-info-content)}.range-error{color:var(--color-error);--range-thumb:var(--color-error-content)}.range-xs{--range-thumb-size:calc(var(--size-selector,.25rem)*4)}.range-sm{--range-thumb-size:calc(var(--size-selector,.25rem)*5)}.range-md{--range-thumb-size:calc(var(--size-selector,.25rem)*6)}.range-lg{--range-thumb-size:calc(var(--size-selector,.25rem)*7)}.range-xl{--range-thumb-size:calc(var(--size-selector,.25rem)*8)}@media (min-width:640px){.sm\:range{appearance:none;--range-thumb:var(--color-base-100);--range-thumb-size:calc(var(--size-selector,.25rem)*6);--range-progress:currentColor;--range-fill:1;--range-p:.25rem;--range-bg:color-mix(in oklab,currentColor 10%,transparent);cursor:pointer;vertical-align:middle;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));width:clamp(3rem,20rem,100%);height:var(--range-thumb-size);background-color:transparent;border:none;overflow:hidden}[dir=rtl] .sm\:range{--range-dir:-1}.sm\:range:focus{outline:none}.sm\:range:focus-visible{outline-offset:2px;outline:2px solid}.sm\:range::-webkit-slider-runnable-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.sm\:range::-webkit-slider-runnable-track{border:1px solid}}.sm\:range::-webkit-slider-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;appearance:none;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%;transform:translateY(-50%)}.sm\:range::-moz-range-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.sm\:range::-moz-range-track{border:1px solid}}.sm\:range::-moz-range-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%}.sm\:range:disabled{cursor:not-allowed;opacity:.3}.sm\:range-primary{color:var(--color-primary);--range-thumb:var(--color-primary-content)}.sm\:range-secondary{color:var(--color-secondary);--range-thumb:var(--color-secondary-content)}.sm\:range-accent{color:var(--color-accent);--range-thumb:var(--color-accent-content)}.sm\:range-neutral{color:var(--color-neutral);--range-thumb:var(--color-neutral-content)}.sm\:range-success{color:var(--color-success);--range-thumb:var(--color-success-content)}.sm\:range-warning{color:var(--color-warning);--range-thumb:var(--color-warning-content)}.sm\:range-info{color:var(--color-info);--range-thumb:var(--color-info-content)}.sm\:range-error{color:var(--color-error);--range-thumb:var(--color-error-content)}.sm\:range-xs{--range-thumb-size:calc(var(--size-selector,.25rem)*4)}.sm\:range-sm{--range-thumb-size:calc(var(--size-selector,.25rem)*5)}.sm\:range-md{--range-thumb-size:calc(var(--size-selector,.25rem)*6)}.sm\:range-lg{--range-thumb-size:calc(var(--size-selector,.25rem)*7)}.sm\:range-xl{--range-thumb-size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:768px){.md\:range{appearance:none;--range-thumb:var(--color-base-100);--range-thumb-size:calc(var(--size-selector,.25rem)*6);--range-progress:currentColor;--range-fill:1;--range-p:.25rem;--range-bg:color-mix(in oklab,currentColor 10%,transparent);cursor:pointer;vertical-align:middle;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));width:clamp(3rem,20rem,100%);height:var(--range-thumb-size);background-color:transparent;border:none;overflow:hidden}[dir=rtl] .md\:range{--range-dir:-1}.md\:range:focus{outline:none}.md\:range:focus-visible{outline-offset:2px;outline:2px solid}.md\:range::-webkit-slider-runnable-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.md\:range::-webkit-slider-runnable-track{border:1px solid}}.md\:range::-webkit-slider-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;appearance:none;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%;transform:translateY(-50%)}.md\:range::-moz-range-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.md\:range::-moz-range-track{border:1px solid}}.md\:range::-moz-range-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%}.md\:range:disabled{cursor:not-allowed;opacity:.3}.md\:range-primary{color:var(--color-primary);--range-thumb:var(--color-primary-content)}.md\:range-secondary{color:var(--color-secondary);--range-thumb:var(--color-secondary-content)}.md\:range-accent{color:var(--color-accent);--range-thumb:var(--color-accent-content)}.md\:range-neutral{color:var(--color-neutral);--range-thumb:var(--color-neutral-content)}.md\:range-success{color:var(--color-success);--range-thumb:var(--color-success-content)}.md\:range-warning{color:var(--color-warning);--range-thumb:var(--color-warning-content)}.md\:range-info{color:var(--color-info);--range-thumb:var(--color-info-content)}.md\:range-error{color:var(--color-error);--range-thumb:var(--color-error-content)}.md\:range-xs{--range-thumb-size:calc(var(--size-selector,.25rem)*4)}.md\:range-sm{--range-thumb-size:calc(var(--size-selector,.25rem)*5)}.md\:range-md{--range-thumb-size:calc(var(--size-selector,.25rem)*6)}.md\:range-lg{--range-thumb-size:calc(var(--size-selector,.25rem)*7)}.md\:range-xl{--range-thumb-size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:1024px){.lg\:range{appearance:none;--range-thumb:var(--color-base-100);--range-thumb-size:calc(var(--size-selector,.25rem)*6);--range-progress:currentColor;--range-fill:1;--range-p:.25rem;--range-bg:color-mix(in oklab,currentColor 10%,transparent);cursor:pointer;vertical-align:middle;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));width:clamp(3rem,20rem,100%);height:var(--range-thumb-size);background-color:transparent;border:none;overflow:hidden}[dir=rtl] .lg\:range{--range-dir:-1}.lg\:range:focus{outline:none}.lg\:range:focus-visible{outline-offset:2px;outline:2px solid}.lg\:range::-webkit-slider-runnable-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.lg\:range::-webkit-slider-runnable-track{border:1px solid}}.lg\:range::-webkit-slider-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;appearance:none;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%;transform:translateY(-50%)}.lg\:range::-moz-range-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.lg\:range::-moz-range-track{border:1px solid}}.lg\:range::-moz-range-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%}.lg\:range:disabled{cursor:not-allowed;opacity:.3}.lg\:range-primary{color:var(--color-primary);--range-thumb:var(--color-primary-content)}.lg\:range-secondary{color:var(--color-secondary);--range-thumb:var(--color-secondary-content)}.lg\:range-accent{color:var(--color-accent);--range-thumb:var(--color-accent-content)}.lg\:range-neutral{color:var(--color-neutral);--range-thumb:var(--color-neutral-content)}.lg\:range-success{color:var(--color-success);--range-thumb:var(--color-success-content)}.lg\:range-warning{color:var(--color-warning);--range-thumb:var(--color-warning-content)}.lg\:range-info{color:var(--color-info);--range-thumb:var(--color-info-content)}.lg\:range-error{color:var(--color-error);--range-thumb:var(--color-error-content)}.lg\:range-xs{--range-thumb-size:calc(var(--size-selector,.25rem)*4)}.lg\:range-sm{--range-thumb-size:calc(var(--size-selector,.25rem)*5)}.lg\:range-md{--range-thumb-size:calc(var(--size-selector,.25rem)*6)}.lg\:range-lg{--range-thumb-size:calc(var(--size-selector,.25rem)*7)}.lg\:range-xl{--range-thumb-size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:1280px){.xl\:range{appearance:none;--range-thumb:var(--color-base-100);--range-thumb-size:calc(var(--size-selector,.25rem)*6);--range-progress:currentColor;--range-fill:1;--range-p:.25rem;--range-bg:color-mix(in oklab,currentColor 10%,transparent);cursor:pointer;vertical-align:middle;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));width:clamp(3rem,20rem,100%);height:var(--range-thumb-size);background-color:transparent;border:none;overflow:hidden}[dir=rtl] .xl\:range{--range-dir:-1}.xl\:range:focus{outline:none}.xl\:range:focus-visible{outline-offset:2px;outline:2px solid}.xl\:range::-webkit-slider-runnable-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.xl\:range::-webkit-slider-runnable-track{border:1px solid}}.xl\:range::-webkit-slider-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;appearance:none;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%;transform:translateY(-50%)}.xl\:range::-moz-range-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.xl\:range::-moz-range-track{border:1px solid}}.xl\:range::-moz-range-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%}.xl\:range:disabled{cursor:not-allowed;opacity:.3}.xl\:range-primary{color:var(--color-primary);--range-thumb:var(--color-primary-content)}.xl\:range-secondary{color:var(--color-secondary);--range-thumb:var(--color-secondary-content)}.xl\:range-accent{color:var(--color-accent);--range-thumb:var(--color-accent-content)}.xl\:range-neutral{color:var(--color-neutral);--range-thumb:var(--color-neutral-content)}.xl\:range-success{color:var(--color-success);--range-thumb:var(--color-success-content)}.xl\:range-warning{color:var(--color-warning);--range-thumb:var(--color-warning-content)}.xl\:range-info{color:var(--color-info);--range-thumb:var(--color-info-content)}.xl\:range-error{color:var(--color-error);--range-thumb:var(--color-error-content)}.xl\:range-xs{--range-thumb-size:calc(var(--size-selector,.25rem)*4)}.xl\:range-sm{--range-thumb-size:calc(var(--size-selector,.25rem)*5)}.xl\:range-md{--range-thumb-size:calc(var(--size-selector,.25rem)*6)}.xl\:range-lg{--range-thumb-size:calc(var(--size-selector,.25rem)*7)}.xl\:range-xl{--range-thumb-size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:1536px){.\32 xl\:range{appearance:none;--range-thumb:var(--color-base-100);--range-thumb-size:calc(var(--size-selector,.25rem)*6);--range-progress:currentColor;--range-fill:1;--range-p:.25rem;--range-bg:color-mix(in oklab,currentColor 10%,transparent);cursor:pointer;vertical-align:middle;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));width:clamp(3rem,20rem,100%);height:var(--range-thumb-size);background-color:transparent;border:none;overflow:hidden}[dir=rtl] .\32 xl\:range{--range-dir:-1}.\32 xl\:range:focus{outline:none}.\32 xl\:range:focus-visible{outline-offset:2px;outline:2px solid}.\32 xl\:range::-webkit-slider-runnable-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.\32 xl\:range::-webkit-slider-runnable-track{border:1px solid}}.\32 xl\:range::-webkit-slider-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;appearance:none;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%;transform:translateY(-50%)}.\32 xl\:range::-moz-range-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.\32 xl\:range::-moz-range-track{border:1px solid}}.\32 xl\:range::-moz-range-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent),0 0 0 2rem var(--range-thumb)inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2))0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%}.\32 xl\:range:disabled{cursor:not-allowed;opacity:.3}.\32 xl\:range-primary{color:var(--color-primary);--range-thumb:var(--color-primary-content)}.\32 xl\:range-secondary{color:var(--color-secondary);--range-thumb:var(--color-secondary-content)}.\32 xl\:range-accent{color:var(--color-accent);--range-thumb:var(--color-accent-content)}.\32 xl\:range-neutral{color:var(--color-neutral);--range-thumb:var(--color-neutral-content)}.\32 xl\:range-success{color:var(--color-success);--range-thumb:var(--color-success-content)}.\32 xl\:range-warning{color:var(--color-warning);--range-thumb:var(--color-warning-content)}.\32 xl\:range-info{color:var(--color-info);--range-thumb:var(--color-info-content)}.\32 xl\:range-error{color:var(--color-error);--range-thumb:var(--color-error-content)}.\32 xl\:range-xs{--range-thumb-size:calc(var(--size-selector,.25rem)*4)}.\32 xl\:range-sm{--range-thumb-size:calc(var(--size-selector,.25rem)*5)}.\32 xl\:range-md{--range-thumb-size:calc(var(--size-selector,.25rem)*6)}.\32 xl\:range-lg{--range-thumb-size:calc(var(--size-selector,.25rem)*7)}.\32 xl\:range-xl{--range-thumb-size:calc(var(--size-selector,.25rem)*8)}}.file-input{cursor:pointer;border:var(--border)solid transparent;cursor:pointer;appearance:none;background-color:var(--color-base-100);vertical-align:middle;-webkit-user-select:none;user-select:none;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));align-items:center;padding-inline-end:.75rem;font-size:.875rem;line-height:2;display:inline-flex}.file-input::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;height:calc(100% + var(--border)*2);margin-inline-end:1rem;margin-block:calc(var(--border)*-1);color:var(--btn-fg);border-width:var(--border);border-style:solid;border-color:var(--btn-border);background-color:var(--btn-bg);background-size:calc(var(--noise)*100%);background-image:var(--btn-noise);text-shadow:0 .5px oklch(1 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px color-mix(in oklab,color-mix(in oklab,white 30%,var(--btn-bg))calc(var(--depth)*20%),transparent)inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-border:color-mix(in oklab,var(--btn-bg),#000 5%);--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)30%,transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)30%,transparent);--btn-noise:var(--fx-noise);border-start-start-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-start-radius:calc(var(--join-es,var(--radius-field) - var(--border)));margin-inline-start:calc(var(--border)*-1);padding-inline:1rem;font-size:.875rem;font-weight:600}.file-input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)10%,transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.file-input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.file-input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.file-input:has(>input[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.file-input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.file-input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.file-input:is(:disabled,[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.file-input-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.file-input-ghost::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;border-start-end-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-end-radius:calc(var(--join-es,var(--radius-field) - var(--border)));height:100%;margin-block:0;margin-inline:0 1rem;padding-inline:1rem}.file-input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.file-input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.file-input-neutral{--btn-color:var(--color-neutral)}.file-input-neutral::file-selector-button{color:var(--color-neutral-content)}.file-input-neutral{--input-color:var(--color-neutral)}.file-input-neutral:focus{--input-color:var(--color-neutral)}.file-input-neutral:focus-within{--input-color:var(--color-neutral)}.file-input-primary{--btn-color:var(--color-primary)}.file-input-primary::file-selector-button{color:var(--color-primary-content)}.file-input-primary{--input-color:var(--color-primary)}.file-input-primary:focus{--input-color:var(--color-primary)}.file-input-primary:focus-within{--input-color:var(--color-primary)}.file-input-secondary{--btn-color:var(--color-secondary)}.file-input-secondary::file-selector-button{color:var(--color-secondary-content)}.file-input-secondary{--input-color:var(--color-secondary)}.file-input-secondary:focus{--input-color:var(--color-secondary)}.file-input-secondary:focus-within{--input-color:var(--color-secondary)}.file-input-accent{--btn-color:var(--color-accent)}.file-input-accent::file-selector-button{color:var(--color-accent-content)}.file-input-accent{--input-color:var(--color-accent)}.file-input-accent:focus{--input-color:var(--color-accent)}.file-input-accent:focus-within{--input-color:var(--color-accent)}.file-input-info{--btn-color:var(--color-info)}.file-input-info::file-selector-button{color:var(--color-info-content)}.file-input-info{--input-color:var(--color-info)}.file-input-info:focus{--input-color:var(--color-info)}.file-input-info:focus-within{--input-color:var(--color-info)}.file-input-success{--btn-color:var(--color-success)}.file-input-success::file-selector-button{color:var(--color-success-content)}.file-input-success{--input-color:var(--color-success)}.file-input-success:focus{--input-color:var(--color-success)}.file-input-success:focus-within{--input-color:var(--color-success)}.file-input-warning{--btn-color:var(--color-warning)}.file-input-warning::file-selector-button{color:var(--color-warning-content)}.file-input-warning{--input-color:var(--color-warning)}.file-input-warning:focus{--input-color:var(--color-warning)}.file-input-warning:focus-within{--input-color:var(--color-warning)}.file-input-error{--btn-color:var(--color-error)}.file-input-error::file-selector-button{color:var(--color-error-content)}.file-input-error{--input-color:var(--color-error)}.file-input-error:focus{--input-color:var(--color-error)}.file-input-error:focus-within{--input-color:var(--color-error)}.file-input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem;line-height:1rem}.file-input-xs::file-selector-button{font-size:.6875rem}.file-input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem;line-height:1.5rem}.file-input-sm::file-selector-button{font-size:.75rem}.file-input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem;line-height:2}.file-input-md::file-selector-button{font-size:.875rem}.file-input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem;line-height:2.5rem}.file-input-lg::file-selector-button{font-size:1.125rem}.file-input-xl{--size:calc(var(--size-field,.25rem)*14);padding-inline-end:1.5rem;font-size:1.125rem;line-height:3rem}.file-input-xl::file-selector-button{font-size:1.375rem}@media (min-width:640px){.sm\:file-input{cursor:pointer;border:var(--border)solid transparent;cursor:pointer;appearance:none;background-color:var(--color-base-100);vertical-align:middle;-webkit-user-select:none;user-select:none;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));align-items:center;padding-inline-end:.75rem;font-size:.875rem;line-height:2;display:inline-flex}.sm\:file-input::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;height:calc(100% + var(--border)*2);margin-inline-end:1rem;margin-block:calc(var(--border)*-1);color:var(--btn-fg);border-width:var(--border);border-style:solid;border-color:var(--btn-border);background-color:var(--btn-bg);background-size:calc(var(--noise)*100%);background-image:var(--btn-noise);text-shadow:0 .5px oklch(1 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px color-mix(in oklab,color-mix(in oklab,white 30%,var(--btn-bg))calc(var(--depth)*20%),transparent)inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-border:color-mix(in oklab,var(--btn-bg),#000 5%);--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)30%,transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)30%,transparent);--btn-noise:var(--fx-noise);border-start-start-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-start-radius:calc(var(--join-es,var(--radius-field) - var(--border)));margin-inline-start:calc(var(--border)*-1);padding-inline:1rem;font-size:.875rem;font-weight:600}.sm\:file-input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)10%,transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.sm\:file-input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.sm\:file-input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.sm\:file-input:has(>input[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.sm\:file-input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.sm\:file-input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.sm\:file-input:is(:disabled,[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.sm\:file-input-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.sm\:file-input-ghost::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;border-start-end-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-end-radius:calc(var(--join-es,var(--radius-field) - var(--border)));height:100%;margin-block:0;margin-inline:0 1rem;padding-inline:1rem}.sm\:file-input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.sm\:file-input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.sm\:file-input-neutral{--btn-color:var(--color-neutral)}.sm\:file-input-neutral::file-selector-button{color:var(--color-neutral-content)}.sm\:file-input-neutral{--input-color:var(--color-neutral)}.sm\:file-input-neutral:focus{--input-color:var(--color-neutral)}.sm\:file-input-neutral:focus-within{--input-color:var(--color-neutral)}.sm\:file-input-primary{--btn-color:var(--color-primary)}.sm\:file-input-primary::file-selector-button{color:var(--color-primary-content)}.sm\:file-input-primary{--input-color:var(--color-primary)}.sm\:file-input-primary:focus{--input-color:var(--color-primary)}.sm\:file-input-primary:focus-within{--input-color:var(--color-primary)}.sm\:file-input-secondary{--btn-color:var(--color-secondary)}.sm\:file-input-secondary::file-selector-button{color:var(--color-secondary-content)}.sm\:file-input-secondary{--input-color:var(--color-secondary)}.sm\:file-input-secondary:focus{--input-color:var(--color-secondary)}.sm\:file-input-secondary:focus-within{--input-color:var(--color-secondary)}.sm\:file-input-accent{--btn-color:var(--color-accent)}.sm\:file-input-accent::file-selector-button{color:var(--color-accent-content)}.sm\:file-input-accent{--input-color:var(--color-accent)}.sm\:file-input-accent:focus{--input-color:var(--color-accent)}.sm\:file-input-accent:focus-within{--input-color:var(--color-accent)}.sm\:file-input-info{--btn-color:var(--color-info)}.sm\:file-input-info::file-selector-button{color:var(--color-info-content)}.sm\:file-input-info{--input-color:var(--color-info)}.sm\:file-input-info:focus{--input-color:var(--color-info)}.sm\:file-input-info:focus-within{--input-color:var(--color-info)}.sm\:file-input-success{--btn-color:var(--color-success)}.sm\:file-input-success::file-selector-button{color:var(--color-success-content)}.sm\:file-input-success{--input-color:var(--color-success)}.sm\:file-input-success:focus{--input-color:var(--color-success)}.sm\:file-input-success:focus-within{--input-color:var(--color-success)}.sm\:file-input-warning{--btn-color:var(--color-warning)}.sm\:file-input-warning::file-selector-button{color:var(--color-warning-content)}.sm\:file-input-warning{--input-color:var(--color-warning)}.sm\:file-input-warning:focus{--input-color:var(--color-warning)}.sm\:file-input-warning:focus-within{--input-color:var(--color-warning)}.sm\:file-input-error{--btn-color:var(--color-error)}.sm\:file-input-error::file-selector-button{color:var(--color-error-content)}.sm\:file-input-error{--input-color:var(--color-error)}.sm\:file-input-error:focus{--input-color:var(--color-error)}.sm\:file-input-error:focus-within{--input-color:var(--color-error)}.sm\:file-input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem;line-height:1rem}.sm\:file-input-xs::file-selector-button{font-size:.6875rem}.sm\:file-input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem;line-height:1.5rem}.sm\:file-input-sm::file-selector-button{font-size:.75rem}.sm\:file-input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem;line-height:2}.sm\:file-input-md::file-selector-button{font-size:.875rem}.sm\:file-input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem;line-height:2.5rem}.sm\:file-input-lg::file-selector-button{font-size:1.125rem}.sm\:file-input-xl{--size:calc(var(--size-field,.25rem)*14);padding-inline-end:1.5rem;font-size:1.125rem;line-height:3rem}.sm\:file-input-xl::file-selector-button{font-size:1.375rem}}@media (min-width:768px){.md\:file-input{cursor:pointer;border:var(--border)solid transparent;cursor:pointer;appearance:none;background-color:var(--color-base-100);vertical-align:middle;-webkit-user-select:none;user-select:none;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));align-items:center;padding-inline-end:.75rem;font-size:.875rem;line-height:2;display:inline-flex}.md\:file-input::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;height:calc(100% + var(--border)*2);margin-inline-end:1rem;margin-block:calc(var(--border)*-1);color:var(--btn-fg);border-width:var(--border);border-style:solid;border-color:var(--btn-border);background-color:var(--btn-bg);background-size:calc(var(--noise)*100%);background-image:var(--btn-noise);text-shadow:0 .5px oklch(1 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px color-mix(in oklab,color-mix(in oklab,white 30%,var(--btn-bg))calc(var(--depth)*20%),transparent)inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-border:color-mix(in oklab,var(--btn-bg),#000 5%);--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)30%,transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)30%,transparent);--btn-noise:var(--fx-noise);border-start-start-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-start-radius:calc(var(--join-es,var(--radius-field) - var(--border)));margin-inline-start:calc(var(--border)*-1);padding-inline:1rem;font-size:.875rem;font-weight:600}.md\:file-input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)10%,transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.md\:file-input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.md\:file-input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.md\:file-input:has(>input[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.md\:file-input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.md\:file-input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.md\:file-input:is(:disabled,[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.md\:file-input-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.md\:file-input-ghost::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;border-start-end-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-end-radius:calc(var(--join-es,var(--radius-field) - var(--border)));height:100%;margin-block:0;margin-inline:0 1rem;padding-inline:1rem}.md\:file-input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.md\:file-input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.md\:file-input-neutral{--btn-color:var(--color-neutral)}.md\:file-input-neutral::file-selector-button{color:var(--color-neutral-content)}.md\:file-input-neutral{--input-color:var(--color-neutral)}.md\:file-input-neutral:focus{--input-color:var(--color-neutral)}.md\:file-input-neutral:focus-within{--input-color:var(--color-neutral)}.md\:file-input-primary{--btn-color:var(--color-primary)}.md\:file-input-primary::file-selector-button{color:var(--color-primary-content)}.md\:file-input-primary{--input-color:var(--color-primary)}.md\:file-input-primary:focus{--input-color:var(--color-primary)}.md\:file-input-primary:focus-within{--input-color:var(--color-primary)}.md\:file-input-secondary{--btn-color:var(--color-secondary)}.md\:file-input-secondary::file-selector-button{color:var(--color-secondary-content)}.md\:file-input-secondary{--input-color:var(--color-secondary)}.md\:file-input-secondary:focus{--input-color:var(--color-secondary)}.md\:file-input-secondary:focus-within{--input-color:var(--color-secondary)}.md\:file-input-accent{--btn-color:var(--color-accent)}.md\:file-input-accent::file-selector-button{color:var(--color-accent-content)}.md\:file-input-accent{--input-color:var(--color-accent)}.md\:file-input-accent:focus{--input-color:var(--color-accent)}.md\:file-input-accent:focus-within{--input-color:var(--color-accent)}.md\:file-input-info{--btn-color:var(--color-info)}.md\:file-input-info::file-selector-button{color:var(--color-info-content)}.md\:file-input-info{--input-color:var(--color-info)}.md\:file-input-info:focus{--input-color:var(--color-info)}.md\:file-input-info:focus-within{--input-color:var(--color-info)}.md\:file-input-success{--btn-color:var(--color-success)}.md\:file-input-success::file-selector-button{color:var(--color-success-content)}.md\:file-input-success{--input-color:var(--color-success)}.md\:file-input-success:focus{--input-color:var(--color-success)}.md\:file-input-success:focus-within{--input-color:var(--color-success)}.md\:file-input-warning{--btn-color:var(--color-warning)}.md\:file-input-warning::file-selector-button{color:var(--color-warning-content)}.md\:file-input-warning{--input-color:var(--color-warning)}.md\:file-input-warning:focus{--input-color:var(--color-warning)}.md\:file-input-warning:focus-within{--input-color:var(--color-warning)}.md\:file-input-error{--btn-color:var(--color-error)}.md\:file-input-error::file-selector-button{color:var(--color-error-content)}.md\:file-input-error{--input-color:var(--color-error)}.md\:file-input-error:focus{--input-color:var(--color-error)}.md\:file-input-error:focus-within{--input-color:var(--color-error)}.md\:file-input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem;line-height:1rem}.md\:file-input-xs::file-selector-button{font-size:.6875rem}.md\:file-input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem;line-height:1.5rem}.md\:file-input-sm::file-selector-button{font-size:.75rem}.md\:file-input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem;line-height:2}.md\:file-input-md::file-selector-button{font-size:.875rem}.md\:file-input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem;line-height:2.5rem}.md\:file-input-lg::file-selector-button{font-size:1.125rem}.md\:file-input-xl{--size:calc(var(--size-field,.25rem)*14);padding-inline-end:1.5rem;font-size:1.125rem;line-height:3rem}.md\:file-input-xl::file-selector-button{font-size:1.375rem}}@media (min-width:1024px){.lg\:file-input{cursor:pointer;border:var(--border)solid transparent;cursor:pointer;appearance:none;background-color:var(--color-base-100);vertical-align:middle;-webkit-user-select:none;user-select:none;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));align-items:center;padding-inline-end:.75rem;font-size:.875rem;line-height:2;display:inline-flex}.lg\:file-input::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;height:calc(100% + var(--border)*2);margin-inline-end:1rem;margin-block:calc(var(--border)*-1);color:var(--btn-fg);border-width:var(--border);border-style:solid;border-color:var(--btn-border);background-color:var(--btn-bg);background-size:calc(var(--noise)*100%);background-image:var(--btn-noise);text-shadow:0 .5px oklch(1 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px color-mix(in oklab,color-mix(in oklab,white 30%,var(--btn-bg))calc(var(--depth)*20%),transparent)inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-border:color-mix(in oklab,var(--btn-bg),#000 5%);--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)30%,transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)30%,transparent);--btn-noise:var(--fx-noise);border-start-start-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-start-radius:calc(var(--join-es,var(--radius-field) - var(--border)));margin-inline-start:calc(var(--border)*-1);padding-inline:1rem;font-size:.875rem;font-weight:600}.lg\:file-input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)10%,transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.lg\:file-input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.lg\:file-input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.lg\:file-input:has(>input[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.lg\:file-input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.lg\:file-input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.lg\:file-input:is(:disabled,[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.lg\:file-input-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.lg\:file-input-ghost::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;border-start-end-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-end-radius:calc(var(--join-es,var(--radius-field) - var(--border)));height:100%;margin-block:0;margin-inline:0 1rem;padding-inline:1rem}.lg\:file-input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.lg\:file-input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.lg\:file-input-neutral{--btn-color:var(--color-neutral)}.lg\:file-input-neutral::file-selector-button{color:var(--color-neutral-content)}.lg\:file-input-neutral{--input-color:var(--color-neutral)}.lg\:file-input-neutral:focus{--input-color:var(--color-neutral)}.lg\:file-input-neutral:focus-within{--input-color:var(--color-neutral)}.lg\:file-input-primary{--btn-color:var(--color-primary)}.lg\:file-input-primary::file-selector-button{color:var(--color-primary-content)}.lg\:file-input-primary{--input-color:var(--color-primary)}.lg\:file-input-primary:focus{--input-color:var(--color-primary)}.lg\:file-input-primary:focus-within{--input-color:var(--color-primary)}.lg\:file-input-secondary{--btn-color:var(--color-secondary)}.lg\:file-input-secondary::file-selector-button{color:var(--color-secondary-content)}.lg\:file-input-secondary{--input-color:var(--color-secondary)}.lg\:file-input-secondary:focus{--input-color:var(--color-secondary)}.lg\:file-input-secondary:focus-within{--input-color:var(--color-secondary)}.lg\:file-input-accent{--btn-color:var(--color-accent)}.lg\:file-input-accent::file-selector-button{color:var(--color-accent-content)}.lg\:file-input-accent{--input-color:var(--color-accent)}.lg\:file-input-accent:focus{--input-color:var(--color-accent)}.lg\:file-input-accent:focus-within{--input-color:var(--color-accent)}.lg\:file-input-info{--btn-color:var(--color-info)}.lg\:file-input-info::file-selector-button{color:var(--color-info-content)}.lg\:file-input-info{--input-color:var(--color-info)}.lg\:file-input-info:focus{--input-color:var(--color-info)}.lg\:file-input-info:focus-within{--input-color:var(--color-info)}.lg\:file-input-success{--btn-color:var(--color-success)}.lg\:file-input-success::file-selector-button{color:var(--color-success-content)}.lg\:file-input-success{--input-color:var(--color-success)}.lg\:file-input-success:focus{--input-color:var(--color-success)}.lg\:file-input-success:focus-within{--input-color:var(--color-success)}.lg\:file-input-warning{--btn-color:var(--color-warning)}.lg\:file-input-warning::file-selector-button{color:var(--color-warning-content)}.lg\:file-input-warning{--input-color:var(--color-warning)}.lg\:file-input-warning:focus{--input-color:var(--color-warning)}.lg\:file-input-warning:focus-within{--input-color:var(--color-warning)}.lg\:file-input-error{--btn-color:var(--color-error)}.lg\:file-input-error::file-selector-button{color:var(--color-error-content)}.lg\:file-input-error{--input-color:var(--color-error)}.lg\:file-input-error:focus{--input-color:var(--color-error)}.lg\:file-input-error:focus-within{--input-color:var(--color-error)}.lg\:file-input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem;line-height:1rem}.lg\:file-input-xs::file-selector-button{font-size:.6875rem}.lg\:file-input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem;line-height:1.5rem}.lg\:file-input-sm::file-selector-button{font-size:.75rem}.lg\:file-input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem;line-height:2}.lg\:file-input-md::file-selector-button{font-size:.875rem}.lg\:file-input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem;line-height:2.5rem}.lg\:file-input-lg::file-selector-button{font-size:1.125rem}.lg\:file-input-xl{--size:calc(var(--size-field,.25rem)*14);padding-inline-end:1.5rem;font-size:1.125rem;line-height:3rem}.lg\:file-input-xl::file-selector-button{font-size:1.375rem}}@media (min-width:1280px){.xl\:file-input{cursor:pointer;border:var(--border)solid transparent;cursor:pointer;appearance:none;background-color:var(--color-base-100);vertical-align:middle;-webkit-user-select:none;user-select:none;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));align-items:center;padding-inline-end:.75rem;font-size:.875rem;line-height:2;display:inline-flex}.xl\:file-input::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;height:calc(100% + var(--border)*2);margin-inline-end:1rem;margin-block:calc(var(--border)*-1);color:var(--btn-fg);border-width:var(--border);border-style:solid;border-color:var(--btn-border);background-color:var(--btn-bg);background-size:calc(var(--noise)*100%);background-image:var(--btn-noise);text-shadow:0 .5px oklch(1 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px color-mix(in oklab,color-mix(in oklab,white 30%,var(--btn-bg))calc(var(--depth)*20%),transparent)inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-border:color-mix(in oklab,var(--btn-bg),#000 5%);--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)30%,transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)30%,transparent);--btn-noise:var(--fx-noise);border-start-start-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-start-radius:calc(var(--join-es,var(--radius-field) - var(--border)));margin-inline-start:calc(var(--border)*-1);padding-inline:1rem;font-size:.875rem;font-weight:600}.xl\:file-input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)10%,transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.xl\:file-input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.xl\:file-input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.xl\:file-input:has(>input[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.xl\:file-input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.xl\:file-input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.xl\:file-input:is(:disabled,[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.xl\:file-input-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.xl\:file-input-ghost::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;border-start-end-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-end-radius:calc(var(--join-es,var(--radius-field) - var(--border)));height:100%;margin-block:0;margin-inline:0 1rem;padding-inline:1rem}.xl\:file-input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.xl\:file-input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.xl\:file-input-neutral{--btn-color:var(--color-neutral)}.xl\:file-input-neutral::file-selector-button{color:var(--color-neutral-content)}.xl\:file-input-neutral{--input-color:var(--color-neutral)}.xl\:file-input-neutral:focus{--input-color:var(--color-neutral)}.xl\:file-input-neutral:focus-within{--input-color:var(--color-neutral)}.xl\:file-input-primary{--btn-color:var(--color-primary)}.xl\:file-input-primary::file-selector-button{color:var(--color-primary-content)}.xl\:file-input-primary{--input-color:var(--color-primary)}.xl\:file-input-primary:focus{--input-color:var(--color-primary)}.xl\:file-input-primary:focus-within{--input-color:var(--color-primary)}.xl\:file-input-secondary{--btn-color:var(--color-secondary)}.xl\:file-input-secondary::file-selector-button{color:var(--color-secondary-content)}.xl\:file-input-secondary{--input-color:var(--color-secondary)}.xl\:file-input-secondary:focus{--input-color:var(--color-secondary)}.xl\:file-input-secondary:focus-within{--input-color:var(--color-secondary)}.xl\:file-input-accent{--btn-color:var(--color-accent)}.xl\:file-input-accent::file-selector-button{color:var(--color-accent-content)}.xl\:file-input-accent{--input-color:var(--color-accent)}.xl\:file-input-accent:focus{--input-color:var(--color-accent)}.xl\:file-input-accent:focus-within{--input-color:var(--color-accent)}.xl\:file-input-info{--btn-color:var(--color-info)}.xl\:file-input-info::file-selector-button{color:var(--color-info-content)}.xl\:file-input-info{--input-color:var(--color-info)}.xl\:file-input-info:focus{--input-color:var(--color-info)}.xl\:file-input-info:focus-within{--input-color:var(--color-info)}.xl\:file-input-success{--btn-color:var(--color-success)}.xl\:file-input-success::file-selector-button{color:var(--color-success-content)}.xl\:file-input-success{--input-color:var(--color-success)}.xl\:file-input-success:focus{--input-color:var(--color-success)}.xl\:file-input-success:focus-within{--input-color:var(--color-success)}.xl\:file-input-warning{--btn-color:var(--color-warning)}.xl\:file-input-warning::file-selector-button{color:var(--color-warning-content)}.xl\:file-input-warning{--input-color:var(--color-warning)}.xl\:file-input-warning:focus{--input-color:var(--color-warning)}.xl\:file-input-warning:focus-within{--input-color:var(--color-warning)}.xl\:file-input-error{--btn-color:var(--color-error)}.xl\:file-input-error::file-selector-button{color:var(--color-error-content)}.xl\:file-input-error{--input-color:var(--color-error)}.xl\:file-input-error:focus{--input-color:var(--color-error)}.xl\:file-input-error:focus-within{--input-color:var(--color-error)}.xl\:file-input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem;line-height:1rem}.xl\:file-input-xs::file-selector-button{font-size:.6875rem}.xl\:file-input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem;line-height:1.5rem}.xl\:file-input-sm::file-selector-button{font-size:.75rem}.xl\:file-input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem;line-height:2}.xl\:file-input-md::file-selector-button{font-size:.875rem}.xl\:file-input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem;line-height:2.5rem}.xl\:file-input-lg::file-selector-button{font-size:1.125rem}.xl\:file-input-xl{--size:calc(var(--size-field,.25rem)*14);padding-inline-end:1.5rem;font-size:1.125rem;line-height:3rem}.xl\:file-input-xl::file-selector-button{font-size:1.375rem}}@media (min-width:1536px){.\32 xl\:file-input{cursor:pointer;border:var(--border)solid transparent;cursor:pointer;appearance:none;background-color:var(--color-base-100);vertical-align:middle;-webkit-user-select:none;user-select:none;width:clamp(3rem,20rem,100%);height:var(--size);border-color:var(--input-color);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-field,.25rem)*10);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));align-items:center;padding-inline-end:.75rem;font-size:.875rem;line-height:2;display:inline-flex}.\32 xl\:file-input::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;height:calc(100% + var(--border)*2);margin-inline-end:1rem;margin-block:calc(var(--border)*-1);color:var(--btn-fg);border-width:var(--border);border-style:solid;border-color:var(--btn-border);background-color:var(--btn-bg);background-size:calc(var(--noise)*100%);background-image:var(--btn-noise);text-shadow:0 .5px oklch(1 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px color-mix(in oklab,color-mix(in oklab,white 30%,var(--btn-bg))calc(var(--depth)*20%),transparent)inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-border:color-mix(in oklab,var(--btn-bg),#000 5%);--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)30%,transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)30%,transparent);--btn-noise:var(--fx-noise);border-start-start-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-start-radius:calc(var(--join-es,var(--radius-field) - var(--border)));margin-inline-start:calc(var(--border)*-1);padding-inline:1rem;font-size:.875rem;font-weight:600}.\32 xl\:file-input:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)10%,transparent);outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.\32 xl\:file-input:has(>input[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.\32 xl\:file-input:has(>input[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.\32 xl\:file-input:has(>input[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.\32 xl\:file-input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);box-shadow:none;color:color-mix(in oklch,var(--color-base-content)20%,transparent)}.\32 xl\:file-input:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.\32 xl\:file-input:is(:disabled,[disabled])::file-selector-button{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.\32 xl\:file-input-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.\32 xl\:file-input-ghost::file-selector-button{cursor:pointer;-webkit-user-select:none;user-select:none;border-start-end-radius:calc(var(--join-ss,var(--radius-field) - var(--border)));border-end-end-radius:calc(var(--join-es,var(--radius-field) - var(--border)));height:100%;margin-block:0;margin-inline:0 1rem;padding-inline:1rem}.\32 xl\:file-input-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.\32 xl\:file-input-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.\32 xl\:file-input-neutral{--btn-color:var(--color-neutral)}.\32 xl\:file-input-neutral::file-selector-button{color:var(--color-neutral-content)}.\32 xl\:file-input-neutral{--input-color:var(--color-neutral)}.\32 xl\:file-input-neutral:focus{--input-color:var(--color-neutral)}.\32 xl\:file-input-neutral:focus-within{--input-color:var(--color-neutral)}.\32 xl\:file-input-primary{--btn-color:var(--color-primary)}.\32 xl\:file-input-primary::file-selector-button{color:var(--color-primary-content)}.\32 xl\:file-input-primary{--input-color:var(--color-primary)}.\32 xl\:file-input-primary:focus{--input-color:var(--color-primary)}.\32 xl\:file-input-primary:focus-within{--input-color:var(--color-primary)}.\32 xl\:file-input-secondary{--btn-color:var(--color-secondary)}.\32 xl\:file-input-secondary::file-selector-button{color:var(--color-secondary-content)}.\32 xl\:file-input-secondary{--input-color:var(--color-secondary)}.\32 xl\:file-input-secondary:focus{--input-color:var(--color-secondary)}.\32 xl\:file-input-secondary:focus-within{--input-color:var(--color-secondary)}.\32 xl\:file-input-accent{--btn-color:var(--color-accent)}.\32 xl\:file-input-accent::file-selector-button{color:var(--color-accent-content)}.\32 xl\:file-input-accent{--input-color:var(--color-accent)}.\32 xl\:file-input-accent:focus{--input-color:var(--color-accent)}.\32 xl\:file-input-accent:focus-within{--input-color:var(--color-accent)}.\32 xl\:file-input-info{--btn-color:var(--color-info)}.\32 xl\:file-input-info::file-selector-button{color:var(--color-info-content)}.\32 xl\:file-input-info{--input-color:var(--color-info)}.\32 xl\:file-input-info:focus{--input-color:var(--color-info)}.\32 xl\:file-input-info:focus-within{--input-color:var(--color-info)}.\32 xl\:file-input-success{--btn-color:var(--color-success)}.\32 xl\:file-input-success::file-selector-button{color:var(--color-success-content)}.\32 xl\:file-input-success{--input-color:var(--color-success)}.\32 xl\:file-input-success:focus{--input-color:var(--color-success)}.\32 xl\:file-input-success:focus-within{--input-color:var(--color-success)}.\32 xl\:file-input-warning{--btn-color:var(--color-warning)}.\32 xl\:file-input-warning::file-selector-button{color:var(--color-warning-content)}.\32 xl\:file-input-warning{--input-color:var(--color-warning)}.\32 xl\:file-input-warning:focus{--input-color:var(--color-warning)}.\32 xl\:file-input-warning:focus-within{--input-color:var(--color-warning)}.\32 xl\:file-input-error{--btn-color:var(--color-error)}.\32 xl\:file-input-error::file-selector-button{color:var(--color-error-content)}.\32 xl\:file-input-error{--input-color:var(--color-error)}.\32 xl\:file-input-error:focus{--input-color:var(--color-error)}.\32 xl\:file-input-error:focus-within{--input-color:var(--color-error)}.\32 xl\:file-input-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem;line-height:1rem}.\32 xl\:file-input-xs::file-selector-button{font-size:.6875rem}.\32 xl\:file-input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem;line-height:1.5rem}.\32 xl\:file-input-sm::file-selector-button{font-size:.75rem}.\32 xl\:file-input-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem;line-height:2}.\32 xl\:file-input-md::file-selector-button{font-size:.875rem}.\32 xl\:file-input-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem;line-height:2.5rem}.\32 xl\:file-input-lg::file-selector-button{font-size:1.125rem}.\32 xl\:file-input-xl{--size:calc(var(--size-field,.25rem)*14);padding-inline-end:1.5rem;font-size:1.125rem;line-height:3rem}.\32 xl\:file-input-xl::file-selector-button{font-size:1.375rem}}.table{border-radius:var(--radius-box);text-align:left;width:100%;font-size:.875rem;position:relative}.table:where(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)),[dir=rtl],[dir=rtl] *){text-align:right}@media (hover:hover){.table tr.row-hover:hover{background-color:var(--color-base-200)}}@media (hover:hover){.table tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-200)}}.table :where(th,td){vertical-align:middle;padding-block:.75rem;padding-inline:1rem}.table :where(thead,tfoot){white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);font-size:.875rem;font-weight:600}.table :where(tfoot){border-top:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.table :where(.table-pin-rows thead tr){z-index:1;background-color:var(--color-base-100);position:sticky;top:0}.table :where(.table-pin-rows tfoot tr){z-index:1;background-color:var(--color-base-100);position:sticky;bottom:0}.table :where(.table-pin-cols tr th){background-color:var(--color-base-100);position:sticky;left:0;right:0}.table :where(thead tr,tbody tr:not(:last-child)){border-bottom:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.table-zebra tbody tr:nth-child(2n){background-color:var(--color-base-200)}.table-zebra tbody tr:nth-child(2n) :where(.table-pin-cols tr th){background-color:var(--color-base-200)}@media (hover:hover){.table-zebra tbody tr.row-hover:hover{background-color:var(--color-base-300)}}@media (hover:hover){.table-zebra tbody tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-300)}}.table-xs :not(:is(thead,tfoot)) tr{font-size:.6875rem}.table-xs :where(th,td){padding-block:.25rem;padding-inline:.5rem}.table-sm :not(:is(thead,tfoot)) tr{font-size:.75rem}.table-sm :where(th,td){padding-block:.5rem;padding-inline:.75rem}.table-md :not(:is(thead,tfoot)) tr{font-size:.875rem}.table-md :where(th,td){padding-block:.75rem;padding-inline:1rem}.table-lg :not(:is(thead,tfoot)) tr{font-size:1.125rem}.table-lg :where(th,td){padding-block:1rem;padding-inline:1.25rem}.table-xl :not(:is(thead,tfoot)) tr{font-size:1.375rem}.table-xl :where(th,td){padding-block:1.25rem;padding-inline:1.5rem}@media (min-width:640px){.sm\:table{border-radius:var(--radius-box);text-align:left;width:100%;font-size:.875rem;position:relative}.sm\:table:where(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)),[dir=rtl],[dir=rtl] *){text-align:right}@media (hover:hover){.sm\:table tr.row-hover:hover{background-color:var(--color-base-200)}}@media (hover:hover){.sm\:table tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-200)}}.sm\:table :where(th,td){vertical-align:middle;padding-block:.75rem;padding-inline:1rem}.sm\:table :where(thead,tfoot){white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);font-size:.875rem;font-weight:600}.sm\:table :where(tfoot){border-top:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.sm\:table :where(.table-pin-rows thead tr){z-index:1;background-color:var(--color-base-100);position:sticky;top:0}.sm\:table :where(.table-pin-rows tfoot tr){z-index:1;background-color:var(--color-base-100);position:sticky;bottom:0}.sm\:table :where(.table-pin-cols tr th){background-color:var(--color-base-100);position:sticky;left:0;right:0}.sm\:table :where(thead tr,tbody tr:not(:last-child)){border-bottom:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.sm\:table-zebra tbody tr:nth-child(2n){background-color:var(--color-base-200)}.sm\:table-zebra tbody tr:nth-child(2n) :where(.table-pin-cols tr th){background-color:var(--color-base-200)}@media (hover:hover){.sm\:table-zebra tbody tr.row-hover:hover{background-color:var(--color-base-300)}}@media (hover:hover){.sm\:table-zebra tbody tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-300)}}.sm\:table-xs :not(:is(thead,tfoot)) tr{font-size:.6875rem}.sm\:table-xs :where(th,td){padding-block:.25rem;padding-inline:.5rem}.sm\:table-sm :not(:is(thead,tfoot)) tr{font-size:.75rem}.sm\:table-sm :where(th,td){padding-block:.5rem;padding-inline:.75rem}.sm\:table-md :not(:is(thead,tfoot)) tr{font-size:.875rem}.sm\:table-md :where(th,td){padding-block:.75rem;padding-inline:1rem}.sm\:table-lg :not(:is(thead,tfoot)) tr{font-size:1.125rem}.sm\:table-lg :where(th,td){padding-block:1rem;padding-inline:1.25rem}.sm\:table-xl :not(:is(thead,tfoot)) tr{font-size:1.375rem}.sm\:table-xl :where(th,td){padding-block:1.25rem;padding-inline:1.5rem}}@media (min-width:768px){.md\:table{border-radius:var(--radius-box);text-align:left;width:100%;font-size:.875rem;position:relative}.md\:table:where(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)),[dir=rtl],[dir=rtl] *){text-align:right}@media (hover:hover){.md\:table tr.row-hover:hover{background-color:var(--color-base-200)}}@media (hover:hover){.md\:table tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-200)}}.md\:table :where(th,td){vertical-align:middle;padding-block:.75rem;padding-inline:1rem}.md\:table :where(thead,tfoot){white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);font-size:.875rem;font-weight:600}.md\:table :where(tfoot){border-top:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.md\:table :where(.table-pin-rows thead tr){z-index:1;background-color:var(--color-base-100);position:sticky;top:0}.md\:table :where(.table-pin-rows tfoot tr){z-index:1;background-color:var(--color-base-100);position:sticky;bottom:0}.md\:table :where(.table-pin-cols tr th){background-color:var(--color-base-100);position:sticky;left:0;right:0}.md\:table :where(thead tr,tbody tr:not(:last-child)){border-bottom:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.md\:table-zebra tbody tr:nth-child(2n){background-color:var(--color-base-200)}.md\:table-zebra tbody tr:nth-child(2n) :where(.table-pin-cols tr th){background-color:var(--color-base-200)}@media (hover:hover){.md\:table-zebra tbody tr.row-hover:hover{background-color:var(--color-base-300)}}@media (hover:hover){.md\:table-zebra tbody tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-300)}}.md\:table-xs :not(:is(thead,tfoot)) tr{font-size:.6875rem}.md\:table-xs :where(th,td){padding-block:.25rem;padding-inline:.5rem}.md\:table-sm :not(:is(thead,tfoot)) tr{font-size:.75rem}.md\:table-sm :where(th,td){padding-block:.5rem;padding-inline:.75rem}.md\:table-md :not(:is(thead,tfoot)) tr{font-size:.875rem}.md\:table-md :where(th,td){padding-block:.75rem;padding-inline:1rem}.md\:table-lg :not(:is(thead,tfoot)) tr{font-size:1.125rem}.md\:table-lg :where(th,td){padding-block:1rem;padding-inline:1.25rem}.md\:table-xl :not(:is(thead,tfoot)) tr{font-size:1.375rem}.md\:table-xl :where(th,td){padding-block:1.25rem;padding-inline:1.5rem}}@media (min-width:1024px){.lg\:table{border-radius:var(--radius-box);text-align:left;width:100%;font-size:.875rem;position:relative}.lg\:table:where(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)),[dir=rtl],[dir=rtl] *){text-align:right}@media (hover:hover){.lg\:table tr.row-hover:hover{background-color:var(--color-base-200)}}@media (hover:hover){.lg\:table tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-200)}}.lg\:table :where(th,td){vertical-align:middle;padding-block:.75rem;padding-inline:1rem}.lg\:table :where(thead,tfoot){white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);font-size:.875rem;font-weight:600}.lg\:table :where(tfoot){border-top:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.lg\:table :where(.table-pin-rows thead tr){z-index:1;background-color:var(--color-base-100);position:sticky;top:0}.lg\:table :where(.table-pin-rows tfoot tr){z-index:1;background-color:var(--color-base-100);position:sticky;bottom:0}.lg\:table :where(.table-pin-cols tr th){background-color:var(--color-base-100);position:sticky;left:0;right:0}.lg\:table :where(thead tr,tbody tr:not(:last-child)){border-bottom:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.lg\:table-zebra tbody tr:nth-child(2n){background-color:var(--color-base-200)}.lg\:table-zebra tbody tr:nth-child(2n) :where(.table-pin-cols tr th){background-color:var(--color-base-200)}@media (hover:hover){.lg\:table-zebra tbody tr.row-hover:hover{background-color:var(--color-base-300)}}@media (hover:hover){.lg\:table-zebra tbody tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-300)}}.lg\:table-xs :not(:is(thead,tfoot)) tr{font-size:.6875rem}.lg\:table-xs :where(th,td){padding-block:.25rem;padding-inline:.5rem}.lg\:table-sm :not(:is(thead,tfoot)) tr{font-size:.75rem}.lg\:table-sm :where(th,td){padding-block:.5rem;padding-inline:.75rem}.lg\:table-md :not(:is(thead,tfoot)) tr{font-size:.875rem}.lg\:table-md :where(th,td){padding-block:.75rem;padding-inline:1rem}.lg\:table-lg :not(:is(thead,tfoot)) tr{font-size:1.125rem}.lg\:table-lg :where(th,td){padding-block:1rem;padding-inline:1.25rem}.lg\:table-xl :not(:is(thead,tfoot)) tr{font-size:1.375rem}.lg\:table-xl :where(th,td){padding-block:1.25rem;padding-inline:1.5rem}}@media (min-width:1280px){.xl\:table{border-radius:var(--radius-box);text-align:left;width:100%;font-size:.875rem;position:relative}.xl\:table:where(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)),[dir=rtl],[dir=rtl] *){text-align:right}@media (hover:hover){.xl\:table tr.row-hover:hover{background-color:var(--color-base-200)}}@media (hover:hover){.xl\:table tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-200)}}.xl\:table :where(th,td){vertical-align:middle;padding-block:.75rem;padding-inline:1rem}.xl\:table :where(thead,tfoot){white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);font-size:.875rem;font-weight:600}.xl\:table :where(tfoot){border-top:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.xl\:table :where(.table-pin-rows thead tr){z-index:1;background-color:var(--color-base-100);position:sticky;top:0}.xl\:table :where(.table-pin-rows tfoot tr){z-index:1;background-color:var(--color-base-100);position:sticky;bottom:0}.xl\:table :where(.table-pin-cols tr th){background-color:var(--color-base-100);position:sticky;left:0;right:0}.xl\:table :where(thead tr,tbody tr:not(:last-child)){border-bottom:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.xl\:table-zebra tbody tr:nth-child(2n){background-color:var(--color-base-200)}.xl\:table-zebra tbody tr:nth-child(2n) :where(.table-pin-cols tr th){background-color:var(--color-base-200)}@media (hover:hover){.xl\:table-zebra tbody tr.row-hover:hover{background-color:var(--color-base-300)}}@media (hover:hover){.xl\:table-zebra tbody tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-300)}}.xl\:table-xs :not(:is(thead,tfoot)) tr{font-size:.6875rem}.xl\:table-xs :where(th,td){padding-block:.25rem;padding-inline:.5rem}.xl\:table-sm :not(:is(thead,tfoot)) tr{font-size:.75rem}.xl\:table-sm :where(th,td){padding-block:.5rem;padding-inline:.75rem}.xl\:table-md :not(:is(thead,tfoot)) tr{font-size:.875rem}.xl\:table-md :where(th,td){padding-block:.75rem;padding-inline:1rem}.xl\:table-lg :not(:is(thead,tfoot)) tr{font-size:1.125rem}.xl\:table-lg :where(th,td){padding-block:1rem;padding-inline:1.25rem}.xl\:table-xl :not(:is(thead,tfoot)) tr{font-size:1.375rem}.xl\:table-xl :where(th,td){padding-block:1.25rem;padding-inline:1.5rem}}@media (min-width:1536px){.\32 xl\:table{border-radius:var(--radius-box);text-align:left;width:100%;font-size:.875rem;position:relative}.\32 xl\:table:where(:is(:lang(ae),:lang(ar),:lang(arc),:lang(bcc),:lang(bqi),:lang(ckb),:lang(dv),:lang(fa),:lang(glk),:lang(he),:lang(ku),:lang(mzn),:lang(nqo),:lang(pnb),:lang(ps),:lang(sd),:lang(ug),:lang(ur),:lang(yi)),[dir=rtl],[dir=rtl] *){text-align:right}@media (hover:hover){.\32 xl\:table tr.row-hover:hover{background-color:var(--color-base-200)}}@media (hover:hover){.\32 xl\:table tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-200)}}.\32 xl\:table :where(th,td){vertical-align:middle;padding-block:.75rem;padding-inline:1rem}.\32 xl\:table :where(thead,tfoot){white-space:nowrap;color:color-mix(in oklab,var(--color-base-content)60%,transparent);font-size:.875rem;font-weight:600}.\32 xl\:table :where(tfoot){border-top:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.\32 xl\:table :where(.table-pin-rows thead tr){z-index:1;background-color:var(--color-base-100);position:sticky;top:0}.\32 xl\:table :where(.table-pin-rows tfoot tr){z-index:1;background-color:var(--color-base-100);position:sticky;bottom:0}.\32 xl\:table :where(.table-pin-cols tr th){background-color:var(--color-base-100);position:sticky;left:0;right:0}.\32 xl\:table :where(thead tr,tbody tr:not(:last-child)){border-bottom:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,transparent)}.\32 xl\:table-zebra tbody tr:nth-child(2n){background-color:var(--color-base-200)}.\32 xl\:table-zebra tbody tr:nth-child(2n) :where(.table-pin-cols tr th){background-color:var(--color-base-200)}@media (hover:hover){.\32 xl\:table-zebra tbody tr.row-hover:hover{background-color:var(--color-base-300)}}@media (hover:hover){.\32 xl\:table-zebra tbody tr.row-hover:nth-child(2n):hover{background-color:var(--color-base-300)}}.\32 xl\:table-xs :not(:is(thead,tfoot)) tr{font-size:.6875rem}.\32 xl\:table-xs :where(th,td){padding-block:.25rem;padding-inline:.5rem}.\32 xl\:table-sm :not(:is(thead,tfoot)) tr{font-size:.75rem}.\32 xl\:table-sm :where(th,td){padding-block:.5rem;padding-inline:.75rem}.\32 xl\:table-md :not(:is(thead,tfoot)) tr{font-size:.875rem}.\32 xl\:table-md :where(th,td){padding-block:.75rem;padding-inline:1rem}.\32 xl\:table-lg :not(:is(thead,tfoot)) tr{font-size:1.125rem}.\32 xl\:table-lg :where(th,td){padding-block:1rem;padding-inline:1.25rem}.\32 xl\:table-xl :not(:is(thead,tfoot)) tr{font-size:1.375rem}.\32 xl\:table-xl :where(th,td){padding-block:1.25rem;padding-inline:1.5rem}}.toggle{border:var(--border)solid currentColor;color:var(--input-color);cursor:pointer;appearance:none;vertical-align:middle;-webkit-user-select:none;user-select:none;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--toggle-p),var(--radius-selector-max)) + min(var(--border),var(--radius-selector-max)));padding:var(--toggle-p);box-shadow:0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent)inset;--input-color:color-mix(in oklab,var(--color-base-content)50%,transparent);--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6);width:calc((var(--size)*2) - (var(--border) + var(--toggle-p))*2);height:var(--size);flex-shrink:0;grid-template-columns:0fr 1fr 1fr;place-content:center;transition:color .3s,grid-template-columns .2s;display:inline-grid;position:relative}.toggle>*{z-index:1;cursor:pointer;appearance:none;background-color:transparent;border:none;grid-column:2/span 1;grid-row-start:1;height:100%;padding:.125rem;transition:opacity .2s,rotate .4s}.toggle>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.toggle>*:focus{outline-offset:2px;outline:2px solid transparent}}.toggle>*:nth-child(2){color:var(--color-base-100);rotate:none}.toggle>*:nth-child(3){color:var(--color-base-100);opacity:0;rotate:-15deg}.toggle:has(:checked)>:nth-child(2){opacity:0;rotate:15deg}.toggle:has(:checked)>:nth-child(3){opacity:1;rotate:none}.toggle:before{aspect-ratio:1;border-radius:var(--radius-selector);--tw-content:"";content:var(--tw-content);height:100%;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent);background-color:currentColor;background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);grid-row-start:1;grid-column-start:2;transition:background-color .1s,translate .2s,inset-inline-start .2s;position:relative;inset-inline-start:0;translate:0}@media (forced-colors:active){.toggle:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.toggle:before{outline-offset:-1rem;outline:.25rem solid}}.toggle:focus-visible{outline-offset:2px;outline:2px solid}.toggle:has(:focus-visible){outline-offset:2px;outline:2px solid}.toggle:checked{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.toggle:checked:before{background-color:currentColor}@starting-style{.toggle:checked:before{opacity:0}}.toggle[aria-checked=true]{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.toggle[aria-checked=true]:before{background-color:currentColor}@starting-style{.toggle[aria-checked=true]:before{opacity:0}}.toggle:has(>input:checked){background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.toggle:has(>input:checked):before{background-color:currentColor}@starting-style{.toggle:has(>input:checked):before{opacity:0}}.toggle:indeterminate{grid-template-columns:.5fr 1fr .5fr}.toggle:disabled{cursor:not-allowed;opacity:.3}.toggle:disabled:before{border:var(--border)solid currentColor;background-color:transparent}.toggle-primary:checked{--input-color:var(--color-primary)}.toggle-primary[aria-checked=true]{--input-color:var(--color-primary)}.toggle-secondary:checked{--input-color:var(--color-secondary)}.toggle-secondary[aria-checked=true]{--input-color:var(--color-secondary)}.toggle-accent:checked{--input-color:var(--color-accent)}.toggle-accent[aria-checked=true]{--input-color:var(--color-accent)}.toggle-neutral:checked{--input-color:var(--color-neutral)}.toggle-neutral[aria-checked=true]{--input-color:var(--color-neutral)}.toggle-success:checked{--input-color:var(--color-success)}.toggle-success[aria-checked=true]{--input-color:var(--color-success)}.toggle-warning:checked{--input-color:var(--color-warning)}.toggle-warning[aria-checked=true]{--input-color:var(--color-warning)}.toggle-info:checked{--input-color:var(--color-info)}.toggle-info[aria-checked=true]{--input-color:var(--color-info)}.toggle-error:checked{--input-color:var(--color-error)}.toggle-error[aria-checked=true]{--input-color:var(--color-error)}.toggle-xs[type=checkbox]{--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.toggle-xs:has([type=checkbox]){--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.toggle-sm[type=checkbox]{--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.toggle-sm:has([type=checkbox]){--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.toggle-md[type=checkbox]{--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.toggle-md:has([type=checkbox]){--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.toggle-lg[type=checkbox]{--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.toggle-lg:has([type=checkbox]){--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.toggle-xl[type=checkbox]{--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}.toggle-xl:has([type=checkbox]){--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}@media (min-width:640px){.sm\:toggle{border:var(--border)solid currentColor;color:var(--input-color);cursor:pointer;appearance:none;vertical-align:middle;-webkit-user-select:none;user-select:none;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--toggle-p),var(--radius-selector-max)) + min(var(--border),var(--radius-selector-max)));padding:var(--toggle-p);box-shadow:0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent)inset;--input-color:color-mix(in oklab,var(--color-base-content)50%,transparent);--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6);width:calc((var(--size)*2) - (var(--border) + var(--toggle-p))*2);height:var(--size);flex-shrink:0;grid-template-columns:0fr 1fr 1fr;place-content:center;transition:color .3s,grid-template-columns .2s;display:inline-grid;position:relative}.sm\:toggle>*{z-index:1;cursor:pointer;appearance:none;background-color:transparent;border:none;grid-column:2/span 1;grid-row-start:1;height:100%;padding:.125rem;transition:opacity .2s,rotate .4s}.sm\:toggle>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:toggle>*:focus{outline-offset:2px;outline:2px solid transparent}}.sm\:toggle>*:nth-child(2){color:var(--color-base-100);rotate:none}.sm\:toggle>*:nth-child(3){color:var(--color-base-100);opacity:0;rotate:-15deg}.sm\:toggle:has(:checked)>:nth-child(2){opacity:0;rotate:15deg}.sm\:toggle:has(:checked)>:nth-child(3){opacity:1;rotate:none}.sm\:toggle:before{aspect-ratio:1;border-radius:var(--radius-selector);--tw-content:"";content:var(--tw-content);height:100%;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent);background-color:currentColor;background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);grid-row-start:1;grid-column-start:2;transition:background-color .1s,translate .2s,inset-inline-start .2s;position:relative;inset-inline-start:0;translate:0}@media (forced-colors:active){.sm\:toggle:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.sm\:toggle:before{outline-offset:-1rem;outline:.25rem solid}}.sm\:toggle:focus-visible{outline-offset:2px;outline:2px solid}.sm\:toggle:has(:focus-visible){outline-offset:2px;outline:2px solid}.sm\:toggle:checked{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.sm\:toggle:checked:before{background-color:currentColor}@starting-style{.sm\:toggle:checked:before{opacity:0}}.sm\:toggle[aria-checked=true]{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.sm\:toggle[aria-checked=true]:before{background-color:currentColor}@starting-style{.sm\:toggle[aria-checked=true]:before{opacity:0}}.sm\:toggle:has(>input:checked){background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.sm\:toggle:has(>input:checked):before{background-color:currentColor}@starting-style{.sm\:toggle:has(>input:checked):before{opacity:0}}.sm\:toggle:indeterminate{grid-template-columns:.5fr 1fr .5fr}.sm\:toggle:disabled{cursor:not-allowed;opacity:.3}.sm\:toggle:disabled:before{border:var(--border)solid currentColor;background-color:transparent}.sm\:toggle-primary:checked{--input-color:var(--color-primary)}.sm\:toggle-primary[aria-checked=true]{--input-color:var(--color-primary)}.sm\:toggle-secondary:checked{--input-color:var(--color-secondary)}.sm\:toggle-secondary[aria-checked=true]{--input-color:var(--color-secondary)}.sm\:toggle-accent:checked{--input-color:var(--color-accent)}.sm\:toggle-accent[aria-checked=true]{--input-color:var(--color-accent)}.sm\:toggle-neutral:checked{--input-color:var(--color-neutral)}.sm\:toggle-neutral[aria-checked=true]{--input-color:var(--color-neutral)}.sm\:toggle-success:checked{--input-color:var(--color-success)}.sm\:toggle-success[aria-checked=true]{--input-color:var(--color-success)}.sm\:toggle-warning:checked{--input-color:var(--color-warning)}.sm\:toggle-warning[aria-checked=true]{--input-color:var(--color-warning)}.sm\:toggle-info:checked{--input-color:var(--color-info)}.sm\:toggle-info[aria-checked=true]{--input-color:var(--color-info)}.sm\:toggle-error:checked{--input-color:var(--color-error)}.sm\:toggle-error[aria-checked=true]{--input-color:var(--color-error)}.sm\:toggle-xs[type=checkbox]{--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.sm\:toggle-xs:has([type=checkbox]){--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.sm\:toggle-sm[type=checkbox]{--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.sm\:toggle-sm:has([type=checkbox]){--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.sm\:toggle-md[type=checkbox]{--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.sm\:toggle-md:has([type=checkbox]){--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.sm\:toggle-lg[type=checkbox]{--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.sm\:toggle-lg:has([type=checkbox]){--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.sm\:toggle-xl[type=checkbox]{--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}.sm\:toggle-xl:has([type=checkbox]){--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:768px){.md\:toggle{border:var(--border)solid currentColor;color:var(--input-color);cursor:pointer;appearance:none;vertical-align:middle;-webkit-user-select:none;user-select:none;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--toggle-p),var(--radius-selector-max)) + min(var(--border),var(--radius-selector-max)));padding:var(--toggle-p);box-shadow:0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent)inset;--input-color:color-mix(in oklab,var(--color-base-content)50%,transparent);--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6);width:calc((var(--size)*2) - (var(--border) + var(--toggle-p))*2);height:var(--size);flex-shrink:0;grid-template-columns:0fr 1fr 1fr;place-content:center;transition:color .3s,grid-template-columns .2s;display:inline-grid;position:relative}.md\:toggle>*{z-index:1;cursor:pointer;appearance:none;background-color:transparent;border:none;grid-column:2/span 1;grid-row-start:1;height:100%;padding:.125rem;transition:opacity .2s,rotate .4s}.md\:toggle>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:toggle>*:focus{outline-offset:2px;outline:2px solid transparent}}.md\:toggle>*:nth-child(2){color:var(--color-base-100);rotate:none}.md\:toggle>*:nth-child(3){color:var(--color-base-100);opacity:0;rotate:-15deg}.md\:toggle:has(:checked)>:nth-child(2){opacity:0;rotate:15deg}.md\:toggle:has(:checked)>:nth-child(3){opacity:1;rotate:none}.md\:toggle:before{aspect-ratio:1;border-radius:var(--radius-selector);--tw-content:"";content:var(--tw-content);height:100%;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent);background-color:currentColor;background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);grid-row-start:1;grid-column-start:2;transition:background-color .1s,translate .2s,inset-inline-start .2s;position:relative;inset-inline-start:0;translate:0}@media (forced-colors:active){.md\:toggle:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.md\:toggle:before{outline-offset:-1rem;outline:.25rem solid}}.md\:toggle:focus-visible{outline-offset:2px;outline:2px solid}.md\:toggle:has(:focus-visible){outline-offset:2px;outline:2px solid}.md\:toggle:checked{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.md\:toggle:checked:before{background-color:currentColor}@starting-style{.md\:toggle:checked:before{opacity:0}}.md\:toggle[aria-checked=true]{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.md\:toggle[aria-checked=true]:before{background-color:currentColor}@starting-style{.md\:toggle[aria-checked=true]:before{opacity:0}}.md\:toggle:has(>input:checked){background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.md\:toggle:has(>input:checked):before{background-color:currentColor}@starting-style{.md\:toggle:has(>input:checked):before{opacity:0}}.md\:toggle:indeterminate{grid-template-columns:.5fr 1fr .5fr}.md\:toggle:disabled{cursor:not-allowed;opacity:.3}.md\:toggle:disabled:before{border:var(--border)solid currentColor;background-color:transparent}.md\:toggle-primary:checked{--input-color:var(--color-primary)}.md\:toggle-primary[aria-checked=true]{--input-color:var(--color-primary)}.md\:toggle-secondary:checked{--input-color:var(--color-secondary)}.md\:toggle-secondary[aria-checked=true]{--input-color:var(--color-secondary)}.md\:toggle-accent:checked{--input-color:var(--color-accent)}.md\:toggle-accent[aria-checked=true]{--input-color:var(--color-accent)}.md\:toggle-neutral:checked{--input-color:var(--color-neutral)}.md\:toggle-neutral[aria-checked=true]{--input-color:var(--color-neutral)}.md\:toggle-success:checked{--input-color:var(--color-success)}.md\:toggle-success[aria-checked=true]{--input-color:var(--color-success)}.md\:toggle-warning:checked{--input-color:var(--color-warning)}.md\:toggle-warning[aria-checked=true]{--input-color:var(--color-warning)}.md\:toggle-info:checked{--input-color:var(--color-info)}.md\:toggle-info[aria-checked=true]{--input-color:var(--color-info)}.md\:toggle-error:checked{--input-color:var(--color-error)}.md\:toggle-error[aria-checked=true]{--input-color:var(--color-error)}.md\:toggle-xs[type=checkbox]{--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.md\:toggle-xs:has([type=checkbox]){--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.md\:toggle-sm[type=checkbox]{--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.md\:toggle-sm:has([type=checkbox]){--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.md\:toggle-md[type=checkbox]{--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.md\:toggle-md:has([type=checkbox]){--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.md\:toggle-lg[type=checkbox]{--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.md\:toggle-lg:has([type=checkbox]){--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.md\:toggle-xl[type=checkbox]{--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}.md\:toggle-xl:has([type=checkbox]){--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:1024px){.lg\:toggle{border:var(--border)solid currentColor;color:var(--input-color);cursor:pointer;appearance:none;vertical-align:middle;-webkit-user-select:none;user-select:none;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--toggle-p),var(--radius-selector-max)) + min(var(--border),var(--radius-selector-max)));padding:var(--toggle-p);box-shadow:0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent)inset;--input-color:color-mix(in oklab,var(--color-base-content)50%,transparent);--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6);width:calc((var(--size)*2) - (var(--border) + var(--toggle-p))*2);height:var(--size);flex-shrink:0;grid-template-columns:0fr 1fr 1fr;place-content:center;transition:color .3s,grid-template-columns .2s;display:inline-grid;position:relative}.lg\:toggle>*{z-index:1;cursor:pointer;appearance:none;background-color:transparent;border:none;grid-column:2/span 1;grid-row-start:1;height:100%;padding:.125rem;transition:opacity .2s,rotate .4s}.lg\:toggle>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:toggle>*:focus{outline-offset:2px;outline:2px solid transparent}}.lg\:toggle>*:nth-child(2){color:var(--color-base-100);rotate:none}.lg\:toggle>*:nth-child(3){color:var(--color-base-100);opacity:0;rotate:-15deg}.lg\:toggle:has(:checked)>:nth-child(2){opacity:0;rotate:15deg}.lg\:toggle:has(:checked)>:nth-child(3){opacity:1;rotate:none}.lg\:toggle:before{aspect-ratio:1;border-radius:var(--radius-selector);--tw-content:"";content:var(--tw-content);height:100%;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent);background-color:currentColor;background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);grid-row-start:1;grid-column-start:2;transition:background-color .1s,translate .2s,inset-inline-start .2s;position:relative;inset-inline-start:0;translate:0}@media (forced-colors:active){.lg\:toggle:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.lg\:toggle:before{outline-offset:-1rem;outline:.25rem solid}}.lg\:toggle:focus-visible{outline-offset:2px;outline:2px solid}.lg\:toggle:has(:focus-visible){outline-offset:2px;outline:2px solid}.lg\:toggle:checked{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.lg\:toggle:checked:before{background-color:currentColor}@starting-style{.lg\:toggle:checked:before{opacity:0}}.lg\:toggle[aria-checked=true]{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.lg\:toggle[aria-checked=true]:before{background-color:currentColor}@starting-style{.lg\:toggle[aria-checked=true]:before{opacity:0}}.lg\:toggle:has(>input:checked){background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.lg\:toggle:has(>input:checked):before{background-color:currentColor}@starting-style{.lg\:toggle:has(>input:checked):before{opacity:0}}.lg\:toggle:indeterminate{grid-template-columns:.5fr 1fr .5fr}.lg\:toggle:disabled{cursor:not-allowed;opacity:.3}.lg\:toggle:disabled:before{border:var(--border)solid currentColor;background-color:transparent}.lg\:toggle-primary:checked{--input-color:var(--color-primary)}.lg\:toggle-primary[aria-checked=true]{--input-color:var(--color-primary)}.lg\:toggle-secondary:checked{--input-color:var(--color-secondary)}.lg\:toggle-secondary[aria-checked=true]{--input-color:var(--color-secondary)}.lg\:toggle-accent:checked{--input-color:var(--color-accent)}.lg\:toggle-accent[aria-checked=true]{--input-color:var(--color-accent)}.lg\:toggle-neutral:checked{--input-color:var(--color-neutral)}.lg\:toggle-neutral[aria-checked=true]{--input-color:var(--color-neutral)}.lg\:toggle-success:checked{--input-color:var(--color-success)}.lg\:toggle-success[aria-checked=true]{--input-color:var(--color-success)}.lg\:toggle-warning:checked{--input-color:var(--color-warning)}.lg\:toggle-warning[aria-checked=true]{--input-color:var(--color-warning)}.lg\:toggle-info:checked{--input-color:var(--color-info)}.lg\:toggle-info[aria-checked=true]{--input-color:var(--color-info)}.lg\:toggle-error:checked{--input-color:var(--color-error)}.lg\:toggle-error[aria-checked=true]{--input-color:var(--color-error)}.lg\:toggle-xs[type=checkbox]{--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.lg\:toggle-xs:has([type=checkbox]){--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.lg\:toggle-sm[type=checkbox]{--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.lg\:toggle-sm:has([type=checkbox]){--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.lg\:toggle-md[type=checkbox]{--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.lg\:toggle-md:has([type=checkbox]){--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.lg\:toggle-lg[type=checkbox]{--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.lg\:toggle-lg:has([type=checkbox]){--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.lg\:toggle-xl[type=checkbox]{--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}.lg\:toggle-xl:has([type=checkbox]){--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:1280px){.xl\:toggle{border:var(--border)solid currentColor;color:var(--input-color);cursor:pointer;appearance:none;vertical-align:middle;-webkit-user-select:none;user-select:none;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--toggle-p),var(--radius-selector-max)) + min(var(--border),var(--radius-selector-max)));padding:var(--toggle-p);box-shadow:0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent)inset;--input-color:color-mix(in oklab,var(--color-base-content)50%,transparent);--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6);width:calc((var(--size)*2) - (var(--border) + var(--toggle-p))*2);height:var(--size);flex-shrink:0;grid-template-columns:0fr 1fr 1fr;place-content:center;transition:color .3s,grid-template-columns .2s;display:inline-grid;position:relative}.xl\:toggle>*{z-index:1;cursor:pointer;appearance:none;background-color:transparent;border:none;grid-column:2/span 1;grid-row-start:1;height:100%;padding:.125rem;transition:opacity .2s,rotate .4s}.xl\:toggle>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:toggle>*:focus{outline-offset:2px;outline:2px solid transparent}}.xl\:toggle>*:nth-child(2){color:var(--color-base-100);rotate:none}.xl\:toggle>*:nth-child(3){color:var(--color-base-100);opacity:0;rotate:-15deg}.xl\:toggle:has(:checked)>:nth-child(2){opacity:0;rotate:15deg}.xl\:toggle:has(:checked)>:nth-child(3){opacity:1;rotate:none}.xl\:toggle:before{aspect-ratio:1;border-radius:var(--radius-selector);--tw-content:"";content:var(--tw-content);height:100%;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent);background-color:currentColor;background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);grid-row-start:1;grid-column-start:2;transition:background-color .1s,translate .2s,inset-inline-start .2s;position:relative;inset-inline-start:0;translate:0}@media (forced-colors:active){.xl\:toggle:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.xl\:toggle:before{outline-offset:-1rem;outline:.25rem solid}}.xl\:toggle:focus-visible{outline-offset:2px;outline:2px solid}.xl\:toggle:has(:focus-visible){outline-offset:2px;outline:2px solid}.xl\:toggle:checked{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.xl\:toggle:checked:before{background-color:currentColor}@starting-style{.xl\:toggle:checked:before{opacity:0}}.xl\:toggle[aria-checked=true]{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.xl\:toggle[aria-checked=true]:before{background-color:currentColor}@starting-style{.xl\:toggle[aria-checked=true]:before{opacity:0}}.xl\:toggle:has(>input:checked){background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.xl\:toggle:has(>input:checked):before{background-color:currentColor}@starting-style{.xl\:toggle:has(>input:checked):before{opacity:0}}.xl\:toggle:indeterminate{grid-template-columns:.5fr 1fr .5fr}.xl\:toggle:disabled{cursor:not-allowed;opacity:.3}.xl\:toggle:disabled:before{border:var(--border)solid currentColor;background-color:transparent}.xl\:toggle-primary:checked{--input-color:var(--color-primary)}.xl\:toggle-primary[aria-checked=true]{--input-color:var(--color-primary)}.xl\:toggle-secondary:checked{--input-color:var(--color-secondary)}.xl\:toggle-secondary[aria-checked=true]{--input-color:var(--color-secondary)}.xl\:toggle-accent:checked{--input-color:var(--color-accent)}.xl\:toggle-accent[aria-checked=true]{--input-color:var(--color-accent)}.xl\:toggle-neutral:checked{--input-color:var(--color-neutral)}.xl\:toggle-neutral[aria-checked=true]{--input-color:var(--color-neutral)}.xl\:toggle-success:checked{--input-color:var(--color-success)}.xl\:toggle-success[aria-checked=true]{--input-color:var(--color-success)}.xl\:toggle-warning:checked{--input-color:var(--color-warning)}.xl\:toggle-warning[aria-checked=true]{--input-color:var(--color-warning)}.xl\:toggle-info:checked{--input-color:var(--color-info)}.xl\:toggle-info[aria-checked=true]{--input-color:var(--color-info)}.xl\:toggle-error:checked{--input-color:var(--color-error)}.xl\:toggle-error[aria-checked=true]{--input-color:var(--color-error)}.xl\:toggle-xs[type=checkbox]{--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.xl\:toggle-xs:has([type=checkbox]){--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.xl\:toggle-sm[type=checkbox]{--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.xl\:toggle-sm:has([type=checkbox]){--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.xl\:toggle-md[type=checkbox]{--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.xl\:toggle-md:has([type=checkbox]){--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.xl\:toggle-lg[type=checkbox]{--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.xl\:toggle-lg:has([type=checkbox]){--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.xl\:toggle-xl[type=checkbox]{--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}.xl\:toggle-xl:has([type=checkbox]){--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:1536px){.\32 xl\:toggle{border:var(--border)solid currentColor;color:var(--input-color);cursor:pointer;appearance:none;vertical-align:middle;-webkit-user-select:none;user-select:none;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--toggle-p),var(--radius-selector-max)) + min(var(--border),var(--radius-selector-max)));padding:var(--toggle-p);box-shadow:0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent)inset;--input-color:color-mix(in oklab,var(--color-base-content)50%,transparent);--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6);width:calc((var(--size)*2) - (var(--border) + var(--toggle-p))*2);height:var(--size);flex-shrink:0;grid-template-columns:0fr 1fr 1fr;place-content:center;transition:color .3s,grid-template-columns .2s;display:inline-grid;position:relative}.\32 xl\:toggle>*{z-index:1;cursor:pointer;appearance:none;background-color:transparent;border:none;grid-column:2/span 1;grid-row-start:1;height:100%;padding:.125rem;transition:opacity .2s,rotate .4s}.\32 xl\:toggle>*:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:toggle>*:focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:toggle>*:nth-child(2){color:var(--color-base-100);rotate:none}.\32 xl\:toggle>*:nth-child(3){color:var(--color-base-100);opacity:0;rotate:-15deg}.\32 xl\:toggle:has(:checked)>:nth-child(2){opacity:0;rotate:15deg}.\32 xl\:toggle:has(:checked)>:nth-child(3){opacity:1;rotate:none}.\32 xl\:toggle:before{aspect-ratio:1;border-radius:var(--radius-selector);--tw-content:"";content:var(--tw-content);height:100%;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),transparent);background-color:currentColor;background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);grid-row-start:1;grid-column-start:2;transition:background-color .1s,translate .2s,inset-inline-start .2s;position:relative;inset-inline-start:0;translate:0}@media (forced-colors:active){.\32 xl\:toggle:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.\32 xl\:toggle:before{outline-offset:-1rem;outline:.25rem solid}}.\32 xl\:toggle:focus-visible{outline-offset:2px;outline:2px solid}.\32 xl\:toggle:has(:focus-visible){outline-offset:2px;outline:2px solid}.\32 xl\:toggle:checked{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.\32 xl\:toggle:checked:before{background-color:currentColor}@starting-style{.\32 xl\:toggle:checked:before{opacity:0}}.\32 xl\:toggle[aria-checked=true]{background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.\32 xl\:toggle[aria-checked=true]:before{background-color:currentColor}@starting-style{.\32 xl\:toggle[aria-checked=true]:before{opacity:0}}.\32 xl\:toggle:has(>input:checked){background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}.\32 xl\:toggle:has(>input:checked):before{background-color:currentColor}@starting-style{.\32 xl\:toggle:has(>input:checked):before{opacity:0}}.\32 xl\:toggle:indeterminate{grid-template-columns:.5fr 1fr .5fr}.\32 xl\:toggle:disabled{cursor:not-allowed;opacity:.3}.\32 xl\:toggle:disabled:before{border:var(--border)solid currentColor;background-color:transparent}.\32 xl\:toggle-primary:checked{--input-color:var(--color-primary)}.\32 xl\:toggle-primary[aria-checked=true]{--input-color:var(--color-primary)}.\32 xl\:toggle-secondary:checked{--input-color:var(--color-secondary)}.\32 xl\:toggle-secondary[aria-checked=true]{--input-color:var(--color-secondary)}.\32 xl\:toggle-accent:checked{--input-color:var(--color-accent)}.\32 xl\:toggle-accent[aria-checked=true]{--input-color:var(--color-accent)}.\32 xl\:toggle-neutral:checked{--input-color:var(--color-neutral)}.\32 xl\:toggle-neutral[aria-checked=true]{--input-color:var(--color-neutral)}.\32 xl\:toggle-success:checked{--input-color:var(--color-success)}.\32 xl\:toggle-success[aria-checked=true]{--input-color:var(--color-success)}.\32 xl\:toggle-warning:checked{--input-color:var(--color-warning)}.\32 xl\:toggle-warning[aria-checked=true]{--input-color:var(--color-warning)}.\32 xl\:toggle-info:checked{--input-color:var(--color-info)}.\32 xl\:toggle-info[aria-checked=true]{--input-color:var(--color-info)}.\32 xl\:toggle-error:checked{--input-color:var(--color-error)}.\32 xl\:toggle-error[aria-checked=true]{--input-color:var(--color-error)}.\32 xl\:toggle-xs[type=checkbox]{--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.\32 xl\:toggle-xs:has([type=checkbox]){--toggle-p:.0625rem;--size:calc(var(--size-selector,.25rem)*4)}.\32 xl\:toggle-sm[type=checkbox]{--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.\32 xl\:toggle-sm:has([type=checkbox]){--toggle-p:.125rem;--size:calc(var(--size-selector,.25rem)*5)}.\32 xl\:toggle-md[type=checkbox]{--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.\32 xl\:toggle-md:has([type=checkbox]){--toggle-p:.1875rem;--size:calc(var(--size-selector,.25rem)*6)}.\32 xl\:toggle-lg[type=checkbox]{--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.\32 xl\:toggle-lg:has([type=checkbox]){--toggle-p:.25rem;--size:calc(var(--size-selector,.25rem)*7)}.\32 xl\:toggle-xl[type=checkbox]{--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}.\32 xl\:toggle-xl:has([type=checkbox]){--toggle-p:.3125rem;--size:calc(var(--size-selector,.25rem)*8)}}.divider{white-space:nowrap;height:1rem;margin:var(--divider-m,1rem 0);flex-direction:row;align-self:stretch;align-items:center;display:flex}.divider:before{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}.divider:after{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}@media print{.divider:before{border:.5px solid}.divider:after{border:.5px solid}}.divider:not(:empty){gap:1rem}.divider-horizontal{--divider-m:0 1rem}.divider-horizontal.divider{flex-direction:column;width:1rem;height:auto}.divider-horizontal.divider:before{width:.125rem;height:100%}.divider-horizontal.divider:after{width:.125rem;height:100%}.divider-vertical{--divider-m:1rem 0}.divider-vertical.divider{flex-direction:row;width:auto;height:1rem}.divider-vertical.divider:before{width:100%;height:.125rem}.divider-vertical.divider:after{width:100%;height:.125rem}.divider-neutral:before{background-color:var(--color-neutral)}.divider-neutral:after{background-color:var(--color-neutral)}.divider-primary:before{background-color:var(--color-primary)}.divider-primary:after{background-color:var(--color-primary)}.divider-secondary:before{background-color:var(--color-secondary)}.divider-secondary:after{background-color:var(--color-secondary)}.divider-accent:before{background-color:var(--color-accent)}.divider-accent:after{background-color:var(--color-accent)}.divider-success:before{background-color:var(--color-success)}.divider-success:after{background-color:var(--color-success)}.divider-warning:before{background-color:var(--color-warning)}.divider-warning:after{background-color:var(--color-warning)}.divider-info:before{background-color:var(--color-info)}.divider-info:after{background-color:var(--color-info)}.divider-error:before{background-color:var(--color-error)}.divider-error:after{background-color:var(--color-error)}.divider-start:before,.divider-end:after{display:none}@media (min-width:640px){.sm\:divider{white-space:nowrap;height:1rem;margin:var(--divider-m,1rem 0);flex-direction:row;align-self:stretch;align-items:center;display:flex}.sm\:divider:before{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}.sm\:divider:after{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}@media print{.sm\:divider:before{border:.5px solid}.sm\:divider:after{border:.5px solid}}.sm\:divider:not(:empty){gap:1rem}.sm\:divider-horizontal{--divider-m:0 1rem}.sm\:divider-horizontal.divider{flex-direction:column;width:1rem;height:auto}.sm\:divider-horizontal.divider:before{width:.125rem;height:100%}.sm\:divider-horizontal.divider:after{width:.125rem;height:100%}.sm\:divider-vertical{--divider-m:1rem 0}.sm\:divider-vertical.divider{flex-direction:row;width:auto;height:1rem}.sm\:divider-vertical.divider:before{width:100%;height:.125rem}.sm\:divider-vertical.divider:after{width:100%;height:.125rem}.sm\:divider-neutral:before{background-color:var(--color-neutral)}.sm\:divider-neutral:after{background-color:var(--color-neutral)}.sm\:divider-primary:before{background-color:var(--color-primary)}.sm\:divider-primary:after{background-color:var(--color-primary)}.sm\:divider-secondary:before{background-color:var(--color-secondary)}.sm\:divider-secondary:after{background-color:var(--color-secondary)}.sm\:divider-accent:before{background-color:var(--color-accent)}.sm\:divider-accent:after{background-color:var(--color-accent)}.sm\:divider-success:before{background-color:var(--color-success)}.sm\:divider-success:after{background-color:var(--color-success)}.sm\:divider-warning:before{background-color:var(--color-warning)}.sm\:divider-warning:after{background-color:var(--color-warning)}.sm\:divider-info:before{background-color:var(--color-info)}.sm\:divider-info:after{background-color:var(--color-info)}.sm\:divider-error:before{background-color:var(--color-error)}.sm\:divider-error:after{background-color:var(--color-error)}.sm\:divider-start:before,.sm\:divider-end:after{display:none}}@media (min-width:768px){.md\:divider{white-space:nowrap;height:1rem;margin:var(--divider-m,1rem 0);flex-direction:row;align-self:stretch;align-items:center;display:flex}.md\:divider:before{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}.md\:divider:after{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}@media print{.md\:divider:before{border:.5px solid}.md\:divider:after{border:.5px solid}}.md\:divider:not(:empty){gap:1rem}.md\:divider-horizontal{--divider-m:0 1rem}.md\:divider-horizontal.divider{flex-direction:column;width:1rem;height:auto}.md\:divider-horizontal.divider:before{width:.125rem;height:100%}.md\:divider-horizontal.divider:after{width:.125rem;height:100%}.md\:divider-vertical{--divider-m:1rem 0}.md\:divider-vertical.divider{flex-direction:row;width:auto;height:1rem}.md\:divider-vertical.divider:before{width:100%;height:.125rem}.md\:divider-vertical.divider:after{width:100%;height:.125rem}.md\:divider-neutral:before{background-color:var(--color-neutral)}.md\:divider-neutral:after{background-color:var(--color-neutral)}.md\:divider-primary:before{background-color:var(--color-primary)}.md\:divider-primary:after{background-color:var(--color-primary)}.md\:divider-secondary:before{background-color:var(--color-secondary)}.md\:divider-secondary:after{background-color:var(--color-secondary)}.md\:divider-accent:before{background-color:var(--color-accent)}.md\:divider-accent:after{background-color:var(--color-accent)}.md\:divider-success:before{background-color:var(--color-success)}.md\:divider-success:after{background-color:var(--color-success)}.md\:divider-warning:before{background-color:var(--color-warning)}.md\:divider-warning:after{background-color:var(--color-warning)}.md\:divider-info:before{background-color:var(--color-info)}.md\:divider-info:after{background-color:var(--color-info)}.md\:divider-error:before{background-color:var(--color-error)}.md\:divider-error:after{background-color:var(--color-error)}.md\:divider-start:before,.md\:divider-end:after{display:none}}@media (min-width:1024px){.lg\:divider{white-space:nowrap;height:1rem;margin:var(--divider-m,1rem 0);flex-direction:row;align-self:stretch;align-items:center;display:flex}.lg\:divider:before{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}.lg\:divider:after{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}@media print{.lg\:divider:before{border:.5px solid}.lg\:divider:after{border:.5px solid}}.lg\:divider:not(:empty){gap:1rem}.lg\:divider-horizontal{--divider-m:0 1rem}.lg\:divider-horizontal.divider{flex-direction:column;width:1rem;height:auto}.lg\:divider-horizontal.divider:before{width:.125rem;height:100%}.lg\:divider-horizontal.divider:after{width:.125rem;height:100%}.lg\:divider-vertical{--divider-m:1rem 0}.lg\:divider-vertical.divider{flex-direction:row;width:auto;height:1rem}.lg\:divider-vertical.divider:before{width:100%;height:.125rem}.lg\:divider-vertical.divider:after{width:100%;height:.125rem}.lg\:divider-neutral:before{background-color:var(--color-neutral)}.lg\:divider-neutral:after{background-color:var(--color-neutral)}.lg\:divider-primary:before{background-color:var(--color-primary)}.lg\:divider-primary:after{background-color:var(--color-primary)}.lg\:divider-secondary:before{background-color:var(--color-secondary)}.lg\:divider-secondary:after{background-color:var(--color-secondary)}.lg\:divider-accent:before{background-color:var(--color-accent)}.lg\:divider-accent:after{background-color:var(--color-accent)}.lg\:divider-success:before{background-color:var(--color-success)}.lg\:divider-success:after{background-color:var(--color-success)}.lg\:divider-warning:before{background-color:var(--color-warning)}.lg\:divider-warning:after{background-color:var(--color-warning)}.lg\:divider-info:before{background-color:var(--color-info)}.lg\:divider-info:after{background-color:var(--color-info)}.lg\:divider-error:before{background-color:var(--color-error)}.lg\:divider-error:after{background-color:var(--color-error)}.lg\:divider-start:before,.lg\:divider-end:after{display:none}}@media (min-width:1280px){.xl\:divider{white-space:nowrap;height:1rem;margin:var(--divider-m,1rem 0);flex-direction:row;align-self:stretch;align-items:center;display:flex}.xl\:divider:before{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}.xl\:divider:after{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}@media print{.xl\:divider:before{border:.5px solid}.xl\:divider:after{border:.5px solid}}.xl\:divider:not(:empty){gap:1rem}.xl\:divider-horizontal{--divider-m:0 1rem}.xl\:divider-horizontal.divider{flex-direction:column;width:1rem;height:auto}.xl\:divider-horizontal.divider:before{width:.125rem;height:100%}.xl\:divider-horizontal.divider:after{width:.125rem;height:100%}.xl\:divider-vertical{--divider-m:1rem 0}.xl\:divider-vertical.divider{flex-direction:row;width:auto;height:1rem}.xl\:divider-vertical.divider:before{width:100%;height:.125rem}.xl\:divider-vertical.divider:after{width:100%;height:.125rem}.xl\:divider-neutral:before{background-color:var(--color-neutral)}.xl\:divider-neutral:after{background-color:var(--color-neutral)}.xl\:divider-primary:before{background-color:var(--color-primary)}.xl\:divider-primary:after{background-color:var(--color-primary)}.xl\:divider-secondary:before{background-color:var(--color-secondary)}.xl\:divider-secondary:after{background-color:var(--color-secondary)}.xl\:divider-accent:before{background-color:var(--color-accent)}.xl\:divider-accent:after{background-color:var(--color-accent)}.xl\:divider-success:before{background-color:var(--color-success)}.xl\:divider-success:after{background-color:var(--color-success)}.xl\:divider-warning:before{background-color:var(--color-warning)}.xl\:divider-warning:after{background-color:var(--color-warning)}.xl\:divider-info:before{background-color:var(--color-info)}.xl\:divider-info:after{background-color:var(--color-info)}.xl\:divider-error:before{background-color:var(--color-error)}.xl\:divider-error:after{background-color:var(--color-error)}.xl\:divider-start:before,.xl\:divider-end:after{display:none}}@media (min-width:1536px){.\32 xl\:divider{white-space:nowrap;height:1rem;margin:var(--divider-m,1rem 0);flex-direction:row;align-self:stretch;align-items:center;display:flex}.\32 xl\:divider:before{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}.\32 xl\:divider:after{content:"";background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);flex-grow:1;width:100%;height:.125rem}@media print{.\32 xl\:divider:before{border:.5px solid}.\32 xl\:divider:after{border:.5px solid}}.\32 xl\:divider:not(:empty){gap:1rem}.\32 xl\:divider-horizontal{--divider-m:0 1rem}.\32 xl\:divider-horizontal.divider{flex-direction:column;width:1rem;height:auto}.\32 xl\:divider-horizontal.divider:before{width:.125rem;height:100%}.\32 xl\:divider-horizontal.divider:after{width:.125rem;height:100%}.\32 xl\:divider-vertical{--divider-m:1rem 0}.\32 xl\:divider-vertical.divider{flex-direction:row;width:auto;height:1rem}.\32 xl\:divider-vertical.divider:before{width:100%;height:.125rem}.\32 xl\:divider-vertical.divider:after{width:100%;height:.125rem}.\32 xl\:divider-neutral:before{background-color:var(--color-neutral)}.\32 xl\:divider-neutral:after{background-color:var(--color-neutral)}.\32 xl\:divider-primary:before{background-color:var(--color-primary)}.\32 xl\:divider-primary:after{background-color:var(--color-primary)}.\32 xl\:divider-secondary:before{background-color:var(--color-secondary)}.\32 xl\:divider-secondary:after{background-color:var(--color-secondary)}.\32 xl\:divider-accent:before{background-color:var(--color-accent)}.\32 xl\:divider-accent:after{background-color:var(--color-accent)}.\32 xl\:divider-success:before{background-color:var(--color-success)}.\32 xl\:divider-success:after{background-color:var(--color-success)}.\32 xl\:divider-warning:before{background-color:var(--color-warning)}.\32 xl\:divider-warning:after{background-color:var(--color-warning)}.\32 xl\:divider-info:before{background-color:var(--color-info)}.\32 xl\:divider-info:after{background-color:var(--color-info)}.\32 xl\:divider-error:before{background-color:var(--color-error)}.\32 xl\:divider-error:after{background-color:var(--color-error)}.\32 xl\:divider-start:before,.\32 xl\:divider-end:after{display:none}}:where(.btn){width:unset}.btn{cursor:pointer;text-align:center;vertical-align:middle;outline-offset:2px;-webkit-user-select:none;user-select:none;padding-inline:var(--btn-p);color:var(--btn-fg);--tw-prose-links:var(--btn-fg);height:var(--size);font-size:var(--fontsize,.875rem);outline-color:var(--btn-color,var(--color-base-content));background-color:var(--btn-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--btn-noise);border-width:var(--border);border-style:solid;border-color:var(--btn-border);text-shadow:0 .5px oklch(100% 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px oklch(100% 0 0/calc(var(--depth)*6%))inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-p:1rem;--btn-border:color-mix(in oklab,var(--btn-bg),#000 calc(var(--depth)*5%));--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent);--btn-noise:var(--fx-noise);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-wrap:nowrap;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;font-weight:600;transition-property:color,background-color,border-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:inline-flex}.prose .btn{text-decoration-line:none}@media (hover:hover){.btn:hover{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}.btn:focus-visible{outline-width:2px;outline-style:solid}.btn:active:not(.btn-active){--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 5%);--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;translate:0 .5px}@supports (color:lab(0% 0 0)){.btn:active:not(.btn-active){--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.btn:is(:disabled,[disabled],.btn-disabled){pointer-events:none;--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.btn:is(:disabled,[disabled],.btn-disabled):not(:is(.btn-link,.btn-ghost)){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);box-shadow:none}@media (hover:hover){.btn:is(:disabled,[disabled],.btn-disabled):hover{pointer-events:none;background-color:color-mix(in oklab,var(--color-neutral)20%,transparent);--btn-border:transparent;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}}.btn:is(input[type=checkbox],input[type=radio]){appearance:none}.btn:is(input[type=checkbox],input[type=radio]):after{content:attr(aria-label)}.btn:where(input:checked:not(.filter .btn)){--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content);isolation:isolate}.btn-active{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;isolation:isolate}@supports (color:lab(0% 0 0)){.btn-active{--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.btn-primary{--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content)}.btn-secondary{--btn-color:var(--color-secondary);--btn-fg:var(--color-secondary-content)}.btn-accent{--btn-color:var(--color-accent);--btn-fg:var(--color-accent-content)}.btn-neutral{--btn-color:var(--color-neutral);--btn-fg:var(--color-neutral-content)}.btn-info{--btn-color:var(--color-info);--btn-fg:var(--color-info-content)}.btn-success{--btn-color:var(--color-success);--btn-fg:var(--color-success-content)}.btn-warning{--btn-color:var(--color-warning);--btn-fg:var(--color-warning-content)}.btn-error{--btn-color:var(--color-error);--btn-fg:var(--color-error-content)}.btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)){--btn-shadow:"";--btn-bg:transparent;--btn-border:transparent;--btn-noise:none}.btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)):not(:is(:disabled,[disabled],.btn-disabled)){--btn-fg:currentColor;outline-color:currentColor}.btn-link{--btn-border:transparent;--btn-bg:transparent;--btn-fg:var(--color-primary);--btn-noise:none;--btn-shadow:"";outline-color:currentColor;text-decoration-line:underline}.btn-link:is(.btn-active,:hover,:active:focus,:focus-visible){--btn-border:transparent;--btn-bg:transparent;text-decoration-line:underline}.btn-outline:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none}.btn-dash:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none;border-style:dashed}.btn-soft:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled)){--btn-shadow:"";--btn-fg:var(--btn-color,var(--color-base-content));--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-content))8%,var(--color-base-100));--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-content))10%,var(--color-base-100));--btn-noise:none}.btn-xs{--fontsize:.6875rem;--btn-p:.5rem;--size:calc(var(--size-field,.25rem)*6)}.btn-sm{--fontsize:.75rem;--btn-p:.75rem;--size:calc(var(--size-field,.25rem)*8)}.btn-md{--fontsize:.875rem;--btn-p:1rem;--size:calc(var(--size-field,.25rem)*10)}.btn-lg{--fontsize:1.125rem;--btn-p:1.25rem;--size:calc(var(--size-field,.25rem)*12)}.btn-xl{--fontsize:1.375rem;--btn-p:1.5rem;--size:calc(var(--size-field,.25rem)*14)}.btn-square{width:var(--size);height:var(--size);padding-inline:0}.btn-circle{width:var(--size);height:var(--size);border-radius:3.40282e38px;padding-inline:0}.btn-wide{width:100%;max-width:16rem}.btn-block{width:100%}@media (min-width:640px){:where(.btn){width:unset}.sm\:btn{cursor:pointer;text-align:center;vertical-align:middle;outline-offset:2px;-webkit-user-select:none;user-select:none;padding-inline:var(--btn-p);color:var(--btn-fg);--tw-prose-links:var(--btn-fg);height:var(--size);font-size:var(--fontsize,.875rem);outline-color:var(--btn-color,var(--color-base-content));background-color:var(--btn-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--btn-noise);border-width:var(--border);border-style:solid;border-color:var(--btn-border);text-shadow:0 .5px oklch(100% 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px oklch(100% 0 0/calc(var(--depth)*6%))inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-p:1rem;--btn-border:color-mix(in oklab,var(--btn-bg),#000 calc(var(--depth)*5%));--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent);--btn-noise:var(--fx-noise);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-wrap:nowrap;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;font-weight:600;transition-property:color,background-color,border-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:inline-flex}.prose .sm\:btn{text-decoration-line:none}@media (hover:hover){.sm\:btn:hover{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}.sm\:btn:focus-visible{outline-width:2px;outline-style:solid}.sm\:btn:active:not(.btn-active){--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 5%);--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;translate:0 .5px}@supports (color:lab(0% 0 0)){.sm\:btn:active:not(.btn-active){--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.sm\:btn:is(:disabled,[disabled],.btn-disabled){pointer-events:none;--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.sm\:btn:is(:disabled,[disabled],.btn-disabled):not(:is(.btn-link,.btn-ghost)){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);box-shadow:none}@media (hover:hover){.sm\:btn:is(:disabled,[disabled],.btn-disabled):hover{pointer-events:none;background-color:color-mix(in oklab,var(--color-neutral)20%,transparent);--btn-border:transparent;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}}.sm\:btn:is(input[type=checkbox],input[type=radio]){appearance:none}.sm\:btn:is(input[type=checkbox],input[type=radio]):after{content:attr(aria-label)}.sm\:btn:where(input:checked:not(.filter .btn)){--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content);isolation:isolate}.sm\:btn-active{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;isolation:isolate}@supports (color:lab(0% 0 0)){.sm\:btn-active{--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.sm\:btn-primary{--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content)}.sm\:btn-secondary{--btn-color:var(--color-secondary);--btn-fg:var(--color-secondary-content)}.sm\:btn-accent{--btn-color:var(--color-accent);--btn-fg:var(--color-accent-content)}.sm\:btn-neutral{--btn-color:var(--color-neutral);--btn-fg:var(--color-neutral-content)}.sm\:btn-info{--btn-color:var(--color-info);--btn-fg:var(--color-info-content)}.sm\:btn-success{--btn-color:var(--color-success);--btn-fg:var(--color-success-content)}.sm\:btn-warning{--btn-color:var(--color-warning);--btn-fg:var(--color-warning-content)}.sm\:btn-error{--btn-color:var(--color-error);--btn-fg:var(--color-error-content)}.sm\:btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)){--btn-shadow:"";--btn-bg:transparent;--btn-border:transparent;--btn-noise:none}.sm\:btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)):not(:is(:disabled,[disabled],.btn-disabled)){--btn-fg:currentColor;outline-color:currentColor}.sm\:btn-link{--btn-border:transparent;--btn-bg:transparent;--btn-fg:var(--color-primary);--btn-noise:none;--btn-shadow:"";outline-color:currentColor;text-decoration-line:underline}.sm\:btn-link:is(.btn-active,:hover,:active:focus,:focus-visible){--btn-border:transparent;--btn-bg:transparent;text-decoration-line:underline}.sm\:btn-outline:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none}.sm\:btn-dash:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none;border-style:dashed}.sm\:btn-soft:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled)){--btn-shadow:"";--btn-fg:var(--btn-color,var(--color-base-content));--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-content))8%,var(--color-base-100));--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-content))10%,var(--color-base-100));--btn-noise:none}.sm\:btn-xs{--fontsize:.6875rem;--btn-p:.5rem;--size:calc(var(--size-field,.25rem)*6)}.sm\:btn-sm{--fontsize:.75rem;--btn-p:.75rem;--size:calc(var(--size-field,.25rem)*8)}.sm\:btn-md{--fontsize:.875rem;--btn-p:1rem;--size:calc(var(--size-field,.25rem)*10)}.sm\:btn-lg{--fontsize:1.125rem;--btn-p:1.25rem;--size:calc(var(--size-field,.25rem)*12)}.sm\:btn-xl{--fontsize:1.375rem;--btn-p:1.5rem;--size:calc(var(--size-field,.25rem)*14)}.sm\:btn-square{width:var(--size);height:var(--size);padding-inline:0}.sm\:btn-circle{width:var(--size);height:var(--size);border-radius:3.40282e38px;padding-inline:0}.sm\:btn-wide{width:100%;max-width:16rem}.sm\:btn-block{width:100%}}@media (min-width:768px){:where(.btn){width:unset}.md\:btn{cursor:pointer;text-align:center;vertical-align:middle;outline-offset:2px;-webkit-user-select:none;user-select:none;padding-inline:var(--btn-p);color:var(--btn-fg);--tw-prose-links:var(--btn-fg);height:var(--size);font-size:var(--fontsize,.875rem);outline-color:var(--btn-color,var(--color-base-content));background-color:var(--btn-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--btn-noise);border-width:var(--border);border-style:solid;border-color:var(--btn-border);text-shadow:0 .5px oklch(100% 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px oklch(100% 0 0/calc(var(--depth)*6%))inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-p:1rem;--btn-border:color-mix(in oklab,var(--btn-bg),#000 calc(var(--depth)*5%));--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent);--btn-noise:var(--fx-noise);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-wrap:nowrap;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;font-weight:600;transition-property:color,background-color,border-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:inline-flex}.prose .md\:btn{text-decoration-line:none}@media (hover:hover){.md\:btn:hover{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}.md\:btn:focus-visible{outline-width:2px;outline-style:solid}.md\:btn:active:not(.btn-active){--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 5%);--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;translate:0 .5px}@supports (color:lab(0% 0 0)){.md\:btn:active:not(.btn-active){--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.md\:btn:is(:disabled,[disabled],.btn-disabled){pointer-events:none;--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.md\:btn:is(:disabled,[disabled],.btn-disabled):not(:is(.btn-link,.btn-ghost)){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);box-shadow:none}@media (hover:hover){.md\:btn:is(:disabled,[disabled],.btn-disabled):hover{pointer-events:none;background-color:color-mix(in oklab,var(--color-neutral)20%,transparent);--btn-border:transparent;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}}.md\:btn:is(input[type=checkbox],input[type=radio]){appearance:none}.md\:btn:is(input[type=checkbox],input[type=radio]):after{content:attr(aria-label)}.md\:btn:where(input:checked:not(.filter .btn)){--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content);isolation:isolate}.md\:btn-active{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;isolation:isolate}@supports (color:lab(0% 0 0)){.md\:btn-active{--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.md\:btn-primary{--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content)}.md\:btn-secondary{--btn-color:var(--color-secondary);--btn-fg:var(--color-secondary-content)}.md\:btn-accent{--btn-color:var(--color-accent);--btn-fg:var(--color-accent-content)}.md\:btn-neutral{--btn-color:var(--color-neutral);--btn-fg:var(--color-neutral-content)}.md\:btn-info{--btn-color:var(--color-info);--btn-fg:var(--color-info-content)}.md\:btn-success{--btn-color:var(--color-success);--btn-fg:var(--color-success-content)}.md\:btn-warning{--btn-color:var(--color-warning);--btn-fg:var(--color-warning-content)}.md\:btn-error{--btn-color:var(--color-error);--btn-fg:var(--color-error-content)}.md\:btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)){--btn-shadow:"";--btn-bg:transparent;--btn-border:transparent;--btn-noise:none}.md\:btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)):not(:is(:disabled,[disabled],.btn-disabled)){--btn-fg:currentColor;outline-color:currentColor}.md\:btn-link{--btn-border:transparent;--btn-bg:transparent;--btn-fg:var(--color-primary);--btn-noise:none;--btn-shadow:"";outline-color:currentColor;text-decoration-line:underline}.md\:btn-link:is(.btn-active,:hover,:active:focus,:focus-visible){--btn-border:transparent;--btn-bg:transparent;text-decoration-line:underline}.md\:btn-outline:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none}.md\:btn-dash:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none;border-style:dashed}.md\:btn-soft:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled)){--btn-shadow:"";--btn-fg:var(--btn-color,var(--color-base-content));--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-content))8%,var(--color-base-100));--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-content))10%,var(--color-base-100));--btn-noise:none}.md\:btn-xs{--fontsize:.6875rem;--btn-p:.5rem;--size:calc(var(--size-field,.25rem)*6)}.md\:btn-sm{--fontsize:.75rem;--btn-p:.75rem;--size:calc(var(--size-field,.25rem)*8)}.md\:btn-md{--fontsize:.875rem;--btn-p:1rem;--size:calc(var(--size-field,.25rem)*10)}.md\:btn-lg{--fontsize:1.125rem;--btn-p:1.25rem;--size:calc(var(--size-field,.25rem)*12)}.md\:btn-xl{--fontsize:1.375rem;--btn-p:1.5rem;--size:calc(var(--size-field,.25rem)*14)}.md\:btn-square{width:var(--size);height:var(--size);padding-inline:0}.md\:btn-circle{width:var(--size);height:var(--size);border-radius:3.40282e38px;padding-inline:0}.md\:btn-wide{width:100%;max-width:16rem}.md\:btn-block{width:100%}}@media (min-width:1024px){:where(.btn){width:unset}.lg\:btn{cursor:pointer;text-align:center;vertical-align:middle;outline-offset:2px;-webkit-user-select:none;user-select:none;padding-inline:var(--btn-p);color:var(--btn-fg);--tw-prose-links:var(--btn-fg);height:var(--size);font-size:var(--fontsize,.875rem);outline-color:var(--btn-color,var(--color-base-content));background-color:var(--btn-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--btn-noise);border-width:var(--border);border-style:solid;border-color:var(--btn-border);text-shadow:0 .5px oklch(100% 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px oklch(100% 0 0/calc(var(--depth)*6%))inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-p:1rem;--btn-border:color-mix(in oklab,var(--btn-bg),#000 calc(var(--depth)*5%));--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent);--btn-noise:var(--fx-noise);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-wrap:nowrap;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;font-weight:600;transition-property:color,background-color,border-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:inline-flex}.prose .lg\:btn{text-decoration-line:none}@media (hover:hover){.lg\:btn:hover{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}.lg\:btn:focus-visible{outline-width:2px;outline-style:solid}.lg\:btn:active:not(.btn-active){--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 5%);--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;translate:0 .5px}@supports (color:lab(0% 0 0)){.lg\:btn:active:not(.btn-active){--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.lg\:btn:is(:disabled,[disabled],.btn-disabled){pointer-events:none;--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.lg\:btn:is(:disabled,[disabled],.btn-disabled):not(:is(.btn-link,.btn-ghost)){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);box-shadow:none}@media (hover:hover){.lg\:btn:is(:disabled,[disabled],.btn-disabled):hover{pointer-events:none;background-color:color-mix(in oklab,var(--color-neutral)20%,transparent);--btn-border:transparent;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}}.lg\:btn:is(input[type=checkbox],input[type=radio]){appearance:none}.lg\:btn:is(input[type=checkbox],input[type=radio]):after{content:attr(aria-label)}.lg\:btn:where(input:checked:not(.filter .btn)){--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content);isolation:isolate}.lg\:btn-active{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;isolation:isolate}@supports (color:lab(0% 0 0)){.lg\:btn-active{--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.lg\:btn-primary{--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content)}.lg\:btn-secondary{--btn-color:var(--color-secondary);--btn-fg:var(--color-secondary-content)}.lg\:btn-accent{--btn-color:var(--color-accent);--btn-fg:var(--color-accent-content)}.lg\:btn-neutral{--btn-color:var(--color-neutral);--btn-fg:var(--color-neutral-content)}.lg\:btn-info{--btn-color:var(--color-info);--btn-fg:var(--color-info-content)}.lg\:btn-success{--btn-color:var(--color-success);--btn-fg:var(--color-success-content)}.lg\:btn-warning{--btn-color:var(--color-warning);--btn-fg:var(--color-warning-content)}.lg\:btn-error{--btn-color:var(--color-error);--btn-fg:var(--color-error-content)}.lg\:btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)){--btn-shadow:"";--btn-bg:transparent;--btn-border:transparent;--btn-noise:none}.lg\:btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)):not(:is(:disabled,[disabled],.btn-disabled)){--btn-fg:currentColor;outline-color:currentColor}.lg\:btn-link{--btn-border:transparent;--btn-bg:transparent;--btn-fg:var(--color-primary);--btn-noise:none;--btn-shadow:"";outline-color:currentColor;text-decoration-line:underline}.lg\:btn-link:is(.btn-active,:hover,:active:focus,:focus-visible){--btn-border:transparent;--btn-bg:transparent;text-decoration-line:underline}.lg\:btn-outline:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none}.lg\:btn-dash:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none;border-style:dashed}.lg\:btn-soft:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled)){--btn-shadow:"";--btn-fg:var(--btn-color,var(--color-base-content));--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-content))8%,var(--color-base-100));--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-content))10%,var(--color-base-100));--btn-noise:none}.lg\:btn-xs{--fontsize:.6875rem;--btn-p:.5rem;--size:calc(var(--size-field,.25rem)*6)}.lg\:btn-sm{--fontsize:.75rem;--btn-p:.75rem;--size:calc(var(--size-field,.25rem)*8)}.lg\:btn-md{--fontsize:.875rem;--btn-p:1rem;--size:calc(var(--size-field,.25rem)*10)}.lg\:btn-lg{--fontsize:1.125rem;--btn-p:1.25rem;--size:calc(var(--size-field,.25rem)*12)}.lg\:btn-xl{--fontsize:1.375rem;--btn-p:1.5rem;--size:calc(var(--size-field,.25rem)*14)}.lg\:btn-square{width:var(--size);height:var(--size);padding-inline:0}.lg\:btn-circle{width:var(--size);height:var(--size);border-radius:3.40282e38px;padding-inline:0}.lg\:btn-wide{width:100%;max-width:16rem}.lg\:btn-block{width:100%}}@media (min-width:1280px){:where(.btn){width:unset}.xl\:btn{cursor:pointer;text-align:center;vertical-align:middle;outline-offset:2px;-webkit-user-select:none;user-select:none;padding-inline:var(--btn-p);color:var(--btn-fg);--tw-prose-links:var(--btn-fg);height:var(--size);font-size:var(--fontsize,.875rem);outline-color:var(--btn-color,var(--color-base-content));background-color:var(--btn-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--btn-noise);border-width:var(--border);border-style:solid;border-color:var(--btn-border);text-shadow:0 .5px oklch(100% 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px oklch(100% 0 0/calc(var(--depth)*6%))inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-p:1rem;--btn-border:color-mix(in oklab,var(--btn-bg),#000 calc(var(--depth)*5%));--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent);--btn-noise:var(--fx-noise);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-wrap:nowrap;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;font-weight:600;transition-property:color,background-color,border-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:inline-flex}.prose .xl\:btn{text-decoration-line:none}@media (hover:hover){.xl\:btn:hover{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}.xl\:btn:focus-visible{outline-width:2px;outline-style:solid}.xl\:btn:active:not(.btn-active){--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 5%);--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;translate:0 .5px}@supports (color:lab(0% 0 0)){.xl\:btn:active:not(.btn-active){--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.xl\:btn:is(:disabled,[disabled],.btn-disabled){pointer-events:none;--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.xl\:btn:is(:disabled,[disabled],.btn-disabled):not(:is(.btn-link,.btn-ghost)){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);box-shadow:none}@media (hover:hover){.xl\:btn:is(:disabled,[disabled],.btn-disabled):hover{pointer-events:none;background-color:color-mix(in oklab,var(--color-neutral)20%,transparent);--btn-border:transparent;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}}.xl\:btn:is(input[type=checkbox],input[type=radio]){appearance:none}.xl\:btn:is(input[type=checkbox],input[type=radio]):after{content:attr(aria-label)}.xl\:btn:where(input:checked:not(.filter .btn)){--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content);isolation:isolate}.xl\:btn-active{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;isolation:isolate}@supports (color:lab(0% 0 0)){.xl\:btn-active{--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.xl\:btn-primary{--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content)}.xl\:btn-secondary{--btn-color:var(--color-secondary);--btn-fg:var(--color-secondary-content)}.xl\:btn-accent{--btn-color:var(--color-accent);--btn-fg:var(--color-accent-content)}.xl\:btn-neutral{--btn-color:var(--color-neutral);--btn-fg:var(--color-neutral-content)}.xl\:btn-info{--btn-color:var(--color-info);--btn-fg:var(--color-info-content)}.xl\:btn-success{--btn-color:var(--color-success);--btn-fg:var(--color-success-content)}.xl\:btn-warning{--btn-color:var(--color-warning);--btn-fg:var(--color-warning-content)}.xl\:btn-error{--btn-color:var(--color-error);--btn-fg:var(--color-error-content)}.xl\:btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)){--btn-shadow:"";--btn-bg:transparent;--btn-border:transparent;--btn-noise:none}.xl\:btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)):not(:is(:disabled,[disabled],.btn-disabled)){--btn-fg:currentColor;outline-color:currentColor}.xl\:btn-link{--btn-border:transparent;--btn-bg:transparent;--btn-fg:var(--color-primary);--btn-noise:none;--btn-shadow:"";outline-color:currentColor;text-decoration-line:underline}.xl\:btn-link:is(.btn-active,:hover,:active:focus,:focus-visible){--btn-border:transparent;--btn-bg:transparent;text-decoration-line:underline}.xl\:btn-outline:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none}.xl\:btn-dash:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none;border-style:dashed}.xl\:btn-soft:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled)){--btn-shadow:"";--btn-fg:var(--btn-color,var(--color-base-content));--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-content))8%,var(--color-base-100));--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-content))10%,var(--color-base-100));--btn-noise:none}.xl\:btn-xs{--fontsize:.6875rem;--btn-p:.5rem;--size:calc(var(--size-field,.25rem)*6)}.xl\:btn-sm{--fontsize:.75rem;--btn-p:.75rem;--size:calc(var(--size-field,.25rem)*8)}.xl\:btn-md{--fontsize:.875rem;--btn-p:1rem;--size:calc(var(--size-field,.25rem)*10)}.xl\:btn-lg{--fontsize:1.125rem;--btn-p:1.25rem;--size:calc(var(--size-field,.25rem)*12)}.xl\:btn-xl{--fontsize:1.375rem;--btn-p:1.5rem;--size:calc(var(--size-field,.25rem)*14)}.xl\:btn-square{width:var(--size);height:var(--size);padding-inline:0}.xl\:btn-circle{width:var(--size);height:var(--size);border-radius:3.40282e38px;padding-inline:0}.xl\:btn-wide{width:100%;max-width:16rem}.xl\:btn-block{width:100%}}@media (min-width:1536px){:where(.btn){width:unset}.\32 xl\:btn{cursor:pointer;text-align:center;vertical-align:middle;outline-offset:2px;-webkit-user-select:none;user-select:none;padding-inline:var(--btn-p);color:var(--btn-fg);--tw-prose-links:var(--btn-fg);height:var(--size);font-size:var(--fontsize,.875rem);outline-color:var(--btn-color,var(--color-base-content));background-color:var(--btn-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--btn-noise);border-width:var(--border);border-style:solid;border-color:var(--btn-border);text-shadow:0 .5px oklch(100% 0 0/calc(var(--depth)*.15));box-shadow:0 .5px 0 .5px oklch(100% 0 0/calc(var(--depth)*6%))inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-p:1rem;--btn-border:color-mix(in oklab,var(--btn-bg),#000 calc(var(--depth)*5%));--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),transparent);--btn-noise:var(--fx-noise);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-wrap:nowrap;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;font-weight:600;transition-property:color,background-color,border-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:inline-flex}.prose .\32 xl\:btn{text-decoration-line:none}@media (hover:hover){.\32 xl\:btn:hover{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}.\32 xl\:btn:focus-visible{outline-width:2px;outline-style:solid}.\32 xl\:btn:active:not(.btn-active){--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 5%);--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;translate:0 .5px}@supports (color:lab(0% 0 0)){.\32 xl\:btn:active:not(.btn-active){--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.\32 xl\:btn:is(:disabled,[disabled],.btn-disabled){pointer-events:none;--btn-border:transparent;--btn-noise:none;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}.\32 xl\:btn:is(:disabled,[disabled],.btn-disabled):not(:is(.btn-link,.btn-ghost)){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent);box-shadow:none}@media (hover:hover){.\32 xl\:btn:is(:disabled,[disabled],.btn-disabled):hover{pointer-events:none;background-color:color-mix(in oklab,var(--color-neutral)20%,transparent);--btn-border:transparent;--btn-fg:color-mix(in oklch,var(--color-base-content)20%,transparent)}}.\32 xl\:btn:is(input[type=checkbox],input[type=radio]){appearance:none}.\32 xl\:btn:is(input[type=checkbox],input[type=radio]):after{content:attr(aria-label)}.\32 xl\:btn:where(input:checked:not(.filter .btn)){--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content);isolation:isolate}.\32 xl\:btn-active{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%);--btn-shadow:0 0 0 0 transparent,0 0 0 0 transparent;isolation:isolate}@supports (color:lab(0% 0 0)){.\32 xl\:btn-active{--btn-shadow:0 0 0 0 lab(0% 0 0/0),0 0 0 0 lab(0% 0 0/0)}}.\32 xl\:btn-primary{--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content)}.\32 xl\:btn-secondary{--btn-color:var(--color-secondary);--btn-fg:var(--color-secondary-content)}.\32 xl\:btn-accent{--btn-color:var(--color-accent);--btn-fg:var(--color-accent-content)}.\32 xl\:btn-neutral{--btn-color:var(--color-neutral);--btn-fg:var(--color-neutral-content)}.\32 xl\:btn-info{--btn-color:var(--color-info);--btn-fg:var(--color-info-content)}.\32 xl\:btn-success{--btn-color:var(--color-success);--btn-fg:var(--color-success-content)}.\32 xl\:btn-warning{--btn-color:var(--color-warning);--btn-fg:var(--color-warning-content)}.\32 xl\:btn-error{--btn-color:var(--color-error);--btn-fg:var(--color-error-content)}.\32 xl\:btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)){--btn-shadow:"";--btn-bg:transparent;--btn-border:transparent;--btn-noise:none}.\32 xl\:btn-ghost:not(:is(.btn-active,:hover,:active:focus,:focus-visible)):not(:is(:disabled,[disabled],.btn-disabled)){--btn-fg:currentColor;outline-color:currentColor}.\32 xl\:btn-link{--btn-border:transparent;--btn-bg:transparent;--btn-fg:var(--color-primary);--btn-noise:none;--btn-shadow:"";outline-color:currentColor;text-decoration-line:underline}.\32 xl\:btn-link:is(.btn-active,:hover,:active:focus,:focus-visible){--btn-border:transparent;--btn-bg:transparent;text-decoration-line:underline}.\32 xl\:btn-outline:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none}.\32 xl\:btn-dash:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled,:checked)){--btn-shadow:"";--btn-bg:transparent;--btn-fg:var(--btn-color);--btn-border:var(--btn-color);--btn-noise:none;border-style:dashed}.\32 xl\:btn-soft:not(:is(.btn-active,:hover,:active:focus,:focus-visible,:disabled,[disabled],.btn-disabled)){--btn-shadow:"";--btn-fg:var(--btn-color,var(--color-base-content));--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-content))8%,var(--color-base-100));--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-content))10%,var(--color-base-100));--btn-noise:none}.\32 xl\:btn-xs{--fontsize:.6875rem;--btn-p:.5rem;--size:calc(var(--size-field,.25rem)*6)}.\32 xl\:btn-sm{--fontsize:.75rem;--btn-p:.75rem;--size:calc(var(--size-field,.25rem)*8)}.\32 xl\:btn-md{--fontsize:.875rem;--btn-p:1rem;--size:calc(var(--size-field,.25rem)*10)}.\32 xl\:btn-lg{--fontsize:1.125rem;--btn-p:1.25rem;--size:calc(var(--size-field,.25rem)*12)}.\32 xl\:btn-xl{--fontsize:1.375rem;--btn-p:1.5rem;--size:calc(var(--size-field,.25rem)*14)}.\32 xl\:btn-square{width:var(--size);height:var(--size);padding-inline:0}.\32 xl\:btn-circle{width:var(--size);height:var(--size);border-radius:3.40282e38px;padding-inline:0}.\32 xl\:btn-wide{width:100%;max-width:16rem}.\32 xl\:btn-block{width:100%}}.checkbox{border:var(--border)solid var(--input-color,color-mix(in oklab,var(--color-base-content)20%,transparent));cursor:pointer;appearance:none;border-radius:var(--radius-selector);vertical-align:middle;color:var(--color-base-content);box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 0 transparent inset,0 0 transparent;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);flex-shrink:0;padding:.25rem;transition:background-color .2s,box-shadow .2s;position:relative}.checkbox:before{--tw-content:"";content:var(--tw-content);opacity:0;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,70% 80%,70% 100%);width:100%;height:100%;box-shadow:0px 3px 0 0px oklch(100% 0 0/calc(var(--depth)*.1))inset;background-color:currentColor;font-size:1rem;line-height:.75;transition:clip-path .3s .1s,opacity .1s .1s,rotate .3s .1s,translate .3s .1s;display:block;rotate:45deg}.checkbox:focus-visible{outline:2px solid var(--input-color,currentColor);outline-offset:2px}.checkbox:checked{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.checkbox:checked:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.checkbox[aria-checked=true]{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.checkbox[aria-checked=true]:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.checkbox:indeterminate:before{opacity:1;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,80% 80%,80% 100%);translate:0 -35%;rotate:none}.checkbox-primary{color:var(--color-primary-content);--input-color:var(--color-primary)}.checkbox-secondary{color:var(--color-secondary-content);--input-color:var(--color-secondary)}.checkbox-accent{color:var(--color-accent-content);--input-color:var(--color-accent)}.checkbox-neutral{color:var(--color-neutral-content);--input-color:var(--color-neutral)}.checkbox-info{color:var(--color-info-content);--input-color:var(--color-info)}.checkbox-success{color:var(--color-success-content);--input-color:var(--color-success)}.checkbox-warning{color:var(--color-warning-content);--input-color:var(--color-warning)}.checkbox-error{color:var(--color-error-content);--input-color:var(--color-error)}.checkbox:disabled{cursor:not-allowed;opacity:.2}.checkbox-xs{--size:calc(var(--size-selector,.25rem)*4);padding:.125rem}.checkbox-sm{--size:calc(var(--size-selector,.25rem)*5);padding:.1875rem}.checkbox-md{--size:calc(var(--size-selector,.25rem)*6);padding:.25rem}.checkbox-lg{--size:calc(var(--size-selector,.25rem)*7);padding:.3125rem}.checkbox-xl{--size:calc(var(--size-selector,.25rem)*8);padding:.375rem}@media (min-width:640px){.sm\:checkbox{border:var(--border)solid var(--input-color,color-mix(in oklab,var(--color-base-content)20%,transparent));cursor:pointer;appearance:none;border-radius:var(--radius-selector);vertical-align:middle;color:var(--color-base-content);box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 0 transparent inset,0 0 transparent;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);flex-shrink:0;padding:.25rem;transition:background-color .2s,box-shadow .2s;position:relative}.sm\:checkbox:before{--tw-content:"";content:var(--tw-content);opacity:0;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,70% 80%,70% 100%);width:100%;height:100%;box-shadow:0px 3px 0 0px oklch(100% 0 0/calc(var(--depth)*.1))inset;background-color:currentColor;font-size:1rem;line-height:.75;transition:clip-path .3s .1s,opacity .1s .1s,rotate .3s .1s,translate .3s .1s;display:block;rotate:45deg}.sm\:checkbox:focus-visible{outline:2px solid var(--input-color,currentColor);outline-offset:2px}.sm\:checkbox:checked{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.sm\:checkbox:checked:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.sm\:checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.sm\:checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.sm\:checkbox[aria-checked=true]{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.sm\:checkbox[aria-checked=true]:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.sm\:checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.sm\:checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.sm\:checkbox:indeterminate:before{opacity:1;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,80% 80%,80% 100%);translate:0 -35%;rotate:none}.sm\:checkbox-primary{color:var(--color-primary-content);--input-color:var(--color-primary)}.sm\:checkbox-secondary{color:var(--color-secondary-content);--input-color:var(--color-secondary)}.sm\:checkbox-accent{color:var(--color-accent-content);--input-color:var(--color-accent)}.sm\:checkbox-neutral{color:var(--color-neutral-content);--input-color:var(--color-neutral)}.sm\:checkbox-info{color:var(--color-info-content);--input-color:var(--color-info)}.sm\:checkbox-success{color:var(--color-success-content);--input-color:var(--color-success)}.sm\:checkbox-warning{color:var(--color-warning-content);--input-color:var(--color-warning)}.sm\:checkbox-error{color:var(--color-error-content);--input-color:var(--color-error)}.sm\:checkbox:disabled{cursor:not-allowed;opacity:.2}.sm\:checkbox-xs{--size:calc(var(--size-selector,.25rem)*4);padding:.125rem}.sm\:checkbox-sm{--size:calc(var(--size-selector,.25rem)*5);padding:.1875rem}.sm\:checkbox-md{--size:calc(var(--size-selector,.25rem)*6);padding:.25rem}.sm\:checkbox-lg{--size:calc(var(--size-selector,.25rem)*7);padding:.3125rem}.sm\:checkbox-xl{--size:calc(var(--size-selector,.25rem)*8);padding:.375rem}}@media (min-width:768px){.md\:checkbox{border:var(--border)solid var(--input-color,color-mix(in oklab,var(--color-base-content)20%,transparent));cursor:pointer;appearance:none;border-radius:var(--radius-selector);vertical-align:middle;color:var(--color-base-content);box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 0 transparent inset,0 0 transparent;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);flex-shrink:0;padding:.25rem;transition:background-color .2s,box-shadow .2s;position:relative}.md\:checkbox:before{--tw-content:"";content:var(--tw-content);opacity:0;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,70% 80%,70% 100%);width:100%;height:100%;box-shadow:0px 3px 0 0px oklch(100% 0 0/calc(var(--depth)*.1))inset;background-color:currentColor;font-size:1rem;line-height:.75;transition:clip-path .3s .1s,opacity .1s .1s,rotate .3s .1s,translate .3s .1s;display:block;rotate:45deg}.md\:checkbox:focus-visible{outline:2px solid var(--input-color,currentColor);outline-offset:2px}.md\:checkbox:checked{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.md\:checkbox:checked:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.md\:checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.md\:checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.md\:checkbox[aria-checked=true]{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.md\:checkbox[aria-checked=true]:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.md\:checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.md\:checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.md\:checkbox:indeterminate:before{opacity:1;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,80% 80%,80% 100%);translate:0 -35%;rotate:none}.md\:checkbox-primary{color:var(--color-primary-content);--input-color:var(--color-primary)}.md\:checkbox-secondary{color:var(--color-secondary-content);--input-color:var(--color-secondary)}.md\:checkbox-accent{color:var(--color-accent-content);--input-color:var(--color-accent)}.md\:checkbox-neutral{color:var(--color-neutral-content);--input-color:var(--color-neutral)}.md\:checkbox-info{color:var(--color-info-content);--input-color:var(--color-info)}.md\:checkbox-success{color:var(--color-success-content);--input-color:var(--color-success)}.md\:checkbox-warning{color:var(--color-warning-content);--input-color:var(--color-warning)}.md\:checkbox-error{color:var(--color-error-content);--input-color:var(--color-error)}.md\:checkbox:disabled{cursor:not-allowed;opacity:.2}.md\:checkbox-xs{--size:calc(var(--size-selector,.25rem)*4);padding:.125rem}.md\:checkbox-sm{--size:calc(var(--size-selector,.25rem)*5);padding:.1875rem}.md\:checkbox-md{--size:calc(var(--size-selector,.25rem)*6);padding:.25rem}.md\:checkbox-lg{--size:calc(var(--size-selector,.25rem)*7);padding:.3125rem}.md\:checkbox-xl{--size:calc(var(--size-selector,.25rem)*8);padding:.375rem}}@media (min-width:1024px){.lg\:checkbox{border:var(--border)solid var(--input-color,color-mix(in oklab,var(--color-base-content)20%,transparent));cursor:pointer;appearance:none;border-radius:var(--radius-selector);vertical-align:middle;color:var(--color-base-content);box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 0 transparent inset,0 0 transparent;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);flex-shrink:0;padding:.25rem;transition:background-color .2s,box-shadow .2s;position:relative}.lg\:checkbox:before{--tw-content:"";content:var(--tw-content);opacity:0;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,70% 80%,70% 100%);width:100%;height:100%;box-shadow:0px 3px 0 0px oklch(100% 0 0/calc(var(--depth)*.1))inset;background-color:currentColor;font-size:1rem;line-height:.75;transition:clip-path .3s .1s,opacity .1s .1s,rotate .3s .1s,translate .3s .1s;display:block;rotate:45deg}.lg\:checkbox:focus-visible{outline:2px solid var(--input-color,currentColor);outline-offset:2px}.lg\:checkbox:checked{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.lg\:checkbox:checked:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.lg\:checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.lg\:checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.lg\:checkbox[aria-checked=true]{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.lg\:checkbox[aria-checked=true]:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.lg\:checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.lg\:checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.lg\:checkbox:indeterminate:before{opacity:1;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,80% 80%,80% 100%);translate:0 -35%;rotate:none}.lg\:checkbox-primary{color:var(--color-primary-content);--input-color:var(--color-primary)}.lg\:checkbox-secondary{color:var(--color-secondary-content);--input-color:var(--color-secondary)}.lg\:checkbox-accent{color:var(--color-accent-content);--input-color:var(--color-accent)}.lg\:checkbox-neutral{color:var(--color-neutral-content);--input-color:var(--color-neutral)}.lg\:checkbox-info{color:var(--color-info-content);--input-color:var(--color-info)}.lg\:checkbox-success{color:var(--color-success-content);--input-color:var(--color-success)}.lg\:checkbox-warning{color:var(--color-warning-content);--input-color:var(--color-warning)}.lg\:checkbox-error{color:var(--color-error-content);--input-color:var(--color-error)}.lg\:checkbox:disabled{cursor:not-allowed;opacity:.2}.lg\:checkbox-xs{--size:calc(var(--size-selector,.25rem)*4);padding:.125rem}.lg\:checkbox-sm{--size:calc(var(--size-selector,.25rem)*5);padding:.1875rem}.lg\:checkbox-md{--size:calc(var(--size-selector,.25rem)*6);padding:.25rem}.lg\:checkbox-lg{--size:calc(var(--size-selector,.25rem)*7);padding:.3125rem}.lg\:checkbox-xl{--size:calc(var(--size-selector,.25rem)*8);padding:.375rem}}@media (min-width:1280px){.xl\:checkbox{border:var(--border)solid var(--input-color,color-mix(in oklab,var(--color-base-content)20%,transparent));cursor:pointer;appearance:none;border-radius:var(--radius-selector);vertical-align:middle;color:var(--color-base-content);box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 0 transparent inset,0 0 transparent;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);flex-shrink:0;padding:.25rem;transition:background-color .2s,box-shadow .2s;position:relative}.xl\:checkbox:before{--tw-content:"";content:var(--tw-content);opacity:0;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,70% 80%,70% 100%);width:100%;height:100%;box-shadow:0px 3px 0 0px oklch(100% 0 0/calc(var(--depth)*.1))inset;background-color:currentColor;font-size:1rem;line-height:.75;transition:clip-path .3s .1s,opacity .1s .1s,rotate .3s .1s,translate .3s .1s;display:block;rotate:45deg}.xl\:checkbox:focus-visible{outline:2px solid var(--input-color,currentColor);outline-offset:2px}.xl\:checkbox:checked{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.xl\:checkbox:checked:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.xl\:checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.xl\:checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.xl\:checkbox[aria-checked=true]{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.xl\:checkbox[aria-checked=true]:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.xl\:checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.xl\:checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.xl\:checkbox:indeterminate:before{opacity:1;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,80% 80%,80% 100%);translate:0 -35%;rotate:none}.xl\:checkbox-primary{color:var(--color-primary-content);--input-color:var(--color-primary)}.xl\:checkbox-secondary{color:var(--color-secondary-content);--input-color:var(--color-secondary)}.xl\:checkbox-accent{color:var(--color-accent-content);--input-color:var(--color-accent)}.xl\:checkbox-neutral{color:var(--color-neutral-content);--input-color:var(--color-neutral)}.xl\:checkbox-info{color:var(--color-info-content);--input-color:var(--color-info)}.xl\:checkbox-success{color:var(--color-success-content);--input-color:var(--color-success)}.xl\:checkbox-warning{color:var(--color-warning-content);--input-color:var(--color-warning)}.xl\:checkbox-error{color:var(--color-error-content);--input-color:var(--color-error)}.xl\:checkbox:disabled{cursor:not-allowed;opacity:.2}.xl\:checkbox-xs{--size:calc(var(--size-selector,.25rem)*4);padding:.125rem}.xl\:checkbox-sm{--size:calc(var(--size-selector,.25rem)*5);padding:.1875rem}.xl\:checkbox-md{--size:calc(var(--size-selector,.25rem)*6);padding:.25rem}.xl\:checkbox-lg{--size:calc(var(--size-selector,.25rem)*7);padding:.3125rem}.xl\:checkbox-xl{--size:calc(var(--size-selector,.25rem)*8);padding:.375rem}}@media (min-width:1536px){.\32 xl\:checkbox{border:var(--border)solid var(--input-color,color-mix(in oklab,var(--color-base-content)20%,transparent));cursor:pointer;appearance:none;border-radius:var(--radius-selector);vertical-align:middle;color:var(--color-base-content);box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 0 transparent inset,0 0 transparent;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);flex-shrink:0;padding:.25rem;transition:background-color .2s,box-shadow .2s;position:relative}.\32 xl\:checkbox:before{--tw-content:"";content:var(--tw-content);opacity:0;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,70% 80%,70% 100%);width:100%;height:100%;box-shadow:0px 3px 0 0px oklch(100% 0 0/calc(var(--depth)*.1))inset;background-color:currentColor;font-size:1rem;line-height:.75;transition:clip-path .3s .1s,opacity .1s .1s,rotate .3s .1s,translate .3s .1s;display:block;rotate:45deg}.\32 xl\:checkbox:focus-visible{outline:2px solid var(--input-color,currentColor);outline-offset:2px}.\32 xl\:checkbox:checked{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.\32 xl\:checkbox:checked:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.\32 xl\:checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.\32 xl\:checkbox:checked:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.\32 xl\:checkbox[aria-checked=true]{background-color:var(--input-color,transparent);box-shadow:0 0 transparent inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}.\32 xl\:checkbox[aria-checked=true]:before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){.\32 xl\:checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}@media print{.\32 xl\:checkbox[aria-checked=true]:before{--tw-content:"✔︎";clip-path:none;background-color:transparent;rotate:none}}.\32 xl\:checkbox:indeterminate:before{opacity:1;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,80% 80%,80% 100%);translate:0 -35%;rotate:none}.\32 xl\:checkbox-primary{color:var(--color-primary-content);--input-color:var(--color-primary)}.\32 xl\:checkbox-secondary{color:var(--color-secondary-content);--input-color:var(--color-secondary)}.\32 xl\:checkbox-accent{color:var(--color-accent-content);--input-color:var(--color-accent)}.\32 xl\:checkbox-neutral{color:var(--color-neutral-content);--input-color:var(--color-neutral)}.\32 xl\:checkbox-info{color:var(--color-info-content);--input-color:var(--color-info)}.\32 xl\:checkbox-success{color:var(--color-success-content);--input-color:var(--color-success)}.\32 xl\:checkbox-warning{color:var(--color-warning-content);--input-color:var(--color-warning)}.\32 xl\:checkbox-error{color:var(--color-error-content);--input-color:var(--color-error)}.\32 xl\:checkbox:disabled{cursor:not-allowed;opacity:.2}.\32 xl\:checkbox-xs{--size:calc(var(--size-selector,.25rem)*4);padding:.125rem}.\32 xl\:checkbox-sm{--size:calc(var(--size-selector,.25rem)*5);padding:.1875rem}.\32 xl\:checkbox-md{--size:calc(var(--size-selector,.25rem)*6);padding:.25rem}.\32 xl\:checkbox-lg{--size:calc(var(--size-selector,.25rem)*7);padding:.3125rem}.\32 xl\:checkbox-xl{--size:calc(var(--size-selector,.25rem)*8);padding:.375rem}}.radial-progress{height:var(--size);width:var(--size);vertical-align:middle;box-sizing:content-box;--value:0;--size:5rem;--thickness:calc(var(--size)/10);--radialprogress:calc(var(--value)*1%);background-color:transparent;border-radius:3.40282e38px;place-content:center;transition:--radialprogress .3s linear;display:inline-grid;position:relative}.radial-progress:before{content:"";background:radial-gradient(farthest-side,currentColor 98%,transparent)top/var(--thickness)var(--thickness)no-repeat,conic-gradient(currentColor var(--radialprogress),transparent 0);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));border-radius:3.40282e38px;position:absolute;inset:0}.radial-progress:after{content:"";inset:calc(50% - var(--thickness)/2);transform:rotate(calc(var(--value)*3.6deg - 90deg))translate(calc(var(--size)/2 - 50%));background-color:currentColor;border-radius:3.40282e38px;transition:transform .3s linear;position:absolute}@media (min-width:640px){.sm\:radial-progress{height:var(--size);width:var(--size);vertical-align:middle;box-sizing:content-box;--value:0;--size:5rem;--thickness:calc(var(--size)/10);--radialprogress:calc(var(--value)*1%);background-color:transparent;border-radius:3.40282e38px;place-content:center;transition:--radialprogress .3s linear;display:inline-grid;position:relative}.sm\:radial-progress:before{content:"";background:radial-gradient(farthest-side,currentColor 98%,transparent)top/var(--thickness)var(--thickness)no-repeat,conic-gradient(currentColor var(--radialprogress),transparent 0);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));border-radius:3.40282e38px;position:absolute;inset:0}.sm\:radial-progress:after{content:"";inset:calc(50% - var(--thickness)/2);transform:rotate(calc(var(--value)*3.6deg - 90deg))translate(calc(var(--size)/2 - 50%));background-color:currentColor;border-radius:3.40282e38px;transition:transform .3s linear;position:absolute}}@media (min-width:768px){.md\:radial-progress{height:var(--size);width:var(--size);vertical-align:middle;box-sizing:content-box;--value:0;--size:5rem;--thickness:calc(var(--size)/10);--radialprogress:calc(var(--value)*1%);background-color:transparent;border-radius:3.40282e38px;place-content:center;transition:--radialprogress .3s linear;display:inline-grid;position:relative}.md\:radial-progress:before{content:"";background:radial-gradient(farthest-side,currentColor 98%,transparent)top/var(--thickness)var(--thickness)no-repeat,conic-gradient(currentColor var(--radialprogress),transparent 0);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));border-radius:3.40282e38px;position:absolute;inset:0}.md\:radial-progress:after{content:"";inset:calc(50% - var(--thickness)/2);transform:rotate(calc(var(--value)*3.6deg - 90deg))translate(calc(var(--size)/2 - 50%));background-color:currentColor;border-radius:3.40282e38px;transition:transform .3s linear;position:absolute}}@media (min-width:1024px){.lg\:radial-progress{height:var(--size);width:var(--size);vertical-align:middle;box-sizing:content-box;--value:0;--size:5rem;--thickness:calc(var(--size)/10);--radialprogress:calc(var(--value)*1%);background-color:transparent;border-radius:3.40282e38px;place-content:center;transition:--radialprogress .3s linear;display:inline-grid;position:relative}.lg\:radial-progress:before{content:"";background:radial-gradient(farthest-side,currentColor 98%,transparent)top/var(--thickness)var(--thickness)no-repeat,conic-gradient(currentColor var(--radialprogress),transparent 0);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));border-radius:3.40282e38px;position:absolute;inset:0}.lg\:radial-progress:after{content:"";inset:calc(50% - var(--thickness)/2);transform:rotate(calc(var(--value)*3.6deg - 90deg))translate(calc(var(--size)/2 - 50%));background-color:currentColor;border-radius:3.40282e38px;transition:transform .3s linear;position:absolute}}@media (min-width:1280px){.xl\:radial-progress{height:var(--size);width:var(--size);vertical-align:middle;box-sizing:content-box;--value:0;--size:5rem;--thickness:calc(var(--size)/10);--radialprogress:calc(var(--value)*1%);background-color:transparent;border-radius:3.40282e38px;place-content:center;transition:--radialprogress .3s linear;display:inline-grid;position:relative}.xl\:radial-progress:before{content:"";background:radial-gradient(farthest-side,currentColor 98%,transparent)top/var(--thickness)var(--thickness)no-repeat,conic-gradient(currentColor var(--radialprogress),transparent 0);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));border-radius:3.40282e38px;position:absolute;inset:0}.xl\:radial-progress:after{content:"";inset:calc(50% - var(--thickness)/2);transform:rotate(calc(var(--value)*3.6deg - 90deg))translate(calc(var(--size)/2 - 50%));background-color:currentColor;border-radius:3.40282e38px;transition:transform .3s linear;position:absolute}}@media (min-width:1536px){.\32 xl\:radial-progress{height:var(--size);width:var(--size);vertical-align:middle;box-sizing:content-box;--value:0;--size:5rem;--thickness:calc(var(--size)/10);--radialprogress:calc(var(--value)*1%);background-color:transparent;border-radius:3.40282e38px;place-content:center;transition:--radialprogress .3s linear;display:inline-grid;position:relative}.\32 xl\:radial-progress:before{content:"";background:radial-gradient(farthest-side,currentColor 98%,transparent)top/var(--thickness)var(--thickness)no-repeat,conic-gradient(currentColor var(--radialprogress),transparent 0);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));mask:radial-gradient(farthest-side,transparent calc(100% - var(--thickness)),#000 calc(100% + .5px - var(--thickness)));border-radius:3.40282e38px;position:absolute;inset:0}.\32 xl\:radial-progress:after{content:"";inset:calc(50% - var(--thickness)/2);transform:rotate(calc(var(--value)*3.6deg - 90deg))translate(calc(var(--size)/2 - 50%));background-color:currentColor;border-radius:3.40282e38px;transition:transform .3s linear;position:absolute}}.filter{flex-wrap:wrap;display:flex}.filter input[type=radio]{width:auto}.filter input{opacity:1;transition:margin .1s,opacity .3s,padding .3s,border-width .1s;overflow:hidden;scale:1}.filter input:not(:last-child){margin-inline-end:.25rem}.filter input.filter-reset{aspect-ratio:1}.filter input.filter-reset:after{content:"×"}.filter:not(:has(input:checked:not(.filter-reset))) .filter-reset{opacity:0;border-width:0;width:0;margin-inline:0;padding-inline:0;scale:0}.filter:not(:has(input:checked:not(.filter-reset))) input[type=reset]{opacity:0;border-width:0;width:0;margin-inline:0;padding-inline:0;scale:0}.filter:has(input:checked:not(.filter-reset)) input:not(:is(:checked,.filter-reset,input[type=reset])){opacity:0;border-width:0;width:0;margin-inline:0;padding-inline:0;scale:0}.steps{counter-reset:step;grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.steps .step{text-align:center;--step-bg:var(--color-base-300);--step-fg:var(--color-base-content);grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.steps .step:before{width:100%;height:.5rem;color:var(--step-bg);background-color:var(--step-bg);--tw-content:"";content:var(--tw-content);border:1px solid;grid-row-start:1;grid-column-start:1;margin-inline-start:-100%;top:0}.steps .step>.step-icon{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.steps .step:not(:has(.step-icon)):after{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.steps .step:first-child:before{content:none}.steps .step[data-content]:after{content:attr(data-content)}.steps .step-neutral+.step-neutral:before{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.steps .step-neutral:after{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.steps .step-neutral>.step-icon{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.steps .step-primary+.step-primary:before{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.steps .step-primary:after{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.steps .step-primary>.step-icon{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.steps .step-secondary+.step-secondary:before{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.steps .step-secondary:after{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.steps .step-secondary>.step-icon{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.steps .step-accent+.step-accent:before{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.steps .step-accent:after{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.steps .step-accent>.step-icon{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.steps .step-info+.step-info:before{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.steps .step-info:after{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.steps .step-info>.step-icon{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.steps .step-success+.step-success:before{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.steps .step-success:after{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.steps .step-success>.step-icon{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.steps .step-warning+.step-warning:before{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.steps .step-warning:after{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.steps .step-warning>.step-icon{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.steps .step-error+.step-error:before{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.steps .step-error:after{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.steps .step-error>.step-icon{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.steps-horizontal{grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.steps-horizontal .step{text-align:center;grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.steps-horizontal .step:before{content:"";width:100%;height:.5rem;margin-inline-start:-100%;translate:0}[dir=rtl] :is(.steps-horizontal .step):before{translate:0}.steps-vertical{grid-auto-rows:1fr;grid-auto-flow:row}.steps-vertical .step{grid-template-rows:auto;grid-template-columns:40px 1fr;justify-items:start;gap:.5rem;min-height:4rem;display:grid}.steps-vertical .step:before{width:.5rem;height:100%;margin-inline-start:50%;translate:-50% -50%}[dir=rtl] :is(.steps-vertical .step):before{translate:50% -50%}@media (min-width:640px){.sm\:steps{counter-reset:step;grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.sm\:steps .step{text-align:center;--step-bg:var(--color-base-300);--step-fg:var(--color-base-content);grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.sm\:steps .step:before{width:100%;height:.5rem;color:var(--step-bg);background-color:var(--step-bg);--tw-content:"";content:var(--tw-content);border:1px solid;grid-row-start:1;grid-column-start:1;margin-inline-start:-100%;top:0}.sm\:steps .step>.step-icon{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.sm\:steps .step:not(:has(.step-icon)):after{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.sm\:steps .step:first-child:before{content:none}.sm\:steps .step[data-content]:after{content:attr(data-content)}.sm\:steps .step-neutral+.step-neutral:before{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.sm\:steps .step-neutral:after{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.sm\:steps .step-neutral>.step-icon{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.sm\:steps .step-primary+.step-primary:before{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.sm\:steps .step-primary:after{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.sm\:steps .step-primary>.step-icon{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.sm\:steps .step-secondary+.step-secondary:before{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.sm\:steps .step-secondary:after{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.sm\:steps .step-secondary>.step-icon{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.sm\:steps .step-accent+.step-accent:before{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.sm\:steps .step-accent:after{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.sm\:steps .step-accent>.step-icon{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.sm\:steps .step-info+.step-info:before{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.sm\:steps .step-info:after{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.sm\:steps .step-info>.step-icon{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.sm\:steps .step-success+.step-success:before{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.sm\:steps .step-success:after{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.sm\:steps .step-success>.step-icon{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.sm\:steps .step-warning+.step-warning:before{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.sm\:steps .step-warning:after{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.sm\:steps .step-warning>.step-icon{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.sm\:steps .step-error+.step-error:before{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.sm\:steps .step-error:after{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.sm\:steps .step-error>.step-icon{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.sm\:steps-horizontal{grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.sm\:steps-horizontal .step{text-align:center;grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.sm\:steps-horizontal .step:before{content:"";width:100%;height:.5rem;margin-inline-start:-100%;translate:0}[dir=rtl] :is(.sm\:steps-horizontal .step):before{translate:0}.sm\:steps-vertical{grid-auto-rows:1fr;grid-auto-flow:row}.sm\:steps-vertical .step{grid-template-rows:auto;grid-template-columns:40px 1fr;justify-items:start;gap:.5rem;min-height:4rem;display:grid}.sm\:steps-vertical .step:before{width:.5rem;height:100%;margin-inline-start:50%;translate:-50% -50%}[dir=rtl] :is(.sm\:steps-vertical .step):before{translate:50% -50%}}@media (min-width:768px){.md\:steps{counter-reset:step;grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.md\:steps .step{text-align:center;--step-bg:var(--color-base-300);--step-fg:var(--color-base-content);grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.md\:steps .step:before{width:100%;height:.5rem;color:var(--step-bg);background-color:var(--step-bg);--tw-content:"";content:var(--tw-content);border:1px solid;grid-row-start:1;grid-column-start:1;margin-inline-start:-100%;top:0}.md\:steps .step>.step-icon{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.md\:steps .step:not(:has(.step-icon)):after{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.md\:steps .step:first-child:before{content:none}.md\:steps .step[data-content]:after{content:attr(data-content)}.md\:steps .step-neutral+.step-neutral:before{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.md\:steps .step-neutral:after{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.md\:steps .step-neutral>.step-icon{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.md\:steps .step-primary+.step-primary:before{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.md\:steps .step-primary:after{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.md\:steps .step-primary>.step-icon{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.md\:steps .step-secondary+.step-secondary:before{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.md\:steps .step-secondary:after{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.md\:steps .step-secondary>.step-icon{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.md\:steps .step-accent+.step-accent:before{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.md\:steps .step-accent:after{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.md\:steps .step-accent>.step-icon{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.md\:steps .step-info+.step-info:before{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.md\:steps .step-info:after{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.md\:steps .step-info>.step-icon{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.md\:steps .step-success+.step-success:before{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.md\:steps .step-success:after{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.md\:steps .step-success>.step-icon{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.md\:steps .step-warning+.step-warning:before{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.md\:steps .step-warning:after{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.md\:steps .step-warning>.step-icon{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.md\:steps .step-error+.step-error:before{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.md\:steps .step-error:after{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.md\:steps .step-error>.step-icon{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.md\:steps-horizontal{grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.md\:steps-horizontal .step{text-align:center;grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.md\:steps-horizontal .step:before{content:"";width:100%;height:.5rem;margin-inline-start:-100%;translate:0}[dir=rtl] :is(.md\:steps-horizontal .step):before{translate:0}.md\:steps-vertical{grid-auto-rows:1fr;grid-auto-flow:row}.md\:steps-vertical .step{grid-template-rows:auto;grid-template-columns:40px 1fr;justify-items:start;gap:.5rem;min-height:4rem;display:grid}.md\:steps-vertical .step:before{width:.5rem;height:100%;margin-inline-start:50%;translate:-50% -50%}[dir=rtl] :is(.md\:steps-vertical .step):before{translate:50% -50%}}@media (min-width:1024px){.lg\:steps{counter-reset:step;grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.lg\:steps .step{text-align:center;--step-bg:var(--color-base-300);--step-fg:var(--color-base-content);grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.lg\:steps .step:before{width:100%;height:.5rem;color:var(--step-bg);background-color:var(--step-bg);--tw-content:"";content:var(--tw-content);border:1px solid;grid-row-start:1;grid-column-start:1;margin-inline-start:-100%;top:0}.lg\:steps .step>.step-icon{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.lg\:steps .step:not(:has(.step-icon)):after{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.lg\:steps .step:first-child:before{content:none}.lg\:steps .step[data-content]:after{content:attr(data-content)}.lg\:steps .step-neutral+.step-neutral:before{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.lg\:steps .step-neutral:after{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.lg\:steps .step-neutral>.step-icon{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.lg\:steps .step-primary+.step-primary:before{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.lg\:steps .step-primary:after{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.lg\:steps .step-primary>.step-icon{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.lg\:steps .step-secondary+.step-secondary:before{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.lg\:steps .step-secondary:after{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.lg\:steps .step-secondary>.step-icon{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.lg\:steps .step-accent+.step-accent:before{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.lg\:steps .step-accent:after{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.lg\:steps .step-accent>.step-icon{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.lg\:steps .step-info+.step-info:before{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.lg\:steps .step-info:after{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.lg\:steps .step-info>.step-icon{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.lg\:steps .step-success+.step-success:before{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.lg\:steps .step-success:after{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.lg\:steps .step-success>.step-icon{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.lg\:steps .step-warning+.step-warning:before{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.lg\:steps .step-warning:after{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.lg\:steps .step-warning>.step-icon{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.lg\:steps .step-error+.step-error:before{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.lg\:steps .step-error:after{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.lg\:steps .step-error>.step-icon{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.lg\:steps-horizontal{grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.lg\:steps-horizontal .step{text-align:center;grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.lg\:steps-horizontal .step:before{content:"";width:100%;height:.5rem;margin-inline-start:-100%;translate:0}[dir=rtl] :is(.lg\:steps-horizontal .step):before{translate:0}.lg\:steps-vertical{grid-auto-rows:1fr;grid-auto-flow:row}.lg\:steps-vertical .step{grid-template-rows:auto;grid-template-columns:40px 1fr;justify-items:start;gap:.5rem;min-height:4rem;display:grid}.lg\:steps-vertical .step:before{width:.5rem;height:100%;margin-inline-start:50%;translate:-50% -50%}[dir=rtl] :is(.lg\:steps-vertical .step):before{translate:50% -50%}}@media (min-width:1280px){.xl\:steps{counter-reset:step;grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.xl\:steps .step{text-align:center;--step-bg:var(--color-base-300);--step-fg:var(--color-base-content);grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.xl\:steps .step:before{width:100%;height:.5rem;color:var(--step-bg);background-color:var(--step-bg);--tw-content:"";content:var(--tw-content);border:1px solid;grid-row-start:1;grid-column-start:1;margin-inline-start:-100%;top:0}.xl\:steps .step>.step-icon{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.xl\:steps .step:not(:has(.step-icon)):after{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.xl\:steps .step:first-child:before{content:none}.xl\:steps .step[data-content]:after{content:attr(data-content)}.xl\:steps .step-neutral+.step-neutral:before{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.xl\:steps .step-neutral:after{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.xl\:steps .step-neutral>.step-icon{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.xl\:steps .step-primary+.step-primary:before{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.xl\:steps .step-primary:after{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.xl\:steps .step-primary>.step-icon{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.xl\:steps .step-secondary+.step-secondary:before{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.xl\:steps .step-secondary:after{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.xl\:steps .step-secondary>.step-icon{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.xl\:steps .step-accent+.step-accent:before{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.xl\:steps .step-accent:after{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.xl\:steps .step-accent>.step-icon{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.xl\:steps .step-info+.step-info:before{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.xl\:steps .step-info:after{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.xl\:steps .step-info>.step-icon{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.xl\:steps .step-success+.step-success:before{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.xl\:steps .step-success:after{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.xl\:steps .step-success>.step-icon{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.xl\:steps .step-warning+.step-warning:before{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.xl\:steps .step-warning:after{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.xl\:steps .step-warning>.step-icon{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.xl\:steps .step-error+.step-error:before{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.xl\:steps .step-error:after{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.xl\:steps .step-error>.step-icon{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.xl\:steps-horizontal{grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.xl\:steps-horizontal .step{text-align:center;grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.xl\:steps-horizontal .step:before{content:"";width:100%;height:.5rem;margin-inline-start:-100%;translate:0}[dir=rtl] :is(.xl\:steps-horizontal .step):before{translate:0}.xl\:steps-vertical{grid-auto-rows:1fr;grid-auto-flow:row}.xl\:steps-vertical .step{grid-template-rows:auto;grid-template-columns:40px 1fr;justify-items:start;gap:.5rem;min-height:4rem;display:grid}.xl\:steps-vertical .step:before{width:.5rem;height:100%;margin-inline-start:50%;translate:-50% -50%}[dir=rtl] :is(.xl\:steps-vertical .step):before{translate:50% -50%}}@media (min-width:1536px){.\32 xl\:steps{counter-reset:step;grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.\32 xl\:steps .step{text-align:center;--step-bg:var(--color-base-300);--step-fg:var(--color-base-content);grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.\32 xl\:steps .step:before{width:100%;height:.5rem;color:var(--step-bg);background-color:var(--step-bg);--tw-content:"";content:var(--tw-content);border:1px solid;grid-row-start:1;grid-column-start:1;margin-inline-start:-100%;top:0}.\32 xl\:steps .step>.step-icon{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.\32 xl\:steps .step:not(:has(.step-icon)):after{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.\32 xl\:steps .step:first-child:before{content:none}.\32 xl\:steps .step[data-content]:after{content:attr(data-content)}.\32 xl\:steps .step-neutral+.step-neutral:before{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.\32 xl\:steps .step-neutral:after{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.\32 xl\:steps .step-neutral>.step-icon{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.\32 xl\:steps .step-primary+.step-primary:before{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.\32 xl\:steps .step-primary:after{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.\32 xl\:steps .step-primary>.step-icon{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.\32 xl\:steps .step-secondary+.step-secondary:before{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.\32 xl\:steps .step-secondary:after{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.\32 xl\:steps .step-secondary>.step-icon{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.\32 xl\:steps .step-accent+.step-accent:before{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.\32 xl\:steps .step-accent:after{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.\32 xl\:steps .step-accent>.step-icon{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.\32 xl\:steps .step-info+.step-info:before{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.\32 xl\:steps .step-info:after{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.\32 xl\:steps .step-info>.step-icon{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.\32 xl\:steps .step-success+.step-success:before{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.\32 xl\:steps .step-success:after{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.\32 xl\:steps .step-success>.step-icon{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.\32 xl\:steps .step-warning+.step-warning:before{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.\32 xl\:steps .step-warning:after{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.\32 xl\:steps .step-warning>.step-icon{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.\32 xl\:steps .step-error+.step-error:before{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.\32 xl\:steps .step-error:after{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.\32 xl\:steps .step-error>.step-icon{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.\32 xl\:steps-horizontal{grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.\32 xl\:steps-horizontal .step{text-align:center;grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.\32 xl\:steps-horizontal .step:before{content:"";width:100%;height:.5rem;margin-inline-start:-100%;translate:0}[dir=rtl] :is(.\32 xl\:steps-horizontal .step):before{translate:0}.\32 xl\:steps-vertical{grid-auto-rows:1fr;grid-auto-flow:row}.\32 xl\:steps-vertical .step{grid-template-rows:auto;grid-template-columns:40px 1fr;justify-items:start;gap:.5rem;min-height:4rem;display:grid}.\32 xl\:steps-vertical .step:before{width:.5rem;height:100%;margin-inline-start:50%;translate:-50% -50%}[dir=rtl] :is(.\32 xl\:steps-vertical .step):before{translate:50% -50%}}.radio{cursor:pointer;appearance:none;vertical-align:middle;border:var(--border)solid var(--input-color,color-mix(in srgb,currentColor 20%,transparent));box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);color:var(--input-color,currentColor);border-radius:3.40282e38px;flex-shrink:0;padding:.25rem;position:relative}.radio:before{--tw-content:"";content:var(--tw-content);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);border-radius:3.40282e38px;width:100%;height:100%;display:block}.radio:focus-visible{outline:2px solid}.radio:checked{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.radio:checked:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.radio:checked:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.radio:checked:before{outline-offset:-1rem;outline:.25rem solid}}.radio[aria-checked=true]{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.radio[aria-checked=true]:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.radio[aria-checked=true]:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.radio[aria-checked=true]:before{outline-offset:-1rem;outline:.25rem solid}}.radio-primary{--input-color:var(--color-primary)}.radio-secondary{--input-color:var(--color-secondary)}.radio-accent{--input-color:var(--color-accent)}.radio-neutral{--input-color:var(--color-neutral)}.radio-info{--input-color:var(--color-info)}.radio-success{--input-color:var(--color-success)}.radio-warning{--input-color:var(--color-warning)}.radio-error{--input-color:var(--color-error)}.radio:disabled{cursor:not-allowed;opacity:.2}.radio-xs{padding:.125rem}.radio-xs[type=radio]{--size:calc(var(--size-selector,.25rem)*4)}.radio-sm{padding:.1875rem}.radio-sm[type=radio]{--size:calc(var(--size-selector,.25rem)*5)}.radio-md{padding:.25rem}.radio-md[type=radio]{--size:calc(var(--size-selector,.25rem)*6)}.radio-lg{padding:.3125rem}.radio-lg[type=radio]{--size:calc(var(--size-selector,.25rem)*7)}.radio-xl{padding:.375rem}.radio-xl[type=radio]{--size:calc(var(--size-selector,.25rem)*8)}@keyframes radio{0%{padding:5px}50%{padding:3px}}@media (min-width:640px){.sm\:radio{cursor:pointer;appearance:none;vertical-align:middle;border:var(--border)solid var(--input-color,color-mix(in srgb,currentColor 20%,transparent));box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);color:var(--input-color,currentColor);border-radius:3.40282e38px;flex-shrink:0;padding:.25rem;position:relative}.sm\:radio:before{--tw-content:"";content:var(--tw-content);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);border-radius:3.40282e38px;width:100%;height:100%;display:block}.sm\:radio:focus-visible{outline:2px solid}.sm\:radio:checked{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.sm\:radio:checked:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.sm\:radio:checked:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.sm\:radio:checked:before{outline-offset:-1rem;outline:.25rem solid}}.sm\:radio[aria-checked=true]{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.sm\:radio[aria-checked=true]:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.sm\:radio[aria-checked=true]:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.sm\:radio[aria-checked=true]:before{outline-offset:-1rem;outline:.25rem solid}}.sm\:radio-primary{--input-color:var(--color-primary)}.sm\:radio-secondary{--input-color:var(--color-secondary)}.sm\:radio-accent{--input-color:var(--color-accent)}.sm\:radio-neutral{--input-color:var(--color-neutral)}.sm\:radio-info{--input-color:var(--color-info)}.sm\:radio-success{--input-color:var(--color-success)}.sm\:radio-warning{--input-color:var(--color-warning)}.sm\:radio-error{--input-color:var(--color-error)}.sm\:radio:disabled{cursor:not-allowed;opacity:.2}.sm\:radio-xs{padding:.125rem}.sm\:radio-xs[type=radio]{--size:calc(var(--size-selector,.25rem)*4)}.sm\:radio-sm{padding:.1875rem}.sm\:radio-sm[type=radio]{--size:calc(var(--size-selector,.25rem)*5)}.sm\:radio-md{padding:.25rem}.sm\:radio-md[type=radio]{--size:calc(var(--size-selector,.25rem)*6)}.sm\:radio-lg{padding:.3125rem}.sm\:radio-lg[type=radio]{--size:calc(var(--size-selector,.25rem)*7)}.sm\:radio-xl{padding:.375rem}.sm\:radio-xl[type=radio]{--size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:768px){.md\:radio{cursor:pointer;appearance:none;vertical-align:middle;border:var(--border)solid var(--input-color,color-mix(in srgb,currentColor 20%,transparent));box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);color:var(--input-color,currentColor);border-radius:3.40282e38px;flex-shrink:0;padding:.25rem;position:relative}.md\:radio:before{--tw-content:"";content:var(--tw-content);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);border-radius:3.40282e38px;width:100%;height:100%;display:block}.md\:radio:focus-visible{outline:2px solid}.md\:radio:checked{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.md\:radio:checked:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.md\:radio:checked:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.md\:radio:checked:before{outline-offset:-1rem;outline:.25rem solid}}.md\:radio[aria-checked=true]{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.md\:radio[aria-checked=true]:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.md\:radio[aria-checked=true]:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.md\:radio[aria-checked=true]:before{outline-offset:-1rem;outline:.25rem solid}}.md\:radio-primary{--input-color:var(--color-primary)}.md\:radio-secondary{--input-color:var(--color-secondary)}.md\:radio-accent{--input-color:var(--color-accent)}.md\:radio-neutral{--input-color:var(--color-neutral)}.md\:radio-info{--input-color:var(--color-info)}.md\:radio-success{--input-color:var(--color-success)}.md\:radio-warning{--input-color:var(--color-warning)}.md\:radio-error{--input-color:var(--color-error)}.md\:radio:disabled{cursor:not-allowed;opacity:.2}.md\:radio-xs{padding:.125rem}.md\:radio-xs[type=radio]{--size:calc(var(--size-selector,.25rem)*4)}.md\:radio-sm{padding:.1875rem}.md\:radio-sm[type=radio]{--size:calc(var(--size-selector,.25rem)*5)}.md\:radio-md{padding:.25rem}.md\:radio-md[type=radio]{--size:calc(var(--size-selector,.25rem)*6)}.md\:radio-lg{padding:.3125rem}.md\:radio-lg[type=radio]{--size:calc(var(--size-selector,.25rem)*7)}.md\:radio-xl{padding:.375rem}.md\:radio-xl[type=radio]{--size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:1024px){.lg\:radio{cursor:pointer;appearance:none;vertical-align:middle;border:var(--border)solid var(--input-color,color-mix(in srgb,currentColor 20%,transparent));box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);color:var(--input-color,currentColor);border-radius:3.40282e38px;flex-shrink:0;padding:.25rem;position:relative}.lg\:radio:before{--tw-content:"";content:var(--tw-content);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);border-radius:3.40282e38px;width:100%;height:100%;display:block}.lg\:radio:focus-visible{outline:2px solid}.lg\:radio:checked{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.lg\:radio:checked:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.lg\:radio:checked:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.lg\:radio:checked:before{outline-offset:-1rem;outline:.25rem solid}}.lg\:radio[aria-checked=true]{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.lg\:radio[aria-checked=true]:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.lg\:radio[aria-checked=true]:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.lg\:radio[aria-checked=true]:before{outline-offset:-1rem;outline:.25rem solid}}.lg\:radio-primary{--input-color:var(--color-primary)}.lg\:radio-secondary{--input-color:var(--color-secondary)}.lg\:radio-accent{--input-color:var(--color-accent)}.lg\:radio-neutral{--input-color:var(--color-neutral)}.lg\:radio-info{--input-color:var(--color-info)}.lg\:radio-success{--input-color:var(--color-success)}.lg\:radio-warning{--input-color:var(--color-warning)}.lg\:radio-error{--input-color:var(--color-error)}.lg\:radio:disabled{cursor:not-allowed;opacity:.2}.lg\:radio-xs{padding:.125rem}.lg\:radio-xs[type=radio]{--size:calc(var(--size-selector,.25rem)*4)}.lg\:radio-sm{padding:.1875rem}.lg\:radio-sm[type=radio]{--size:calc(var(--size-selector,.25rem)*5)}.lg\:radio-md{padding:.25rem}.lg\:radio-md[type=radio]{--size:calc(var(--size-selector,.25rem)*6)}.lg\:radio-lg{padding:.3125rem}.lg\:radio-lg[type=radio]{--size:calc(var(--size-selector,.25rem)*7)}.lg\:radio-xl{padding:.375rem}.lg\:radio-xl[type=radio]{--size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:1280px){.xl\:radio{cursor:pointer;appearance:none;vertical-align:middle;border:var(--border)solid var(--input-color,color-mix(in srgb,currentColor 20%,transparent));box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);color:var(--input-color,currentColor);border-radius:3.40282e38px;flex-shrink:0;padding:.25rem;position:relative}.xl\:radio:before{--tw-content:"";content:var(--tw-content);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);border-radius:3.40282e38px;width:100%;height:100%;display:block}.xl\:radio:focus-visible{outline:2px solid}.xl\:radio:checked{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.xl\:radio:checked:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.xl\:radio:checked:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.xl\:radio:checked:before{outline-offset:-1rem;outline:.25rem solid}}.xl\:radio[aria-checked=true]{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.xl\:radio[aria-checked=true]:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.xl\:radio[aria-checked=true]:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.xl\:radio[aria-checked=true]:before{outline-offset:-1rem;outline:.25rem solid}}.xl\:radio-primary{--input-color:var(--color-primary)}.xl\:radio-secondary{--input-color:var(--color-secondary)}.xl\:radio-accent{--input-color:var(--color-accent)}.xl\:radio-neutral{--input-color:var(--color-neutral)}.xl\:radio-info{--input-color:var(--color-info)}.xl\:radio-success{--input-color:var(--color-success)}.xl\:radio-warning{--input-color:var(--color-warning)}.xl\:radio-error{--input-color:var(--color-error)}.xl\:radio:disabled{cursor:not-allowed;opacity:.2}.xl\:radio-xs{padding:.125rem}.xl\:radio-xs[type=radio]{--size:calc(var(--size-selector,.25rem)*4)}.xl\:radio-sm{padding:.1875rem}.xl\:radio-sm[type=radio]{--size:calc(var(--size-selector,.25rem)*5)}.xl\:radio-md{padding:.25rem}.xl\:radio-md[type=radio]{--size:calc(var(--size-selector,.25rem)*6)}.xl\:radio-lg{padding:.3125rem}.xl\:radio-lg[type=radio]{--size:calc(var(--size-selector,.25rem)*7)}.xl\:radio-xl{padding:.375rem}.xl\:radio-xl[type=radio]{--size:calc(var(--size-selector,.25rem)*8)}}@media (min-width:1536px){.\32 xl\:radio{cursor:pointer;appearance:none;vertical-align:middle;border:var(--border)solid var(--input-color,color-mix(in srgb,currentColor 20%,transparent));box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1))inset;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);color:var(--input-color,currentColor);border-radius:3.40282e38px;flex-shrink:0;padding:.25rem;position:relative}.\32 xl\:radio:before{--tw-content:"";content:var(--tw-content);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);border-radius:3.40282e38px;width:100%;height:100%;display:block}.\32 xl\:radio:focus-visible{outline:2px solid}.\32 xl\:radio:checked{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.\32 xl\:radio:checked:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.\32 xl\:radio:checked:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.\32 xl\:radio:checked:before{outline-offset:-1rem;outline:.25rem solid}}.\32 xl\:radio[aria-checked=true]{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}.\32 xl\:radio[aria-checked=true]:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1))inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1))inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){.\32 xl\:radio[aria-checked=true]:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px*-1);outline-width:1px}}@media print{.\32 xl\:radio[aria-checked=true]:before{outline-offset:-1rem;outline:.25rem solid}}.\32 xl\:radio-primary{--input-color:var(--color-primary)}.\32 xl\:radio-secondary{--input-color:var(--color-secondary)}.\32 xl\:radio-accent{--input-color:var(--color-accent)}.\32 xl\:radio-neutral{--input-color:var(--color-neutral)}.\32 xl\:radio-info{--input-color:var(--color-info)}.\32 xl\:radio-success{--input-color:var(--color-success)}.\32 xl\:radio-warning{--input-color:var(--color-warning)}.\32 xl\:radio-error{--input-color:var(--color-error)}.\32 xl\:radio:disabled{cursor:not-allowed;opacity:.2}.\32 xl\:radio-xs{padding:.125rem}.\32 xl\:radio-xs[type=radio]{--size:calc(var(--size-selector,.25rem)*4)}.\32 xl\:radio-sm{padding:.1875rem}.\32 xl\:radio-sm[type=radio]{--size:calc(var(--size-selector,.25rem)*5)}.\32 xl\:radio-md{padding:.25rem}.\32 xl\:radio-md[type=radio]{--size:calc(var(--size-selector,.25rem)*6)}.\32 xl\:radio-lg{padding:.3125rem}.\32 xl\:radio-lg[type=radio]{--size:calc(var(--size-selector,.25rem)*7)}.\32 xl\:radio-xl{padding:.375rem}.\32 xl\:radio-xl[type=radio]{--size:calc(var(--size-selector,.25rem)*8)}}.footer{grid-auto-flow:row;place-items:start;gap:2.5rem 1rem;width:100%;font-size:.875rem;line-height:1.25rem;display:grid}.footer>*{place-items:start;gap:.5rem;display:grid}.footer.footer-center{text-align:center;grid-auto-flow:column dense;place-items:center}.footer.footer-center>*{place-items:center}.footer-title{text-transform:uppercase;opacity:.6;margin-bottom:.5rem;font-weight:600}.footer-horizontal{grid-auto-flow:column}.footer-horizontal.footer-center{grid-auto-flow:dense}.footer-vertical{grid-auto-flow:row}.footer-vertical.footer-center{grid-auto-flow:column dense}@media (min-width:640px){.sm\:footer{grid-auto-flow:row;place-items:start;gap:2.5rem 1rem;width:100%;font-size:.875rem;line-height:1.25rem;display:grid}.sm\:footer>*{place-items:start;gap:.5rem;display:grid}.sm\:footer.footer-center{text-align:center;grid-auto-flow:column dense;place-items:center}.sm\:footer.footer-center>*{place-items:center}.sm\:footer-title{text-transform:uppercase;opacity:.6;margin-bottom:.5rem;font-weight:600}.sm\:footer-horizontal{grid-auto-flow:column}.sm\:footer-horizontal.footer-center{grid-auto-flow:dense}.sm\:footer-vertical{grid-auto-flow:row}.sm\:footer-vertical.footer-center{grid-auto-flow:column dense}}@media (min-width:768px){.md\:footer{grid-auto-flow:row;place-items:start;gap:2.5rem 1rem;width:100%;font-size:.875rem;line-height:1.25rem;display:grid}.md\:footer>*{place-items:start;gap:.5rem;display:grid}.md\:footer.footer-center{text-align:center;grid-auto-flow:column dense;place-items:center}.md\:footer.footer-center>*{place-items:center}.md\:footer-title{text-transform:uppercase;opacity:.6;margin-bottom:.5rem;font-weight:600}.md\:footer-horizontal{grid-auto-flow:column}.md\:footer-horizontal.footer-center{grid-auto-flow:dense}.md\:footer-vertical{grid-auto-flow:row}.md\:footer-vertical.footer-center{grid-auto-flow:column dense}}@media (min-width:1024px){.lg\:footer{grid-auto-flow:row;place-items:start;gap:2.5rem 1rem;width:100%;font-size:.875rem;line-height:1.25rem;display:grid}.lg\:footer>*{place-items:start;gap:.5rem;display:grid}.lg\:footer.footer-center{text-align:center;grid-auto-flow:column dense;place-items:center}.lg\:footer.footer-center>*{place-items:center}.lg\:footer-title{text-transform:uppercase;opacity:.6;margin-bottom:.5rem;font-weight:600}.lg\:footer-horizontal{grid-auto-flow:column}.lg\:footer-horizontal.footer-center{grid-auto-flow:dense}.lg\:footer-vertical{grid-auto-flow:row}.lg\:footer-vertical.footer-center{grid-auto-flow:column dense}}@media (min-width:1280px){.xl\:footer{grid-auto-flow:row;place-items:start;gap:2.5rem 1rem;width:100%;font-size:.875rem;line-height:1.25rem;display:grid}.xl\:footer>*{place-items:start;gap:.5rem;display:grid}.xl\:footer.footer-center{text-align:center;grid-auto-flow:column dense;place-items:center}.xl\:footer.footer-center>*{place-items:center}.xl\:footer-title{text-transform:uppercase;opacity:.6;margin-bottom:.5rem;font-weight:600}.xl\:footer-horizontal{grid-auto-flow:column}.xl\:footer-horizontal.footer-center{grid-auto-flow:dense}.xl\:footer-vertical{grid-auto-flow:row}.xl\:footer-vertical.footer-center{grid-auto-flow:column dense}}@media (min-width:1536px){.\32 xl\:footer{grid-auto-flow:row;place-items:start;gap:2.5rem 1rem;width:100%;font-size:.875rem;line-height:1.25rem;display:grid}.\32 xl\:footer>*{place-items:start;gap:.5rem;display:grid}.\32 xl\:footer.footer-center{text-align:center;grid-auto-flow:column dense;place-items:center}.\32 xl\:footer.footer-center>*{place-items:center}.\32 xl\:footer-title{text-transform:uppercase;opacity:.6;margin-bottom:.5rem;font-weight:600}.\32 xl\:footer-horizontal{grid-auto-flow:column}.\32 xl\:footer-horizontal.footer-center{grid-auto-flow:dense}.\32 xl\:footer-vertical{grid-auto-flow:row}.\32 xl\:footer-vertical.footer-center{grid-auto-flow:column dense}}.loading{pointer-events:none;aspect-ratio:1;vertical-align:middle;width:calc(var(--size-selector,.25rem)*6);background-color:currentColor;display:inline-block;-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");-webkit-mask-position:50%;mask-position:50%;-webkit-mask-size:100%;mask-size:100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.loading-spinner{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E")}.loading-dots{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='4' cy='12' r='3'%3E%3Canimate attributeName='cy' values='12;6;12;12' keyTimes='0;0.286;0.571;1' dur='1.05s' repeatCount='indefinite' keySplines='.33,0,.66,.33;.33,.66,.66,1'/%3E%3C/circle%3E%3Ccircle cx='12' cy='12' r='3'%3E%3Canimate attributeName='cy' values='12;6;12;12' keyTimes='0;0.286;0.571;1' dur='1.05s' repeatCount='indefinite' keySplines='.33,0,.66,.33;.33,.66,.66,1' begin='0.1s'/%3E%3C/circle%3E%3Ccircle cx='20' cy='12' r='3'%3E%3Canimate attributeName='cy' values='12;6;12;12' keyTimes='0;0.286;0.571;1' dur='1.05s' repeatCount='indefinite' keySplines='.33,0,.66,.33;.33,.66,.66,1' begin='0.2s'/%3E%3C/circle%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='4' cy='12' r='3'%3E%3Canimate attributeName='cy' values='12;6;12;12' keyTimes='0;0.286;0.571;1' dur='1.05s' repeatCount='indefinite' keySplines='.33,0,.66,.33;.33,.66,.66,1'/%3E%3C/circle%3E%3Ccircle cx='12' cy='12' r='3'%3E%3Canimate attributeName='cy' values='12;6;12;12' keyTimes='0;0.286;0.571;1' dur='1.05s' repeatCount='indefinite' keySplines='.33,0,.66,.33;.33,.66,.66,1' begin='0.1s'/%3E%3C/circle%3E%3Ccircle cx='20' cy='12' r='3'%3E%3Canimate attributeName='cy' values='12;6;12;12' keyTimes='0;0.286;0.571;1' dur='1.05s' repeatCount='indefinite' keySplines='.33,0,.66,.33;.33,.66,.66,1' begin='0.2s'/%3E%3C/circle%3E%3C/svg%3E")}.loading-ring{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='44' height='44' viewBox='0 0 44 44' xmlns='http://www.w3.org/2000/svg' stroke='white'%3E%3Cg fill='none' fill-rule='evenodd' stroke-width='2'%3E%3Ccircle cx='22' cy='22' r='1'%3E%3Canimate attributeName='r' begin='0s' dur='1.8s' values='1;20' calcMode='spline' keyTimes='0;1' keySplines='0.165,0.84,0.44,1' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-opacity' begin='0s' dur='1.8s' values='1;0' calcMode='spline' keyTimes='0;1' keySplines='0.3,0.61,0.355,1' repeatCount='indefinite'/%3E%3C/circle%3E%3Ccircle cx='22' cy='22' r='1'%3E%3Canimate attributeName='r' begin='-0.9s' dur='1.8s' values='1;20' calcMode='spline' keyTimes='0;1' keySplines='0.165,0.84,0.44,1' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-opacity' begin='-0.9s' dur='1.8s' values='1;0' calcMode='spline' keyTimes='0;1' keySplines='0.3,0.61,0.355,1' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='44' height='44' viewBox='0 0 44 44' xmlns='http://www.w3.org/2000/svg' stroke='white'%3E%3Cg fill='none' fill-rule='evenodd' stroke-width='2'%3E%3Ccircle cx='22' cy='22' r='1'%3E%3Canimate attributeName='r' begin='0s' dur='1.8s' values='1;20' calcMode='spline' keyTimes='0;1' keySplines='0.165,0.84,0.44,1' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-opacity' begin='0s' dur='1.8s' values='1;0' calcMode='spline' keyTimes='0;1' keySplines='0.3,0.61,0.355,1' repeatCount='indefinite'/%3E%3C/circle%3E%3Ccircle cx='22' cy='22' r='1'%3E%3Canimate attributeName='r' begin='-0.9s' dur='1.8s' values='1;20' calcMode='spline' keyTimes='0;1' keySplines='0.165,0.84,0.44,1' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-opacity' begin='-0.9s' dur='1.8s' values='1;0' calcMode='spline' keyTimes='0;1' keySplines='0.3,0.61,0.355,1' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E")}.loading-ball{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cellipse cx='12' cy='5' rx='4' ry='4'%3E%3Canimate attributeName='cy' values='5;20;20.5;20;5' keyTimes='0;0.469;0.5;0.531;1' dur='.8s' repeatCount='indefinite' keySplines='.33,0,.66,.33;.33,.66,.66,1'/%3E%3Canimate attributeName='rx' values='4;4;4.8;4;4' keyTimes='0;0.469;0.5;0.531;1' dur='.8s' repeatCount='indefinite'/%3E%3Canimate attributeName='ry' values='4;4;3;4;4' keyTimes='0;0.469;0.5;0.531;1' dur='.8s' repeatCount='indefinite'/%3E%3C/ellipse%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cellipse cx='12' cy='5' rx='4' ry='4'%3E%3Canimate attributeName='cy' values='5;20;20.5;20;5' keyTimes='0;0.469;0.5;0.531;1' dur='.8s' repeatCount='indefinite' keySplines='.33,0,.66,.33;.33,.66,.66,1'/%3E%3Canimate attributeName='rx' values='4;4;4.8;4;4' keyTimes='0;0.469;0.5;0.531;1' dur='.8s' repeatCount='indefinite'/%3E%3Canimate attributeName='ry' values='4;4;3;4;4' keyTimes='0;0.469;0.5;0.531;1' dur='.8s' repeatCount='indefinite'/%3E%3C/ellipse%3E%3C/svg%3E")}.loading-bars{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='1' y='1' width='6' height='22'%3E%3Canimate attributeName='y' values='1;5;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite'/%3E%3Canimate attributeName='height' values='22;14;22' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite'/%3E%3Canimate attributeName='opacity' values='1;0.2;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite'/%3E%3C/rect%3E%3Crect x='9' y='1' width='6' height='22'%3E%3Canimate attributeName='y' values='1;5;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.65s'/%3E%3Canimate attributeName='height' values='22;14;22' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.65s'/%3E%3Canimate attributeName='opacity' values='1;0.2;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.65s'/%3E%3C/rect%3E%3Crect x='17' y='1' width='6' height='22'%3E%3Canimate attributeName='y' values='1;5;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.5s'/%3E%3Canimate attributeName='height' values='22;14;22' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.5s'/%3E%3Canimate attributeName='opacity' values='1;0.2;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.5s'/%3E%3C/rect%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='1' y='1' width='6' height='22'%3E%3Canimate attributeName='y' values='1;5;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite'/%3E%3Canimate attributeName='height' values='22;14;22' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite'/%3E%3Canimate attributeName='opacity' values='1;0.2;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite'/%3E%3C/rect%3E%3Crect x='9' y='1' width='6' height='22'%3E%3Canimate attributeName='y' values='1;5;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.65s'/%3E%3Canimate attributeName='height' values='22;14;22' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.65s'/%3E%3Canimate attributeName='opacity' values='1;0.2;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.65s'/%3E%3C/rect%3E%3Crect x='17' y='1' width='6' height='22'%3E%3Canimate attributeName='y' values='1;5;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.5s'/%3E%3Canimate attributeName='height' values='22;14;22' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.5s'/%3E%3Canimate attributeName='opacity' values='1;0.2;1' keyTimes='0;0.938;1' dur='.8s' repeatCount='indefinite' begin='-0.5s'/%3E%3C/rect%3E%3C/svg%3E")}.loading-infinity{-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' style='shape-rendering:auto;' width='200px' height='200px' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid'%3E%3Cpath fill='none' stroke='black' stroke-width='10' stroke-dasharray='205.271 51.318' d='M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z' stroke-linecap='round' style='transform:scale(0.8);transform-origin:50px 50px'%3E%3Canimate attributeName='stroke-dashoffset' repeatCount='indefinite' dur='2s' keyTimes='0;1' values='0;256.589'/%3E%3C/path%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' style='shape-rendering:auto;' width='200px' height='200px' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid'%3E%3Cpath fill='none' stroke='black' stroke-width='10' stroke-dasharray='205.271 51.318' d='M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z' stroke-linecap='round' style='transform:scale(0.8);transform-origin:50px 50px'%3E%3Canimate attributeName='stroke-dashoffset' repeatCount='indefinite' dur='2s' keyTimes='0;1' values='0;256.589'/%3E%3C/path%3E%3C/svg%3E")}.loading-xs{width:calc(var(--size-selector,.25rem)*4)}.loading-sm{width:calc(var(--size-selector,.25rem)*5)}.loading-md{width:calc(var(--size-selector,.25rem)*6)}.loading-lg{width:calc(var(--size-selector,.25rem)*7)}.loading-xl{width:calc(var(--size-selector,.25rem)*8)}.status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:color-mix(in oklab,var(--color-base-content)20%,transparent);vertical-align:middle;color:rgba(0,0,0,.3);background-position:50%;background-repeat:no-repeat;background-image:radial-gradient(circle at 35% 30%,oklch(1 0 0/calc(var(--depth)*.5)),transparent);width:.5rem;height:.5rem;box-shadow:0 2px 3px -1px color-mix(in oklab,currentColor calc(var(--depth)*100%),transparent);display:inline-block}@supports (color:color-mix(in lab, red, red)){.status{color:color-mix(in oklab,var(--color-black)30%,transparent)}}.status-primary{background-color:var(--color-primary);color:var(--color-primary)}.status-secondary{background-color:var(--color-secondary);color:var(--color-secondary)}.status-accent{background-color:var(--color-accent);color:var(--color-accent)}.status-neutral{background-color:var(--color-neutral);color:var(--color-neutral)}.status-info{background-color:var(--color-info);color:var(--color-info)}.status-success{background-color:var(--color-success);color:var(--color-success)}.status-warning{background-color:var(--color-warning);color:var(--color-warning)}.status-error{background-color:var(--color-error);color:var(--color-error)}.status-xs{width:.125rem;height:.125rem}.status-sm{width:.25rem;height:.25rem}.status-md{width:.5rem;height:.5rem}.status-lg{width:.75rem;height:.75rem}.status-xl{width:1rem;height:1rem}@media (min-width:640px){.sm\:status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:color-mix(in oklab,var(--color-base-content)20%,transparent);vertical-align:middle;color:rgba(0,0,0,.3);background-position:50%;background-repeat:no-repeat;background-image:radial-gradient(circle at 35% 30%,oklch(1 0 0/calc(var(--depth)*.5)),transparent);width:.5rem;height:.5rem;box-shadow:0 2px 3px -1px color-mix(in oklab,currentColor calc(var(--depth)*100%),transparent);display:inline-block}@supports (color:color-mix(in lab, red, red)){.sm\:status{color:color-mix(in oklab,var(--color-black)30%,transparent)}}.sm\:status-primary{background-color:var(--color-primary);color:var(--color-primary)}.sm\:status-secondary{background-color:var(--color-secondary);color:var(--color-secondary)}.sm\:status-accent{background-color:var(--color-accent);color:var(--color-accent)}.sm\:status-neutral{background-color:var(--color-neutral);color:var(--color-neutral)}.sm\:status-info{background-color:var(--color-info);color:var(--color-info)}.sm\:status-success{background-color:var(--color-success);color:var(--color-success)}.sm\:status-warning{background-color:var(--color-warning);color:var(--color-warning)}.sm\:status-error{background-color:var(--color-error);color:var(--color-error)}.sm\:status-xs{width:.125rem;height:.125rem}.sm\:status-sm{width:.25rem;height:.25rem}.sm\:status-md{width:.5rem;height:.5rem}.sm\:status-lg{width:.75rem;height:.75rem}.sm\:status-xl{width:1rem;height:1rem}}@media (min-width:768px){.md\:status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:color-mix(in oklab,var(--color-base-content)20%,transparent);vertical-align:middle;color:rgba(0,0,0,.3);background-position:50%;background-repeat:no-repeat;background-image:radial-gradient(circle at 35% 30%,oklch(1 0 0/calc(var(--depth)*.5)),transparent);width:.5rem;height:.5rem;box-shadow:0 2px 3px -1px color-mix(in oklab,currentColor calc(var(--depth)*100%),transparent);display:inline-block}@supports (color:color-mix(in lab, red, red)){.md\:status{color:color-mix(in oklab,var(--color-black)30%,transparent)}}.md\:status-primary{background-color:var(--color-primary);color:var(--color-primary)}.md\:status-secondary{background-color:var(--color-secondary);color:var(--color-secondary)}.md\:status-accent{background-color:var(--color-accent);color:var(--color-accent)}.md\:status-neutral{background-color:var(--color-neutral);color:var(--color-neutral)}.md\:status-info{background-color:var(--color-info);color:var(--color-info)}.md\:status-success{background-color:var(--color-success);color:var(--color-success)}.md\:status-warning{background-color:var(--color-warning);color:var(--color-warning)}.md\:status-error{background-color:var(--color-error);color:var(--color-error)}.md\:status-xs{width:.125rem;height:.125rem}.md\:status-sm{width:.25rem;height:.25rem}.md\:status-md{width:.5rem;height:.5rem}.md\:status-lg{width:.75rem;height:.75rem}.md\:status-xl{width:1rem;height:1rem}}@media (min-width:1024px){.lg\:status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:color-mix(in oklab,var(--color-base-content)20%,transparent);vertical-align:middle;color:rgba(0,0,0,.3);background-position:50%;background-repeat:no-repeat;background-image:radial-gradient(circle at 35% 30%,oklch(1 0 0/calc(var(--depth)*.5)),transparent);width:.5rem;height:.5rem;box-shadow:0 2px 3px -1px color-mix(in oklab,currentColor calc(var(--depth)*100%),transparent);display:inline-block}@supports (color:color-mix(in lab, red, red)){.lg\:status{color:color-mix(in oklab,var(--color-black)30%,transparent)}}.lg\:status-primary{background-color:var(--color-primary);color:var(--color-primary)}.lg\:status-secondary{background-color:var(--color-secondary);color:var(--color-secondary)}.lg\:status-accent{background-color:var(--color-accent);color:var(--color-accent)}.lg\:status-neutral{background-color:var(--color-neutral);color:var(--color-neutral)}.lg\:status-info{background-color:var(--color-info);color:var(--color-info)}.lg\:status-success{background-color:var(--color-success);color:var(--color-success)}.lg\:status-warning{background-color:var(--color-warning);color:var(--color-warning)}.lg\:status-error{background-color:var(--color-error);color:var(--color-error)}.lg\:status-xs{width:.125rem;height:.125rem}.lg\:status-sm{width:.25rem;height:.25rem}.lg\:status-md{width:.5rem;height:.5rem}.lg\:status-lg{width:.75rem;height:.75rem}.lg\:status-xl{width:1rem;height:1rem}}@media (min-width:1280px){.xl\:status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:color-mix(in oklab,var(--color-base-content)20%,transparent);vertical-align:middle;color:rgba(0,0,0,.3);background-position:50%;background-repeat:no-repeat;background-image:radial-gradient(circle at 35% 30%,oklch(1 0 0/calc(var(--depth)*.5)),transparent);width:.5rem;height:.5rem;box-shadow:0 2px 3px -1px color-mix(in oklab,currentColor calc(var(--depth)*100%),transparent);display:inline-block}@supports (color:color-mix(in lab, red, red)){.xl\:status{color:color-mix(in oklab,var(--color-black)30%,transparent)}}.xl\:status-primary{background-color:var(--color-primary);color:var(--color-primary)}.xl\:status-secondary{background-color:var(--color-secondary);color:var(--color-secondary)}.xl\:status-accent{background-color:var(--color-accent);color:var(--color-accent)}.xl\:status-neutral{background-color:var(--color-neutral);color:var(--color-neutral)}.xl\:status-info{background-color:var(--color-info);color:var(--color-info)}.xl\:status-success{background-color:var(--color-success);color:var(--color-success)}.xl\:status-warning{background-color:var(--color-warning);color:var(--color-warning)}.xl\:status-error{background-color:var(--color-error);color:var(--color-error)}.xl\:status-xs{width:.125rem;height:.125rem}.xl\:status-sm{width:.25rem;height:.25rem}.xl\:status-md{width:.5rem;height:.5rem}.xl\:status-lg{width:.75rem;height:.75rem}.xl\:status-xl{width:1rem;height:1rem}}@media (min-width:1536px){.\32 xl\:status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:color-mix(in oklab,var(--color-base-content)20%,transparent);vertical-align:middle;color:rgba(0,0,0,.3);background-position:50%;background-repeat:no-repeat;background-image:radial-gradient(circle at 35% 30%,oklch(1 0 0/calc(var(--depth)*.5)),transparent);width:.5rem;height:.5rem;box-shadow:0 2px 3px -1px color-mix(in oklab,currentColor calc(var(--depth)*100%),transparent);display:inline-block}@supports (color:color-mix(in lab, red, red)){.\32 xl\:status{color:color-mix(in oklab,var(--color-black)30%,transparent)}}.\32 xl\:status-primary{background-color:var(--color-primary);color:var(--color-primary)}.\32 xl\:status-secondary{background-color:var(--color-secondary);color:var(--color-secondary)}.\32 xl\:status-accent{background-color:var(--color-accent);color:var(--color-accent)}.\32 xl\:status-neutral{background-color:var(--color-neutral);color:var(--color-neutral)}.\32 xl\:status-info{background-color:var(--color-info);color:var(--color-info)}.\32 xl\:status-success{background-color:var(--color-success);color:var(--color-success)}.\32 xl\:status-warning{background-color:var(--color-warning);color:var(--color-warning)}.\32 xl\:status-error{background-color:var(--color-error);color:var(--color-error)}.\32 xl\:status-xs{width:.125rem;height:.125rem}.\32 xl\:status-sm{width:.25rem;height:.25rem}.\32 xl\:status-md{width:.5rem;height:.5rem}.\32 xl\:status-lg{width:.75rem;height:.75rem}.\32 xl\:status-xl{width:1rem;height:1rem}}.skeleton{border-radius:var(--radius-box);background-color:var(--color-base-300);will-change:background-position;background-image:linear-gradient(105deg,transparent 0% 40%,var(--color-base-100)50%,transparent 60% 100%);background-position-x:-50%;background-repeat:no-repeat;background-size:200%;animation:1.8s ease-in-out infinite skeleton}@media (prefers-reduced-motion:reduce){.skeleton{transition-duration:15s}}@keyframes skeleton{0%{background-position:150%}to{background-position:-50%}}.select{border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;width:clamp(3rem,20rem,100%);height:var(--size);text-overflow:ellipsis;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;border-color:var(--input-color);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);--size:calc(var(--size-field,.25rem)*10);background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16.1px) calc(1px + 50%);background-repeat:no-repeat;background-size:4px 4px,4px 4px;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.375rem;padding-inline:1rem 1.75rem;font-size:.875rem;display:inline-flex;position:relative}[dir=rtl] .select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}.select select{appearance:none;background:inherit;border-radius:inherit;border-style:none;width:calc(100% + 2.75rem);height:calc(100% - 2px);margin-inline:-1rem -1.75rem;padding-inline:1rem 1.75rem}.select select:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.select select:focus{outline-offset:2px;outline:2px solid transparent}}.select select:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.select select:focus-within{outline-offset:2px;outline:2px solid transparent}}.select select:not(:last-child){background-image:none;margin-inline-end:-1.375rem}.select:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.select:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.select:has(>select[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.select:has(>select[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.select:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.select:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.select:has(>select[disabled])>select[disabled]{cursor:not-allowed}.select-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.select-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.select-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.select-neutral{--input-color:var(--color-neutral)}.select-neutral:focus{--input-color:var(--color-neutral)}.select-neutral:focus-within{--input-color:var(--color-neutral)}.select-primary{--input-color:var(--color-primary)}.select-primary:focus{--input-color:var(--color-primary)}.select-primary:focus-within{--input-color:var(--color-primary)}.select-secondary{--input-color:var(--color-secondary)}.select-secondary:focus{--input-color:var(--color-secondary)}.select-secondary:focus-within{--input-color:var(--color-secondary)}.select-accent{--input-color:var(--color-accent)}.select-accent:focus{--input-color:var(--color-accent)}.select-accent:focus-within{--input-color:var(--color-accent)}.select-info{--input-color:var(--color-info)}.select-info:focus{--input-color:var(--color-info)}.select-info:focus-within{--input-color:var(--color-info)}.select-success{--input-color:var(--color-success)}.select-success:focus{--input-color:var(--color-success)}.select-success:focus-within{--input-color:var(--color-success)}.select-warning{--input-color:var(--color-warning)}.select-warning:focus{--input-color:var(--color-warning)}.select-warning:focus-within{--input-color:var(--color-warning)}.select-error{--input-color:var(--color-error)}.select-error:focus{--input-color:var(--color-error)}.select-error:focus-within{--input-color:var(--color-error)}.select-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.select-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.select-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.select-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.select-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}@media (min-width:640px){.sm\:select{border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;width:clamp(3rem,20rem,100%);height:var(--size);text-overflow:ellipsis;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;border-color:var(--input-color);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);--size:calc(var(--size-field,.25rem)*10);background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16.1px) calc(1px + 50%);background-repeat:no-repeat;background-size:4px 4px,4px 4px;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.375rem;padding-inline:1rem 1.75rem;font-size:.875rem;display:inline-flex;position:relative}[dir=rtl] .sm\:select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}.sm\:select select{appearance:none;background:inherit;border-radius:inherit;border-style:none;width:calc(100% + 2.75rem);height:calc(100% - 2px);margin-inline:-1rem -1.75rem;padding-inline:1rem 1.75rem}.sm\:select select:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:select select:focus{outline-offset:2px;outline:2px solid transparent}}.sm\:select select:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.sm\:select select:focus-within{outline-offset:2px;outline:2px solid transparent}}.sm\:select select:not(:last-child){background-image:none;margin-inline-end:-1.375rem}.sm\:select:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.sm\:select:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.sm\:select:has(>select[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.sm\:select:has(>select[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.sm\:select:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.sm\:select:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.sm\:select:has(>select[disabled])>select[disabled]{cursor:not-allowed}.sm\:select-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.sm\:select-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.sm\:select-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.sm\:select-neutral{--input-color:var(--color-neutral)}.sm\:select-neutral:focus{--input-color:var(--color-neutral)}.sm\:select-neutral:focus-within{--input-color:var(--color-neutral)}.sm\:select-primary{--input-color:var(--color-primary)}.sm\:select-primary:focus{--input-color:var(--color-primary)}.sm\:select-primary:focus-within{--input-color:var(--color-primary)}.sm\:select-secondary{--input-color:var(--color-secondary)}.sm\:select-secondary:focus{--input-color:var(--color-secondary)}.sm\:select-secondary:focus-within{--input-color:var(--color-secondary)}.sm\:select-accent{--input-color:var(--color-accent)}.sm\:select-accent:focus{--input-color:var(--color-accent)}.sm\:select-accent:focus-within{--input-color:var(--color-accent)}.sm\:select-info{--input-color:var(--color-info)}.sm\:select-info:focus{--input-color:var(--color-info)}.sm\:select-info:focus-within{--input-color:var(--color-info)}.sm\:select-success{--input-color:var(--color-success)}.sm\:select-success:focus{--input-color:var(--color-success)}.sm\:select-success:focus-within{--input-color:var(--color-success)}.sm\:select-warning{--input-color:var(--color-warning)}.sm\:select-warning:focus{--input-color:var(--color-warning)}.sm\:select-warning:focus-within{--input-color:var(--color-warning)}.sm\:select-error{--input-color:var(--color-error)}.sm\:select-error:focus{--input-color:var(--color-error)}.sm\:select-error:focus-within{--input-color:var(--color-error)}.sm\:select-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.sm\:select-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.sm\:select-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.sm\:select-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.sm\:select-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}}@media (min-width:768px){.md\:select{border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;width:clamp(3rem,20rem,100%);height:var(--size);text-overflow:ellipsis;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;border-color:var(--input-color);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);--size:calc(var(--size-field,.25rem)*10);background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16.1px) calc(1px + 50%);background-repeat:no-repeat;background-size:4px 4px,4px 4px;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.375rem;padding-inline:1rem 1.75rem;font-size:.875rem;display:inline-flex;position:relative}[dir=rtl] .md\:select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}.md\:select select{appearance:none;background:inherit;border-radius:inherit;border-style:none;width:calc(100% + 2.75rem);height:calc(100% - 2px);margin-inline:-1rem -1.75rem;padding-inline:1rem 1.75rem}.md\:select select:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:select select:focus{outline-offset:2px;outline:2px solid transparent}}.md\:select select:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.md\:select select:focus-within{outline-offset:2px;outline:2px solid transparent}}.md\:select select:not(:last-child){background-image:none;margin-inline-end:-1.375rem}.md\:select:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.md\:select:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.md\:select:has(>select[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.md\:select:has(>select[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.md\:select:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.md\:select:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.md\:select:has(>select[disabled])>select[disabled]{cursor:not-allowed}.md\:select-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.md\:select-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.md\:select-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.md\:select-neutral{--input-color:var(--color-neutral)}.md\:select-neutral:focus{--input-color:var(--color-neutral)}.md\:select-neutral:focus-within{--input-color:var(--color-neutral)}.md\:select-primary{--input-color:var(--color-primary)}.md\:select-primary:focus{--input-color:var(--color-primary)}.md\:select-primary:focus-within{--input-color:var(--color-primary)}.md\:select-secondary{--input-color:var(--color-secondary)}.md\:select-secondary:focus{--input-color:var(--color-secondary)}.md\:select-secondary:focus-within{--input-color:var(--color-secondary)}.md\:select-accent{--input-color:var(--color-accent)}.md\:select-accent:focus{--input-color:var(--color-accent)}.md\:select-accent:focus-within{--input-color:var(--color-accent)}.md\:select-info{--input-color:var(--color-info)}.md\:select-info:focus{--input-color:var(--color-info)}.md\:select-info:focus-within{--input-color:var(--color-info)}.md\:select-success{--input-color:var(--color-success)}.md\:select-success:focus{--input-color:var(--color-success)}.md\:select-success:focus-within{--input-color:var(--color-success)}.md\:select-warning{--input-color:var(--color-warning)}.md\:select-warning:focus{--input-color:var(--color-warning)}.md\:select-warning:focus-within{--input-color:var(--color-warning)}.md\:select-error{--input-color:var(--color-error)}.md\:select-error:focus{--input-color:var(--color-error)}.md\:select-error:focus-within{--input-color:var(--color-error)}.md\:select-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.md\:select-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.md\:select-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.md\:select-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.md\:select-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}}@media (min-width:1024px){.lg\:select{border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;width:clamp(3rem,20rem,100%);height:var(--size);text-overflow:ellipsis;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;border-color:var(--input-color);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);--size:calc(var(--size-field,.25rem)*10);background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16.1px) calc(1px + 50%);background-repeat:no-repeat;background-size:4px 4px,4px 4px;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.375rem;padding-inline:1rem 1.75rem;font-size:.875rem;display:inline-flex;position:relative}[dir=rtl] .lg\:select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}.lg\:select select{appearance:none;background:inherit;border-radius:inherit;border-style:none;width:calc(100% + 2.75rem);height:calc(100% - 2px);margin-inline:-1rem -1.75rem;padding-inline:1rem 1.75rem}.lg\:select select:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:select select:focus{outline-offset:2px;outline:2px solid transparent}}.lg\:select select:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.lg\:select select:focus-within{outline-offset:2px;outline:2px solid transparent}}.lg\:select select:not(:last-child){background-image:none;margin-inline-end:-1.375rem}.lg\:select:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.lg\:select:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.lg\:select:has(>select[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.lg\:select:has(>select[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.lg\:select:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.lg\:select:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.lg\:select:has(>select[disabled])>select[disabled]{cursor:not-allowed}.lg\:select-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.lg\:select-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.lg\:select-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.lg\:select-neutral{--input-color:var(--color-neutral)}.lg\:select-neutral:focus{--input-color:var(--color-neutral)}.lg\:select-neutral:focus-within{--input-color:var(--color-neutral)}.lg\:select-primary{--input-color:var(--color-primary)}.lg\:select-primary:focus{--input-color:var(--color-primary)}.lg\:select-primary:focus-within{--input-color:var(--color-primary)}.lg\:select-secondary{--input-color:var(--color-secondary)}.lg\:select-secondary:focus{--input-color:var(--color-secondary)}.lg\:select-secondary:focus-within{--input-color:var(--color-secondary)}.lg\:select-accent{--input-color:var(--color-accent)}.lg\:select-accent:focus{--input-color:var(--color-accent)}.lg\:select-accent:focus-within{--input-color:var(--color-accent)}.lg\:select-info{--input-color:var(--color-info)}.lg\:select-info:focus{--input-color:var(--color-info)}.lg\:select-info:focus-within{--input-color:var(--color-info)}.lg\:select-success{--input-color:var(--color-success)}.lg\:select-success:focus{--input-color:var(--color-success)}.lg\:select-success:focus-within{--input-color:var(--color-success)}.lg\:select-warning{--input-color:var(--color-warning)}.lg\:select-warning:focus{--input-color:var(--color-warning)}.lg\:select-warning:focus-within{--input-color:var(--color-warning)}.lg\:select-error{--input-color:var(--color-error)}.lg\:select-error:focus{--input-color:var(--color-error)}.lg\:select-error:focus-within{--input-color:var(--color-error)}.lg\:select-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.lg\:select-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.lg\:select-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.lg\:select-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.lg\:select-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}}@media (min-width:1280px){.xl\:select{border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;width:clamp(3rem,20rem,100%);height:var(--size);text-overflow:ellipsis;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;border-color:var(--input-color);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);--size:calc(var(--size-field,.25rem)*10);background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16.1px) calc(1px + 50%);background-repeat:no-repeat;background-size:4px 4px,4px 4px;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.375rem;padding-inline:1rem 1.75rem;font-size:.875rem;display:inline-flex;position:relative}[dir=rtl] .xl\:select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}.xl\:select select{appearance:none;background:inherit;border-radius:inherit;border-style:none;width:calc(100% + 2.75rem);height:calc(100% - 2px);margin-inline:-1rem -1.75rem;padding-inline:1rem 1.75rem}.xl\:select select:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:select select:focus{outline-offset:2px;outline:2px solid transparent}}.xl\:select select:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.xl\:select select:focus-within{outline-offset:2px;outline:2px solid transparent}}.xl\:select select:not(:last-child){background-image:none;margin-inline-end:-1.375rem}.xl\:select:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.xl\:select:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.xl\:select:has(>select[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.xl\:select:has(>select[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.xl\:select:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.xl\:select:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.xl\:select:has(>select[disabled])>select[disabled]{cursor:not-allowed}.xl\:select-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.xl\:select-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.xl\:select-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.xl\:select-neutral{--input-color:var(--color-neutral)}.xl\:select-neutral:focus{--input-color:var(--color-neutral)}.xl\:select-neutral:focus-within{--input-color:var(--color-neutral)}.xl\:select-primary{--input-color:var(--color-primary)}.xl\:select-primary:focus{--input-color:var(--color-primary)}.xl\:select-primary:focus-within{--input-color:var(--color-primary)}.xl\:select-secondary{--input-color:var(--color-secondary)}.xl\:select-secondary:focus{--input-color:var(--color-secondary)}.xl\:select-secondary:focus-within{--input-color:var(--color-secondary)}.xl\:select-accent{--input-color:var(--color-accent)}.xl\:select-accent:focus{--input-color:var(--color-accent)}.xl\:select-accent:focus-within{--input-color:var(--color-accent)}.xl\:select-info{--input-color:var(--color-info)}.xl\:select-info:focus{--input-color:var(--color-info)}.xl\:select-info:focus-within{--input-color:var(--color-info)}.xl\:select-success{--input-color:var(--color-success)}.xl\:select-success:focus{--input-color:var(--color-success)}.xl\:select-success:focus-within{--input-color:var(--color-success)}.xl\:select-warning{--input-color:var(--color-warning)}.xl\:select-warning:focus{--input-color:var(--color-warning)}.xl\:select-warning:focus-within{--input-color:var(--color-warning)}.xl\:select-error{--input-color:var(--color-error)}.xl\:select-error:focus{--input-color:var(--color-error)}.xl\:select-error:focus-within{--input-color:var(--color-error)}.xl\:select-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.xl\:select-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.xl\:select-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.xl\:select-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.xl\:select-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}}@media (min-width:1536px){.\32 xl\:select{border:var(--border)solid transparent;appearance:none;background-color:var(--color-base-100);vertical-align:middle;width:clamp(3rem,20rem,100%);height:var(--size);text-overflow:ellipsis;box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;border-color:var(--input-color);--input-color:color-mix(in oklab,var(--color-base-content)20%,transparent);--size:calc(var(--size-field,.25rem)*10);background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16.1px) calc(1px + 50%);background-repeat:no-repeat;background-size:4px 4px,4px 4px;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.375rem;padding-inline:1rem 1.75rem;font-size:.875rem;display:inline-flex;position:relative}[dir=rtl] .\32 xl\:select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}.\32 xl\:select select{appearance:none;background:inherit;border-radius:inherit;border-style:none;width:calc(100% + 2.75rem);height:calc(100% - 2px);margin-inline:-1rem -1.75rem;padding-inline:1rem 1.75rem}.\32 xl\:select select:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:select select:focus{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:select select:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.\32 xl\:select select:focus-within{outline-offset:2px;outline:2px solid transparent}}.\32 xl\:select select:not(:last-child){background-image:none;margin-inline-end:-1.375rem}.\32 xl\:select:focus{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.\32 xl\:select:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),transparent);outline:2px solid var(--input-color);outline-offset:2px}.\32 xl\:select:has(>select[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.\32 xl\:select:has(>select[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.\32 xl\:select:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.\32 xl\:select:is(:disabled,[disabled])::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.\32 xl\:select:has(>select[disabled])>select[disabled]{cursor:not-allowed}.\32 xl\:select-ghost{box-shadow:none;background-color:transparent;border-color:transparent;transition:background-color .2s}.\32 xl\:select-ghost:focus{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.\32 xl\:select-ghost:focus-within{background-color:var(--color-base-100);color:var(--color-base-content);box-shadow:none;border-color:transparent}.\32 xl\:select-neutral{--input-color:var(--color-neutral)}.\32 xl\:select-neutral:focus{--input-color:var(--color-neutral)}.\32 xl\:select-neutral:focus-within{--input-color:var(--color-neutral)}.\32 xl\:select-primary{--input-color:var(--color-primary)}.\32 xl\:select-primary:focus{--input-color:var(--color-primary)}.\32 xl\:select-primary:focus-within{--input-color:var(--color-primary)}.\32 xl\:select-secondary{--input-color:var(--color-secondary)}.\32 xl\:select-secondary:focus{--input-color:var(--color-secondary)}.\32 xl\:select-secondary:focus-within{--input-color:var(--color-secondary)}.\32 xl\:select-accent{--input-color:var(--color-accent)}.\32 xl\:select-accent:focus{--input-color:var(--color-accent)}.\32 xl\:select-accent:focus-within{--input-color:var(--color-accent)}.\32 xl\:select-info{--input-color:var(--color-info)}.\32 xl\:select-info:focus{--input-color:var(--color-info)}.\32 xl\:select-info:focus-within{--input-color:var(--color-info)}.\32 xl\:select-success{--input-color:var(--color-success)}.\32 xl\:select-success:focus{--input-color:var(--color-success)}.\32 xl\:select-success:focus-within{--input-color:var(--color-success)}.\32 xl\:select-warning{--input-color:var(--color-warning)}.\32 xl\:select-warning:focus{--input-color:var(--color-warning)}.\32 xl\:select-warning:focus-within{--input-color:var(--color-warning)}.\32 xl\:select-error{--input-color:var(--color-error)}.\32 xl\:select-error:focus{--input-color:var(--color-error)}.\32 xl\:select-error:focus-within{--input-color:var(--color-error)}.\32 xl\:select-xs{--size:calc(var(--size-field,.25rem)*6);font-size:.6875rem}.\32 xl\:select-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.\32 xl\:select-md{--size:calc(var(--size-field,.25rem)*10);font-size:.875rem}.\32 xl\:select-lg{--size:calc(var(--size-field,.25rem)*12);font-size:1.125rem}.\32 xl\:select-xl{--size:calc(var(--size-field,.25rem)*14);font-size:1.375rem}}.avatar-group{display:flex;overflow:hidden}.avatar-group :where(.avatar){border:4px solid var(--color-base-100);border-radius:3.40282e38px;overflow:hidden}.avatar{vertical-align:middle;display:inline-flex;position:relative}.avatar>div{aspect-ratio:1;display:block;overflow:hidden}.avatar img{object-fit:cover;width:100%;height:100%}.avatar-placeholder>div{justify-content:center;align-items:center;display:flex}.avatar-online:before{content:"";z-index:1;background-color:var(--color-success);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}.avatar-offline:before{content:"";z-index:1;background-color:var(--color-base-300);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}@media (min-width:640px){.sm\:avatar-group{display:flex;overflow:hidden}.sm\:avatar-group :where(.avatar){border:4px solid var(--color-base-100);border-radius:3.40282e38px;overflow:hidden}.sm\:avatar{vertical-align:middle;display:inline-flex;position:relative}.sm\:avatar>div{aspect-ratio:1;display:block;overflow:hidden}.sm\:avatar img{object-fit:cover;width:100%;height:100%}.sm\:avatar-placeholder>div{justify-content:center;align-items:center;display:flex}.sm\:avatar-online:before{content:"";z-index:1;background-color:var(--color-success);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}.sm\:avatar-offline:before{content:"";z-index:1;background-color:var(--color-base-300);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}}@media (min-width:768px){.md\:avatar-group{display:flex;overflow:hidden}.md\:avatar-group :where(.avatar){border:4px solid var(--color-base-100);border-radius:3.40282e38px;overflow:hidden}.md\:avatar{vertical-align:middle;display:inline-flex;position:relative}.md\:avatar>div{aspect-ratio:1;display:block;overflow:hidden}.md\:avatar img{object-fit:cover;width:100%;height:100%}.md\:avatar-placeholder>div{justify-content:center;align-items:center;display:flex}.md\:avatar-online:before{content:"";z-index:1;background-color:var(--color-success);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}.md\:avatar-offline:before{content:"";z-index:1;background-color:var(--color-base-300);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}}@media (min-width:1024px){.lg\:avatar-group{display:flex;overflow:hidden}.lg\:avatar-group :where(.avatar){border:4px solid var(--color-base-100);border-radius:3.40282e38px;overflow:hidden}.lg\:avatar{vertical-align:middle;display:inline-flex;position:relative}.lg\:avatar>div{aspect-ratio:1;display:block;overflow:hidden}.lg\:avatar img{object-fit:cover;width:100%;height:100%}.lg\:avatar-placeholder>div{justify-content:center;align-items:center;display:flex}.lg\:avatar-online:before{content:"";z-index:1;background-color:var(--color-success);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}.lg\:avatar-offline:before{content:"";z-index:1;background-color:var(--color-base-300);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}}@media (min-width:1280px){.xl\:avatar-group{display:flex;overflow:hidden}.xl\:avatar-group :where(.avatar){border:4px solid var(--color-base-100);border-radius:3.40282e38px;overflow:hidden}.xl\:avatar{vertical-align:middle;display:inline-flex;position:relative}.xl\:avatar>div{aspect-ratio:1;display:block;overflow:hidden}.xl\:avatar img{object-fit:cover;width:100%;height:100%}.xl\:avatar-placeholder>div{justify-content:center;align-items:center;display:flex}.xl\:avatar-online:before{content:"";z-index:1;background-color:var(--color-success);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}.xl\:avatar-offline:before{content:"";z-index:1;background-color:var(--color-base-300);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}}@media (min-width:1536px){.\32 xl\:avatar-group{display:flex;overflow:hidden}.\32 xl\:avatar-group :where(.avatar){border:4px solid var(--color-base-100);border-radius:3.40282e38px;overflow:hidden}.\32 xl\:avatar{vertical-align:middle;display:inline-flex;position:relative}.\32 xl\:avatar>div{aspect-ratio:1;display:block;overflow:hidden}.\32 xl\:avatar img{object-fit:cover;width:100%;height:100%}.\32 xl\:avatar-placeholder>div{justify-content:center;align-items:center;display:flex}.\32 xl\:avatar-online:before{content:"";z-index:1;background-color:var(--color-success);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}.\32 xl\:avatar-offline:before{content:"";z-index:1;background-color:var(--color-base-300);outline:2px solid var(--color-base-100);border-radius:3.40282e38px;width:15%;height:15%;display:block;position:absolute;top:7%;right:7%}}.glass{-webkit-backdrop-filter:blur(var(--glass-blur,40px));backdrop-filter:blur(var(--glass-blur,40px));background-color:transparent;background-image:linear-gradient(135deg,oklch(100% 0 0/var(--glass-opacity,30%))0%,transparent 100%),linear-gradient(var(--glass-reflect-degree,100deg),oklch(100% 0 0/var(--glass-reflect-opacity,5%))25%,transparent 25%);box-shadow:0 0 0 1px oklch(100% 0 0/var(--glass-border-opacity,20%))inset,0 0 0 2px rgba(0,0,0,.05);text-shadow:0 1px oklch(0% 0 0/var(--glass-text-shadow-opacity,5%));border:none}@supports (color:lab(0% 0 0)){.glass{background-image:linear-gradient(135deg,oklch(100% 0 0/var(--glass-opacity,30%))0%,lab(0% 0 0/0) 100%),linear-gradient(var(--glass-reflect-degree,100deg),oklch(100% 0 0/var(--glass-reflect-opacity,5%))25%,lab(0% 0 0/0) 25%);box-shadow:0 0 0 1px oklch(100% 0 0/var(--glass-border-opacity,20%))inset,0 0 0 2px lab(0% 0 0/.05)}}.join{--join-ss:0;--join-se:0;--join-es:0;--join-ee:0;align-items:stretch;display:inline-flex}.join :where(.join-item){border-start-start-radius:var(--join-ss,0);border-start-end-radius:var(--join-se,0);border-end-end-radius:var(--join-ee,0);border-end-start-radius:var(--join-es,0)}.join :where(.join-item) *{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join>.join-item:where(:first-child){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.join :first-child:not(:last-child) :where(.join-item){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.join>.join-item:where(:last-child){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.join :last-child:not(:first-child) :where(.join-item){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.join>.join-item:where(:only-child){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join :only-child :where(.join-item){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}.join-vertical{flex-direction:column}.join-vertical>.join-item:first-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.join-vertical :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.join-vertical>.join-item:last-child{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join-vertical :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join-vertical>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join-vertical :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join-vertical .join-item:where(:not(:first-child)){margin-block-start:calc(var(--border,1px)*-1);margin-inline-start:0}.join-horizontal{flex-direction:row}.join-horizontal>.join-item:first-child{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.join-horizontal :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.join-horizontal>.join-item:last-child{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.join-horizontal :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.join-horizontal>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join-horizontal :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join-horizontal .join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}@media (min-width:640px){.sm\:join{--join-ss:0;--join-se:0;--join-es:0;--join-ee:0;align-items:stretch;display:inline-flex}.sm\:join :where(.join-item){border-start-start-radius:var(--join-ss,0);border-start-end-radius:var(--join-se,0);border-end-end-radius:var(--join-ee,0);border-end-start-radius:var(--join-es,0)}.sm\:join :where(.join-item) *{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.sm\:join>.join-item:where(:first-child){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.sm\:join :first-child:not(:last-child) :where(.join-item){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.sm\:join>.join-item:where(:last-child){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.sm\:join :last-child:not(:first-child) :where(.join-item){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.sm\:join>.join-item:where(:only-child){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.sm\:join :only-child :where(.join-item){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.sm\:join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}.sm\:join-vertical{flex-direction:column}.sm\:join-vertical>.join-item:first-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.sm\:join-vertical :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.sm\:join-vertical>.join-item:last-child{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.sm\:join-vertical :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.sm\:join-vertical>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.sm\:join-vertical :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.sm\:join-vertical .join-item:where(:not(:first-child)){margin-block-start:calc(var(--border,1px)*-1);margin-inline-start:0}.sm\:join-horizontal{flex-direction:row}.sm\:join-horizontal>.join-item:first-child{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.sm\:join-horizontal :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.sm\:join-horizontal>.join-item:last-child{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.sm\:join-horizontal :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.sm\:join-horizontal>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.sm\:join-horizontal :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.sm\:join-horizontal .join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}}@media (min-width:768px){.md\:join{--join-ss:0;--join-se:0;--join-es:0;--join-ee:0;align-items:stretch;display:inline-flex}.md\:join :where(.join-item){border-start-start-radius:var(--join-ss,0);border-start-end-radius:var(--join-se,0);border-end-end-radius:var(--join-ee,0);border-end-start-radius:var(--join-es,0)}.md\:join :where(.join-item) *{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.md\:join>.join-item:where(:first-child){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.md\:join :first-child:not(:last-child) :where(.join-item){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.md\:join>.join-item:where(:last-child){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.md\:join :last-child:not(:first-child) :where(.join-item){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.md\:join>.join-item:where(:only-child){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.md\:join :only-child :where(.join-item){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.md\:join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}.md\:join-vertical{flex-direction:column}.md\:join-vertical>.join-item:first-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.md\:join-vertical :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.md\:join-vertical>.join-item:last-child{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.md\:join-vertical :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.md\:join-vertical>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.md\:join-vertical :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.md\:join-vertical .join-item:where(:not(:first-child)){margin-block-start:calc(var(--border,1px)*-1);margin-inline-start:0}.md\:join-horizontal{flex-direction:row}.md\:join-horizontal>.join-item:first-child{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.md\:join-horizontal :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.md\:join-horizontal>.join-item:last-child{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.md\:join-horizontal :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.md\:join-horizontal>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.md\:join-horizontal :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.md\:join-horizontal .join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}}@media (min-width:1024px){.lg\:join{--join-ss:0;--join-se:0;--join-es:0;--join-ee:0;align-items:stretch;display:inline-flex}.lg\:join :where(.join-item){border-start-start-radius:var(--join-ss,0);border-start-end-radius:var(--join-se,0);border-end-end-radius:var(--join-ee,0);border-end-start-radius:var(--join-es,0)}.lg\:join :where(.join-item) *{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.lg\:join>.join-item:where(:first-child){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.lg\:join :first-child:not(:last-child) :where(.join-item){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.lg\:join>.join-item:where(:last-child){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.lg\:join :last-child:not(:first-child) :where(.join-item){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.lg\:join>.join-item:where(:only-child){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.lg\:join :only-child :where(.join-item){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.lg\:join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}.lg\:join-vertical{flex-direction:column}.lg\:join-vertical>.join-item:first-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.lg\:join-vertical :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.lg\:join-vertical>.join-item:last-child{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.lg\:join-vertical :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.lg\:join-vertical>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.lg\:join-vertical :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.lg\:join-vertical .join-item:where(:not(:first-child)){margin-block-start:calc(var(--border,1px)*-1);margin-inline-start:0}.lg\:join-horizontal{flex-direction:row}.lg\:join-horizontal>.join-item:first-child{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.lg\:join-horizontal :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.lg\:join-horizontal>.join-item:last-child{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.lg\:join-horizontal :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.lg\:join-horizontal>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.lg\:join-horizontal :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.lg\:join-horizontal .join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}}@media (min-width:1280px){.xl\:join{--join-ss:0;--join-se:0;--join-es:0;--join-ee:0;align-items:stretch;display:inline-flex}.xl\:join :where(.join-item){border-start-start-radius:var(--join-ss,0);border-start-end-radius:var(--join-se,0);border-end-end-radius:var(--join-ee,0);border-end-start-radius:var(--join-es,0)}.xl\:join :where(.join-item) *{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.xl\:join>.join-item:where(:first-child){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.xl\:join :first-child:not(:last-child) :where(.join-item){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.xl\:join>.join-item:where(:last-child){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.xl\:join :last-child:not(:first-child) :where(.join-item){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.xl\:join>.join-item:where(:only-child){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.xl\:join :only-child :where(.join-item){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.xl\:join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}.xl\:join-vertical{flex-direction:column}.xl\:join-vertical>.join-item:first-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.xl\:join-vertical :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.xl\:join-vertical>.join-item:last-child{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.xl\:join-vertical :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.xl\:join-vertical>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.xl\:join-vertical :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.xl\:join-vertical .join-item:where(:not(:first-child)){margin-block-start:calc(var(--border,1px)*-1);margin-inline-start:0}.xl\:join-horizontal{flex-direction:row}.xl\:join-horizontal>.join-item:first-child{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.xl\:join-horizontal :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.xl\:join-horizontal>.join-item:last-child{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.xl\:join-horizontal :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.xl\:join-horizontal>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.xl\:join-horizontal :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.xl\:join-horizontal .join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}}@media (min-width:1536px){.\32 xl\:join{--join-ss:0;--join-se:0;--join-es:0;--join-ee:0;align-items:stretch;display:inline-flex}.\32 xl\:join :where(.join-item){border-start-start-radius:var(--join-ss,0);border-start-end-radius:var(--join-se,0);border-end-end-radius:var(--join-ee,0);border-end-start-radius:var(--join-es,0)}.\32 xl\:join :where(.join-item) *{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.\32 xl\:join>.join-item:where(:first-child){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.\32 xl\:join :first-child:not(:last-child) :where(.join-item){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.\32 xl\:join>.join-item:where(:last-child){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.\32 xl\:join :last-child:not(:first-child) :where(.join-item){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.\32 xl\:join>.join-item:where(:only-child){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.\32 xl\:join :only-child :where(.join-item){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.\32 xl\:join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}.\32 xl\:join-vertical{flex-direction:column}.\32 xl\:join-vertical>.join-item:first-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.\32 xl\:join-vertical :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:0;--join-ee:0}.\32 xl\:join-vertical>.join-item:last-child{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.\32 xl\:join-vertical :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:0;--join-es:var(--radius-field);--join-ee:var(--radius-field)}.\32 xl\:join-vertical>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.\32 xl\:join-vertical :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.\32 xl\:join-vertical .join-item:where(:not(:first-child)){margin-block-start:calc(var(--border,1px)*-1);margin-inline-start:0}.\32 xl\:join-horizontal{flex-direction:row}.\32 xl\:join-horizontal>.join-item:first-child{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.\32 xl\:join-horizontal :first-child:not(:last-child) .join-item{--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.\32 xl\:join-horizontal>.join-item:last-child{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.\32 xl\:join-horizontal :last-child:not(:first-child) .join-item{--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.\32 xl\:join-horizontal>.join-item:only-child{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.\32 xl\:join-horizontal :only-child .join-item{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.\32 xl\:join-horizontal .join-item:where(:not(:first-child)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}}.rounded-box{border-radius:var(--radius-box)}.rounded-field{border-radius:var(--radius-field)}.rounded-selector{border-radius:var(--radius-selector)}.rounded-t-box{border-top-left-radius:var(--radius-box);border-top-right-radius:var(--radius-box)}.rounded-b-box{border-bottom-left-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.rounded-l-box{border-top-left-radius:var(--radius-box);border-bottom-left-radius:var(--radius-box)}.rounded-r-box{border-top-right-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.rounded-tl-box{border-top-left-radius:var(--radius-box)}.rounded-tr-box{border-top-right-radius:var(--radius-box)}.rounded-br-box{border-bottom-right-radius:var(--radius-box)}.rounded-bl-box{border-bottom-left-radius:var(--radius-box)}.rounded-t-field{border-top-left-radius:var(--radius-field);border-top-right-radius:var(--radius-field)}.rounded-b-field{border-bottom-left-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.rounded-l-field{border-top-left-radius:var(--radius-field);border-bottom-left-radius:var(--radius-field)}.rounded-r-field{border-top-right-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.rounded-tl-field{border-top-left-radius:var(--radius-field)}.rounded-tr-field{border-top-right-radius:var(--radius-field)}.rounded-br-field{border-bottom-right-radius:var(--radius-field)}.rounded-bl-field{border-bottom-left-radius:var(--radius-field)}.rounded-t-selector{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector)}.rounded-b-selector{border-bottom-left-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.rounded-l-selector{border-top-left-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.rounded-r-selector{border-top-right-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.rounded-tl-selector{border-top-left-radius:var(--radius-selector)}.rounded-tr-selector{border-top-right-radius:var(--radius-selector)}.rounded-br-selector{border-bottom-right-radius:var(--radius-selector)}.rounded-bl-selector{border-bottom-left-radius:var(--radius-selector)}@media (min-width:640px){.sm\:rounded-box{border-radius:var(--radius-box)}.sm\:rounded-field{border-radius:var(--radius-field)}.sm\:rounded-selector{border-radius:var(--radius-selector)}.sm\:rounded-t-box{border-top-left-radius:var(--radius-box);border-top-right-radius:var(--radius-box)}.sm\:rounded-b-box{border-bottom-left-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.sm\:rounded-l-box{border-top-left-radius:var(--radius-box);border-bottom-left-radius:var(--radius-box)}.sm\:rounded-r-box{border-top-right-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.sm\:rounded-tl-box{border-top-left-radius:var(--radius-box)}.sm\:rounded-tr-box{border-top-right-radius:var(--radius-box)}.sm\:rounded-br-box{border-bottom-right-radius:var(--radius-box)}.sm\:rounded-bl-box{border-bottom-left-radius:var(--radius-box)}.sm\:rounded-t-field{border-top-left-radius:var(--radius-field);border-top-right-radius:var(--radius-field)}.sm\:rounded-b-field{border-bottom-left-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.sm\:rounded-l-field{border-top-left-radius:var(--radius-field);border-bottom-left-radius:var(--radius-field)}.sm\:rounded-r-field{border-top-right-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.sm\:rounded-tl-field{border-top-left-radius:var(--radius-field)}.sm\:rounded-tr-field{border-top-right-radius:var(--radius-field)}.sm\:rounded-br-field{border-bottom-right-radius:var(--radius-field)}.sm\:rounded-bl-field{border-bottom-left-radius:var(--radius-field)}.sm\:rounded-t-selector{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector)}.sm\:rounded-b-selector{border-bottom-left-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.sm\:rounded-l-selector{border-top-left-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.sm\:rounded-r-selector{border-top-right-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.sm\:rounded-tl-selector{border-top-left-radius:var(--radius-selector)}.sm\:rounded-tr-selector{border-top-right-radius:var(--radius-selector)}.sm\:rounded-br-selector{border-bottom-right-radius:var(--radius-selector)}.sm\:rounded-bl-selector{border-bottom-left-radius:var(--radius-selector)}}@media (min-width:768px){.md\:rounded-box{border-radius:var(--radius-box)}.md\:rounded-field{border-radius:var(--radius-field)}.md\:rounded-selector{border-radius:var(--radius-selector)}.md\:rounded-t-box{border-top-left-radius:var(--radius-box);border-top-right-radius:var(--radius-box)}.md\:rounded-b-box{border-bottom-left-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.md\:rounded-l-box{border-top-left-radius:var(--radius-box);border-bottom-left-radius:var(--radius-box)}.md\:rounded-r-box{border-top-right-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.md\:rounded-tl-box{border-top-left-radius:var(--radius-box)}.md\:rounded-tr-box{border-top-right-radius:var(--radius-box)}.md\:rounded-br-box{border-bottom-right-radius:var(--radius-box)}.md\:rounded-bl-box{border-bottom-left-radius:var(--radius-box)}.md\:rounded-t-field{border-top-left-radius:var(--radius-field);border-top-right-radius:var(--radius-field)}.md\:rounded-b-field{border-bottom-left-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.md\:rounded-l-field{border-top-left-radius:var(--radius-field);border-bottom-left-radius:var(--radius-field)}.md\:rounded-r-field{border-top-right-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.md\:rounded-tl-field{border-top-left-radius:var(--radius-field)}.md\:rounded-tr-field{border-top-right-radius:var(--radius-field)}.md\:rounded-br-field{border-bottom-right-radius:var(--radius-field)}.md\:rounded-bl-field{border-bottom-left-radius:var(--radius-field)}.md\:rounded-t-selector{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector)}.md\:rounded-b-selector{border-bottom-left-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.md\:rounded-l-selector{border-top-left-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.md\:rounded-r-selector{border-top-right-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.md\:rounded-tl-selector{border-top-left-radius:var(--radius-selector)}.md\:rounded-tr-selector{border-top-right-radius:var(--radius-selector)}.md\:rounded-br-selector{border-bottom-right-radius:var(--radius-selector)}.md\:rounded-bl-selector{border-bottom-left-radius:var(--radius-selector)}}@media (min-width:1024px){.lg\:rounded-box{border-radius:var(--radius-box)}.lg\:rounded-field{border-radius:var(--radius-field)}.lg\:rounded-selector{border-radius:var(--radius-selector)}.lg\:rounded-t-box{border-top-left-radius:var(--radius-box);border-top-right-radius:var(--radius-box)}.lg\:rounded-b-box{border-bottom-left-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.lg\:rounded-l-box{border-top-left-radius:var(--radius-box);border-bottom-left-radius:var(--radius-box)}.lg\:rounded-r-box{border-top-right-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.lg\:rounded-tl-box{border-top-left-radius:var(--radius-box)}.lg\:rounded-tr-box{border-top-right-radius:var(--radius-box)}.lg\:rounded-br-box{border-bottom-right-radius:var(--radius-box)}.lg\:rounded-bl-box{border-bottom-left-radius:var(--radius-box)}.lg\:rounded-t-field{border-top-left-radius:var(--radius-field);border-top-right-radius:var(--radius-field)}.lg\:rounded-b-field{border-bottom-left-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.lg\:rounded-l-field{border-top-left-radius:var(--radius-field);border-bottom-left-radius:var(--radius-field)}.lg\:rounded-r-field{border-top-right-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.lg\:rounded-tl-field{border-top-left-radius:var(--radius-field)}.lg\:rounded-tr-field{border-top-right-radius:var(--radius-field)}.lg\:rounded-br-field{border-bottom-right-radius:var(--radius-field)}.lg\:rounded-bl-field{border-bottom-left-radius:var(--radius-field)}.lg\:rounded-t-selector{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector)}.lg\:rounded-b-selector{border-bottom-left-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.lg\:rounded-l-selector{border-top-left-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.lg\:rounded-r-selector{border-top-right-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.lg\:rounded-tl-selector{border-top-left-radius:var(--radius-selector)}.lg\:rounded-tr-selector{border-top-right-radius:var(--radius-selector)}.lg\:rounded-br-selector{border-bottom-right-radius:var(--radius-selector)}.lg\:rounded-bl-selector{border-bottom-left-radius:var(--radius-selector)}}@media (min-width:1280px){.xl\:rounded-box{border-radius:var(--radius-box)}.xl\:rounded-field{border-radius:var(--radius-field)}.xl\:rounded-selector{border-radius:var(--radius-selector)}.xl\:rounded-t-box{border-top-left-radius:var(--radius-box);border-top-right-radius:var(--radius-box)}.xl\:rounded-b-box{border-bottom-left-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.xl\:rounded-l-box{border-top-left-radius:var(--radius-box);border-bottom-left-radius:var(--radius-box)}.xl\:rounded-r-box{border-top-right-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.xl\:rounded-tl-box{border-top-left-radius:var(--radius-box)}.xl\:rounded-tr-box{border-top-right-radius:var(--radius-box)}.xl\:rounded-br-box{border-bottom-right-radius:var(--radius-box)}.xl\:rounded-bl-box{border-bottom-left-radius:var(--radius-box)}.xl\:rounded-t-field{border-top-left-radius:var(--radius-field);border-top-right-radius:var(--radius-field)}.xl\:rounded-b-field{border-bottom-left-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.xl\:rounded-l-field{border-top-left-radius:var(--radius-field);border-bottom-left-radius:var(--radius-field)}.xl\:rounded-r-field{border-top-right-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.xl\:rounded-tl-field{border-top-left-radius:var(--radius-field)}.xl\:rounded-tr-field{border-top-right-radius:var(--radius-field)}.xl\:rounded-br-field{border-bottom-right-radius:var(--radius-field)}.xl\:rounded-bl-field{border-bottom-left-radius:var(--radius-field)}.xl\:rounded-t-selector{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector)}.xl\:rounded-b-selector{border-bottom-left-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.xl\:rounded-l-selector{border-top-left-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.xl\:rounded-r-selector{border-top-right-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.xl\:rounded-tl-selector{border-top-left-radius:var(--radius-selector)}.xl\:rounded-tr-selector{border-top-right-radius:var(--radius-selector)}.xl\:rounded-br-selector{border-bottom-right-radius:var(--radius-selector)}.xl\:rounded-bl-selector{border-bottom-left-radius:var(--radius-selector)}}@media (min-width:1536px){.\32 xl\:rounded-box{border-radius:var(--radius-box)}.\32 xl\:rounded-field{border-radius:var(--radius-field)}.\32 xl\:rounded-selector{border-radius:var(--radius-selector)}.\32 xl\:rounded-t-box{border-top-left-radius:var(--radius-box);border-top-right-radius:var(--radius-box)}.\32 xl\:rounded-b-box{border-bottom-left-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.\32 xl\:rounded-l-box{border-top-left-radius:var(--radius-box);border-bottom-left-radius:var(--radius-box)}.\32 xl\:rounded-r-box{border-top-right-radius:var(--radius-box);border-bottom-right-radius:var(--radius-box)}.\32 xl\:rounded-tl-box{border-top-left-radius:var(--radius-box)}.\32 xl\:rounded-tr-box{border-top-right-radius:var(--radius-box)}.\32 xl\:rounded-br-box{border-bottom-right-radius:var(--radius-box)}.\32 xl\:rounded-bl-box{border-bottom-left-radius:var(--radius-box)}.\32 xl\:rounded-t-field{border-top-left-radius:var(--radius-field);border-top-right-radius:var(--radius-field)}.\32 xl\:rounded-b-field{border-bottom-left-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.\32 xl\:rounded-l-field{border-top-left-radius:var(--radius-field);border-bottom-left-radius:var(--radius-field)}.\32 xl\:rounded-r-field{border-top-right-radius:var(--radius-field);border-bottom-right-radius:var(--radius-field)}.\32 xl\:rounded-tl-field{border-top-left-radius:var(--radius-field)}.\32 xl\:rounded-tr-field{border-top-right-radius:var(--radius-field)}.\32 xl\:rounded-br-field{border-bottom-right-radius:var(--radius-field)}.\32 xl\:rounded-bl-field{border-bottom-left-radius:var(--radius-field)}.\32 xl\:rounded-t-selector{border-top-left-radius:var(--radius-selector);border-top-right-radius:var(--radius-selector)}.\32 xl\:rounded-b-selector{border-bottom-left-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.\32 xl\:rounded-l-selector{border-top-left-radius:var(--radius-selector);border-bottom-left-radius:var(--radius-selector)}.\32 xl\:rounded-r-selector{border-top-right-radius:var(--radius-selector);border-bottom-right-radius:var(--radius-selector)}.\32 xl\:rounded-tl-selector{border-top-left-radius:var(--radius-selector)}.\32 xl\:rounded-tr-selector{border-top-right-radius:var(--radius-selector)}.\32 xl\:rounded-br-selector{border-bottom-right-radius:var(--radius-selector)}.\32 xl\:rounded-bl-selector{border-bottom-left-radius:var(--radius-selector)}}:root .prose{--tw-prose-body:color-mix(in oklab,var(--color-base-content)80%,transparent);--tw-prose-headings:var(--color-base-content);--tw-prose-lead:var(--color-base-content);--tw-prose-links:var(--color-base-content);--tw-prose-bold:var(--color-base-content);--tw-prose-counters:var(--color-base-content);--tw-prose-bullets:color-mix(in oklab,var(--color-base-content)50%,transparent);--tw-prose-hr:color-mix(in oklab,var(--color-base-content)20%,transparent);--tw-prose-quotes:var(--color-base-content);--tw-prose-quote-borders:color-mix(in oklab,var(--color-base-content)20%,transparent);--tw-prose-captions:color-mix(in oklab,var(--color-base-content)50%,transparent);--tw-prose-code:var(--color-base-content);--tw-prose-pre-code:var(--color-neutral-content);--tw-prose-pre-bg:var(--color-neutral);--tw-prose-th-borders:color-mix(in oklab,var(--color-base-content)50%,transparent);--tw-prose-td-borders:color-mix(in oklab,var(--color-base-content)20%,transparent);--tw-prose-kbd:color-mix(in oklab,var(--color-base-content)80%,transparent)}:root .prose :where(code):not(pre>code){background-color:var(--color-base-200);border-radius:var(--radius-selector);border:var(--border)solid var(--color-base-300);font-weight:inherit;padding-inline:.5em}:root .prose :where(code):not(pre>code):before{display:none}:root .prose :where(code):not(pre>code):after{display:none}@media (hover:hover){.hover\:bg-base-100:hover:hover{background-color:var(--color-base-100)}}@media (hover:hover){.hover\:text-base-100:hover:hover{color:var(--color-base-100)}}@media (hover:hover){.hover\:border-base-100:hover:hover{border-color:var(--color-base-100)}}@media (hover:hover){.hover\:bg-base-200:hover:hover{background-color:var(--color-base-200)}}@media (hover:hover){.hover\:text-base-200:hover:hover{color:var(--color-base-200)}}@media (hover:hover){.hover\:border-base-200:hover:hover{border-color:var(--color-base-200)}}@media (hover:hover){.hover\:bg-base-300:hover:hover{background-color:var(--color-base-300)}}@media (hover:hover){.hover\:text-base-300:hover:hover{color:var(--color-base-300)}}@media (hover:hover){.hover\:border-base-300:hover:hover{border-color:var(--color-base-300)}}@media (hover:hover){.hover\:bg-base-content:hover:hover{background-color:var(--color-base-content)}}@media (hover:hover){.hover\:text-base-content:hover:hover{color:var(--color-base-content)}}@media (hover:hover){.hover\:border-base-content:hover:hover{border-color:var(--color-base-content)}}@media (hover:hover){.hover\:bg-primary:hover:hover{background-color:var(--color-primary)}}@media (hover:hover){.hover\:text-primary:hover:hover{color:var(--color-primary)}}@media (hover:hover){.hover\:border-primary:hover:hover{border-color:var(--color-primary)}}@media (hover:hover){.hover\:bg-primary-content:hover:hover{background-color:var(--color-primary-content)}}@media (hover:hover){.hover\:text-primary-content:hover:hover{color:var(--color-primary-content)}}@media (hover:hover){.hover\:border-primary-content:hover:hover{border-color:var(--color-primary-content)}}@media (hover:hover){.hover\:bg-secondary:hover:hover{background-color:var(--color-secondary)}}@media (hover:hover){.hover\:text-secondary:hover:hover{color:var(--color-secondary)}}@media (hover:hover){.hover\:border-secondary:hover:hover{border-color:var(--color-secondary)}}@media (hover:hover){.hover\:bg-secondary-content:hover:hover{background-color:var(--color-secondary-content)}}@media (hover:hover){.hover\:text-secondary-content:hover:hover{color:var(--color-secondary-content)}}@media (hover:hover){.hover\:border-secondary-content:hover:hover{border-color:var(--color-secondary-content)}}@media (hover:hover){.hover\:bg-accent:hover:hover{background-color:var(--color-accent)}}@media (hover:hover){.hover\:text-accent:hover:hover{color:var(--color-accent)}}@media (hover:hover){.hover\:border-accent:hover:hover{border-color:var(--color-accent)}}@media (hover:hover){.hover\:bg-accent-content:hover:hover{background-color:var(--color-accent-content)}}@media (hover:hover){.hover\:text-accent-content:hover:hover{color:var(--color-accent-content)}}@media (hover:hover){.hover\:border-accent-content:hover:hover{border-color:var(--color-accent-content)}}@media (hover:hover){.hover\:bg-neutral:hover:hover{background-color:var(--color-neutral)}}@media (hover:hover){.hover\:text-neutral:hover:hover{color:var(--color-neutral)}}@media (hover:hover){.hover\:border-neutral:hover:hover{border-color:var(--color-neutral)}}@media (hover:hover){.hover\:bg-neutral-content:hover:hover{background-color:var(--color-neutral-content)}}@media (hover:hover){.hover\:text-neutral-content:hover:hover{color:var(--color-neutral-content)}}@media (hover:hover){.hover\:border-neutral-content:hover:hover{border-color:var(--color-neutral-content)}}@media (hover:hover){.hover\:bg-info:hover:hover{background-color:var(--color-info)}}@media (hover:hover){.hover\:text-info:hover:hover{color:var(--color-info)}}@media (hover:hover){.hover\:border-info:hover:hover{border-color:var(--color-info)}}@media (hover:hover){.hover\:bg-info-content:hover:hover{background-color:var(--color-info-content)}}@media (hover:hover){.hover\:text-info-content:hover:hover{color:var(--color-info-content)}}@media (hover:hover){.hover\:border-info-content:hover:hover{border-color:var(--color-info-content)}}@media (hover:hover){.hover\:bg-success:hover:hover{background-color:var(--color-success)}}@media (hover:hover){.hover\:text-success:hover:hover{color:var(--color-success)}}@media (hover:hover){.hover\:border-success:hover:hover{border-color:var(--color-success)}}@media (hover:hover){.hover\:bg-success-content:hover:hover{background-color:var(--color-success-content)}}@media (hover:hover){.hover\:text-success-content:hover:hover{color:var(--color-success-content)}}@media (hover:hover){.hover\:border-success-content:hover:hover{border-color:var(--color-success-content)}}@media (hover:hover){.hover\:bg-warning:hover:hover{background-color:var(--color-warning)}}@media (hover:hover){.hover\:text-warning:hover:hover{color:var(--color-warning)}}@media (hover:hover){.hover\:border-warning:hover:hover{border-color:var(--color-warning)}}@media (hover:hover){.hover\:bg-warning-content:hover:hover{background-color:var(--color-warning-content)}}@media (hover:hover){.hover\:text-warning-content:hover:hover{color:var(--color-warning-content)}}@media (hover:hover){.hover\:border-warning-content:hover:hover{border-color:var(--color-warning-content)}}@media (hover:hover){.hover\:bg-error:hover:hover{background-color:var(--color-error)}}@media (hover:hover){.hover\:text-error:hover:hover{color:var(--color-error)}}@media (hover:hover){.hover\:border-error:hover:hover{border-color:var(--color-error)}}@media (hover:hover){.hover\:bg-error-content:hover:hover{background-color:var(--color-error-content)}}@media (hover:hover){.hover\:text-error-content:hover:hover{color:var(--color-error-content)}}@media (hover:hover){.hover\:border-error-content:hover:hover{border-color:var(--color-error-content)}}@media (min-width:40rem){.sm\:bg-base-100{background-color:var(--color-base-100)}.sm\:text-base-100{color:var(--color-base-100)}.sm\:border-base-100{border-color:var(--color-base-100)}.sm\:bg-base-200{background-color:var(--color-base-200)}.sm\:text-base-200{color:var(--color-base-200)}.sm\:border-base-200{border-color:var(--color-base-200)}.sm\:bg-base-300{background-color:var(--color-base-300)}.sm\:text-base-300{color:var(--color-base-300)}.sm\:border-base-300{border-color:var(--color-base-300)}.sm\:bg-base-content{background-color:var(--color-base-content)}.sm\:text-base-content{color:var(--color-base-content)}.sm\:border-base-content{border-color:var(--color-base-content)}.sm\:bg-primary{background-color:var(--color-primary)}.sm\:text-primary{color:var(--color-primary)}.sm\:border-primary{border-color:var(--color-primary)}.sm\:bg-primary-content{background-color:var(--color-primary-content)}.sm\:text-primary-content{color:var(--color-primary-content)}.sm\:border-primary-content{border-color:var(--color-primary-content)}.sm\:bg-secondary{background-color:var(--color-secondary)}.sm\:text-secondary{color:var(--color-secondary)}.sm\:border-secondary{border-color:var(--color-secondary)}.sm\:bg-secondary-content{background-color:var(--color-secondary-content)}.sm\:text-secondary-content{color:var(--color-secondary-content)}.sm\:border-secondary-content{border-color:var(--color-secondary-content)}.sm\:bg-accent{background-color:var(--color-accent)}.sm\:text-accent{color:var(--color-accent)}.sm\:border-accent{border-color:var(--color-accent)}.sm\:bg-accent-content{background-color:var(--color-accent-content)}.sm\:text-accent-content{color:var(--color-accent-content)}.sm\:border-accent-content{border-color:var(--color-accent-content)}.sm\:bg-neutral{background-color:var(--color-neutral)}.sm\:text-neutral{color:var(--color-neutral)}.sm\:border-neutral{border-color:var(--color-neutral)}.sm\:bg-neutral-content{background-color:var(--color-neutral-content)}.sm\:text-neutral-content{color:var(--color-neutral-content)}.sm\:border-neutral-content{border-color:var(--color-neutral-content)}.sm\:bg-info{background-color:var(--color-info)}.sm\:text-info{color:var(--color-info)}.sm\:border-info{border-color:var(--color-info)}.sm\:bg-info-content{background-color:var(--color-info-content)}.sm\:text-info-content{color:var(--color-info-content)}.sm\:border-info-content{border-color:var(--color-info-content)}.sm\:bg-success{background-color:var(--color-success)}.sm\:text-success{color:var(--color-success)}.sm\:border-success{border-color:var(--color-success)}.sm\:bg-success-content{background-color:var(--color-success-content)}.sm\:text-success-content{color:var(--color-success-content)}.sm\:border-success-content{border-color:var(--color-success-content)}.sm\:bg-warning{background-color:var(--color-warning)}.sm\:text-warning{color:var(--color-warning)}.sm\:border-warning{border-color:var(--color-warning)}.sm\:bg-warning-content{background-color:var(--color-warning-content)}.sm\:text-warning-content{color:var(--color-warning-content)}.sm\:border-warning-content{border-color:var(--color-warning-content)}.sm\:bg-error{background-color:var(--color-error)}.sm\:text-error{color:var(--color-error)}.sm\:border-error{border-color:var(--color-error)}.sm\:bg-error-content{background-color:var(--color-error-content)}.sm\:text-error-content{color:var(--color-error-content)}.sm\:border-error-content{border-color:var(--color-error-content)}}@media (min-width:48rem){.md\:bg-base-100{background-color:var(--color-base-100)}.md\:text-base-100{color:var(--color-base-100)}.md\:border-base-100{border-color:var(--color-base-100)}.md\:bg-base-200{background-color:var(--color-base-200)}.md\:text-base-200{color:var(--color-base-200)}.md\:border-base-200{border-color:var(--color-base-200)}.md\:bg-base-300{background-color:var(--color-base-300)}.md\:text-base-300{color:var(--color-base-300)}.md\:border-base-300{border-color:var(--color-base-300)}.md\:bg-base-content{background-color:var(--color-base-content)}.md\:text-base-content{color:var(--color-base-content)}.md\:border-base-content{border-color:var(--color-base-content)}.md\:bg-primary{background-color:var(--color-primary)}.md\:text-primary{color:var(--color-primary)}.md\:border-primary{border-color:var(--color-primary)}.md\:bg-primary-content{background-color:var(--color-primary-content)}.md\:text-primary-content{color:var(--color-primary-content)}.md\:border-primary-content{border-color:var(--color-primary-content)}.md\:bg-secondary{background-color:var(--color-secondary)}.md\:text-secondary{color:var(--color-secondary)}.md\:border-secondary{border-color:var(--color-secondary)}.md\:bg-secondary-content{background-color:var(--color-secondary-content)}.md\:text-secondary-content{color:var(--color-secondary-content)}.md\:border-secondary-content{border-color:var(--color-secondary-content)}.md\:bg-accent{background-color:var(--color-accent)}.md\:text-accent{color:var(--color-accent)}.md\:border-accent{border-color:var(--color-accent)}.md\:bg-accent-content{background-color:var(--color-accent-content)}.md\:text-accent-content{color:var(--color-accent-content)}.md\:border-accent-content{border-color:var(--color-accent-content)}.md\:bg-neutral{background-color:var(--color-neutral)}.md\:text-neutral{color:var(--color-neutral)}.md\:border-neutral{border-color:var(--color-neutral)}.md\:bg-neutral-content{background-color:var(--color-neutral-content)}.md\:text-neutral-content{color:var(--color-neutral-content)}.md\:border-neutral-content{border-color:var(--color-neutral-content)}.md\:bg-info{background-color:var(--color-info)}.md\:text-info{color:var(--color-info)}.md\:border-info{border-color:var(--color-info)}.md\:bg-info-content{background-color:var(--color-info-content)}.md\:text-info-content{color:var(--color-info-content)}.md\:border-info-content{border-color:var(--color-info-content)}.md\:bg-success{background-color:var(--color-success)}.md\:text-success{color:var(--color-success)}.md\:border-success{border-color:var(--color-success)}.md\:bg-success-content{background-color:var(--color-success-content)}.md\:text-success-content{color:var(--color-success-content)}.md\:border-success-content{border-color:var(--color-success-content)}.md\:bg-warning{background-color:var(--color-warning)}.md\:text-warning{color:var(--color-warning)}.md\:border-warning{border-color:var(--color-warning)}.md\:bg-warning-content{background-color:var(--color-warning-content)}.md\:text-warning-content{color:var(--color-warning-content)}.md\:border-warning-content{border-color:var(--color-warning-content)}.md\:bg-error{background-color:var(--color-error)}.md\:text-error{color:var(--color-error)}.md\:border-error{border-color:var(--color-error)}.md\:bg-error-content{background-color:var(--color-error-content)}.md\:text-error-content{color:var(--color-error-content)}.md\:border-error-content{border-color:var(--color-error-content)}}@media (min-width:64rem){.lg\:bg-base-100{background-color:var(--color-base-100)}.lg\:text-base-100{color:var(--color-base-100)}.lg\:border-base-100{border-color:var(--color-base-100)}.lg\:bg-base-200{background-color:var(--color-base-200)}.lg\:text-base-200{color:var(--color-base-200)}.lg\:border-base-200{border-color:var(--color-base-200)}.lg\:bg-base-300{background-color:var(--color-base-300)}.lg\:text-base-300{color:var(--color-base-300)}.lg\:border-base-300{border-color:var(--color-base-300)}.lg\:bg-base-content{background-color:var(--color-base-content)}.lg\:text-base-content{color:var(--color-base-content)}.lg\:border-base-content{border-color:var(--color-base-content)}.lg\:bg-primary{background-color:var(--color-primary)}.lg\:text-primary{color:var(--color-primary)}.lg\:border-primary{border-color:var(--color-primary)}.lg\:bg-primary-content{background-color:var(--color-primary-content)}.lg\:text-primary-content{color:var(--color-primary-content)}.lg\:border-primary-content{border-color:var(--color-primary-content)}.lg\:bg-secondary{background-color:var(--color-secondary)}.lg\:text-secondary{color:var(--color-secondary)}.lg\:border-secondary{border-color:var(--color-secondary)}.lg\:bg-secondary-content{background-color:var(--color-secondary-content)}.lg\:text-secondary-content{color:var(--color-secondary-content)}.lg\:border-secondary-content{border-color:var(--color-secondary-content)}.lg\:bg-accent{background-color:var(--color-accent)}.lg\:text-accent{color:var(--color-accent)}.lg\:border-accent{border-color:var(--color-accent)}.lg\:bg-accent-content{background-color:var(--color-accent-content)}.lg\:text-accent-content{color:var(--color-accent-content)}.lg\:border-accent-content{border-color:var(--color-accent-content)}.lg\:bg-neutral{background-color:var(--color-neutral)}.lg\:text-neutral{color:var(--color-neutral)}.lg\:border-neutral{border-color:var(--color-neutral)}.lg\:bg-neutral-content{background-color:var(--color-neutral-content)}.lg\:text-neutral-content{color:var(--color-neutral-content)}.lg\:border-neutral-content{border-color:var(--color-neutral-content)}.lg\:bg-info{background-color:var(--color-info)}.lg\:text-info{color:var(--color-info)}.lg\:border-info{border-color:var(--color-info)}.lg\:bg-info-content{background-color:var(--color-info-content)}.lg\:text-info-content{color:var(--color-info-content)}.lg\:border-info-content{border-color:var(--color-info-content)}.lg\:bg-success{background-color:var(--color-success)}.lg\:text-success{color:var(--color-success)}.lg\:border-success{border-color:var(--color-success)}.lg\:bg-success-content{background-color:var(--color-success-content)}.lg\:text-success-content{color:var(--color-success-content)}.lg\:border-success-content{border-color:var(--color-success-content)}.lg\:bg-warning{background-color:var(--color-warning)}.lg\:text-warning{color:var(--color-warning)}.lg\:border-warning{border-color:var(--color-warning)}.lg\:bg-warning-content{background-color:var(--color-warning-content)}.lg\:text-warning-content{color:var(--color-warning-content)}.lg\:border-warning-content{border-color:var(--color-warning-content)}.lg\:bg-error{background-color:var(--color-error)}.lg\:text-error{color:var(--color-error)}.lg\:border-error{border-color:var(--color-error)}.lg\:bg-error-content{background-color:var(--color-error-content)}.lg\:text-error-content{color:var(--color-error-content)}.lg\:border-error-content{border-color:var(--color-error-content)}}@media (min-width:80rem){.xl\:bg-base-100{background-color:var(--color-base-100)}.xl\:text-base-100{color:var(--color-base-100)}.xl\:border-base-100{border-color:var(--color-base-100)}.xl\:bg-base-200{background-color:var(--color-base-200)}.xl\:text-base-200{color:var(--color-base-200)}.xl\:border-base-200{border-color:var(--color-base-200)}.xl\:bg-base-300{background-color:var(--color-base-300)}.xl\:text-base-300{color:var(--color-base-300)}.xl\:border-base-300{border-color:var(--color-base-300)}.xl\:bg-base-content{background-color:var(--color-base-content)}.xl\:text-base-content{color:var(--color-base-content)}.xl\:border-base-content{border-color:var(--color-base-content)}.xl\:bg-primary{background-color:var(--color-primary)}.xl\:text-primary{color:var(--color-primary)}.xl\:border-primary{border-color:var(--color-primary)}.xl\:bg-primary-content{background-color:var(--color-primary-content)}.xl\:text-primary-content{color:var(--color-primary-content)}.xl\:border-primary-content{border-color:var(--color-primary-content)}.xl\:bg-secondary{background-color:var(--color-secondary)}.xl\:text-secondary{color:var(--color-secondary)}.xl\:border-secondary{border-color:var(--color-secondary)}.xl\:bg-secondary-content{background-color:var(--color-secondary-content)}.xl\:text-secondary-content{color:var(--color-secondary-content)}.xl\:border-secondary-content{border-color:var(--color-secondary-content)}.xl\:bg-accent{background-color:var(--color-accent)}.xl\:text-accent{color:var(--color-accent)}.xl\:border-accent{border-color:var(--color-accent)}.xl\:bg-accent-content{background-color:var(--color-accent-content)}.xl\:text-accent-content{color:var(--color-accent-content)}.xl\:border-accent-content{border-color:var(--color-accent-content)}.xl\:bg-neutral{background-color:var(--color-neutral)}.xl\:text-neutral{color:var(--color-neutral)}.xl\:border-neutral{border-color:var(--color-neutral)}.xl\:bg-neutral-content{background-color:var(--color-neutral-content)}.xl\:text-neutral-content{color:var(--color-neutral-content)}.xl\:border-neutral-content{border-color:var(--color-neutral-content)}.xl\:bg-info{background-color:var(--color-info)}.xl\:text-info{color:var(--color-info)}.xl\:border-info{border-color:var(--color-info)}.xl\:bg-info-content{background-color:var(--color-info-content)}.xl\:text-info-content{color:var(--color-info-content)}.xl\:border-info-content{border-color:var(--color-info-content)}.xl\:bg-success{background-color:var(--color-success)}.xl\:text-success{color:var(--color-success)}.xl\:border-success{border-color:var(--color-success)}.xl\:bg-success-content{background-color:var(--color-success-content)}.xl\:text-success-content{color:var(--color-success-content)}.xl\:border-success-content{border-color:var(--color-success-content)}.xl\:bg-warning{background-color:var(--color-warning)}.xl\:text-warning{color:var(--color-warning)}.xl\:border-warning{border-color:var(--color-warning)}.xl\:bg-warning-content{background-color:var(--color-warning-content)}.xl\:text-warning-content{color:var(--color-warning-content)}.xl\:border-warning-content{border-color:var(--color-warning-content)}.xl\:bg-error{background-color:var(--color-error)}.xl\:text-error{color:var(--color-error)}.xl\:border-error{border-color:var(--color-error)}.xl\:bg-error-content{background-color:var(--color-error-content)}.xl\:text-error-content{color:var(--color-error-content)}.xl\:border-error-content{border-color:var(--color-error-content)}}@media (min-width:96rem){.\32 xl\:bg-base-100{background-color:var(--color-base-100)}.\32 xl\:text-base-100{color:var(--color-base-100)}.\32 xl\:border-base-100{border-color:var(--color-base-100)}.\32 xl\:bg-base-200{background-color:var(--color-base-200)}.\32 xl\:text-base-200{color:var(--color-base-200)}.\32 xl\:border-base-200{border-color:var(--color-base-200)}.\32 xl\:bg-base-300{background-color:var(--color-base-300)}.\32 xl\:text-base-300{color:var(--color-base-300)}.\32 xl\:border-base-300{border-color:var(--color-base-300)}.\32 xl\:bg-base-content{background-color:var(--color-base-content)}.\32 xl\:text-base-content{color:var(--color-base-content)}.\32 xl\:border-base-content{border-color:var(--color-base-content)}.\32 xl\:bg-primary{background-color:var(--color-primary)}.\32 xl\:text-primary{color:var(--color-primary)}.\32 xl\:border-primary{border-color:var(--color-primary)}.\32 xl\:bg-primary-content{background-color:var(--color-primary-content)}.\32 xl\:text-primary-content{color:var(--color-primary-content)}.\32 xl\:border-primary-content{border-color:var(--color-primary-content)}.\32 xl\:bg-secondary{background-color:var(--color-secondary)}.\32 xl\:text-secondary{color:var(--color-secondary)}.\32 xl\:border-secondary{border-color:var(--color-secondary)}.\32 xl\:bg-secondary-content{background-color:var(--color-secondary-content)}.\32 xl\:text-secondary-content{color:var(--color-secondary-content)}.\32 xl\:border-secondary-content{border-color:var(--color-secondary-content)}.\32 xl\:bg-accent{background-color:var(--color-accent)}.\32 xl\:text-accent{color:var(--color-accent)}.\32 xl\:border-accent{border-color:var(--color-accent)}.\32 xl\:bg-accent-content{background-color:var(--color-accent-content)}.\32 xl\:text-accent-content{color:var(--color-accent-content)}.\32 xl\:border-accent-content{border-color:var(--color-accent-content)}.\32 xl\:bg-neutral{background-color:var(--color-neutral)}.\32 xl\:text-neutral{color:var(--color-neutral)}.\32 xl\:border-neutral{border-color:var(--color-neutral)}.\32 xl\:bg-neutral-content{background-color:var(--color-neutral-content)}.\32 xl\:text-neutral-content{color:var(--color-neutral-content)}.\32 xl\:border-neutral-content{border-color:var(--color-neutral-content)}.\32 xl\:bg-info{background-color:var(--color-info)}.\32 xl\:text-info{color:var(--color-info)}.\32 xl\:border-info{border-color:var(--color-info)}.\32 xl\:bg-info-content{background-color:var(--color-info-content)}.\32 xl\:text-info-content{color:var(--color-info-content)}.\32 xl\:border-info-content{border-color:var(--color-info-content)}.\32 xl\:bg-success{background-color:var(--color-success)}.\32 xl\:text-success{color:var(--color-success)}.\32 xl\:border-success{border-color:var(--color-success)}.\32 xl\:bg-success-content{background-color:var(--color-success-content)}.\32 xl\:text-success-content{color:var(--color-success-content)}.\32 xl\:border-success-content{border-color:var(--color-success-content)}.\32 xl\:bg-warning{background-color:var(--color-warning)}.\32 xl\:text-warning{color:var(--color-warning)}.\32 xl\:border-warning{border-color:var(--color-warning)}.\32 xl\:bg-warning-content{background-color:var(--color-warning-content)}.\32 xl\:text-warning-content{color:var(--color-warning-content)}.\32 xl\:border-warning-content{border-color:var(--color-warning-content)}.\32 xl\:bg-error{background-color:var(--color-error)}.\32 xl\:text-error{color:var(--color-error)}.\32 xl\:border-error{border-color:var(--color-error)}.\32 xl\:bg-error-content{background-color:var(--color-error-content)}.\32 xl\:text-error-content{color:var(--color-error-content)}.\32 xl\:border-error-content{border-color:var(--color-error-content)}}.bg-base-100{background-color:var(--color-base-100)}.bg-base-100\/10{background-color:color-mix(in oklab,var(--color-base-100)10%,transparent)}.bg-base-100\/20{background-color:color-mix(in oklab,var(--color-base-100)20%,transparent)}.bg-base-100\/30{background-color:color-mix(in oklab,var(--color-base-100)30%,transparent)}.bg-base-100\/40{background-color:color-mix(in oklab,var(--color-base-100)40%,transparent)}.bg-base-100\/50{background-color:color-mix(in oklab,var(--color-base-100)50%,transparent)}.bg-base-100\/60{background-color:color-mix(in oklab,var(--color-base-100)60%,transparent)}.bg-base-100\/70{background-color:color-mix(in oklab,var(--color-base-100)70%,transparent)}.bg-base-100\/80{background-color:color-mix(in oklab,var(--color-base-100)80%,transparent)}.bg-base-100\/90{background-color:color-mix(in oklab,var(--color-base-100)90%,transparent)}.text-base-100{color:var(--color-base-100)}.text-base-100\/10{color:color-mix(in oklab,var(--color-base-100)10%,transparent)}.text-base-100\/20{color:color-mix(in oklab,var(--color-base-100)20%,transparent)}.text-base-100\/30{color:color-mix(in oklab,var(--color-base-100)30%,transparent)}.text-base-100\/40{color:color-mix(in oklab,var(--color-base-100)40%,transparent)}.text-base-100\/50{color:color-mix(in oklab,var(--color-base-100)50%,transparent)}.text-base-100\/60{color:color-mix(in oklab,var(--color-base-100)60%,transparent)}.text-base-100\/70{color:color-mix(in oklab,var(--color-base-100)70%,transparent)}.text-base-100\/80{color:color-mix(in oklab,var(--color-base-100)80%,transparent)}.text-base-100\/90{color:color-mix(in oklab,var(--color-base-100)90%,transparent)}.border-base-100{border-color:var(--color-base-100)}.border-base-100\/10{border-color:color-mix(in oklab,var(--color-base-100)10%,transparent)}.border-base-100\/20{border-color:color-mix(in oklab,var(--color-base-100)20%,transparent)}.border-base-100\/30{border-color:color-mix(in oklab,var(--color-base-100)30%,transparent)}.border-base-100\/40{border-color:color-mix(in oklab,var(--color-base-100)40%,transparent)}.border-base-100\/50{border-color:color-mix(in oklab,var(--color-base-100)50%,transparent)}.border-base-100\/60{border-color:color-mix(in oklab,var(--color-base-100)60%,transparent)}.border-base-100\/70{border-color:color-mix(in oklab,var(--color-base-100)70%,transparent)}.border-base-100\/80{border-color:color-mix(in oklab,var(--color-base-100)80%,transparent)}.border-base-100\/90{border-color:color-mix(in oklab,var(--color-base-100)90%,transparent)}.bg-base-200{background-color:var(--color-base-200)}.bg-base-200\/10{background-color:color-mix(in oklab,var(--color-base-200)10%,transparent)}.bg-base-200\/20{background-color:color-mix(in oklab,var(--color-base-200)20%,transparent)}.bg-base-200\/30{background-color:color-mix(in oklab,var(--color-base-200)30%,transparent)}.bg-base-200\/40{background-color:color-mix(in oklab,var(--color-base-200)40%,transparent)}.bg-base-200\/50{background-color:color-mix(in oklab,var(--color-base-200)50%,transparent)}.bg-base-200\/60{background-color:color-mix(in oklab,var(--color-base-200)60%,transparent)}.bg-base-200\/70{background-color:color-mix(in oklab,var(--color-base-200)70%,transparent)}.bg-base-200\/80{background-color:color-mix(in oklab,var(--color-base-200)80%,transparent)}.bg-base-200\/90{background-color:color-mix(in oklab,var(--color-base-200)90%,transparent)}.text-base-200{color:var(--color-base-200)}.text-base-200\/10{color:color-mix(in oklab,var(--color-base-200)10%,transparent)}.text-base-200\/20{color:color-mix(in oklab,var(--color-base-200)20%,transparent)}.text-base-200\/30{color:color-mix(in oklab,var(--color-base-200)30%,transparent)}.text-base-200\/40{color:color-mix(in oklab,var(--color-base-200)40%,transparent)}.text-base-200\/50{color:color-mix(in oklab,var(--color-base-200)50%,transparent)}.text-base-200\/60{color:color-mix(in oklab,var(--color-base-200)60%,transparent)}.text-base-200\/70{color:color-mix(in oklab,var(--color-base-200)70%,transparent)}.text-base-200\/80{color:color-mix(in oklab,var(--color-base-200)80%,transparent)}.text-base-200\/90{color:color-mix(in oklab,var(--color-base-200)90%,transparent)}.border-base-200{border-color:var(--color-base-200)}.border-base-200\/10{border-color:color-mix(in oklab,var(--color-base-200)10%,transparent)}.border-base-200\/20{border-color:color-mix(in oklab,var(--color-base-200)20%,transparent)}.border-base-200\/30{border-color:color-mix(in oklab,var(--color-base-200)30%,transparent)}.border-base-200\/40{border-color:color-mix(in oklab,var(--color-base-200)40%,transparent)}.border-base-200\/50{border-color:color-mix(in oklab,var(--color-base-200)50%,transparent)}.border-base-200\/60{border-color:color-mix(in oklab,var(--color-base-200)60%,transparent)}.border-base-200\/70{border-color:color-mix(in oklab,var(--color-base-200)70%,transparent)}.border-base-200\/80{border-color:color-mix(in oklab,var(--color-base-200)80%,transparent)}.border-base-200\/90{border-color:color-mix(in oklab,var(--color-base-200)90%,transparent)}.bg-base-300{background-color:var(--color-base-300)}.bg-base-300\/10{background-color:color-mix(in oklab,var(--color-base-300)10%,transparent)}.bg-base-300\/20{background-color:color-mix(in oklab,var(--color-base-300)20%,transparent)}.bg-base-300\/30{background-color:color-mix(in oklab,var(--color-base-300)30%,transparent)}.bg-base-300\/40{background-color:color-mix(in oklab,var(--color-base-300)40%,transparent)}.bg-base-300\/50{background-color:color-mix(in oklab,var(--color-base-300)50%,transparent)}.bg-base-300\/60{background-color:color-mix(in oklab,var(--color-base-300)60%,transparent)}.bg-base-300\/70{background-color:color-mix(in oklab,var(--color-base-300)70%,transparent)}.bg-base-300\/80{background-color:color-mix(in oklab,var(--color-base-300)80%,transparent)}.bg-base-300\/90{background-color:color-mix(in oklab,var(--color-base-300)90%,transparent)}.text-base-300{color:var(--color-base-300)}.text-base-300\/10{color:color-mix(in oklab,var(--color-base-300)10%,transparent)}.text-base-300\/20{color:color-mix(in oklab,var(--color-base-300)20%,transparent)}.text-base-300\/30{color:color-mix(in oklab,var(--color-base-300)30%,transparent)}.text-base-300\/40{color:color-mix(in oklab,var(--color-base-300)40%,transparent)}.text-base-300\/50{color:color-mix(in oklab,var(--color-base-300)50%,transparent)}.text-base-300\/60{color:color-mix(in oklab,var(--color-base-300)60%,transparent)}.text-base-300\/70{color:color-mix(in oklab,var(--color-base-300)70%,transparent)}.text-base-300\/80{color:color-mix(in oklab,var(--color-base-300)80%,transparent)}.text-base-300\/90{color:color-mix(in oklab,var(--color-base-300)90%,transparent)}.border-base-300{border-color:var(--color-base-300)}.border-base-300\/10{border-color:color-mix(in oklab,var(--color-base-300)10%,transparent)}.border-base-300\/20{border-color:color-mix(in oklab,var(--color-base-300)20%,transparent)}.border-base-300\/30{border-color:color-mix(in oklab,var(--color-base-300)30%,transparent)}.border-base-300\/40{border-color:color-mix(in oklab,var(--color-base-300)40%,transparent)}.border-base-300\/50{border-color:color-mix(in oklab,var(--color-base-300)50%,transparent)}.border-base-300\/60{border-color:color-mix(in oklab,var(--color-base-300)60%,transparent)}.border-base-300\/70{border-color:color-mix(in oklab,var(--color-base-300)70%,transparent)}.border-base-300\/80{border-color:color-mix(in oklab,var(--color-base-300)80%,transparent)}.border-base-300\/90{border-color:color-mix(in oklab,var(--color-base-300)90%,transparent)}.bg-base-content{background-color:var(--color-base-content)}.bg-base-content\/10{background-color:color-mix(in oklab,var(--color-base-content)10%,transparent)}.bg-base-content\/20{background-color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.bg-base-content\/30{background-color:color-mix(in oklab,var(--color-base-content)30%,transparent)}.bg-base-content\/40{background-color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.bg-base-content\/50{background-color:color-mix(in oklab,var(--color-base-content)50%,transparent)}.bg-base-content\/60{background-color:color-mix(in oklab,var(--color-base-content)60%,transparent)}.bg-base-content\/70{background-color:color-mix(in oklab,var(--color-base-content)70%,transparent)}.bg-base-content\/80{background-color:color-mix(in oklab,var(--color-base-content)80%,transparent)}.bg-base-content\/90{background-color:color-mix(in oklab,var(--color-base-content)90%,transparent)}.text-base-content{color:var(--color-base-content)}.text-base-content\/10{color:color-mix(in oklab,var(--color-base-content)10%,transparent)}.text-base-content\/20{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.text-base-content\/30{color:color-mix(in oklab,var(--color-base-content)30%,transparent)}.text-base-content\/40{color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.text-base-content\/50{color:color-mix(in oklab,var(--color-base-content)50%,transparent)}.text-base-content\/60{color:color-mix(in oklab,var(--color-base-content)60%,transparent)}.text-base-content\/70{color:color-mix(in oklab,var(--color-base-content)70%,transparent)}.text-base-content\/80{color:color-mix(in oklab,var(--color-base-content)80%,transparent)}.text-base-content\/90{color:color-mix(in oklab,var(--color-base-content)90%,transparent)}.border-base-content{border-color:var(--color-base-content)}.border-base-content\/10{border-color:color-mix(in oklab,var(--color-base-content)10%,transparent)}.border-base-content\/20{border-color:color-mix(in oklab,var(--color-base-content)20%,transparent)}.border-base-content\/30{border-color:color-mix(in oklab,var(--color-base-content)30%,transparent)}.border-base-content\/40{border-color:color-mix(in oklab,var(--color-base-content)40%,transparent)}.border-base-content\/50{border-color:color-mix(in oklab,var(--color-base-content)50%,transparent)}.border-base-content\/60{border-color:color-mix(in oklab,var(--color-base-content)60%,transparent)}.border-base-content\/70{border-color:color-mix(in oklab,var(--color-base-content)70%,transparent)}.border-base-content\/80{border-color:color-mix(in oklab,var(--color-base-content)80%,transparent)}.border-base-content\/90{border-color:color-mix(in oklab,var(--color-base-content)90%,transparent)}.bg-primary{background-color:var(--color-primary)}.bg-primary\/10{background-color:color-mix(in oklab,var(--color-primary)10%,transparent)}.bg-primary\/20{background-color:color-mix(in oklab,var(--color-primary)20%,transparent)}.bg-primary\/30{background-color:color-mix(in oklab,var(--color-primary)30%,transparent)}.bg-primary\/40{background-color:color-mix(in oklab,var(--color-primary)40%,transparent)}.bg-primary\/50{background-color:color-mix(in oklab,var(--color-primary)50%,transparent)}.bg-primary\/60{background-color:color-mix(in oklab,var(--color-primary)60%,transparent)}.bg-primary\/70{background-color:color-mix(in oklab,var(--color-primary)70%,transparent)}.bg-primary\/80{background-color:color-mix(in oklab,var(--color-primary)80%,transparent)}.bg-primary\/90{background-color:color-mix(in oklab,var(--color-primary)90%,transparent)}.text-primary{color:var(--color-primary)}.text-primary\/10{color:color-mix(in oklab,var(--color-primary)10%,transparent)}.text-primary\/20{color:color-mix(in oklab,var(--color-primary)20%,transparent)}.text-primary\/30{color:color-mix(in oklab,var(--color-primary)30%,transparent)}.text-primary\/40{color:color-mix(in oklab,var(--color-primary)40%,transparent)}.text-primary\/50{color:color-mix(in oklab,var(--color-primary)50%,transparent)}.text-primary\/60{color:color-mix(in oklab,var(--color-primary)60%,transparent)}.text-primary\/70{color:color-mix(in oklab,var(--color-primary)70%,transparent)}.text-primary\/80{color:color-mix(in oklab,var(--color-primary)80%,transparent)}.text-primary\/90{color:color-mix(in oklab,var(--color-primary)90%,transparent)}.border-primary{border-color:var(--color-primary)}.border-primary\/10{border-color:color-mix(in oklab,var(--color-primary)10%,transparent)}.border-primary\/20{border-color:color-mix(in oklab,var(--color-primary)20%,transparent)}.border-primary\/30{border-color:color-mix(in oklab,var(--color-primary)30%,transparent)}.border-primary\/40{border-color:color-mix(in oklab,var(--color-primary)40%,transparent)}.border-primary\/50{border-color:color-mix(in oklab,var(--color-primary)50%,transparent)}.border-primary\/60{border-color:color-mix(in oklab,var(--color-primary)60%,transparent)}.border-primary\/70{border-color:color-mix(in oklab,var(--color-primary)70%,transparent)}.border-primary\/80{border-color:color-mix(in oklab,var(--color-primary)80%,transparent)}.border-primary\/90{border-color:color-mix(in oklab,var(--color-primary)90%,transparent)}.bg-primary-content{background-color:var(--color-primary-content)}.bg-primary-content\/10{background-color:color-mix(in oklab,var(--color-primary-content)10%,transparent)}.bg-primary-content\/20{background-color:color-mix(in oklab,var(--color-primary-content)20%,transparent)}.bg-primary-content\/30{background-color:color-mix(in oklab,var(--color-primary-content)30%,transparent)}.bg-primary-content\/40{background-color:color-mix(in oklab,var(--color-primary-content)40%,transparent)}.bg-primary-content\/50{background-color:color-mix(in oklab,var(--color-primary-content)50%,transparent)}.bg-primary-content\/60{background-color:color-mix(in oklab,var(--color-primary-content)60%,transparent)}.bg-primary-content\/70{background-color:color-mix(in oklab,var(--color-primary-content)70%,transparent)}.bg-primary-content\/80{background-color:color-mix(in oklab,var(--color-primary-content)80%,transparent)}.bg-primary-content\/90{background-color:color-mix(in oklab,var(--color-primary-content)90%,transparent)}.text-primary-content{color:var(--color-primary-content)}.text-primary-content\/10{color:color-mix(in oklab,var(--color-primary-content)10%,transparent)}.text-primary-content\/20{color:color-mix(in oklab,var(--color-primary-content)20%,transparent)}.text-primary-content\/30{color:color-mix(in oklab,var(--color-primary-content)30%,transparent)}.text-primary-content\/40{color:color-mix(in oklab,var(--color-primary-content)40%,transparent)}.text-primary-content\/50{color:color-mix(in oklab,var(--color-primary-content)50%,transparent)}.text-primary-content\/60{color:color-mix(in oklab,var(--color-primary-content)60%,transparent)}.text-primary-content\/70{color:color-mix(in oklab,var(--color-primary-content)70%,transparent)}.text-primary-content\/80{color:color-mix(in oklab,var(--color-primary-content)80%,transparent)}.text-primary-content\/90{color:color-mix(in oklab,var(--color-primary-content)90%,transparent)}.border-primary-content{border-color:var(--color-primary-content)}.border-primary-content\/10{border-color:color-mix(in oklab,var(--color-primary-content)10%,transparent)}.border-primary-content\/20{border-color:color-mix(in oklab,var(--color-primary-content)20%,transparent)}.border-primary-content\/30{border-color:color-mix(in oklab,var(--color-primary-content)30%,transparent)}.border-primary-content\/40{border-color:color-mix(in oklab,var(--color-primary-content)40%,transparent)}.border-primary-content\/50{border-color:color-mix(in oklab,var(--color-primary-content)50%,transparent)}.border-primary-content\/60{border-color:color-mix(in oklab,var(--color-primary-content)60%,transparent)}.border-primary-content\/70{border-color:color-mix(in oklab,var(--color-primary-content)70%,transparent)}.border-primary-content\/80{border-color:color-mix(in oklab,var(--color-primary-content)80%,transparent)}.border-primary-content\/90{border-color:color-mix(in oklab,var(--color-primary-content)90%,transparent)}.bg-secondary{background-color:var(--color-secondary)}.bg-secondary\/10{background-color:color-mix(in oklab,var(--color-secondary)10%,transparent)}.bg-secondary\/20{background-color:color-mix(in oklab,var(--color-secondary)20%,transparent)}.bg-secondary\/30{background-color:color-mix(in oklab,var(--color-secondary)30%,transparent)}.bg-secondary\/40{background-color:color-mix(in oklab,var(--color-secondary)40%,transparent)}.bg-secondary\/50{background-color:color-mix(in oklab,var(--color-secondary)50%,transparent)}.bg-secondary\/60{background-color:color-mix(in oklab,var(--color-secondary)60%,transparent)}.bg-secondary\/70{background-color:color-mix(in oklab,var(--color-secondary)70%,transparent)}.bg-secondary\/80{background-color:color-mix(in oklab,var(--color-secondary)80%,transparent)}.bg-secondary\/90{background-color:color-mix(in oklab,var(--color-secondary)90%,transparent)}.text-secondary{color:var(--color-secondary)}.text-secondary\/10{color:color-mix(in oklab,var(--color-secondary)10%,transparent)}.text-secondary\/20{color:color-mix(in oklab,var(--color-secondary)20%,transparent)}.text-secondary\/30{color:color-mix(in oklab,var(--color-secondary)30%,transparent)}.text-secondary\/40{color:color-mix(in oklab,var(--color-secondary)40%,transparent)}.text-secondary\/50{color:color-mix(in oklab,var(--color-secondary)50%,transparent)}.text-secondary\/60{color:color-mix(in oklab,var(--color-secondary)60%,transparent)}.text-secondary\/70{color:color-mix(in oklab,var(--color-secondary)70%,transparent)}.text-secondary\/80{color:color-mix(in oklab,var(--color-secondary)80%,transparent)}.text-secondary\/90{color:color-mix(in oklab,var(--color-secondary)90%,transparent)}.border-secondary{border-color:var(--color-secondary)}.border-secondary\/10{border-color:color-mix(in oklab,var(--color-secondary)10%,transparent)}.border-secondary\/20{border-color:color-mix(in oklab,var(--color-secondary)20%,transparent)}.border-secondary\/30{border-color:color-mix(in oklab,var(--color-secondary)30%,transparent)}.border-secondary\/40{border-color:color-mix(in oklab,var(--color-secondary)40%,transparent)}.border-secondary\/50{border-color:color-mix(in oklab,var(--color-secondary)50%,transparent)}.border-secondary\/60{border-color:color-mix(in oklab,var(--color-secondary)60%,transparent)}.border-secondary\/70{border-color:color-mix(in oklab,var(--color-secondary)70%,transparent)}.border-secondary\/80{border-color:color-mix(in oklab,var(--color-secondary)80%,transparent)}.border-secondary\/90{border-color:color-mix(in oklab,var(--color-secondary)90%,transparent)}.bg-secondary-content{background-color:var(--color-secondary-content)}.bg-secondary-content\/10{background-color:color-mix(in oklab,var(--color-secondary-content)10%,transparent)}.bg-secondary-content\/20{background-color:color-mix(in oklab,var(--color-secondary-content)20%,transparent)}.bg-secondary-content\/30{background-color:color-mix(in oklab,var(--color-secondary-content)30%,transparent)}.bg-secondary-content\/40{background-color:color-mix(in oklab,var(--color-secondary-content)40%,transparent)}.bg-secondary-content\/50{background-color:color-mix(in oklab,var(--color-secondary-content)50%,transparent)}.bg-secondary-content\/60{background-color:color-mix(in oklab,var(--color-secondary-content)60%,transparent)}.bg-secondary-content\/70{background-color:color-mix(in oklab,var(--color-secondary-content)70%,transparent)}.bg-secondary-content\/80{background-color:color-mix(in oklab,var(--color-secondary-content)80%,transparent)}.bg-secondary-content\/90{background-color:color-mix(in oklab,var(--color-secondary-content)90%,transparent)}.text-secondary-content{color:var(--color-secondary-content)}.text-secondary-content\/10{color:color-mix(in oklab,var(--color-secondary-content)10%,transparent)}.text-secondary-content\/20{color:color-mix(in oklab,var(--color-secondary-content)20%,transparent)}.text-secondary-content\/30{color:color-mix(in oklab,var(--color-secondary-content)30%,transparent)}.text-secondary-content\/40{color:color-mix(in oklab,var(--color-secondary-content)40%,transparent)}.text-secondary-content\/50{color:color-mix(in oklab,var(--color-secondary-content)50%,transparent)}.text-secondary-content\/60{color:color-mix(in oklab,var(--color-secondary-content)60%,transparent)}.text-secondary-content\/70{color:color-mix(in oklab,var(--color-secondary-content)70%,transparent)}.text-secondary-content\/80{color:color-mix(in oklab,var(--color-secondary-content)80%,transparent)}.text-secondary-content\/90{color:color-mix(in oklab,var(--color-secondary-content)90%,transparent)}.border-secondary-content{border-color:var(--color-secondary-content)}.border-secondary-content\/10{border-color:color-mix(in oklab,var(--color-secondary-content)10%,transparent)}.border-secondary-content\/20{border-color:color-mix(in oklab,var(--color-secondary-content)20%,transparent)}.border-secondary-content\/30{border-color:color-mix(in oklab,var(--color-secondary-content)30%,transparent)}.border-secondary-content\/40{border-color:color-mix(in oklab,var(--color-secondary-content)40%,transparent)}.border-secondary-content\/50{border-color:color-mix(in oklab,var(--color-secondary-content)50%,transparent)}.border-secondary-content\/60{border-color:color-mix(in oklab,var(--color-secondary-content)60%,transparent)}.border-secondary-content\/70{border-color:color-mix(in oklab,var(--color-secondary-content)70%,transparent)}.border-secondary-content\/80{border-color:color-mix(in oklab,var(--color-secondary-content)80%,transparent)}.border-secondary-content\/90{border-color:color-mix(in oklab,var(--color-secondary-content)90%,transparent)}.bg-accent{background-color:var(--color-accent)}.bg-accent\/10{background-color:color-mix(in oklab,var(--color-accent)10%,transparent)}.bg-accent\/20{background-color:color-mix(in oklab,var(--color-accent)20%,transparent)}.bg-accent\/30{background-color:color-mix(in oklab,var(--color-accent)30%,transparent)}.bg-accent\/40{background-color:color-mix(in oklab,var(--color-accent)40%,transparent)}.bg-accent\/50{background-color:color-mix(in oklab,var(--color-accent)50%,transparent)}.bg-accent\/60{background-color:color-mix(in oklab,var(--color-accent)60%,transparent)}.bg-accent\/70{background-color:color-mix(in oklab,var(--color-accent)70%,transparent)}.bg-accent\/80{background-color:color-mix(in oklab,var(--color-accent)80%,transparent)}.bg-accent\/90{background-color:color-mix(in oklab,var(--color-accent)90%,transparent)}.text-accent{color:var(--color-accent)}.text-accent\/10{color:color-mix(in oklab,var(--color-accent)10%,transparent)}.text-accent\/20{color:color-mix(in oklab,var(--color-accent)20%,transparent)}.text-accent\/30{color:color-mix(in oklab,var(--color-accent)30%,transparent)}.text-accent\/40{color:color-mix(in oklab,var(--color-accent)40%,transparent)}.text-accent\/50{color:color-mix(in oklab,var(--color-accent)50%,transparent)}.text-accent\/60{color:color-mix(in oklab,var(--color-accent)60%,transparent)}.text-accent\/70{color:color-mix(in oklab,var(--color-accent)70%,transparent)}.text-accent\/80{color:color-mix(in oklab,var(--color-accent)80%,transparent)}.text-accent\/90{color:color-mix(in oklab,var(--color-accent)90%,transparent)}.border-accent{border-color:var(--color-accent)}.border-accent\/10{border-color:color-mix(in oklab,var(--color-accent)10%,transparent)}.border-accent\/20{border-color:color-mix(in oklab,var(--color-accent)20%,transparent)}.border-accent\/30{border-color:color-mix(in oklab,var(--color-accent)30%,transparent)}.border-accent\/40{border-color:color-mix(in oklab,var(--color-accent)40%,transparent)}.border-accent\/50{border-color:color-mix(in oklab,var(--color-accent)50%,transparent)}.border-accent\/60{border-color:color-mix(in oklab,var(--color-accent)60%,transparent)}.border-accent\/70{border-color:color-mix(in oklab,var(--color-accent)70%,transparent)}.border-accent\/80{border-color:color-mix(in oklab,var(--color-accent)80%,transparent)}.border-accent\/90{border-color:color-mix(in oklab,var(--color-accent)90%,transparent)}.bg-accent-content{background-color:var(--color-accent-content)}.bg-accent-content\/10{background-color:color-mix(in oklab,var(--color-accent-content)10%,transparent)}.bg-accent-content\/20{background-color:color-mix(in oklab,var(--color-accent-content)20%,transparent)}.bg-accent-content\/30{background-color:color-mix(in oklab,var(--color-accent-content)30%,transparent)}.bg-accent-content\/40{background-color:color-mix(in oklab,var(--color-accent-content)40%,transparent)}.bg-accent-content\/50{background-color:color-mix(in oklab,var(--color-accent-content)50%,transparent)}.bg-accent-content\/60{background-color:color-mix(in oklab,var(--color-accent-content)60%,transparent)}.bg-accent-content\/70{background-color:color-mix(in oklab,var(--color-accent-content)70%,transparent)}.bg-accent-content\/80{background-color:color-mix(in oklab,var(--color-accent-content)80%,transparent)}.bg-accent-content\/90{background-color:color-mix(in oklab,var(--color-accent-content)90%,transparent)}.text-accent-content{color:var(--color-accent-content)}.text-accent-content\/10{color:color-mix(in oklab,var(--color-accent-content)10%,transparent)}.text-accent-content\/20{color:color-mix(in oklab,var(--color-accent-content)20%,transparent)}.text-accent-content\/30{color:color-mix(in oklab,var(--color-accent-content)30%,transparent)}.text-accent-content\/40{color:color-mix(in oklab,var(--color-accent-content)40%,transparent)}.text-accent-content\/50{color:color-mix(in oklab,var(--color-accent-content)50%,transparent)}.text-accent-content\/60{color:color-mix(in oklab,var(--color-accent-content)60%,transparent)}.text-accent-content\/70{color:color-mix(in oklab,var(--color-accent-content)70%,transparent)}.text-accent-content\/80{color:color-mix(in oklab,var(--color-accent-content)80%,transparent)}.text-accent-content\/90{color:color-mix(in oklab,var(--color-accent-content)90%,transparent)}.border-accent-content{border-color:var(--color-accent-content)}.border-accent-content\/10{border-color:color-mix(in oklab,var(--color-accent-content)10%,transparent)}.border-accent-content\/20{border-color:color-mix(in oklab,var(--color-accent-content)20%,transparent)}.border-accent-content\/30{border-color:color-mix(in oklab,var(--color-accent-content)30%,transparent)}.border-accent-content\/40{border-color:color-mix(in oklab,var(--color-accent-content)40%,transparent)}.border-accent-content\/50{border-color:color-mix(in oklab,var(--color-accent-content)50%,transparent)}.border-accent-content\/60{border-color:color-mix(in oklab,var(--color-accent-content)60%,transparent)}.border-accent-content\/70{border-color:color-mix(in oklab,var(--color-accent-content)70%,transparent)}.border-accent-content\/80{border-color:color-mix(in oklab,var(--color-accent-content)80%,transparent)}.border-accent-content\/90{border-color:color-mix(in oklab,var(--color-accent-content)90%,transparent)}.bg-neutral{background-color:var(--color-neutral)}.bg-neutral\/10{background-color:color-mix(in oklab,var(--color-neutral)10%,transparent)}.bg-neutral\/20{background-color:color-mix(in oklab,var(--color-neutral)20%,transparent)}.bg-neutral\/30{background-color:color-mix(in oklab,var(--color-neutral)30%,transparent)}.bg-neutral\/40{background-color:color-mix(in oklab,var(--color-neutral)40%,transparent)}.bg-neutral\/50{background-color:color-mix(in oklab,var(--color-neutral)50%,transparent)}.bg-neutral\/60{background-color:color-mix(in oklab,var(--color-neutral)60%,transparent)}.bg-neutral\/70{background-color:color-mix(in oklab,var(--color-neutral)70%,transparent)}.bg-neutral\/80{background-color:color-mix(in oklab,var(--color-neutral)80%,transparent)}.bg-neutral\/90{background-color:color-mix(in oklab,var(--color-neutral)90%,transparent)}.text-neutral{color:var(--color-neutral)}.text-neutral\/10{color:color-mix(in oklab,var(--color-neutral)10%,transparent)}.text-neutral\/20{color:color-mix(in oklab,var(--color-neutral)20%,transparent)}.text-neutral\/30{color:color-mix(in oklab,var(--color-neutral)30%,transparent)}.text-neutral\/40{color:color-mix(in oklab,var(--color-neutral)40%,transparent)}.text-neutral\/50{color:color-mix(in oklab,var(--color-neutral)50%,transparent)}.text-neutral\/60{color:color-mix(in oklab,var(--color-neutral)60%,transparent)}.text-neutral\/70{color:color-mix(in oklab,var(--color-neutral)70%,transparent)}.text-neutral\/80{color:color-mix(in oklab,var(--color-neutral)80%,transparent)}.text-neutral\/90{color:color-mix(in oklab,var(--color-neutral)90%,transparent)}.border-neutral{border-color:var(--color-neutral)}.border-neutral\/10{border-color:color-mix(in oklab,var(--color-neutral)10%,transparent)}.border-neutral\/20{border-color:color-mix(in oklab,var(--color-neutral)20%,transparent)}.border-neutral\/30{border-color:color-mix(in oklab,var(--color-neutral)30%,transparent)}.border-neutral\/40{border-color:color-mix(in oklab,var(--color-neutral)40%,transparent)}.border-neutral\/50{border-color:color-mix(in oklab,var(--color-neutral)50%,transparent)}.border-neutral\/60{border-color:color-mix(in oklab,var(--color-neutral)60%,transparent)}.border-neutral\/70{border-color:color-mix(in oklab,var(--color-neutral)70%,transparent)}.border-neutral\/80{border-color:color-mix(in oklab,var(--color-neutral)80%,transparent)}.border-neutral\/90{border-color:color-mix(in oklab,var(--color-neutral)90%,transparent)}.bg-neutral-content{background-color:var(--color-neutral-content)}.bg-neutral-content\/10{background-color:color-mix(in oklab,var(--color-neutral-content)10%,transparent)}.bg-neutral-content\/20{background-color:color-mix(in oklab,var(--color-neutral-content)20%,transparent)}.bg-neutral-content\/30{background-color:color-mix(in oklab,var(--color-neutral-content)30%,transparent)}.bg-neutral-content\/40{background-color:color-mix(in oklab,var(--color-neutral-content)40%,transparent)}.bg-neutral-content\/50{background-color:color-mix(in oklab,var(--color-neutral-content)50%,transparent)}.bg-neutral-content\/60{background-color:color-mix(in oklab,var(--color-neutral-content)60%,transparent)}.bg-neutral-content\/70{background-color:color-mix(in oklab,var(--color-neutral-content)70%,transparent)}.bg-neutral-content\/80{background-color:color-mix(in oklab,var(--color-neutral-content)80%,transparent)}.bg-neutral-content\/90{background-color:color-mix(in oklab,var(--color-neutral-content)90%,transparent)}.text-neutral-content{color:var(--color-neutral-content)}.text-neutral-content\/10{color:color-mix(in oklab,var(--color-neutral-content)10%,transparent)}.text-neutral-content\/20{color:color-mix(in oklab,var(--color-neutral-content)20%,transparent)}.text-neutral-content\/30{color:color-mix(in oklab,var(--color-neutral-content)30%,transparent)}.text-neutral-content\/40{color:color-mix(in oklab,var(--color-neutral-content)40%,transparent)}.text-neutral-content\/50{color:color-mix(in oklab,var(--color-neutral-content)50%,transparent)}.text-neutral-content\/60{color:color-mix(in oklab,var(--color-neutral-content)60%,transparent)}.text-neutral-content\/70{color:color-mix(in oklab,var(--color-neutral-content)70%,transparent)}.text-neutral-content\/80{color:color-mix(in oklab,var(--color-neutral-content)80%,transparent)}.text-neutral-content\/90{color:color-mix(in oklab,var(--color-neutral-content)90%,transparent)}.border-neutral-content{border-color:var(--color-neutral-content)}.border-neutral-content\/10{border-color:color-mix(in oklab,var(--color-neutral-content)10%,transparent)}.border-neutral-content\/20{border-color:color-mix(in oklab,var(--color-neutral-content)20%,transparent)}.border-neutral-content\/30{border-color:color-mix(in oklab,var(--color-neutral-content)30%,transparent)}.border-neutral-content\/40{border-color:color-mix(in oklab,var(--color-neutral-content)40%,transparent)}.border-neutral-content\/50{border-color:color-mix(in oklab,var(--color-neutral-content)50%,transparent)}.border-neutral-content\/60{border-color:color-mix(in oklab,var(--color-neutral-content)60%,transparent)}.border-neutral-content\/70{border-color:color-mix(in oklab,var(--color-neutral-content)70%,transparent)}.border-neutral-content\/80{border-color:color-mix(in oklab,var(--color-neutral-content)80%,transparent)}.border-neutral-content\/90{border-color:color-mix(in oklab,var(--color-neutral-content)90%,transparent)}.bg-info{background-color:var(--color-info)}.bg-info\/10{background-color:color-mix(in oklab,var(--color-info)10%,transparent)}.bg-info\/20{background-color:color-mix(in oklab,var(--color-info)20%,transparent)}.bg-info\/30{background-color:color-mix(in oklab,var(--color-info)30%,transparent)}.bg-info\/40{background-color:color-mix(in oklab,var(--color-info)40%,transparent)}.bg-info\/50{background-color:color-mix(in oklab,var(--color-info)50%,transparent)}.bg-info\/60{background-color:color-mix(in oklab,var(--color-info)60%,transparent)}.bg-info\/70{background-color:color-mix(in oklab,var(--color-info)70%,transparent)}.bg-info\/80{background-color:color-mix(in oklab,var(--color-info)80%,transparent)}.bg-info\/90{background-color:color-mix(in oklab,var(--color-info)90%,transparent)}.text-info{color:var(--color-info)}.text-info\/10{color:color-mix(in oklab,var(--color-info)10%,transparent)}.text-info\/20{color:color-mix(in oklab,var(--color-info)20%,transparent)}.text-info\/30{color:color-mix(in oklab,var(--color-info)30%,transparent)}.text-info\/40{color:color-mix(in oklab,var(--color-info)40%,transparent)}.text-info\/50{color:color-mix(in oklab,var(--color-info)50%,transparent)}.text-info\/60{color:color-mix(in oklab,var(--color-info)60%,transparent)}.text-info\/70{color:color-mix(in oklab,var(--color-info)70%,transparent)}.text-info\/80{color:color-mix(in oklab,var(--color-info)80%,transparent)}.text-info\/90{color:color-mix(in oklab,var(--color-info)90%,transparent)}.border-info{border-color:var(--color-info)}.border-info\/10{border-color:color-mix(in oklab,var(--color-info)10%,transparent)}.border-info\/20{border-color:color-mix(in oklab,var(--color-info)20%,transparent)}.border-info\/30{border-color:color-mix(in oklab,var(--color-info)30%,transparent)}.border-info\/40{border-color:color-mix(in oklab,var(--color-info)40%,transparent)}.border-info\/50{border-color:color-mix(in oklab,var(--color-info)50%,transparent)}.border-info\/60{border-color:color-mix(in oklab,var(--color-info)60%,transparent)}.border-info\/70{border-color:color-mix(in oklab,var(--color-info)70%,transparent)}.border-info\/80{border-color:color-mix(in oklab,var(--color-info)80%,transparent)}.border-info\/90{border-color:color-mix(in oklab,var(--color-info)90%,transparent)}.bg-info-content{background-color:var(--color-info-content)}.bg-info-content\/10{background-color:color-mix(in oklab,var(--color-info-content)10%,transparent)}.bg-info-content\/20{background-color:color-mix(in oklab,var(--color-info-content)20%,transparent)}.bg-info-content\/30{background-color:color-mix(in oklab,var(--color-info-content)30%,transparent)}.bg-info-content\/40{background-color:color-mix(in oklab,var(--color-info-content)40%,transparent)}.bg-info-content\/50{background-color:color-mix(in oklab,var(--color-info-content)50%,transparent)}.bg-info-content\/60{background-color:color-mix(in oklab,var(--color-info-content)60%,transparent)}.bg-info-content\/70{background-color:color-mix(in oklab,var(--color-info-content)70%,transparent)}.bg-info-content\/80{background-color:color-mix(in oklab,var(--color-info-content)80%,transparent)}.bg-info-content\/90{background-color:color-mix(in oklab,var(--color-info-content)90%,transparent)}.text-info-content{color:var(--color-info-content)}.text-info-content\/10{color:color-mix(in oklab,var(--color-info-content)10%,transparent)}.text-info-content\/20{color:color-mix(in oklab,var(--color-info-content)20%,transparent)}.text-info-content\/30{color:color-mix(in oklab,var(--color-info-content)30%,transparent)}.text-info-content\/40{color:color-mix(in oklab,var(--color-info-content)40%,transparent)}.text-info-content\/50{color:color-mix(in oklab,var(--color-info-content)50%,transparent)}.text-info-content\/60{color:color-mix(in oklab,var(--color-info-content)60%,transparent)}.text-info-content\/70{color:color-mix(in oklab,var(--color-info-content)70%,transparent)}.text-info-content\/80{color:color-mix(in oklab,var(--color-info-content)80%,transparent)}.text-info-content\/90{color:color-mix(in oklab,var(--color-info-content)90%,transparent)}.border-info-content{border-color:var(--color-info-content)}.border-info-content\/10{border-color:color-mix(in oklab,var(--color-info-content)10%,transparent)}.border-info-content\/20{border-color:color-mix(in oklab,var(--color-info-content)20%,transparent)}.border-info-content\/30{border-color:color-mix(in oklab,var(--color-info-content)30%,transparent)}.border-info-content\/40{border-color:color-mix(in oklab,var(--color-info-content)40%,transparent)}.border-info-content\/50{border-color:color-mix(in oklab,var(--color-info-content)50%,transparent)}.border-info-content\/60{border-color:color-mix(in oklab,var(--color-info-content)60%,transparent)}.border-info-content\/70{border-color:color-mix(in oklab,var(--color-info-content)70%,transparent)}.border-info-content\/80{border-color:color-mix(in oklab,var(--color-info-content)80%,transparent)}.border-info-content\/90{border-color:color-mix(in oklab,var(--color-info-content)90%,transparent)}.bg-success{background-color:var(--color-success)}.bg-success\/10{background-color:color-mix(in oklab,var(--color-success)10%,transparent)}.bg-success\/20{background-color:color-mix(in oklab,var(--color-success)20%,transparent)}.bg-success\/30{background-color:color-mix(in oklab,var(--color-success)30%,transparent)}.bg-success\/40{background-color:color-mix(in oklab,var(--color-success)40%,transparent)}.bg-success\/50{background-color:color-mix(in oklab,var(--color-success)50%,transparent)}.bg-success\/60{background-color:color-mix(in oklab,var(--color-success)60%,transparent)}.bg-success\/70{background-color:color-mix(in oklab,var(--color-success)70%,transparent)}.bg-success\/80{background-color:color-mix(in oklab,var(--color-success)80%,transparent)}.bg-success\/90{background-color:color-mix(in oklab,var(--color-success)90%,transparent)}.text-success{color:var(--color-success)}.text-success\/10{color:color-mix(in oklab,var(--color-success)10%,transparent)}.text-success\/20{color:color-mix(in oklab,var(--color-success)20%,transparent)}.text-success\/30{color:color-mix(in oklab,var(--color-success)30%,transparent)}.text-success\/40{color:color-mix(in oklab,var(--color-success)40%,transparent)}.text-success\/50{color:color-mix(in oklab,var(--color-success)50%,transparent)}.text-success\/60{color:color-mix(in oklab,var(--color-success)60%,transparent)}.text-success\/70{color:color-mix(in oklab,var(--color-success)70%,transparent)}.text-success\/80{color:color-mix(in oklab,var(--color-success)80%,transparent)}.text-success\/90{color:color-mix(in oklab,var(--color-success)90%,transparent)}.border-success{border-color:var(--color-success)}.border-success\/10{border-color:color-mix(in oklab,var(--color-success)10%,transparent)}.border-success\/20{border-color:color-mix(in oklab,var(--color-success)20%,transparent)}.border-success\/30{border-color:color-mix(in oklab,var(--color-success)30%,transparent)}.border-success\/40{border-color:color-mix(in oklab,var(--color-success)40%,transparent)}.border-success\/50{border-color:color-mix(in oklab,var(--color-success)50%,transparent)}.border-success\/60{border-color:color-mix(in oklab,var(--color-success)60%,transparent)}.border-success\/70{border-color:color-mix(in oklab,var(--color-success)70%,transparent)}.border-success\/80{border-color:color-mix(in oklab,var(--color-success)80%,transparent)}.border-success\/90{border-color:color-mix(in oklab,var(--color-success)90%,transparent)}.bg-success-content{background-color:var(--color-success-content)}.bg-success-content\/10{background-color:color-mix(in oklab,var(--color-success-content)10%,transparent)}.bg-success-content\/20{background-color:color-mix(in oklab,var(--color-success-content)20%,transparent)}.bg-success-content\/30{background-color:color-mix(in oklab,var(--color-success-content)30%,transparent)}.bg-success-content\/40{background-color:color-mix(in oklab,var(--color-success-content)40%,transparent)}.bg-success-content\/50{background-color:color-mix(in oklab,var(--color-success-content)50%,transparent)}.bg-success-content\/60{background-color:color-mix(in oklab,var(--color-success-content)60%,transparent)}.bg-success-content\/70{background-color:color-mix(in oklab,var(--color-success-content)70%,transparent)}.bg-success-content\/80{background-color:color-mix(in oklab,var(--color-success-content)80%,transparent)}.bg-success-content\/90{background-color:color-mix(in oklab,var(--color-success-content)90%,transparent)}.text-success-content{color:var(--color-success-content)}.text-success-content\/10{color:color-mix(in oklab,var(--color-success-content)10%,transparent)}.text-success-content\/20{color:color-mix(in oklab,var(--color-success-content)20%,transparent)}.text-success-content\/30{color:color-mix(in oklab,var(--color-success-content)30%,transparent)}.text-success-content\/40{color:color-mix(in oklab,var(--color-success-content)40%,transparent)}.text-success-content\/50{color:color-mix(in oklab,var(--color-success-content)50%,transparent)}.text-success-content\/60{color:color-mix(in oklab,var(--color-success-content)60%,transparent)}.text-success-content\/70{color:color-mix(in oklab,var(--color-success-content)70%,transparent)}.text-success-content\/80{color:color-mix(in oklab,var(--color-success-content)80%,transparent)}.text-success-content\/90{color:color-mix(in oklab,var(--color-success-content)90%,transparent)}.border-success-content{border-color:var(--color-success-content)}.border-success-content\/10{border-color:color-mix(in oklab,var(--color-success-content)10%,transparent)}.border-success-content\/20{border-color:color-mix(in oklab,var(--color-success-content)20%,transparent)}.border-success-content\/30{border-color:color-mix(in oklab,var(--color-success-content)30%,transparent)}.border-success-content\/40{border-color:color-mix(in oklab,var(--color-success-content)40%,transparent)}.border-success-content\/50{border-color:color-mix(in oklab,var(--color-success-content)50%,transparent)}.border-success-content\/60{border-color:color-mix(in oklab,var(--color-success-content)60%,transparent)}.border-success-content\/70{border-color:color-mix(in oklab,var(--color-success-content)70%,transparent)}.border-success-content\/80{border-color:color-mix(in oklab,var(--color-success-content)80%,transparent)}.border-success-content\/90{border-color:color-mix(in oklab,var(--color-success-content)90%,transparent)}.bg-warning{background-color:var(--color-warning)}.bg-warning\/10{background-color:color-mix(in oklab,var(--color-warning)10%,transparent)}.bg-warning\/20{background-color:color-mix(in oklab,var(--color-warning)20%,transparent)}.bg-warning\/30{background-color:color-mix(in oklab,var(--color-warning)30%,transparent)}.bg-warning\/40{background-color:color-mix(in oklab,var(--color-warning)40%,transparent)}.bg-warning\/50{background-color:color-mix(in oklab,var(--color-warning)50%,transparent)}.bg-warning\/60{background-color:color-mix(in oklab,var(--color-warning)60%,transparent)}.bg-warning\/70{background-color:color-mix(in oklab,var(--color-warning)70%,transparent)}.bg-warning\/80{background-color:color-mix(in oklab,var(--color-warning)80%,transparent)}.bg-warning\/90{background-color:color-mix(in oklab,var(--color-warning)90%,transparent)}.text-warning{color:var(--color-warning)}.text-warning\/10{color:color-mix(in oklab,var(--color-warning)10%,transparent)}.text-warning\/20{color:color-mix(in oklab,var(--color-warning)20%,transparent)}.text-warning\/30{color:color-mix(in oklab,var(--color-warning)30%,transparent)}.text-warning\/40{color:color-mix(in oklab,var(--color-warning)40%,transparent)}.text-warning\/50{color:color-mix(in oklab,var(--color-warning)50%,transparent)}.text-warning\/60{color:color-mix(in oklab,var(--color-warning)60%,transparent)}.text-warning\/70{color:color-mix(in oklab,var(--color-warning)70%,transparent)}.text-warning\/80{color:color-mix(in oklab,var(--color-warning)80%,transparent)}.text-warning\/90{color:color-mix(in oklab,var(--color-warning)90%,transparent)}.border-warning{border-color:var(--color-warning)}.border-warning\/10{border-color:color-mix(in oklab,var(--color-warning)10%,transparent)}.border-warning\/20{border-color:color-mix(in oklab,var(--color-warning)20%,transparent)}.border-warning\/30{border-color:color-mix(in oklab,var(--color-warning)30%,transparent)}.border-warning\/40{border-color:color-mix(in oklab,var(--color-warning)40%,transparent)}.border-warning\/50{border-color:color-mix(in oklab,var(--color-warning)50%,transparent)}.border-warning\/60{border-color:color-mix(in oklab,var(--color-warning)60%,transparent)}.border-warning\/70{border-color:color-mix(in oklab,var(--color-warning)70%,transparent)}.border-warning\/80{border-color:color-mix(in oklab,var(--color-warning)80%,transparent)}.border-warning\/90{border-color:color-mix(in oklab,var(--color-warning)90%,transparent)}.bg-warning-content{background-color:var(--color-warning-content)}.bg-warning-content\/10{background-color:color-mix(in oklab,var(--color-warning-content)10%,transparent)}.bg-warning-content\/20{background-color:color-mix(in oklab,var(--color-warning-content)20%,transparent)}.bg-warning-content\/30{background-color:color-mix(in oklab,var(--color-warning-content)30%,transparent)}.bg-warning-content\/40{background-color:color-mix(in oklab,var(--color-warning-content)40%,transparent)}.bg-warning-content\/50{background-color:color-mix(in oklab,var(--color-warning-content)50%,transparent)}.bg-warning-content\/60{background-color:color-mix(in oklab,var(--color-warning-content)60%,transparent)}.bg-warning-content\/70{background-color:color-mix(in oklab,var(--color-warning-content)70%,transparent)}.bg-warning-content\/80{background-color:color-mix(in oklab,var(--color-warning-content)80%,transparent)}.bg-warning-content\/90{background-color:color-mix(in oklab,var(--color-warning-content)90%,transparent)}.text-warning-content{color:var(--color-warning-content)}.text-warning-content\/10{color:color-mix(in oklab,var(--color-warning-content)10%,transparent)}.text-warning-content\/20{color:color-mix(in oklab,var(--color-warning-content)20%,transparent)}.text-warning-content\/30{color:color-mix(in oklab,var(--color-warning-content)30%,transparent)}.text-warning-content\/40{color:color-mix(in oklab,var(--color-warning-content)40%,transparent)}.text-warning-content\/50{color:color-mix(in oklab,var(--color-warning-content)50%,transparent)}.text-warning-content\/60{color:color-mix(in oklab,var(--color-warning-content)60%,transparent)}.text-warning-content\/70{color:color-mix(in oklab,var(--color-warning-content)70%,transparent)}.text-warning-content\/80{color:color-mix(in oklab,var(--color-warning-content)80%,transparent)}.text-warning-content\/90{color:color-mix(in oklab,var(--color-warning-content)90%,transparent)}.border-warning-content{border-color:var(--color-warning-content)}.border-warning-content\/10{border-color:color-mix(in oklab,var(--color-warning-content)10%,transparent)}.border-warning-content\/20{border-color:color-mix(in oklab,var(--color-warning-content)20%,transparent)}.border-warning-content\/30{border-color:color-mix(in oklab,var(--color-warning-content)30%,transparent)}.border-warning-content\/40{border-color:color-mix(in oklab,var(--color-warning-content)40%,transparent)}.border-warning-content\/50{border-color:color-mix(in oklab,var(--color-warning-content)50%,transparent)}.border-warning-content\/60{border-color:color-mix(in oklab,var(--color-warning-content)60%,transparent)}.border-warning-content\/70{border-color:color-mix(in oklab,var(--color-warning-content)70%,transparent)}.border-warning-content\/80{border-color:color-mix(in oklab,var(--color-warning-content)80%,transparent)}.border-warning-content\/90{border-color:color-mix(in oklab,var(--color-warning-content)90%,transparent)}.bg-error{background-color:var(--color-error)}.bg-error\/10{background-color:color-mix(in oklab,var(--color-error)10%,transparent)}.bg-error\/20{background-color:color-mix(in oklab,var(--color-error)20%,transparent)}.bg-error\/30{background-color:color-mix(in oklab,var(--color-error)30%,transparent)}.bg-error\/40{background-color:color-mix(in oklab,var(--color-error)40%,transparent)}.bg-error\/50{background-color:color-mix(in oklab,var(--color-error)50%,transparent)}.bg-error\/60{background-color:color-mix(in oklab,var(--color-error)60%,transparent)}.bg-error\/70{background-color:color-mix(in oklab,var(--color-error)70%,transparent)}.bg-error\/80{background-color:color-mix(in oklab,var(--color-error)80%,transparent)}.bg-error\/90{background-color:color-mix(in oklab,var(--color-error)90%,transparent)}.text-error{color:var(--color-error)}.text-error\/10{color:color-mix(in oklab,var(--color-error)10%,transparent)}.text-error\/20{color:color-mix(in oklab,var(--color-error)20%,transparent)}.text-error\/30{color:color-mix(in oklab,var(--color-error)30%,transparent)}.text-error\/40{color:color-mix(in oklab,var(--color-error)40%,transparent)}.text-error\/50{color:color-mix(in oklab,var(--color-error)50%,transparent)}.text-error\/60{color:color-mix(in oklab,var(--color-error)60%,transparent)}.text-error\/70{color:color-mix(in oklab,var(--color-error)70%,transparent)}.text-error\/80{color:color-mix(in oklab,var(--color-error)80%,transparent)}.text-error\/90{color:color-mix(in oklab,var(--color-error)90%,transparent)}.border-error{border-color:var(--color-error)}.border-error\/10{border-color:color-mix(in oklab,var(--color-error)10%,transparent)}.border-error\/20{border-color:color-mix(in oklab,var(--color-error)20%,transparent)}.border-error\/30{border-color:color-mix(in oklab,var(--color-error)30%,transparent)}.border-error\/40{border-color:color-mix(in oklab,var(--color-error)40%,transparent)}.border-error\/50{border-color:color-mix(in oklab,var(--color-error)50%,transparent)}.border-error\/60{border-color:color-mix(in oklab,var(--color-error)60%,transparent)}.border-error\/70{border-color:color-mix(in oklab,var(--color-error)70%,transparent)}.border-error\/80{border-color:color-mix(in oklab,var(--color-error)80%,transparent)}.border-error\/90{border-color:color-mix(in oklab,var(--color-error)90%,transparent)}.bg-error-content{background-color:var(--color-error-content)}.bg-error-content\/10{background-color:color-mix(in oklab,var(--color-error-content)10%,transparent)}.bg-error-content\/20{background-color:color-mix(in oklab,var(--color-error-content)20%,transparent)}.bg-error-content\/30{background-color:color-mix(in oklab,var(--color-error-content)30%,transparent)}.bg-error-content\/40{background-color:color-mix(in oklab,var(--color-error-content)40%,transparent)}.bg-error-content\/50{background-color:color-mix(in oklab,var(--color-error-content)50%,transparent)}.bg-error-content\/60{background-color:color-mix(in oklab,var(--color-error-content)60%,transparent)}.bg-error-content\/70{background-color:color-mix(in oklab,var(--color-error-content)70%,transparent)}.bg-error-content\/80{background-color:color-mix(in oklab,var(--color-error-content)80%,transparent)}.bg-error-content\/90{background-color:color-mix(in oklab,var(--color-error-content)90%,transparent)}.text-error-content{color:var(--color-error-content)}.text-error-content\/10{color:color-mix(in oklab,var(--color-error-content)10%,transparent)}.text-error-content\/20{color:color-mix(in oklab,var(--color-error-content)20%,transparent)}.text-error-content\/30{color:color-mix(in oklab,var(--color-error-content)30%,transparent)}.text-error-content\/40{color:color-mix(in oklab,var(--color-error-content)40%,transparent)}.text-error-content\/50{color:color-mix(in oklab,var(--color-error-content)50%,transparent)}.text-error-content\/60{color:color-mix(in oklab,var(--color-error-content)60%,transparent)}.text-error-content\/70{color:color-mix(in oklab,var(--color-error-content)70%,transparent)}.text-error-content\/80{color:color-mix(in oklab,var(--color-error-content)80%,transparent)}.text-error-content\/90{color:color-mix(in oklab,var(--color-error-content)90%,transparent)}.border-error-content{border-color:var(--color-error-content)}.border-error-content\/10{border-color:color-mix(in oklab,var(--color-error-content)10%,transparent)}.border-error-content\/20{border-color:color-mix(in oklab,var(--color-error-content)20%,transparent)}.border-error-content\/30{border-color:color-mix(in oklab,var(--color-error-content)30%,transparent)}.border-error-content\/40{border-color:color-mix(in oklab,var(--color-error-content)40%,transparent)}.border-error-content\/50{border-color:color-mix(in oklab,var(--color-error-content)50%,transparent)}.border-error-content\/60{border-color:color-mix(in oklab,var(--color-error-content)60%,transparent)}.border-error-content\/70{border-color:color-mix(in oklab,var(--color-error-content)70%,transparent)}.border-error-content\/80{border-color:color-mix(in oklab,var(--color-error-content)80%,transparent)}.border-error-content\/90{border-color:color-mix(in oklab,var(--color-error-content)90%,transparent)}} \ No newline at end of file diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui.css.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui.css.br deleted file mode 100644 index 87a4a9cd..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/daisyui.css.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/favicon.ico b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/favicon.ico deleted file mode 100644 index ec1031d8..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/favicon.ico and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/favicon.ico.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/favicon.ico.br deleted file mode 100644 index 792caac6..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/favicon.ico.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_192.png b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_192.png deleted file mode 100644 index cdc1da6c..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_192.png and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_192.png.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_192.png.br deleted file mode 100644 index 2171efd8..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_192.png.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_512.png b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_512.png deleted file mode 100644 index cdc1da6c..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_512.png and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_512.png.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_512.png.br deleted file mode 100644 index 2171efd8..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/logo_512.png.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/manifest.json b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/manifest.json deleted file mode 100644 index f8cc6949..00000000 --- a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/manifest.json +++ /dev/null @@ -1 +0,0 @@ -{"background_color":"#ffffff","description":"Blueprint is a key-value store, and service registry for your distributed systems.","dir":"ltr","display":"standalone","display_override":["window-control-overlay","standalone"],"icons":[{"sizes":"192x192","src":"logo_192.png","type":"image/png"},{"purpose":"any","sizes":"512x512","src":"logo_512.png","type":"image/png"},{"purpose":"any","sizes":"any","src":"logo_512.png","type":"image/png"}],"id":"/","lang":"en","name":"Blueprint","orientation":"portrait","scope":"/","short_name":"Blueprint","start_url":"/","theme_color":"#000000"} \ No newline at end of file diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/manifest.json.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/manifest.json.br deleted file mode 100644 index 818043e7..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/manifest.json.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/sw.js b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/sw.js deleted file mode 100644 index 52746841..00000000 --- a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/sw.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";var version="v1.0.0::";var offlineFundamentals=["favicon.ico"];self.addEventListener("install",function(event){event.waitUntil(caches.open(version+"fundamentals").then(function(cache){return cache.addAll(offlineFundamentals);}).then(function(){}));});self.addEventListener("fetch",function(event){if(event.request.method!=="GET"){return;}event.respondWith(caches.match(event.request).then(function(cached){var networked=fetch(event.request).then(fetchedFromNetwork,unableToResolve).catch(unableToResolve);return cached||networked;function fetchedFromNetwork(response){var cacheCopy=response.clone();caches.open(version+"pages").then(function add(cache){cache.put(event.request,cacheCopy);}).then(function(){});return response;}function unableToResolve(){return new Response("

Service Unavailable

",{status:503,statusText:"Service Unavailable",headers:new Headers({"Content-Type":"text/html"})});}}));});self.addEventListener("activate",function(event){event.waitUntil(caches.keys().then(function(keys){return Promise.all(keys.filter(function(key){return!key.startsWith(version);}).map(function(key){return caches.delete(key);}));}).then(function(){}));}); \ No newline at end of file diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/sw.js.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/sw.js.br deleted file mode 100644 index 8d058e84..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/sw.js.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/tailwind.js b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/tailwind.js deleted file mode 100644 index 713fed32..00000000 --- a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/tailwind.js +++ /dev/null @@ -1,27 +0,0 @@ -"use strict";(()=>{var e1=10;function t(t){"\uFEFF"===t[0]&&(t=t.slice(1)),t=t.replaceAll("\r\n","\n");let o,a=[],i=[],l=[],s=null,c=null,u="",d="";for(let f=0;f0&&t[n]===e1[e1.length-1]&&(e1=e1.slice(0,-1));}}let l=n(u,i);if(!l)throw new Error("Invalid custom property, expected a value");s?s.nodes.push(l):a.push(l),u="";}else if(59===p&&64===u.charCodeAt(0))c=r(u),s?s.nodes.push(c):a.push(c),u="",c=null;else if(59===p&&")"!==d[d.length-1]){let e1=n(u);if(!e1)throw 0===u.length?new Error("Unexpected semicolon"):new Error(`Invalid declaration: \`${u.trim()}\``);s?s.nodes.push(e1):a.push(e1),u="";}else if(123===p&&")"!==d[d.length-1])d+="}",c=b(u.trim()),s&&s.nodes.push(c),l.push(s),s=c,u="",c=null;else if(125===p&&")"!==d[d.length-1]){if(""===d)throw new Error("Missing opening {");if(d=d.slice(0,-1),u.length>0)if(64===u.charCodeAt(0))c=r(u),s?s.nodes.push(c):a.push(c),u="",c=null;else{let e1=u.indexOf(":");if(s){let t=n(u,e1);if(!t)throw new Error(`Invalid declaration: \`${u.trim()}\``);s.nodes.push(t);}}let e1=l.pop()??null;null===e1&&s&&a.push(s),s=e1,u="",c=null;}else if(40===p)d+=")",u+="(";else if(41===p){if(")"!==d[d.length-1])throw new Error("Missing opening (");d=d.slice(0,-1),u+=")";}else{if(0===u.length&&(32===p||p===e1||9===p))continue;u+=String.fromCharCode(p);}}}if(64===u.charCodeAt(0)&&a.push(r(u)),d.length>0&&s){if("rule"===s.kind)throw new Error(`Missing closing } at ${s.selector}`);if("at-rule"===s.kind)throw new Error(`Missing closing } at ${s.name} ${s.params}`);}return i.length>0?i.concat(a):a;}function r(e1,t=[]){for(let r=5;r=1&&t<=31||127===t||0===o&&t>=48&&t<=57||1===o&&t>=48&&t<=57&&45===i?"\\"+t.toString(16)+" ":t>=128||45===t||95===t||t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122?r.charAt(o):"\\"+r.charAt(o):"�";return a;}function a(e1){return e1.replace(/\\([\dA-Fa-f]{1,6}[\t\n\f\r ]?|[\S\s])/g,e1=>e1.length>2?String.fromCodePoint(Number.parseInt(e1.slice(1).trim(),16)):e1[1]);}var i=new Map([["--font",["--font-weight","--font-size"]],["--inset",["--inset-shadow","--inset-ring"]],["--text",["--text-color","--text-decoration-color","--text-decoration-thickness","--text-indent","--text-shadow","--text-underline-offset"]]]);function l(e1,t){return(i.get(t)??[]).some(t=>e1===t||e1.startsWith(`${t}-`));}var s=class{constructor(e1=new Map,t=new Set([])){this.values=e1,this.keyframes=t;}prefix=null;add(e1,t,r=0){if(e1.endsWith("-*")){if("initial"!==t)throw new Error(`Invalid theme value \`${t}\` for namespace \`${e1}\``);"--*"===e1?this.values.clear():this.clearNamespace(e1.slice(0,-2),0);}if(4&r){let t=this.values.get(e1);if(t&&!(4&t.options))return;}"initial"===t?this.values.delete(e1):this.values.set(e1,{value:t,options:r});}keysInNamespaces(e1){let t=[];for(let r of e1){let e1=`${r}-`;for(let n of this.values.keys())n.startsWith(e1)&&-1===n.indexOf("--",2)&&(l(n,r)||t.push(n.slice(e1.length)));}return t;}get(e1){for(let t of e1){let e1=this.values.get(t);if(e1)return e1.value;}return null;}hasDefault(e1){return!(4&~this.getOptions(e1));}getOptions(e1){return e1=a(this.#e(e1)),this.values.get(e1)?.options??0;}entries(){return this.prefix?Array.from(this.values,e1=>(e1[0]=this.prefixKey(e1[0]),e1)):this.values.entries();}prefixKey(e1){return this.prefix?`--${this.prefix}-${e1.slice(2)}`:e1;}#e(e1){return this.prefix?`--${e1.slice(3+this.prefix.length)}`:e1;}clearNamespace(e1,t){let r=i.get(e1)??[];e:for(let n of this.values.keys())if(n.startsWith(e1)){if(0!==t&&(this.getOptions(n)&t)!==t)continue;for(let e1 of r)if(n.startsWith(e1))continue e;this.values.delete(n);}}#t(e1,t){for(let r of t){let t=null!==e1?`${r}-${e1}`:r;if(!this.values.has(t)){if(null===e1||!e1.includes("."))continue;if(t=`${r}-${e1.replaceAll(".","_")}`,!this.values.has(t))continue;}if(!l(t,r))return t;}return null;}#r(e1){let t=this.values.get(e1);if(!t)return null;let r=null;return 2&t.options&&(r=t.value),`var(${o(this.prefixKey(e1))}${r?`, ${r}`:""})`;}markUsedVariable(e1){let t=a(this.#e(e1)),r=this.values.get(t);if(!r)return!1;let n=16&r.options;return r.options|=16,!n;}resolve(e1,t,r=0){let n=this.#t(e1,t);if(!n)return null;let o=this.values.get(n);return 1&(r|o.options)?o.value:this.#r(n);}resolveValue(e1,t){let r=this.#t(e1,t);return r?this.values.get(r).value:null;}resolveWith(e1,t,r=[]){let n=this.#t(e1,t);if(!n)return null;let o={};for(let e1 of r){let t=`${n}${e1}`,r=this.values.get(t);r&&(1&r.options?o[e1]=r.value:o[e1]=this.#r(t));}let a=this.values.get(n);return 1&a.options?[a.value,o]:[this.#r(n),o];}namespace(e1){let t=new Map,r=`${e1}-`;for(let[n,o]of this.values)n===e1?t.set(null,o.value):n.startsWith(`${r}-`)?t.set(n.slice(e1.length),o.value):n.startsWith(r)&&t.set(n.slice(r.length),o.value);return t;}addKeyframes(e1){this.keyframes.add(e1);}getKeyframes(){return Array.from(this.keyframes);}},c=class extends Map{constructor(e1){super(),this.factory=e1;}get(e1){let t=super.get(e1);return void 0===t&&(t=this.factory(e1,this),this.set(e1,t)),t;}};function u(e1){return{kind:"word",value:e1};}function d(e1,t){return{kind:"function",value:e1,nodes:t};}function f(e1){return{kind:"separator",value:e1};}function p(e1,t,r=null){for(let n=0;n0){let e1=u(a);o?o.nodes.push(e1):r.push(e1),a="";}let n=i,l=i+1;for(;l0){let t=u(a);e1.nodes.push(t),a="";}o=n.length>0?n[n.length-1]:null;break;}default:a+=String.fromCharCode(l);}}return a.length>0&&r.push(u(a)),r;}function g(e1){let t=[];return p(m(e1),e1=>{if("function"===e1.kind&&"var"===e1.value)return p(e1.nodes,e1=>{"word"!==e1.kind||"-"!==e1.value[0]||"-"!==e1.value[1]||t.push(e1.value);}),1;}),t;}var v=64;function w(e1,t=[]){return{kind:"rule",selector:e1,nodes:t};}function k(e1,t="",r=[]){return{kind:"at-rule",name:e1,params:t,nodes:r};}function b(e1,t=[]){return e1.charCodeAt(0)===v?r(e1,t):w(e1,t);}function y(e1,t,r=!1){return{kind:"declaration",property:e1,value:t,important:r};}function x(e1){return{kind:"comment",value:e1};}function $(e1,t){return{kind:"context",context:e1,nodes:t};}function z(e1){return{kind:"at-root",nodes:e1};}function A(e1,t,r=[],n={}){for(let o=0;onew Set),i=new Set,l=new Set,s=[],u=[],d=new c(()=>new Set);function f(e1,c,v={},w=0){if("declaration"===e1.kind){if("--tw-sort"===e1.property||void 0===e1.value||null===e1.value)return;if(v.theme&&"-"===e1.property[0]&&"-"===e1.property[1]){if("initial"===e1.value)return void(e1.value=void 0);v.keyframes||a.get(c).add(e1);}if(e1.value.includes("var("))if(v.theme&&"-"===e1.property[0]&&"-"===e1.property[1])for(let t of g(e1.value))d.get(t).add(e1.property);else t.trackUsedVariables(e1.value);if("animation"===e1.property)for(let t of E(e1.value))l.add(t);if(2&r&&e1.value.includes("color-mix(")){let r=m(e1.value),n=!1;if(p(r,(e1,{replaceWith:r})=>{if("function"!==e1.kind||"color-mix"!==e1.value)return;let o=!1,a=!1;if(p(e1.nodes,(e1,{replaceWith:r})=>{if("word"==e1.kind&&"currentcolor"===e1.value.toLowerCase())return a=!0,void(n=!0);if("function"!==e1.kind||"var"!==e1.value)return;let i=e1.nodes[0];if(!i||"word"!==i.kind)return;n=!0;let l=t.theme.resolveValue(null,[i.value]);l?r({kind:"word",value:l}):o=!0;}),o||a){let t=e1.nodes.findIndex(e1=>"separator"===e1.kind&&e1.value.trim().includes(","));if(-1===t)return;let n=e1.nodes.length>t?e1.nodes[t+1]:null;if(!n)return;r(n);}else if(n){let t=e1.nodes[2];"word"===t.kind&&("oklab"===t.value||"oklch"===t.value||"lab"===t.value||"lch"===t.value)&&(t.value="srgb");}}),n){let t={...e1,value:h(r)},n=b("@supports (color: color-mix(in lab, red, red))",[e1]);return void c.push(t,n);}}c.push(e1);}else if("rule"===e1.kind)if("&"===e1.selector)for(let t of e1.nodes){let e1=[];f(t,e1,v,w+1),e1.length>0&&c.push(...e1);}else{let t={...e1,nodes:[]};for(let r of e1.nodes)f(r,t.nodes,v,w+1);t.nodes.length>0&&c.push(t);}else if("at-rule"===e1.kind&&"@property"===e1.name&&0===w){if(o.has(e1.params))return;if(1&r){let t=e1.params,r=null,n=!1;for(let t of e1.nodes)"declaration"===t.kind&&("initial-value"===t.property?r=t.value:"inherits"===t.property&&(n="true"===t.value));n?s.push(y(t,r??"initial")):u.push(y(t,r??"initial"));}o.add(e1.params);let t={...e1,nodes:[]};for(let r of e1.nodes)f(r,t.nodes,v,w+1);c.push(t);}else if("at-rule"===e1.kind){"@keyframes"===e1.name&&(v={...v,keyframes:!0});let t={...e1,nodes:[]};for(let r of e1.nodes)f(r,t.nodes,v,w+1);"@keyframes"===e1.name&&v.theme&&i.add(t),(t.nodes.length>0||"@layer"===t.name||"@charset"===t.name||"@custom-media"===t.name||"@namespace"===t.name||"@import"===t.name)&&c.push(t);}else if("at-root"===e1.kind)for(let t of e1.nodes){let e1=[];f(t,e1,v,0);for(let t of e1)n.push(t);}else if("context"===e1.kind){if(e1.context.reference)return;for(let t of e1.nodes)f(t,c,{...v,...e1.context},w);}else"comment"===e1.kind&&c.push(e1);}let v=[];for(let t of e1)f(t,v,{},0);e:for(let[e1,r]of a)for(let n of r){if(K(n.property,t.theme,d)){if(n.property.startsWith(t.theme.prefixKey("--animate-")))for(let e1 of E(n.value))l.add(e1);continue;}let r=e1.indexOf(n);if(e1.splice(r,1),0===e1.length){let t=S(v,t=>"rule"===t.kind&&t.nodes===e1);if(!t||0===t.length)continue e;for(t.unshift({kind:"at-root",nodes:v});;){let e1=t.pop();if(!e1)break;let r=t[t.length-1];if(!r||"at-root"!==r.kind&&"at-rule"!==r.kind)break;let n=r.nodes.indexOf(e1);if(-1===n)break;r.nodes.splice(n,1);}continue e;}}for(let e1 of i)if(!l.has(e1.params)){let t=n.indexOf(e1);n.splice(t,1);}if(v=v.concat(n),1&r){let e1=[];if(s.length>0&&e1.push(b(":root, :host",s)),u.length>0&&e1.push(b("*, ::before, ::after, ::backdrop",u)),e1.length>0){let t=v.findIndex(e1=>!("comment"===e1.kind||"at-rule"===e1.kind&&("@charset"===e1.name||"@import"===e1.name)));v.splice(t<0?v.length:t,0,k("@layer","properties",[])),v.push(b("@layer properties",[k("@supports","((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b))))",e1)]));}}return v;}function C(e1){function t(e1,r=0){let n="",o=" ".repeat(r);if("declaration"===e1.kind)n+=`${o}${e1.property}: ${e1.value}${e1.important?" !important":""}; -`;else if("rule"===e1.kind){n+=`${o}${e1.selector} { -`;for(let o of e1.nodes)n+=t(o,r+1);n+=`${o}} -`;}else if("at-rule"===e1.kind){if(0===e1.nodes.length)return`${o}${e1.name} ${e1.params}; -`;n+=`${o}${e1.name}${e1.params?` ${e1.params} `:" "}{ -`;for(let o of e1.nodes)n+=t(o,r+1);n+=`${o}} -`;}else if("comment"===e1.kind)n+=`${o}/*${e1.value}*/ -`;else if("context"===e1.kind||"at-root"===e1.kind)return"";return n;}let r="";for(let n of e1){let e1=t(n);""!==e1&&(r+=e1);}return r;}function S(e1,t){let r=[];return A(e1,(e1,{path:n})=>{if(t(e1))return r=[...n],2;}),r;}function K(e1,t,r,n=new Set){if(n.has(e1)||(n.add(e1),24&t.getOptions(e1)))return!0;{let o=r.get(e1)??[];for(let e1 of o)if(K(e1,t,r,n))return!0;}return!1;}function E(e1){return e1.split(/[\s,]+/);}var V=["calc","min","max","clamp","mod","rem","sin","cos","tan","asin","acos","atan","atan2","pow","sqrt","hypot","log","exp","round"],N=["anchor-size"],O=new RegExp(`(${N.join("|")})\\(`,"g");function F(e1){return-1!==e1.indexOf("(")&&V.some(t=>e1.includes(`${t}(`));}function W(e1){if(-1===e1.indexOf("("))return U(e1);let t=m(e1);return D(t),e1=function(e1){if(!V.some(t=>e1.includes(t)))return e1;let t=!1;N.some(t=>e1.includes(t))&&(O.lastIndex=0,e1=e1.replace(O,(e1,r)=>(t=!0,`$${N.indexOf(r)}$(`)));let r="",n=[];for(let t=0;t=0;r--){let t=e1.charCodeAt(r);if(t>=48&&t<=57)a=r;else{if(!(t>=97&&t<=122))break;a=r;}}let i=e1.slice(a,t);if(V.includes(i)){n.unshift(!0);continue;}if(n[0]&&""===i){n.unshift(!0);continue;}n.unshift(!1);}}return t?r.replace(/\$(\d+)\$/g,(e1,t)=>N[t]??e1):r;}(e1=h(t)),e1;}function U(e1,t=!1){let r="";for(let n=0;n0&&o===_[t-1]&&t--;break;case 59:if(0===t)return!1;}}return!0;}var M=new Uint8Array(256);function R(e1,t){let r=0,n=[],o=0,a=e1.length,i=t.charCodeAt(0);for(let t=0;t0&&l===M[r-1]&&r--;}else n.push(e1.slice(o,t)),o=t+1;}return n.push(e1.slice(o)),n;}function I(e1){if("["===e1[0]&&"]"===e1[e1.length-1]){let t=W(e1.slice(1,-1));return L(t)&&0!==t.length&&0!==t.trim().length?{kind:"arbitrary",value:t}:null;}if("("===e1[0]&&")"===e1[e1.length-1]){let t=W(e1.slice(1,-1));return!L(t)||0===t.length||0===t.trim().length||"-"!==t[0]&&"-"!==t[1]?null:{kind:"arbitrary",value:`var(${t})`};}return{kind:"named",value:e1};}function*q(e1,t){t(e1)&&(yield[e1,null]);let r=e1.lastIndexOf("-");if(-1!==r)do{let n=e1.slice(0,r);if(t(n)){let t=[n,e1.slice(r+1)];if(""===t[1])break;yield t;}r=e1.lastIndexOf("-",r-1);}while(r>0)else"@"===e1[0]&&t("@")&&(yield["@",e1.slice(1)]);}function P(e1,t,r){if(e1===t)return 0;let n=e1.indexOf("("),o=t.indexOf("("),a=-1===n?e1.replace(/[\d.]+/g,""):e1.slice(0,n),i=-1===o?t.replace(/[\d.]+/g,""):t.slice(0,o),l=(a===i?0:a0;},"bg-size":function(e1){let t=0;for(let r of R(e1,",")){if("cover"===r||"contain"===r){t+=1;continue;}let e1=R(r," ");if(1!==e1.length&&2!==e1.length)return!1;e1.every(e1=>"auto"===e1||se(e1)||ae(e1))&&(t+=1);}return t>0;},"line-width":function(e1){return R(e1," ").every(e1=>se(e1)||ne(e1)||"thin"===e1||"medium"===e1||"thick"===e1);},image:function(e1){let t=0;for(let r of R(e1,","))if(!r.startsWith("var(")){if(J(r)){t+=1;continue;}if(ee.test(r)){t+=1;continue;}if(Q.test(r)){t+=1;continue;}return!1;}return t>0;},"family-name":function(e1){let t=0;for(let r of R(e1,",")){let e1=r.charCodeAt(0);if(e1>=48&&e1<=57)return!1;r.startsWith("var(")||(t+=1);}return t>0;},"generic-name":function(e1){return"serif"===e1||"sans-serif"===e1||"monospace"===e1||"cursive"===e1||"fantasy"===e1||"system-ui"===e1||"ui-serif"===e1||"ui-sans-serif"===e1||"ui-monospace"===e1||"ui-rounded"===e1||"math"===e1||"emoji"===e1||"fangsong"===e1;},"absolute-size":function(e1){return"xx-small"===e1||"x-small"===e1||"small"===e1||"medium"===e1||"large"===e1||"x-large"===e1||"xx-large"===e1||"xxx-large"===e1;},"relative-size":function(e1){return"larger"===e1||"smaller"===e1;},angle:function(e1){return ce.test(e1);},vector:function(e1){return ue.test(e1);}};function G(e1,t){if(e1.startsWith("var("))return null;for(let r of t)if(Z[r]?.(e1))return r;return null;}var X=/^url\(.*\)$/;function J(e1){return X.test(e1);}var Q=/^(?:element|image|cross-fade|image-set)\(/,ee=/^(repeating-)?(conic|linear|radial)-gradient\(/;var te=/[+-]?\d*\.?\d+(?:[eE][+-]?\d+)?/,re=new RegExp(`^${te.source}$`);function ne(e1){return re.test(e1)||F(e1);}var oe=new RegExp(`^${te.source}%$`);function ae(e1){return oe.test(e1)||F(e1);}var ie=new RegExp(`^${te.source}s*/s*${te.source}$`);var le=new RegExp(`^${te.source}(${["cm","mm","Q","in","pc","pt","px","em","ex","ch","rem","lh","rlh","vw","vh","vmin","vmax","vb","vi","svw","svh","lvw","lvh","dvw","dvh","cqw","cqh","cqi","cqb","cqmin","cqmax"].join("|")})$`);function se(e1){return le.test(e1)||F(e1);}var ce=new RegExp(`^${te.source}(${["deg","rad","grad","turn"].join("|")})$`);var ue=new RegExp(`^${te.source} +${te.source} +${te.source}$`);function de(e1){let t=Number(e1);return Number.isInteger(t)&&t>=0&&String(t)===String(e1);}function fe(e1){let t=Number(e1);return Number.isInteger(t)&&t>0&&String(t)===String(e1);}function pe(e1){return me(e1,.25);}function he(e1){return me(e1,.25);}function me(e1,t){let r=Number(e1);return r>=0&&r%t==0&&String(r)===String(e1);}var ge=new Set(["inset","inherit","initial","revert","unset"]),ve=/^-?(\d+|\.\d+)(.*?)$/g;function we(e1,t){return R(e1,",").map(e1=>{let r=R(e1=e1.trim()," ").filter(e1=>""!==e1.trim()),n=null,o=null,a=null;for(let e1 of r)ge.has(e1)||(ve.test(e1)?(null===o?o=e1:null===a&&(a=e1),ve.lastIndex=0):null===n&&(n=e1));if(null===o||null===a)return e1;let i=t(n??"currentcolor");return null!==n?e1.replace(n,i):`${e1} ${i}`;}).join(", ");}var ke=/^-?[a-z][a-zA-Z0-9/%._-]*$/,be=/^-?[a-z][a-zA-Z0-9/%._-]*-\*$/,ye=["0","0.5","1","1.5","2","2.5","3","3.5","4","5","6","7","8","9","10","11","12","14","16","20","24","28","32","36","40","44","48","52","56","60","64","72","80","96"],xe=class{utilities=new c(()=>[]);completions=new Map;static(e1,t){this.utilities.get(e1).push({kind:"static",compileFn:t});}functional(e1,t,r){this.utilities.get(e1).push({kind:"functional",compileFn:t,options:r});}has(e1,t){return this.utilities.has(e1)&&this.utilities.get(e1).some(e1=>e1.kind===t);}get(e1){return this.utilities.has(e1)?this.utilities.get(e1):[];}getCompletions(e1){return this.completions.get(e1)?.()??[];}suggest(e1,t){this.completions.set(e1,t);}keys(e1){let t=[];for(let[r,n]of this.utilities.entries())for(let o of n)if(o.kind===e1){t.push(r);break;}return t;}};function $e(e1,t,r){return k("@property",e1,[y("syntax",r?`"${r}"`:'"*"'),y("inherits","false"),...t?[y("initial-value",t)]:[]]);}function ze(e1,t){if(null===t)return e1;let r=Number(t);return Number.isNaN(r)||(t=100*r+"%"),`color-mix(in oklab, ${e1} ${t}, transparent)`;}function Ae(e1,t){let r=Number(t);return Number.isNaN(r)||(t=100*r+"%"),`oklab(from ${e1} l a b / ${t})`;}function je(e1,t,r){if(!t)return e1;if("arbitrary"===t.kind)return ze(e1,t.value);let n=r.resolve(t.value,["--opacity"]);return n?ze(e1,n):he(t.value)?ze(e1,`${t.value}%`):null;}function Te(e1,t,r){let n=null;switch(e1.value.value){case"inherit":n="inherit";break;case"transparent":n="transparent";break;case"current":n="currentcolor";break;default:n=t.resolve(e1.value.value,r);}return n?je(n,e1.modifier,t):null;}var Ce=["number","integer","ratio","percentage"];function Se(e1,t,r){for(let n of t.nodes){if("named"===e1.kind&&"word"===n.kind&&("'"===n.value[0]||'"'===n.value[0])&&n.value[n.value.length-1]===n.value[0]&&n.value.slice(1,-1)===e1.value)return{nodes:m(e1.value)};if("named"===e1.kind&&"word"===n.kind&&"-"===n.value[0]&&"-"===n.value[1]){let t=n.value;if(t.endsWith("-*")){t=t.slice(0,-2);let n=r.theme.resolve(e1.value,[t]);if(n)return{nodes:m(n)};}else{let n=t.split("-*");if(n.length<=1)continue;let o=[n.shift()],a=r.theme.resolveWith(e1.value,o,n);if(a){let[,e1={}]=a;{let t=e1[n.pop()];if(t)return{nodes:m(t)};}}}}else{if("named"===e1.kind&&"word"===n.kind){if(!Ce.includes(n.value))continue;let t="ratio"===n.value&&"fraction"in e1?e1.fraction:e1.value;if(!t)continue;let r=G(t,[n.value]);if(null===r)continue;if("ratio"===r){let[e1,r]=R(t,"/");if(!de(e1)||!de(r))continue;}else{if("number"===r&&!pe(t))continue;if("percentage"===r&&!de(t.slice(0,-1)))continue;}return{nodes:m(t),ratio:"ratio"===r};}if("arbitrary"===e1.kind&&"word"===n.kind&&"["===n.value[0]&&"]"===n.value[n.value.length-1]){let t=n.value.slice(1,-1);if("*"===t)return{nodes:m(e1.value)};if("dataType"in e1&&e1.dataType&&e1.dataType!==t)continue;if("dataType"in e1&&e1.dataType)return{nodes:m(e1.value)};if(null!==G(e1.value,[t]))return{nodes:m(e1.value)};}}}}function Ke(e1,t,r,n,o=""){let a=!1,i=we(t,e1=>null==r?n(e1):e1.startsWith("current")?n(ze(e1,r)):((e1.startsWith("var(")||r.startsWith("var("))&&(a=!0),n(Ae(e1,r))));function l(e1){return o?R(e1,",").map(e1=>o+e1).join(","):e1;}return a?[y(e1,l(we(t,n))),b("@supports (color: lab(from red l a b))",[y(e1,l(i))])]:[y(e1,l(i))];}function Ee(e1,t,r,n,o=""){let a=!1,i=R(t,",").map(e1=>we(e1,e1=>null==r?n(e1):e1.startsWith("current")?n(ze(e1,r)):((e1.startsWith("var(")||r.startsWith("var("))&&(a=!0),n(Ae(e1,r))))).map(e1=>`drop-shadow(${e1})`).join(" ");return a?[y(e1,o+R(t,",").map(e1=>`drop-shadow(${we(e1,n)})`).join(" ")),b("@supports (color: lab(from red l a b))",[y(e1,o+i)])]:[y(e1,o+i)];}var Ve={"--alpha":function(e1,t,r,...n){let[o,a]=R(r,"/").map(e1=>e1.trim());if(!o||!a)throw new Error(`The --alpha(…) function requires a color and an alpha value, e.g.: \`--alpha(${o||"var(--my-color)"} / ${a||"50%"})\``);if(n.length>0)throw new Error(`The --alpha(…) function only accepts one argument, e.g.: \`--alpha(${o||"var(--my-color)"} / ${a||"50%"})\``);return ze(o,a);},"--spacing":function(e1,t,r,...n){if(!r)throw new Error("The --spacing(…) function requires an argument, but received none.");if(n.length>0)throw new Error(`The --spacing(…) function only accepts a single argument, but received ${n.length+1}.`);let o=e1.theme.resolve(null,["--spacing"]);if(!o)throw new Error("The --spacing(…) function requires that the `--spacing` theme variable exists, but it was not found.");return`calc(${o} * ${r})`;},"--theme":function(e1,t,r,...n){if(!r.startsWith("--"))throw new Error("The --theme(…) function can only be used with CSS variables from your theme.");let o=!1;r.endsWith(" inline")&&(o=!0,r=r.slice(0,-7)),"at-rule"===t.kind&&(o=!0);let a=e1.resolveThemeValue(r,o);if(!a){if(n.length>0)return n.join(", ");throw new Error(`Could not resolve value for theme function: \`theme(${r})\`. Consider checking if the variable name is correct or provide a fallback value to silence this error.`);}if(0===n.length)return a;let i=n.join(", ");if("initial"===i)return a;if("initial"===a)return i;if(a.startsWith("var(")||a.startsWith("theme(")||a.startsWith("--theme(")){let e1=m(a);return function(e1,t){p(e1,e1=>{if("function"===e1.kind&&("var"===e1.value||"theme"===e1.value||"--theme"===e1.value))if(1===e1.nodes.length)e1.nodes.push({kind:"word",value:`, ${t}`});else{let r=e1.nodes[e1.nodes.length-1];"word"===r.kind&&"initial"===r.value&&(r.value=t);}});}(e1,i),h(e1);}return a;},theme:function(e1,t,r,...n){r=function(e1){if("'"!==e1[0]&&'"'!==e1[0])return e1;let t="",r=e1[0];for(let n=1;n0)return n.join(", ");if(!o)throw new Error(`Could not resolve value for theme function: \`theme(${r})\`. Consider checking if the path is correct or provide a fallback value to silence this error.`);return o;}};var Ne=new RegExp(Object.keys(Ve).map(e1=>`${e1}\\(`).join("|"));function Oe(e1,t){let r=0;return A(e1,e1=>{if("declaration"===e1.kind&&e1.value&&Ne.test(e1.value))return r|=8,void(e1.value=Fe(e1.value,e1,t));"at-rule"===e1.kind&&("@media"===e1.name||"@custom-media"===e1.name||"@container"===e1.name||"@supports"===e1.name)&&Ne.test(e1.params)&&(r|=8,e1.params=Fe(e1.params,e1,t));}),r;}function Fe(e1,t,r){let n=m(e1);return p(n,(e1,{replaceWith:n})=>{if("function"===e1.kind&&e1.value in Ve){let o=R(h(e1.nodes).trim(),",").map(e1=>e1.trim());return n(m(Ve[e1.value](r,t,...o)));}}),h(n);}function We(e1,t){let r=e1.length,n=t.length,o=r=48&&n<=57&&o>=48&&o<=57){let a=r,i=r+1,l=r,s=r+1;for(n=e1.charCodeAt(i);n>=48&&n<=57;)n=e1.charCodeAt(++i);for(o=t.charCodeAt(s);o>=48&&o<=57;)o=t.charCodeAt(++s);let c=e1.slice(a,i),u=t.slice(l,s),d=Number(c)-Number(u);if(d)return d;if(cu)return 1;}else if(n!==o)return n-o;}return e1.length-t.length;}var Ue=/^\d+\/\d+$/;function De(e1){let t=[];for(let r of e1.utilities.keys("static"))t.push({name:r,utility:r,fraction:!1,modifiers:[]});for(let r of e1.utilities.keys("functional")){let n=e1.utilities.getCompletions(r);for(let e1 of n)for(let n of e1.values){let o=null!==n&&Ue.test(n),a=null===n?r:`${r}-${n}`;t.push({name:a,utility:r,fraction:o,modifiers:e1.modifiers}),e1.supportsNegative&&t.push({name:`-${a}`,utility:`-${r}`,fraction:o,modifiers:e1.modifiers});}}return 0===t.length?[]:(t.sort((e1,t)=>We(e1.name,t.name)),function(e1){let t=[],r=null,n=new Map,o=new c(()=>[]);for(let a of e1){let{utility:e1,fraction:i}=a;r||(r={utility:e1,items:[]},n.set(e1,r)),e1!==r.utility&&(t.push(r),r={utility:e1,items:[]},n.set(e1,r)),i?o.get(e1).push(a):r.items.push(a);}r&&t[t.length-1]!==r&&t.push(r);for(let[e1,t]of o){let r=n.get(e1);r&&r.items.push(...t);}let a=[];for(let e1 of t)for(let t of e1.items)a.push([t.name,{modifiers:t.modifiers}]);return a;}(t));}var Be=/^@?[a-zA-Z0-9_-]*$/,_e=class{compareFns=new Map;variants=new Map;completions=new Map;groupOrder=null;lastOrder=0;static(e1,t,{compounds:r,order:n}={}){this.set(e1,{kind:"static",applyFn:t,compoundsWith:0,compounds:r??2,order:n});}fromAst(e1,t){let r=[];A(t,e1=>{"rule"===e1.kind?r.push(e1.selector):"at-rule"===e1.kind&&"@slot"!==e1.name&&r.push(`${e1.name} ${e1.params}`);}),this.static(e1,e1=>{let r=structuredClone(t);Re(r,e1.nodes),e1.nodes=r;},{compounds:Le(r)});}functional(e1,t,{compounds:r,order:n}={}){this.set(e1,{kind:"functional",applyFn:t,compoundsWith:0,compounds:r??2,order:n});}compound(e1,t,r,{compounds:n,order:o}={}){this.set(e1,{kind:"compound",applyFn:r,compoundsWith:t,compounds:n??2,order:o});}group(e1,t){this.groupOrder=this.nextOrder(),t&&this.compareFns.set(this.groupOrder,t),e1(),this.groupOrder=null;}has(e1){return this.variants.has(e1);}get(e1){return this.variants.get(e1);}kind(e1){return this.variants.get(e1)?.kind;}compoundsWith(e1,t){let r=this.variants.get(e1),n="string"==typeof t?this.variants.get(t):"arbitrary"===t.kind?{compounds:Le([t.selector])}:this.variants.get(t.root);return!!(r&&n&&"compound"===r.kind&&0!==n.compounds&&0!==r.compoundsWith&&r.compoundsWith&n.compounds);}suggest(e1,t){this.completions.set(e1,t);}getCompletions(e1){return this.completions.get(e1)?.()??[];}compare(e1,t){if(e1===t)return 0;if(null===e1)return-1;if(null===t)return 1;if("arbitrary"===e1.kind&&"arbitrary"===t.kind)return e1.selector1){let e1=n[n.length-1];if(" "===n[n.length-2]&&("i"===e1||"I"===e1||"s"===e1||"S"===e1))return`${t}="${n.slice(0,-2)}" ${e1}`;}return`${t}="${n}"`;}return e1;}function Re(e1,t){A(e1,(e1,{replaceWith:r})=>{if("at-rule"===e1.kind&&"@slot"===e1.name)r(t);else if("at-rule"===e1.kind&&("@keyframes"===e1.name||"@property"===e1.name))return Object.assign(e1,z([k(e1.name,e1.params,e1.nodes)])),1;});}function Ie(e1){let t=function(e1){let t=new xe;function r(r,n){let o=/(\d+)_(\d+)/g;function*a(t){for(let r of e1.keysInNamespaces(t))yield r.replace(o,(e1,t,r)=>`${t}.${r}`);}let i=["1/2","1/3","2/3","1/4","2/4","3/4","1/5","2/5","3/5","4/5","1/6","2/6","3/6","4/6","5/6","1/12","2/12","3/12","4/12","5/12","6/12","7/12","8/12","9/12","10/12","11/12"];t.suggest(r,()=>{let e1=[];for(let t of n()){if("string"==typeof t){e1.push({values:[t],modifiers:[]});continue;}let r=[...t.values??[],...a(t.valueThemeKeys??[])],n=[...t.modifiers??[],...a(t.modifierThemeKeys??[])];t.supportsFractions&&r.push(...i),t.hasDefaultValue&&r.unshift(null),e1.push({supportsNegative:t.supportsNegative,values:r,modifiers:n});}return e1;});}function n(e1,r){t.static(e1,()=>r.map(e1=>"function"==typeof e1?e1():y(e1[0],e1[1])));}function o(n,o){function a({negative:t}){return r=>{let n=null,a=null;if(r.value)if("arbitrary"===r.value.kind){if(r.modifier)return;n=r.value.value,a=r.value.dataType;}else{if(n=e1.resolve(r.value.fraction??r.value.value,o.themeKeys??[]),null===n&&o.supportsFractions&&r.value.fraction){let[e1,t]=R(r.value.fraction,"/");if(!de(e1)||!de(t))return;n=`calc(${r.value.fraction} * 100%)`;}if(null===n&&t&&o.handleNegativeBareValue){if(n=o.handleNegativeBareValue(r.value),!n?.includes("/")&&r.modifier)return;if(null!==n)return o.handle(n,null);}if(null===n&&o.handleBareValue&&(n=o.handleBareValue(r.value),!n?.includes("/")&&r.modifier))return;}else{if(r.modifier)return;n=void 0!==o.defaultValue?o.defaultValue:e1.resolve(null,o.themeKeys??[]);}if(null!==n)return o.handle(t?`calc(${n} * -1)`:n,a);};}o.supportsNegative&&t.functional(`-${n}`,a({negative:!0})),t.functional(n,a({negative:!1})),r(n,()=>[{supportsNegative:o.supportsNegative,valueThemeKeys:o.themeKeys??[],hasDefaultValue:void 0!==o.defaultValue&&null!==o.defaultValue,supportsFractions:o.supportsFractions}]);}function a(n,o){t.functional(n,t=>{if(!t.value)return;let r=null;return"arbitrary"===t.value.kind?(r=t.value.value,r=je(r,t.modifier,e1)):r=Te(t,e1,o.themeKeys),null!==r?o.handle(r):void 0;}),r(n,()=>[{values:["current","inherit","transparent"],valueThemeKeys:o.themeKeys,modifiers:Array.from({length:21},(e1,t)=>""+5*t)}]);}function i(n,a,i1,{supportsNegative:l=!1,supportsFractions:s=!1}={}){l&&t.static(`-${n}-px`,()=>i1("-1px")),t.static(`${n}-px`,()=>i1("1px")),o(n,{themeKeys:a,supportsFractions:s,supportsNegative:l,defaultValue:null,handleBareValue:({value:t})=>{let r=e1.resolve(null,["--spacing"]);return r&&pe(t)?`calc(${r} * ${t})`:null;},handleNegativeBareValue:({value:t})=>{let r=e1.resolve(null,["--spacing"]);return r&&pe(t)?`calc(${r} * -${t})`:null;},handle:i1}),r(n,()=>[{values:e1.get(["--spacing"])?ye:[],supportsNegative:l,supportsFractions:s,valueThemeKeys:a}]);}n("sr-only",[["position","absolute"],["width","1px"],["height","1px"],["padding","0"],["margin","-1px"],["overflow","hidden"],["clip","rect(0, 0, 0, 0)"],["white-space","nowrap"],["border-width","0"]]),n("not-sr-only",[["position","static"],["width","auto"],["height","auto"],["padding","0"],["margin","0"],["overflow","visible"],["clip","auto"],["white-space","normal"]]),n("pointer-events-none",[["pointer-events","none"]]),n("pointer-events-auto",[["pointer-events","auto"]]),n("visible",[["visibility","visible"]]),n("invisible",[["visibility","hidden"]]),n("collapse",[["visibility","collapse"]]),n("static",[["position","static"]]),n("fixed",[["position","fixed"]]),n("absolute",[["position","absolute"]]),n("relative",[["position","relative"]]),n("sticky",[["position","sticky"]]);for(let[e1,t]of[["inset","inset"],["inset-x","inset-inline"],["inset-y","inset-block"],["start","inset-inline-start"],["end","inset-inline-end"],["top","top"],["right","right"],["bottom","bottom"],["left","left"]])n(`${e1}-auto`,[[t,"auto"]]),n(`${e1}-full`,[[t,"100%"]]),n(`-${e1}-full`,[[t,"-100%"]]),i(e1,["--inset","--spacing"],e1=>[y(t,e1)],{supportsNegative:!0,supportsFractions:!0});n("isolate",[["isolation","isolate"]]),n("isolation-auto",[["isolation","auto"]]),n("z-auto",[["z-index","auto"]]),o("z",{supportsNegative:!0,handleBareValue:({value:e1})=>de(e1)?e1:null,themeKeys:["--z-index"],handle:e1=>[y("z-index",e1)]}),r("z",()=>[{supportsNegative:!0,values:["0","10","20","30","40","50"],valueThemeKeys:["--z-index"]}]),n("order-first",[["order","-9999"]]),n("order-last",[["order","9999"]]),n("order-none",[["order","0"]]),o("order",{supportsNegative:!0,handleBareValue:({value:e1})=>de(e1)?e1:null,themeKeys:["--order"],handle:e1=>[y("order",e1)]}),r("order",()=>[{supportsNegative:!0,values:Array.from({length:12},(e1,t)=>`${t+1}`),valueThemeKeys:["--order"]}]),n("col-auto",[["grid-column","auto"]]),o("col",{supportsNegative:!0,handleBareValue:({value:e1})=>de(e1)?e1:null,themeKeys:["--grid-column"],handle:e1=>[y("grid-column",e1)]}),n("col-span-full",[["grid-column","1 / -1"]]),o("col-span",{handleBareValue:({value:e1})=>de(e1)?e1:null,handle:e1=>[y("grid-column",`span ${e1} / span ${e1}`)]}),n("col-start-auto",[["grid-column-start","auto"]]),o("col-start",{supportsNegative:!0,handleBareValue:({value:e1})=>de(e1)?e1:null,themeKeys:["--grid-column-start"],handle:e1=>[y("grid-column-start",e1)]}),n("col-end-auto",[["grid-column-end","auto"]]),o("col-end",{supportsNegative:!0,handleBareValue:({value:e1})=>de(e1)?e1:null,themeKeys:["--grid-column-end"],handle:e1=>[y("grid-column-end",e1)]}),r("col-span",()=>[{values:Array.from({length:12},(e1,t)=>`${t+1}`),valueThemeKeys:[]}]),r("col-start",()=>[{supportsNegative:!0,values:Array.from({length:13},(e1,t)=>`${t+1}`),valueThemeKeys:["--grid-column-start"]}]),r("col-end",()=>[{supportsNegative:!0,values:Array.from({length:13},(e1,t)=>`${t+1}`),valueThemeKeys:["--grid-column-end"]}]),n("row-auto",[["grid-row","auto"]]),o("row",{supportsNegative:!0,handleBareValue:({value:e1})=>de(e1)?e1:null,themeKeys:["--grid-row"],handle:e1=>[y("grid-row",e1)]}),n("row-span-full",[["grid-row","1 / -1"]]),o("row-span",{themeKeys:[],handleBareValue:({value:e1})=>de(e1)?e1:null,handle:e1=>[y("grid-row",`span ${e1} / span ${e1}`)]}),n("row-start-auto",[["grid-row-start","auto"]]),o("row-start",{supportsNegative:!0,handleBareValue:({value:e1})=>de(e1)?e1:null,themeKeys:["--grid-row-start"],handle:e1=>[y("grid-row-start",e1)]}),n("row-end-auto",[["grid-row-end","auto"]]),o("row-end",{supportsNegative:!0,handleBareValue:({value:e1})=>de(e1)?e1:null,themeKeys:["--grid-row-end"],handle:e1=>[y("grid-row-end",e1)]}),r("row-span",()=>[{values:Array.from({length:12},(e1,t)=>`${t+1}`),valueThemeKeys:[]}]),r("row-start",()=>[{supportsNegative:!0,values:Array.from({length:13},(e1,t)=>`${t+1}`),valueThemeKeys:["--grid-row-start"]}]),r("row-end",()=>[{supportsNegative:!0,values:Array.from({length:13},(e1,t)=>`${t+1}`),valueThemeKeys:["--grid-row-end"]}]),n("float-start",[["float","inline-start"]]),n("float-end",[["float","inline-end"]]),n("float-right",[["float","right"]]),n("float-left",[["float","left"]]),n("float-none",[["float","none"]]),n("clear-start",[["clear","inline-start"]]),n("clear-end",[["clear","inline-end"]]),n("clear-right",[["clear","right"]]),n("clear-left",[["clear","left"]]),n("clear-both",[["clear","both"]]),n("clear-none",[["clear","none"]]);for(let[e1,t]of[["m","margin"],["mx","margin-inline"],["my","margin-block"],["ms","margin-inline-start"],["me","margin-inline-end"],["mt","margin-top"],["mr","margin-right"],["mb","margin-bottom"],["ml","margin-left"]])n(`${e1}-auto`,[[t,"auto"]]),i(e1,["--margin","--spacing"],e1=>[y(t,e1)],{supportsNegative:!0});n("box-border",[["box-sizing","border-box"]]),n("box-content",[["box-sizing","content-box"]]),n("line-clamp-none",[["overflow","visible"],["display","block"],["-webkit-box-orient","horizontal"],["-webkit-line-clamp","unset"]]),o("line-clamp",{themeKeys:["--line-clamp"],handleBareValue:({value:e1})=>de(e1)?e1:null,handle:e1=>[y("overflow","hidden"),y("display","-webkit-box"),y("-webkit-box-orient","vertical"),y("-webkit-line-clamp",e1)]}),r("line-clamp",()=>[{values:["1","2","3","4","5","6"],valueThemeKeys:["--line-clamp"]}]),n("block",[["display","block"]]),n("inline-block",[["display","inline-block"]]),n("inline",[["display","inline"]]),n("hidden",[["display","none"]]),n("inline-flex",[["display","inline-flex"]]),n("table",[["display","table"]]),n("inline-table",[["display","inline-table"]]),n("table-caption",[["display","table-caption"]]),n("table-cell",[["display","table-cell"]]),n("table-column",[["display","table-column"]]),n("table-column-group",[["display","table-column-group"]]),n("table-footer-group",[["display","table-footer-group"]]),n("table-header-group",[["display","table-header-group"]]),n("table-row-group",[["display","table-row-group"]]),n("table-row",[["display","table-row"]]),n("flow-root",[["display","flow-root"]]),n("flex",[["display","flex"]]),n("grid",[["display","grid"]]),n("inline-grid",[["display","inline-grid"]]),n("contents",[["display","contents"]]),n("list-item",[["display","list-item"]]),n("field-sizing-content",[["field-sizing","content"]]),n("field-sizing-fixed",[["field-sizing","fixed"]]),n("aspect-auto",[["aspect-ratio","auto"]]),n("aspect-square",[["aspect-ratio","1 / 1"]]),o("aspect",{themeKeys:["--aspect"],handleBareValue:({fraction:e1})=>{if(null===e1)return null;let[t,r]=R(e1,"/");return de(t)&&de(r)?e1:null;},handle:e1=>[y("aspect-ratio",e1)]});for(let[e1,t]of[["auto","auto"],["full","100%"],["svw","100svw"],["lvw","100lvw"],["dvw","100dvw"],["svh","100svh"],["lvh","100lvh"],["dvh","100dvh"],["min","min-content"],["max","max-content"],["fit","fit-content"]])n(`size-${e1}`,[["--tw-sort","size"],["width",t],["height",t]]),n(`w-${e1}`,[["width",t]]),n(`h-${e1}`,[["height",t]]),n(`min-w-${e1}`,[["min-width",t]]),n(`min-h-${e1}`,[["min-height",t]]),"auto"!==e1&&(n(`max-w-${e1}`,[["max-width",t]]),n(`max-h-${e1}`,[["max-height",t]]));n("w-screen",[["width","100vw"]]),n("min-w-screen",[["min-width","100vw"]]),n("max-w-screen",[["max-width","100vw"]]),n("h-screen",[["height","100vh"]]),n("min-h-screen",[["min-height","100vh"]]),n("max-h-screen",[["max-height","100vh"]]),n("max-w-none",[["max-width","none"]]),n("max-h-none",[["max-height","none"]]),i("size",["--size","--spacing"],e1=>[y("--tw-sort","size"),y("width",e1),y("height",e1)],{supportsFractions:!0});for(let[e1,t,r]of[["w",["--width","--spacing","--container"],"width"],["min-w",["--min-width","--spacing","--container"],"min-width"],["max-w",["--max-width","--spacing","--container"],"max-width"],["h",["--height","--spacing"],"height"],["min-h",["--min-height","--height","--spacing"],"min-height"],["max-h",["--max-height","--height","--spacing"],"max-height"]])i(e1,t,e1=>[y(r,e1)],{supportsFractions:!0});t.static("container",()=>{let t=[...e1.namespace("--breakpoint").values()];t.sort((e1,t)=>P(e1,t,"asc"));let r=[y("--tw-sort","--tw-container-component"),y("width","100%")];for(let e1 of t)r.push(k("@media",`(width >= ${e1})`,[y("max-width",e1)]));return r;}),n("flex-auto",[["flex","auto"]]),n("flex-initial",[["flex","0 auto"]]),n("flex-none",[["flex","none"]]),t.functional("flex",e1=>{if(e1.value){if("arbitrary"===e1.value.kind)return e1.modifier?void 0:[y("flex",e1.value.value)];if(e1.value.fraction){let[t,r]=R(e1.value.fraction,"/");return de(t)&&de(r)?[y("flex",`calc(${e1.value.fraction} * 100%)`)]:void 0;}if(de(e1.value.value))return e1.modifier?void 0:[y("flex",e1.value.value)];}}),r("flex",()=>[{supportsFractions:!0}]),o("shrink",{defaultValue:"1",handleBareValue:({value:e1})=>de(e1)?e1:null,handle:e1=>[y("flex-shrink",e1)]}),o("grow",{defaultValue:"1",handleBareValue:({value:e1})=>de(e1)?e1:null,handle:e1=>[y("flex-grow",e1)]}),r("shrink",()=>[{values:["0"],valueThemeKeys:[],hasDefaultValue:!0}]),r("grow",()=>[{values:["0"],valueThemeKeys:[],hasDefaultValue:!0}]),n("basis-auto",[["flex-basis","auto"]]),n("basis-full",[["flex-basis","100%"]]),i("basis",["--flex-basis","--spacing","--container"],e1=>[y("flex-basis",e1)],{supportsFractions:!0}),n("table-auto",[["table-layout","auto"]]),n("table-fixed",[["table-layout","fixed"]]),n("caption-top",[["caption-side","top"]]),n("caption-bottom",[["caption-side","bottom"]]),n("border-collapse",[["border-collapse","collapse"]]),n("border-separate",[["border-collapse","separate"]]);let l=()=>z([$e("--tw-border-spacing-x","0",""),$e("--tw-border-spacing-y","0","")]);i("border-spacing",["--border-spacing","--spacing"],e1=>[l(),y("--tw-border-spacing-x",e1),y("--tw-border-spacing-y",e1),y("border-spacing","var(--tw-border-spacing-x) var(--tw-border-spacing-y)")]),i("border-spacing-x",["--border-spacing","--spacing"],e1=>[l(),y("--tw-border-spacing-x",e1),y("border-spacing","var(--tw-border-spacing-x) var(--tw-border-spacing-y)")]),i("border-spacing-y",["--border-spacing","--spacing"],e1=>[l(),y("--tw-border-spacing-y",e1),y("border-spacing","var(--tw-border-spacing-x) var(--tw-border-spacing-y)")]),n("origin-center",[["transform-origin","center"]]),n("origin-top",[["transform-origin","top"]]),n("origin-top-right",[["transform-origin","top right"]]),n("origin-right",[["transform-origin","right"]]),n("origin-bottom-right",[["transform-origin","bottom right"]]),n("origin-bottom",[["transform-origin","bottom"]]),n("origin-bottom-left",[["transform-origin","bottom left"]]),n("origin-left",[["transform-origin","left"]]),n("origin-top-left",[["transform-origin","top left"]]),o("origin",{themeKeys:["--transform-origin"],handle:e1=>[y("transform-origin",e1)]}),n("perspective-origin-center",[["perspective-origin","center"]]),n("perspective-origin-top",[["perspective-origin","top"]]),n("perspective-origin-top-right",[["perspective-origin","top right"]]),n("perspective-origin-right",[["perspective-origin","right"]]),n("perspective-origin-bottom-right",[["perspective-origin","bottom right"]]),n("perspective-origin-bottom",[["perspective-origin","bottom"]]),n("perspective-origin-bottom-left",[["perspective-origin","bottom left"]]),n("perspective-origin-left",[["perspective-origin","left"]]),n("perspective-origin-top-left",[["perspective-origin","top left"]]),o("perspective-origin",{themeKeys:["--perspective-origin"],handle:e1=>[y("perspective-origin",e1)]}),n("perspective-none",[["perspective","none"]]),o("perspective",{themeKeys:["--perspective"],handle:e1=>[y("perspective",e1)]});let s=()=>z([$e("--tw-translate-x","0"),$e("--tw-translate-y","0"),$e("--tw-translate-z","0")]);n("translate-none",[["translate","none"]]),n("-translate-full",[s,["--tw-translate-x","-100%"],["--tw-translate-y","-100%"],["translate","var(--tw-translate-x) var(--tw-translate-y)"]]),n("translate-full",[s,["--tw-translate-x","100%"],["--tw-translate-y","100%"],["translate","var(--tw-translate-x) var(--tw-translate-y)"]]),i("translate",["--translate","--spacing"],e1=>[s(),y("--tw-translate-x",e1),y("--tw-translate-y",e1),y("translate","var(--tw-translate-x) var(--tw-translate-y)")],{supportsNegative:!0,supportsFractions:!0});for(let e1 of["x","y"])n(`-translate-${e1}-full`,[s,[`--tw-translate-${e1}`,"-100%"],["translate","var(--tw-translate-x) var(--tw-translate-y)"]]),n(`translate-${e1}-full`,[s,[`--tw-translate-${e1}`,"100%"],["translate","var(--tw-translate-x) var(--tw-translate-y)"]]),i(`translate-${e1}`,["--translate","--spacing"],t=>[s(),y(`--tw-translate-${e1}`,t),y("translate","var(--tw-translate-x) var(--tw-translate-y)")],{supportsNegative:!0,supportsFractions:!0});i("translate-z",["--translate","--spacing"],e1=>[s(),y("--tw-translate-z",e1),y("translate","var(--tw-translate-x) var(--tw-translate-y) var(--tw-translate-z)")],{supportsNegative:!0}),n("translate-3d",[s,["translate","var(--tw-translate-x) var(--tw-translate-y) var(--tw-translate-z)"]]);let c=()=>z([$e("--tw-scale-x","1"),$e("--tw-scale-y","1"),$e("--tw-scale-z","1")]);function u({negative:t}){return r=>{if(!r.value||r.modifier)return;let n;return"arbitrary"===r.value.kind?(n=r.value.value,[y("scale",n)]):(n=e1.resolve(r.value.value,["--scale"]),!n&&de(r.value.value)&&(n=`${r.value.value}%`),n?(n=t?`calc(${n} * -1)`:n,[c(),y("--tw-scale-x",n),y("--tw-scale-y",n),y("--tw-scale-z",n),y("scale","var(--tw-scale-x) var(--tw-scale-y)")]):void 0);};}n("scale-none",[["scale","none"]]),t.functional("-scale",u({negative:!0})),t.functional("scale",u({negative:!1})),r("scale",()=>[{supportsNegative:!0,values:["0","50","75","90","95","100","105","110","125","150","200"],valueThemeKeys:["--scale"]}]);for(let e1 of["x","y","z"])o(`scale-${e1}`,{supportsNegative:!0,themeKeys:["--scale"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,handle:t=>[c(),y(`--tw-scale-${e1}`,t),y("scale","var(--tw-scale-x) var(--tw-scale-y)"+("z"===e1?" var(--tw-scale-z)":""))]}),r(`scale-${e1}`,()=>[{supportsNegative:!0,values:["0","50","75","90","95","100","105","110","125","150","200"],valueThemeKeys:["--scale"]}]);function d({negative:t}){return r=>{if(!r.value||r.modifier)return;let n;if("arbitrary"===r.value.kind){n=r.value.value;let e1=r.value.dataType??G(n,["angle","vector"]);if("vector"===e1)return[y("rotate",`${n} var(--tw-rotate)`)];if("angle"!==e1)return[y("rotate",n)];}else if(n=e1.resolve(r.value.value,["--rotate"]),!n&&de(r.value.value)&&(n=`${r.value.value}deg`),!n)return;return[y("rotate",t?`calc(${n} * -1)`:n)];};}n("scale-3d",[c,["scale","var(--tw-scale-x) var(--tw-scale-y) var(--tw-scale-z)"]]),n("rotate-none",[["rotate","none"]]),t.functional("-rotate",d({negative:!0})),t.functional("rotate",d({negative:!1})),r("rotate",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12","45","90","180"],valueThemeKeys:["--rotate"]}]);{let e1=["var(--tw-rotate-x)","var(--tw-rotate-y)","var(--tw-rotate-z)","var(--tw-skew-x)","var(--tw-skew-y)"].join(" "),a=()=>z([$e("--tw-rotate-x","rotateX(0)"),$e("--tw-rotate-y","rotateY(0)"),$e("--tw-rotate-z","rotateZ(0)"),$e("--tw-skew-x","skewX(0)"),$e("--tw-skew-y","skewY(0)")]);for(let t of["x","y","z"])o(`rotate-${t}`,{supportsNegative:!0,themeKeys:["--rotate"],handleBareValue:({value:e1})=>de(e1)?`${e1}deg`:null,handle:r=>[a(),y(`--tw-rotate-${t}`,`rotate${t.toUpperCase()}(${r})`),y("transform",e1)]}),r(`rotate-${t}`,()=>[{supportsNegative:!0,values:["0","1","2","3","6","12","45","90","180"],valueThemeKeys:["--rotate"]}]);o("skew",{supportsNegative:!0,themeKeys:["--skew"],handleBareValue:({value:e1})=>de(e1)?`${e1}deg`:null,handle:t=>[a(),y("--tw-skew-x",`skewX(${t})`),y("--tw-skew-y",`skewY(${t})`),y("transform",e1)]}),o("skew-x",{supportsNegative:!0,themeKeys:["--skew"],handleBareValue:({value:e1})=>de(e1)?`${e1}deg`:null,handle:t=>[a(),y("--tw-skew-x",`skewX(${t})`),y("transform",e1)]}),o("skew-y",{supportsNegative:!0,themeKeys:["--skew"],handleBareValue:({value:e1})=>de(e1)?`${e1}deg`:null,handle:t=>[a(),y("--tw-skew-y",`skewY(${t})`),y("transform",e1)]}),r("skew",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12"],valueThemeKeys:["--skew"]}]),r("skew-x",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12"],valueThemeKeys:["--skew"]}]),r("skew-y",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12"],valueThemeKeys:["--skew"]}]),t.functional("transform",t=>{if(t.modifier)return;let r=null;return t.value?"arbitrary"===t.value.kind&&(r=t.value.value):r=e1,null!==r?[a(),y("transform",r)]:void 0;}),r("transform",()=>[{hasDefaultValue:!0}]),n("transform-cpu",[["transform",e1]]),n("transform-gpu",[["transform",`translateZ(0) ${e1}`]]),n("transform-none",[["transform","none"]]);}n("transform-flat",[["transform-style","flat"]]),n("transform-3d",[["transform-style","preserve-3d"]]),n("transform-content",[["transform-box","content-box"]]),n("transform-border",[["transform-box","border-box"]]),n("transform-fill",[["transform-box","fill-box"]]),n("transform-stroke",[["transform-box","stroke-box"]]),n("transform-view",[["transform-box","view-box"]]),n("backface-visible",[["backface-visibility","visible"]]),n("backface-hidden",[["backface-visibility","hidden"]]);for(let e1 of["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out"])n(`cursor-${e1}`,[["cursor",e1]]);o("cursor",{themeKeys:["--cursor"],handle:e1=>[y("cursor",e1)]});for(let e1 of["auto","none","manipulation"])n(`touch-${e1}`,[["touch-action",e1]]);let f=()=>z([$e("--tw-pan-x"),$e("--tw-pan-y"),$e("--tw-pinch-zoom")]);for(let e1 of["x","left","right"])n(`touch-pan-${e1}`,[f,["--tw-pan-x",`pan-${e1}`],["touch-action","var(--tw-pan-x,) var(--tw-pan-y,) var(--tw-pinch-zoom,)"]]);for(let e1 of["y","up","down"])n(`touch-pan-${e1}`,[f,["--tw-pan-y",`pan-${e1}`],["touch-action","var(--tw-pan-x,) var(--tw-pan-y,) var(--tw-pinch-zoom,)"]]);n("touch-pinch-zoom",[f,["--tw-pinch-zoom","pinch-zoom"],["touch-action","var(--tw-pan-x,) var(--tw-pan-y,) var(--tw-pinch-zoom,)"]]);for(let e1 of["none","text","all","auto"])n(`select-${e1}`,[["-webkit-user-select",e1],["user-select",e1]]);n("resize-none",[["resize","none"]]),n("resize-x",[["resize","horizontal"]]),n("resize-y",[["resize","vertical"]]),n("resize",[["resize","both"]]),n("snap-none",[["scroll-snap-type","none"]]);let p=()=>z([$e("--tw-scroll-snap-strictness","proximity","*")]);for(let e1 of["x","y","both"])n(`snap-${e1}`,[p,["scroll-snap-type",`${e1} var(--tw-scroll-snap-strictness)`]]);n("snap-mandatory",[p,["--tw-scroll-snap-strictness","mandatory"]]),n("snap-proximity",[p,["--tw-scroll-snap-strictness","proximity"]]),n("snap-align-none",[["scroll-snap-align","none"]]),n("snap-start",[["scroll-snap-align","start"]]),n("snap-end",[["scroll-snap-align","end"]]),n("snap-center",[["scroll-snap-align","center"]]),n("snap-normal",[["scroll-snap-stop","normal"]]),n("snap-always",[["scroll-snap-stop","always"]]);for(let[e1,t]of[["scroll-m","scroll-margin"],["scroll-mx","scroll-margin-inline"],["scroll-my","scroll-margin-block"],["scroll-ms","scroll-margin-inline-start"],["scroll-me","scroll-margin-inline-end"],["scroll-mt","scroll-margin-top"],["scroll-mr","scroll-margin-right"],["scroll-mb","scroll-margin-bottom"],["scroll-ml","scroll-margin-left"]])i(e1,["--scroll-margin","--spacing"],e1=>[y(t,e1)],{supportsNegative:!0});for(let[e1,t]of[["scroll-p","scroll-padding"],["scroll-px","scroll-padding-inline"],["scroll-py","scroll-padding-block"],["scroll-ps","scroll-padding-inline-start"],["scroll-pe","scroll-padding-inline-end"],["scroll-pt","scroll-padding-top"],["scroll-pr","scroll-padding-right"],["scroll-pb","scroll-padding-bottom"],["scroll-pl","scroll-padding-left"]])i(e1,["--scroll-padding","--spacing"],e1=>[y(t,e1)]);n("list-inside",[["list-style-position","inside"]]),n("list-outside",[["list-style-position","outside"]]),n("list-none",[["list-style-type","none"]]),n("list-disc",[["list-style-type","disc"]]),n("list-decimal",[["list-style-type","decimal"]]),o("list",{themeKeys:["--list-style-type"],handle:e1=>[y("list-style-type",e1)]}),n("list-image-none",[["list-style-image","none"]]),o("list-image",{themeKeys:["--list-style-image"],handle:e1=>[y("list-style-image",e1)]}),n("appearance-none",[["appearance","none"]]),n("appearance-auto",[["appearance","auto"]]),n("scheme-normal",[["color-scheme","normal"]]),n("scheme-dark",[["color-scheme","dark"]]),n("scheme-light",[["color-scheme","light"]]),n("scheme-light-dark",[["color-scheme","light dark"]]),n("scheme-only-dark",[["color-scheme","only dark"]]),n("scheme-only-light",[["color-scheme","only light"]]),n("columns-auto",[["columns","auto"]]),o("columns",{themeKeys:["--columns","--container"],handleBareValue:({value:e1})=>de(e1)?e1:null,handle:e1=>[y("columns",e1)]}),r("columns",()=>[{values:Array.from({length:12},(e1,t)=>`${t+1}`),valueThemeKeys:["--columns","--container"]}]);for(let e1 of["auto","avoid","all","avoid-page","page","left","right","column"])n(`break-before-${e1}`,[["break-before",e1]]);for(let e1 of["auto","avoid","avoid-page","avoid-column"])n(`break-inside-${e1}`,[["break-inside",e1]]);for(let e1 of["auto","avoid","all","avoid-page","page","left","right","column"])n(`break-after-${e1}`,[["break-after",e1]]);n("grid-flow-row",[["grid-auto-flow","row"]]),n("grid-flow-col",[["grid-auto-flow","column"]]),n("grid-flow-dense",[["grid-auto-flow","dense"]]),n("grid-flow-row-dense",[["grid-auto-flow","row dense"]]),n("grid-flow-col-dense",[["grid-auto-flow","column dense"]]),n("auto-cols-auto",[["grid-auto-columns","auto"]]),n("auto-cols-min",[["grid-auto-columns","min-content"]]),n("auto-cols-max",[["grid-auto-columns","max-content"]]),n("auto-cols-fr",[["grid-auto-columns","minmax(0, 1fr)"]]),o("auto-cols",{themeKeys:["--grid-auto-columns"],handle:e1=>[y("grid-auto-columns",e1)]}),n("auto-rows-auto",[["grid-auto-rows","auto"]]),n("auto-rows-min",[["grid-auto-rows","min-content"]]),n("auto-rows-max",[["grid-auto-rows","max-content"]]),n("auto-rows-fr",[["grid-auto-rows","minmax(0, 1fr)"]]),o("auto-rows",{themeKeys:["--grid-auto-rows"],handle:e1=>[y("grid-auto-rows",e1)]}),n("grid-cols-none",[["grid-template-columns","none"]]),n("grid-cols-subgrid",[["grid-template-columns","subgrid"]]),o("grid-cols",{themeKeys:["--grid-template-columns"],handleBareValue:({value:e1})=>fe(e1)?`repeat(${e1}, minmax(0, 1fr))`:null,handle:e1=>[y("grid-template-columns",e1)]}),n("grid-rows-none",[["grid-template-rows","none"]]),n("grid-rows-subgrid",[["grid-template-rows","subgrid"]]),o("grid-rows",{themeKeys:["--grid-template-rows"],handleBareValue:({value:e1})=>fe(e1)?`repeat(${e1}, minmax(0, 1fr))`:null,handle:e1=>[y("grid-template-rows",e1)]}),r("grid-cols",()=>[{values:Array.from({length:12},(e1,t)=>`${t+1}`),valueThemeKeys:["--grid-template-columns"]}]),r("grid-rows",()=>[{values:Array.from({length:12},(e1,t)=>`${t+1}`),valueThemeKeys:["--grid-template-rows"]}]),n("flex-row",[["flex-direction","row"]]),n("flex-row-reverse",[["flex-direction","row-reverse"]]),n("flex-col",[["flex-direction","column"]]),n("flex-col-reverse",[["flex-direction","column-reverse"]]),n("flex-wrap",[["flex-wrap","wrap"]]),n("flex-nowrap",[["flex-wrap","nowrap"]]),n("flex-wrap-reverse",[["flex-wrap","wrap-reverse"]]),n("place-content-center",[["place-content","center"]]),n("place-content-start",[["place-content","start"]]),n("place-content-end",[["place-content","end"]]),n("place-content-center-safe",[["place-content","safe center"]]),n("place-content-end-safe",[["place-content","safe end"]]),n("place-content-between",[["place-content","space-between"]]),n("place-content-around",[["place-content","space-around"]]),n("place-content-evenly",[["place-content","space-evenly"]]),n("place-content-baseline",[["place-content","baseline"]]),n("place-content-stretch",[["place-content","stretch"]]),n("place-items-center",[["place-items","center"]]),n("place-items-start",[["place-items","start"]]),n("place-items-end",[["place-items","end"]]),n("place-items-center-safe",[["place-items","safe center"]]),n("place-items-end-safe",[["place-items","safe end"]]),n("place-items-baseline",[["place-items","baseline"]]),n("place-items-stretch",[["place-items","stretch"]]),n("content-normal",[["align-content","normal"]]),n("content-center",[["align-content","center"]]),n("content-start",[["align-content","flex-start"]]),n("content-end",[["align-content","flex-end"]]),n("content-center-safe",[["align-content","safe center"]]),n("content-end-safe",[["align-content","safe flex-end"]]),n("content-between",[["align-content","space-between"]]),n("content-around",[["align-content","space-around"]]),n("content-evenly",[["align-content","space-evenly"]]),n("content-baseline",[["align-content","baseline"]]),n("content-stretch",[["align-content","stretch"]]),n("items-center",[["align-items","center"]]),n("items-start",[["align-items","flex-start"]]),n("items-end",[["align-items","flex-end"]]),n("items-center-safe",[["align-items","safe center"]]),n("items-end-safe",[["align-items","safe flex-end"]]),n("items-baseline",[["align-items","baseline"]]),n("items-baseline-last",[["align-items","last baseline"]]),n("items-stretch",[["align-items","stretch"]]),n("justify-normal",[["justify-content","normal"]]),n("justify-center",[["justify-content","center"]]),n("justify-start",[["justify-content","flex-start"]]),n("justify-end",[["justify-content","flex-end"]]),n("justify-center-safe",[["justify-content","safe center"]]),n("justify-end-safe",[["justify-content","safe flex-end"]]),n("justify-between",[["justify-content","space-between"]]),n("justify-around",[["justify-content","space-around"]]),n("justify-evenly",[["justify-content","space-evenly"]]),n("justify-baseline",[["justify-content","baseline"]]),n("justify-stretch",[["justify-content","stretch"]]),n("justify-items-normal",[["justify-items","normal"]]),n("justify-items-center",[["justify-items","center"]]),n("justify-items-start",[["justify-items","start"]]),n("justify-items-end",[["justify-items","end"]]),n("justify-items-center-safe",[["justify-items","safe center"]]),n("justify-items-end-safe",[["justify-items","safe end"]]),n("justify-items-stretch",[["justify-items","stretch"]]),i("gap",["--gap","--spacing"],e1=>[y("gap",e1)]),i("gap-x",["--gap","--spacing"],e1=>[y("column-gap",e1)]),i("gap-y",["--gap","--spacing"],e1=>[y("row-gap",e1)]),i("space-x",["--space","--spacing"],e1=>[z([$e("--tw-space-x-reverse","0")]),w(":where(& > :not(:last-child))",[y("--tw-sort","row-gap"),y("--tw-space-x-reverse","0"),y("margin-inline-start",`calc(${e1} * var(--tw-space-x-reverse))`),y("margin-inline-end",`calc(${e1} * calc(1 - var(--tw-space-x-reverse)))`)])],{supportsNegative:!0}),i("space-y",["--space","--spacing"],e1=>[z([$e("--tw-space-y-reverse","0")]),w(":where(& > :not(:last-child))",[y("--tw-sort","column-gap"),y("--tw-space-y-reverse","0"),y("margin-block-start",`calc(${e1} * var(--tw-space-y-reverse))`),y("margin-block-end",`calc(${e1} * calc(1 - var(--tw-space-y-reverse)))`)])],{supportsNegative:!0}),n("space-x-reverse",[()=>z([$e("--tw-space-x-reverse","0")]),()=>w(":where(& > :not(:last-child))",[y("--tw-sort","row-gap"),y("--tw-space-x-reverse","1")])]),n("space-y-reverse",[()=>z([$e("--tw-space-y-reverse","0")]),()=>w(":where(& > :not(:last-child))",[y("--tw-sort","column-gap"),y("--tw-space-y-reverse","1")])]),n("accent-auto",[["accent-color","auto"]]),a("accent",{themeKeys:["--accent-color","--color"],handle:e1=>[y("accent-color",e1)]}),a("caret",{themeKeys:["--caret-color","--color"],handle:e1=>[y("caret-color",e1)]}),a("divide",{themeKeys:["--divide-color","--color"],handle:e1=>[w(":where(& > :not(:last-child))",[y("--tw-sort","divide-color"),y("border-color",e1)])]}),n("place-self-auto",[["place-self","auto"]]),n("place-self-start",[["place-self","start"]]),n("place-self-end",[["place-self","end"]]),n("place-self-center",[["place-self","center"]]),n("place-self-end-safe",[["place-self","safe end"]]),n("place-self-center-safe",[["place-self","safe center"]]),n("place-self-stretch",[["place-self","stretch"]]),n("self-auto",[["align-self","auto"]]),n("self-start",[["align-self","flex-start"]]),n("self-end",[["align-self","flex-end"]]),n("self-center",[["align-self","center"]]),n("self-end-safe",[["align-self","safe flex-end"]]),n("self-center-safe",[["align-self","safe center"]]),n("self-stretch",[["align-self","stretch"]]),n("self-baseline",[["align-self","baseline"]]),n("self-baseline-last",[["align-self","last baseline"]]),n("justify-self-auto",[["justify-self","auto"]]),n("justify-self-start",[["justify-self","flex-start"]]),n("justify-self-end",[["justify-self","flex-end"]]),n("justify-self-center",[["justify-self","center"]]),n("justify-self-end-safe",[["justify-self","safe flex-end"]]),n("justify-self-center-safe",[["justify-self","safe center"]]),n("justify-self-stretch",[["justify-self","stretch"]]);for(let e1 of["auto","hidden","clip","visible","scroll"])n(`overflow-${e1}`,[["overflow",e1]]),n(`overflow-x-${e1}`,[["overflow-x",e1]]),n(`overflow-y-${e1}`,[["overflow-y",e1]]);for(let e1 of["auto","contain","none"])n(`overscroll-${e1}`,[["overscroll-behavior",e1]]),n(`overscroll-x-${e1}`,[["overscroll-behavior-x",e1]]),n(`overscroll-y-${e1}`,[["overscroll-behavior-y",e1]]);n("scroll-auto",[["scroll-behavior","auto"]]),n("scroll-smooth",[["scroll-behavior","smooth"]]),n("truncate",[["overflow","hidden"],["text-overflow","ellipsis"],["white-space","nowrap"]]),n("text-ellipsis",[["text-overflow","ellipsis"]]),n("text-clip",[["text-overflow","clip"]]),n("hyphens-none",[["-webkit-hyphens","none"],["hyphens","none"]]),n("hyphens-manual",[["-webkit-hyphens","manual"],["hyphens","manual"]]),n("hyphens-auto",[["-webkit-hyphens","auto"],["hyphens","auto"]]),n("whitespace-normal",[["white-space","normal"]]),n("whitespace-nowrap",[["white-space","nowrap"]]),n("whitespace-pre",[["white-space","pre"]]),n("whitespace-pre-line",[["white-space","pre-line"]]),n("whitespace-pre-wrap",[["white-space","pre-wrap"]]),n("whitespace-break-spaces",[["white-space","break-spaces"]]),n("text-wrap",[["text-wrap","wrap"]]),n("text-nowrap",[["text-wrap","nowrap"]]),n("text-balance",[["text-wrap","balance"]]),n("text-pretty",[["text-wrap","pretty"]]),n("break-normal",[["overflow-wrap","normal"],["word-break","normal"]]),n("break-words",[["overflow-wrap","break-word"]]),n("break-all",[["word-break","break-all"]]),n("break-keep",[["word-break","keep-all"]]),n("wrap-anywhere",[["overflow-wrap","anywhere"]]),n("wrap-break-word",[["overflow-wrap","break-word"]]),n("wrap-normal",[["overflow-wrap","normal"]]);for(let[e1,t]of[["rounded",["border-radius"]],["rounded-s",["border-start-start-radius","border-end-start-radius"]],["rounded-e",["border-start-end-radius","border-end-end-radius"]],["rounded-t",["border-top-left-radius","border-top-right-radius"]],["rounded-r",["border-top-right-radius","border-bottom-right-radius"]],["rounded-b",["border-bottom-right-radius","border-bottom-left-radius"]],["rounded-l",["border-top-left-radius","border-bottom-left-radius"]],["rounded-ss",["border-start-start-radius"]],["rounded-se",["border-start-end-radius"]],["rounded-ee",["border-end-end-radius"]],["rounded-es",["border-end-start-radius"]],["rounded-tl",["border-top-left-radius"]],["rounded-tr",["border-top-right-radius"]],["rounded-br",["border-bottom-right-radius"]],["rounded-bl",["border-bottom-left-radius"]]])n(`${e1}-none`,t.map(e1=>[e1,"0"])),n(`${e1}-full`,t.map(e1=>[e1,"calc(infinity * 1px)"])),o(e1,{themeKeys:["--radius"],handle:e1=>t.map(t=>y(t,e1))});n("border-solid",[["--tw-border-style","solid"],["border-style","solid"]]),n("border-dashed",[["--tw-border-style","dashed"],["border-style","dashed"]]),n("border-dotted",[["--tw-border-style","dotted"],["border-style","dotted"]]),n("border-double",[["--tw-border-style","double"],["border-style","double"]]),n("border-hidden",[["--tw-border-style","hidden"],["border-style","hidden"]]),n("border-none",[["--tw-border-style","none"],["border-style","none"]]);{let a=function(n,o){t.functional(n,t=>{if(!t.value){if(t.modifier)return;let r=e1.get(["--default-border-width"])??"1px",n=o.width(r);return n?[i(),...n]:void 0;}if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??G(r,["color","line-width","length"])){case"line-width":case"length":{if(t.modifier)return;let e1=o.width(r);return e1?[i(),...e1]:void 0;}default:return r=je(r,t.modifier,e1),null===r?void 0:o.color(r);}}{let r=Te(t,e1,["--border-color","--color"]);if(r)return o.color(r);}{if(t.modifier)return;let r=e1.resolve(t.value.value,["--border-width"]);if(r){let e1=o.width(r);return e1?[i(),...e1]:void 0;}if(de(t.value.value)){let e1=o.width(`${t.value.value}px`);return e1?[i(),...e1]:void 0;}}}),r(n,()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--border-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t),hasDefaultValue:!0},{values:["0","2","4","8"],valueThemeKeys:["--border-width"]}]);},i=()=>z([$e("--tw-border-style","solid")]);a("border",{width:e1=>[y("border-style","var(--tw-border-style)"),y("border-width",e1)],color:e1=>[y("border-color",e1)]}),a("border-x",{width:e1=>[y("border-inline-style","var(--tw-border-style)"),y("border-inline-width",e1)],color:e1=>[y("border-inline-color",e1)]}),a("border-y",{width:e1=>[y("border-block-style","var(--tw-border-style)"),y("border-block-width",e1)],color:e1=>[y("border-block-color",e1)]}),a("border-s",{width:e1=>[y("border-inline-start-style","var(--tw-border-style)"),y("border-inline-start-width",e1)],color:e1=>[y("border-inline-start-color",e1)]}),a("border-e",{width:e1=>[y("border-inline-end-style","var(--tw-border-style)"),y("border-inline-end-width",e1)],color:e1=>[y("border-inline-end-color",e1)]}),a("border-t",{width:e1=>[y("border-top-style","var(--tw-border-style)"),y("border-top-width",e1)],color:e1=>[y("border-top-color",e1)]}),a("border-r",{width:e1=>[y("border-right-style","var(--tw-border-style)"),y("border-right-width",e1)],color:e1=>[y("border-right-color",e1)]}),a("border-b",{width:e1=>[y("border-bottom-style","var(--tw-border-style)"),y("border-bottom-width",e1)],color:e1=>[y("border-bottom-color",e1)]}),a("border-l",{width:e1=>[y("border-left-style","var(--tw-border-style)"),y("border-left-width",e1)],color:e1=>[y("border-left-color",e1)]}),o("divide-x",{defaultValue:e1.get(["--default-border-width"])??"1px",themeKeys:["--divide-width","--border-width"],handleBareValue:({value:e1})=>de(e1)?`${e1}px`:null,handle:e1=>[z([$e("--tw-divide-x-reverse","0")]),w(":where(& > :not(:last-child))",[y("--tw-sort","divide-x-width"),i(),y("--tw-divide-x-reverse","0"),y("border-inline-style","var(--tw-border-style)"),y("border-inline-start-width",`calc(${e1} * var(--tw-divide-x-reverse))`),y("border-inline-end-width",`calc(${e1} * calc(1 - var(--tw-divide-x-reverse)))`)])]}),o("divide-y",{defaultValue:e1.get(["--default-border-width"])??"1px",themeKeys:["--divide-width","--border-width"],handleBareValue:({value:e1})=>de(e1)?`${e1}px`:null,handle:e1=>[z([$e("--tw-divide-y-reverse","0")]),w(":where(& > :not(:last-child))",[y("--tw-sort","divide-y-width"),i(),y("--tw-divide-y-reverse","0"),y("border-bottom-style","var(--tw-border-style)"),y("border-top-style","var(--tw-border-style)"),y("border-top-width",`calc(${e1} * var(--tw-divide-y-reverse))`),y("border-bottom-width",`calc(${e1} * calc(1 - var(--tw-divide-y-reverse)))`)])]}),r("divide-x",()=>[{values:["0","2","4","8"],valueThemeKeys:["--divide-width","--border-width"],hasDefaultValue:!0}]),r("divide-y",()=>[{values:["0","2","4","8"],valueThemeKeys:["--divide-width","--border-width"],hasDefaultValue:!0}]),n("divide-x-reverse",[()=>z([$e("--tw-divide-x-reverse","0")]),()=>w(":where(& > :not(:last-child))",[y("--tw-divide-x-reverse","1")])]),n("divide-y-reverse",[()=>z([$e("--tw-divide-y-reverse","0")]),()=>w(":where(& > :not(:last-child))",[y("--tw-divide-y-reverse","1")])]);for(let e1 of["solid","dashed","dotted","double","none"])n(`divide-${e1}`,[()=>w(":where(& > :not(:last-child))",[y("--tw-sort","divide-style"),y("--tw-border-style",e1),y("border-style",e1)])]);}n("bg-auto",[["background-size","auto"]]),n("bg-cover",[["background-size","cover"]]),n("bg-contain",[["background-size","contain"]]),o("bg-size",{handle(e1){if(e1)return[y("background-size",e1)];}}),n("bg-fixed",[["background-attachment","fixed"]]),n("bg-local",[["background-attachment","local"]]),n("bg-scroll",[["background-attachment","scroll"]]),n("bg-top",[["background-position","top"]]),n("bg-top-left",[["background-position","left top"]]),n("bg-top-right",[["background-position","right top"]]),n("bg-bottom",[["background-position","bottom"]]),n("bg-bottom-left",[["background-position","left bottom"]]),n("bg-bottom-right",[["background-position","right bottom"]]),n("bg-left",[["background-position","left"]]),n("bg-right",[["background-position","right"]]),n("bg-center",[["background-position","center"]]),o("bg-position",{handle(e1){if(e1)return[y("background-position",e1)];}}),n("bg-repeat",[["background-repeat","repeat"]]),n("bg-no-repeat",[["background-repeat","no-repeat"]]),n("bg-repeat-x",[["background-repeat","repeat-x"]]),n("bg-repeat-y",[["background-repeat","repeat-y"]]),n("bg-repeat-round",[["background-repeat","round"]]),n("bg-repeat-space",[["background-repeat","space"]]),n("bg-none",[["background-image","none"]]);{let e1=function(e1){let t="in oklab";if("named"===e1?.kind)switch(e1.value){case"longer":case"shorter":case"increasing":case"decreasing":t=`in oklch ${e1.value} hue`;break;default:t=`in ${e1.value}`;}else"arbitrary"===e1?.kind&&(t=e1.value);return t;},n=function({negative:t}){return r=>{if(!r.value)return;if("arbitrary"===r.value.kind){if(r.modifier)return;let e1=r.value.value;return"angle"===(r.value.dataType??G(e1,["angle"]))?(e1=t?`calc(${e1} * -1)`:`${e1}`,[y("--tw-gradient-position",e1),y("background-image",`linear-gradient(var(--tw-gradient-stops,${e1}))`)]):t?void 0:[y("--tw-gradient-position",e1),y("background-image",`linear-gradient(var(--tw-gradient-stops,${e1}))`)];}let n=r.value.value;if(!t&&i.has(n))n=i.get(n);else{if(!de(n))return;n=t?`calc(${n}deg * -1)`:`${n}deg`;}let o=e1(r.modifier);return[y("--tw-gradient-position",`${n}`),b("@supports (background-image: linear-gradient(in lab, red, red))",[y("--tw-gradient-position",`${n} ${o}`)]),y("background-image","linear-gradient(var(--tw-gradient-stops))")];};},o=function({negative:t}){return r=>{if("arbitrary"===r.value?.kind){if(r.modifier)return;let e1=r.value.value;return[y("--tw-gradient-position",e1),y("background-image",`conic-gradient(var(--tw-gradient-stops,${e1}))`)];}let n=e1(r.modifier);if(!r.value)return[y("--tw-gradient-position",n),y("background-image","conic-gradient(var(--tw-gradient-stops))")];let o=r.value.value;return de(o)?(o=t?`calc(${o}deg * -1)`:`${o}deg`,[y("--tw-gradient-position",`from ${o} ${n}`),y("background-image","conic-gradient(var(--tw-gradient-stops))")]):void 0;};},a=["oklab","oklch","srgb","hsl","longer","shorter","increasing","decreasing"],i=new Map([["to-t","to top"],["to-tr","to top right"],["to-r","to right"],["to-br","to bottom right"],["to-b","to bottom"],["to-bl","to bottom left"],["to-l","to left"],["to-tl","to top left"]]);t.functional("-bg-linear",n({negative:!0})),t.functional("bg-linear",n({negative:!1})),r("bg-linear",()=>[{values:[...i.keys()],modifiers:a},{values:["0","30","60","90","120","150","180","210","240","270","300","330"],supportsNegative:!0,modifiers:a}]),t.functional("-bg-conic",o({negative:!0})),t.functional("bg-conic",o({negative:!1})),r("bg-conic",()=>[{hasDefaultValue:!0,modifiers:a},{values:["0","30","60","90","120","150","180","210","240","270","300","330"],supportsNegative:!0,modifiers:a}]),t.functional("bg-radial",t=>{if(!t.value)return[y("--tw-gradient-position",e1(t.modifier)),y("background-image","radial-gradient(var(--tw-gradient-stops))")];if("arbitrary"===t.value.kind){if(t.modifier)return;let e1=t.value.value;return[y("--tw-gradient-position",e1),y("background-image",`radial-gradient(var(--tw-gradient-stops,${e1}))`)];}}),r("bg-radial",()=>[{hasDefaultValue:!0,modifiers:a}]);}t.functional("bg",t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??G(r,["image","color","percentage","position","bg-size","length","url"])){case"percentage":case"position":return t.modifier?void 0:[y("background-position",r)];case"bg-size":case"length":case"size":return t.modifier?void 0:[y("background-size",r)];case"image":case"url":return t.modifier?void 0:[y("background-image",r)];default:return r=je(r,t.modifier,e1),null===r?void 0:[y("background-color",r)];}}{let r=Te(t,e1,["--background-color","--color"]);if(r)return[y("background-color",r)];}{if(t.modifier)return;let r=e1.resolve(t.value.value,["--background-image"]);if(r)return[y("background-image",r)];}}}),r("bg",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--background-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:[],valueThemeKeys:["--background-image"]}]);let h=()=>z([$e("--tw-gradient-position"),$e("--tw-gradient-from","#0000",""),$e("--tw-gradient-via","#0000",""),$e("--tw-gradient-to","#0000",""),$e("--tw-gradient-stops"),$e("--tw-gradient-via-stops"),$e("--tw-gradient-from-position","0%",""),$e("--tw-gradient-via-position","50%",""),$e("--tw-gradient-to-position","100%","")]);function m(n,o){t.functional(n,t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??G(r,["color","length","percentage"])){case"length":case"percentage":return t.modifier?void 0:o.position(r);default:return r=je(r,t.modifier,e1),null===r?void 0:o.color(r);}}{let r=Te(t,e1,["--background-color","--color"]);if(r)return o.color(r);}{if(t.modifier)return;let r=e1.resolve(t.value.value,["--gradient-color-stop-positions"]);if(r)return o.position(r);if("%"===t.value.value[t.value.value.length-1]&&de(t.value.value.slice(0,-1)))return o.position(t.value.value);}}}),r(n,()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--background-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:Array.from({length:21},(e1,t)=>5*t+"%"),valueThemeKeys:["--gradient-color-stop-positions"]}]);}m("from",{color:e1=>[h(),y("--tw-sort","--tw-gradient-from"),y("--tw-gradient-from",e1),y("--tw-gradient-stops","var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))")],position:e1=>[h(),y("--tw-gradient-from-position",e1)]}),n("via-none",[["--tw-gradient-via-stops","initial"]]),m("via",{color:e1=>[h(),y("--tw-sort","--tw-gradient-via"),y("--tw-gradient-via",e1),y("--tw-gradient-via-stops","var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position)"),y("--tw-gradient-stops","var(--tw-gradient-via-stops)")],position:e1=>[h(),y("--tw-gradient-via-position",e1)]}),m("to",{color:e1=>[h(),y("--tw-sort","--tw-gradient-to"),y("--tw-gradient-to",e1),y("--tw-gradient-stops","var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))")],position:e1=>[h(),y("--tw-gradient-to-position",e1)]}),n("mask-none",[["mask-image","none"]]),t.functional("mask",e1=>{if(!e1.value||e1.modifier||"arbitrary"!==e1.value.kind)return;let t=e1.value.value;switch(e1.value.dataType??G(t,["image","percentage","position","bg-size","length","url"])){case"percentage":case"position":return e1.modifier?void 0:[y("mask-position",t)];case"bg-size":case"length":case"size":return[y("mask-size",t)];default:return[y("mask-image",t)];}}),n("mask-add",[["mask-composite","add"]]),n("mask-subtract",[["mask-composite","subtract"]]),n("mask-intersect",[["mask-composite","intersect"]]),n("mask-exclude",[["mask-composite","exclude"]]),n("mask-alpha",[["mask-mode","alpha"]]),n("mask-luminance",[["mask-mode","luminance"]]),n("mask-match",[["mask-mode","match-source"]]),n("mask-type-alpha",[["mask-type","alpha"]]),n("mask-type-luminance",[["mask-type","luminance"]]),n("mask-auto",[["mask-size","auto"]]),n("mask-cover",[["mask-size","cover"]]),n("mask-contain",[["mask-size","contain"]]),o("mask-size",{handle(e1){if(e1)return[y("mask-size",e1)];}}),n("mask-top",[["mask-position","top"]]),n("mask-top-left",[["mask-position","left top"]]),n("mask-top-right",[["mask-position","right top"]]),n("mask-bottom",[["mask-position","bottom"]]),n("mask-bottom-left",[["mask-position","left bottom"]]),n("mask-bottom-right",[["mask-position","right bottom"]]),n("mask-left",[["mask-position","left"]]),n("mask-right",[["mask-position","right"]]),n("mask-center",[["mask-position","center"]]),o("mask-position",{handle(e1){if(e1)return[y("mask-position",e1)];}}),n("mask-repeat",[["mask-repeat","repeat"]]),n("mask-no-repeat",[["mask-repeat","no-repeat"]]),n("mask-repeat-x",[["mask-repeat","repeat-x"]]),n("mask-repeat-y",[["mask-repeat","repeat-y"]]),n("mask-repeat-round",[["mask-repeat","round"]]),n("mask-repeat-space",[["mask-repeat","space"]]),n("mask-clip-border",[["mask-clip","border-box"]]),n("mask-clip-padding",[["mask-clip","padding-box"]]),n("mask-clip-content",[["mask-clip","content-box"]]),n("mask-clip-fill",[["mask-clip","fill-box"]]),n("mask-clip-stroke",[["mask-clip","stroke-box"]]),n("mask-clip-view",[["mask-clip","view-box"]]),n("mask-no-clip",[["mask-clip","no-clip"]]),n("mask-origin-border",[["mask-origin","border-box"]]),n("mask-origin-padding",[["mask-origin","padding-box"]]),n("mask-origin-content",[["mask-origin","content-box"]]),n("mask-origin-fill",[["mask-origin","fill-box"]]),n("mask-origin-stroke",[["mask-origin","stroke-box"]]),n("mask-origin-view",[["mask-origin","view-box"]]);let g=()=>z([$e("--tw-mask-linear","linear-gradient(#fff, #fff)"),$e("--tw-mask-radial","linear-gradient(#fff, #fff)"),$e("--tw-mask-conic","linear-gradient(#fff, #fff)")]);function v(n,o){t.functional(n,t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??G(r,["length","percentage","color"])){case"color":return r=je(r,t.modifier,e1),null===r?void 0:o.color(r);case"percentage":return t.modifier||!de(r.slice(0,-1))?void 0:o.position(r);default:return t.modifier?void 0:o.position(r);}}{let r=Te(t,e1,["--background-color","--color"]);if(r)return o.color(r);}{if(t.modifier)return;let r=G(t.value.value,["number","percentage"]);if(!r)return;switch(r){case"number":{let r=e1.resolve(null,["--spacing"]);return r&&pe(t.value.value)?o.position(`calc(${r} * ${t.value.value})`):void 0;}case"percentage":return de(t.value.value.slice(0,-1))?o.position(t.value.value):void 0;default:return;}}}}),r(n,()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--background-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:Array.from({length:21},(e1,t)=>5*t+"%"),valueThemeKeys:["--gradient-color-stop-positions"]}]),r(n,()=>[{values:Array.from({length:21},(e1,t)=>5*t+"%")},{values:e1.get(["--spacing"])?ye:[]},{values:["current","inherit","transparent"],valueThemeKeys:["--background-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)}]);}let x=()=>z([$e("--tw-mask-left","linear-gradient(#fff, #fff)"),$e("--tw-mask-right","linear-gradient(#fff, #fff)"),$e("--tw-mask-bottom","linear-gradient(#fff, #fff)"),$e("--tw-mask-top","linear-gradient(#fff, #fff)")]);function $(e1,t,r){v(e1,{color(e1){let n=[g(),x(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-linear","var(--tw-mask-left), var(--tw-mask-right), var(--tw-mask-bottom), var(--tw-mask-top)")];for(let o of["top","right","bottom","left"])r[o]&&(n.push(y(`--tw-mask-${o}`,`linear-gradient(to ${o}, var(--tw-mask-${o}-from-color) var(--tw-mask-${o}-from-position), var(--tw-mask-${o}-to-color) var(--tw-mask-${o}-to-position))`)),n.push(z([$e(`--tw-mask-${o}-from-position`,"0%"),$e(`--tw-mask-${o}-to-position`,"100%"),$e(`--tw-mask-${o}-from-color`,"black"),$e(`--tw-mask-${o}-to-color`,"transparent")])),n.push(y(`--tw-mask-${o}-${t}-color`,e1)));return n;},position(e1){let n=[g(),x(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-linear","var(--tw-mask-left), var(--tw-mask-right), var(--tw-mask-bottom), var(--tw-mask-top)")];for(let o of["top","right","bottom","left"])r[o]&&(n.push(y(`--tw-mask-${o}`,`linear-gradient(to ${o}, var(--tw-mask-${o}-from-color) var(--tw-mask-${o}-from-position), var(--tw-mask-${o}-to-color) var(--tw-mask-${o}-to-position))`)),n.push(z([$e(`--tw-mask-${o}-from-position`,"0%"),$e(`--tw-mask-${o}-to-position`,"100%"),$e(`--tw-mask-${o}-from-color`,"black"),$e(`--tw-mask-${o}-to-color`,"transparent")])),n.push(y(`--tw-mask-${o}-${t}-position`,e1)));return n;}});}$("mask-x-from","from",{top:!1,right:!0,bottom:!1,left:!0}),$("mask-x-to","to",{top:!1,right:!0,bottom:!1,left:!0}),$("mask-y-from","from",{top:!0,right:!1,bottom:!0,left:!1}),$("mask-y-to","to",{top:!0,right:!1,bottom:!0,left:!1}),$("mask-t-from","from",{top:!0,right:!1,bottom:!1,left:!1}),$("mask-t-to","to",{top:!0,right:!1,bottom:!1,left:!1}),$("mask-r-from","from",{top:!1,right:!0,bottom:!1,left:!1}),$("mask-r-to","to",{top:!1,right:!0,bottom:!1,left:!1}),$("mask-b-from","from",{top:!1,right:!1,bottom:!0,left:!1}),$("mask-b-to","to",{top:!1,right:!1,bottom:!0,left:!1}),$("mask-l-from","from",{top:!1,right:!1,bottom:!1,left:!0}),$("mask-l-to","to",{top:!1,right:!1,bottom:!1,left:!0});let A=()=>z([$e("--tw-mask-linear-position","0deg"),$e("--tw-mask-linear-from-position","0%"),$e("--tw-mask-linear-to-position","100%"),$e("--tw-mask-linear-from-color","black"),$e("--tw-mask-linear-to-color","transparent")]);o("mask-linear",{defaultValue:null,supportsNegative:!0,supportsFractions:!1,handleBareValue:e1=>de(e1.value)?`calc(1deg * ${e1.value})`:null,handleNegativeBareValue:e1=>de(e1.value)?`calc(1deg * -${e1.value})`:null,handle:e1=>[g(),A(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-linear","linear-gradient(var(--tw-mask-linear-stops, var(--tw-mask-linear-position)))"),y("--tw-mask-linear-position",e1)]}),r("mask-linear",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12","45","90","180"]}]),v("mask-linear-from",{color:e1=>[g(),A(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-linear-stops","var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)"),y("--tw-mask-linear","linear-gradient(var(--tw-mask-linear-stops))"),y("--tw-mask-linear-from-color",e1)],position:e1=>[g(),A(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-linear-stops","var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)"),y("--tw-mask-linear","linear-gradient(var(--tw-mask-linear-stops))"),y("--tw-mask-linear-from-position",e1)]}),v("mask-linear-to",{color:e1=>[g(),A(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-linear-stops","var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)"),y("--tw-mask-linear","linear-gradient(var(--tw-mask-linear-stops))"),y("--tw-mask-linear-to-color",e1)],position:e1=>[g(),A(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-linear-stops","var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)"),y("--tw-mask-linear","linear-gradient(var(--tw-mask-linear-stops))"),y("--tw-mask-linear-to-position",e1)]});let j=()=>z([$e("--tw-mask-radial-from-position","0%"),$e("--tw-mask-radial-to-position","100%"),$e("--tw-mask-radial-from-color","black"),$e("--tw-mask-radial-to-color","transparent"),$e("--tw-mask-radial-shape","ellipse"),$e("--tw-mask-radial-size","farthest-corner"),$e("--tw-mask-radial-position","center")]);n("mask-circle",[["--tw-mask-radial-shape","circle"]]),n("mask-ellipse",[["--tw-mask-radial-shape","ellipse"]]),n("mask-radial-closest-side",[["--tw-mask-radial-size","closest-side"]]),n("mask-radial-farthest-side",[["--tw-mask-radial-size","farthest-side"]]),n("mask-radial-closest-corner",[["--tw-mask-radial-size","closest-corner"]]),n("mask-radial-farthest-corner",[["--tw-mask-radial-size","farthest-corner"]]),n("mask-radial-at-top",[["--tw-mask-radial-position","top"]]),n("mask-radial-at-top-left",[["--tw-mask-radial-position","top left"]]),n("mask-radial-at-top-right",[["--tw-mask-radial-position","top right"]]),n("mask-radial-at-bottom",[["--tw-mask-radial-position","bottom"]]),n("mask-radial-at-bottom-left",[["--tw-mask-radial-position","bottom left"]]),n("mask-radial-at-bottom-right",[["--tw-mask-radial-position","bottom right"]]),n("mask-radial-at-left",[["--tw-mask-radial-position","left"]]),n("mask-radial-at-right",[["--tw-mask-radial-position","right"]]),n("mask-radial-at-center",[["--tw-mask-radial-position","center"]]),o("mask-radial-at",{defaultValue:null,supportsNegative:!1,supportsFractions:!1,handle:e1=>[y("--tw-mask-radial-position",e1)]}),o("mask-radial",{defaultValue:null,supportsNegative:!1,supportsFractions:!1,handle:e1=>[g(),j(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-radial","radial-gradient(var(--tw-mask-radial-stops, var(--tw-mask-radial-size)))"),y("--tw-mask-radial-size",e1)]}),v("mask-radial-from",{color:e1=>[g(),j(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-radial-stops","var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)"),y("--tw-mask-radial","radial-gradient(var(--tw-mask-radial-stops))"),y("--tw-mask-radial-from-color",e1)],position:e1=>[g(),j(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-radial-stops","var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)"),y("--tw-mask-radial","radial-gradient(var(--tw-mask-radial-stops))"),y("--tw-mask-radial-from-position",e1)]}),v("mask-radial-to",{color:e1=>[g(),j(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-radial-stops","var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)"),y("--tw-mask-radial","radial-gradient(var(--tw-mask-radial-stops))"),y("--tw-mask-radial-to-color",e1)],position:e1=>[g(),j(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-radial-stops","var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)"),y("--tw-mask-radial","radial-gradient(var(--tw-mask-radial-stops))"),y("--tw-mask-radial-to-position",e1)]});let T=()=>z([$e("--tw-mask-conic-position","0deg"),$e("--tw-mask-conic-from-position","0%"),$e("--tw-mask-conic-to-position","100%"),$e("--tw-mask-conic-from-color","black"),$e("--tw-mask-conic-to-color","transparent")]);o("mask-conic",{defaultValue:null,supportsNegative:!0,supportsFractions:!1,handleBareValue:e1=>de(e1.value)?`calc(1deg * ${e1.value})`:null,handleNegativeBareValue:e1=>de(e1.value)?`calc(1deg * -${e1.value})`:null,handle:e1=>[g(),T(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-conic","conic-gradient(var(--tw-mask-conic-stops, var(--tw-mask-conic-position)))"),y("--tw-mask-conic-position",e1)]}),r("mask-conic",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12","45","90","180"]}]),v("mask-conic-from",{color:e1=>[g(),T(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-conic-stops","from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)"),y("--tw-mask-conic","conic-gradient(var(--tw-mask-conic-stops))"),y("--tw-mask-conic-from-color",e1)],position:e1=>[g(),T(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-conic-stops","from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)"),y("--tw-mask-conic","conic-gradient(var(--tw-mask-conic-stops))"),y("--tw-mask-conic-from-position",e1)]}),v("mask-conic-to",{color:e1=>[g(),T(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-conic-stops","from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)"),y("--tw-mask-conic","conic-gradient(var(--tw-mask-conic-stops))"),y("--tw-mask-conic-to-color",e1)],position:e1=>[g(),T(),y("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),y("mask-composite","intersect"),y("--tw-mask-conic-stops","from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)"),y("--tw-mask-conic","conic-gradient(var(--tw-mask-conic-stops))"),y("--tw-mask-conic-to-position",e1)]}),n("box-decoration-slice",[["-webkit-box-decoration-break","slice"],["box-decoration-break","slice"]]),n("box-decoration-clone",[["-webkit-box-decoration-break","clone"],["box-decoration-break","clone"]]),n("bg-clip-text",[["background-clip","text"]]),n("bg-clip-border",[["background-clip","border-box"]]),n("bg-clip-padding",[["background-clip","padding-box"]]),n("bg-clip-content",[["background-clip","content-box"]]),n("bg-origin-border",[["background-origin","border-box"]]),n("bg-origin-padding",[["background-origin","padding-box"]]),n("bg-origin-content",[["background-origin","content-box"]]);for(let e1 of["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"])n(`bg-blend-${e1}`,[["background-blend-mode",e1]]),n(`mix-blend-${e1}`,[["mix-blend-mode",e1]]);n("mix-blend-plus-darker",[["mix-blend-mode","plus-darker"]]),n("mix-blend-plus-lighter",[["mix-blend-mode","plus-lighter"]]),n("fill-none",[["fill","none"]]),t.functional("fill",t=>{if(!t.value)return;if("arbitrary"===t.value.kind){let r=je(t.value.value,t.modifier,e1);return null===r?void 0:[y("fill",r)];}let r=Te(t,e1,["--fill","--color"]);return r?[y("fill",r)]:void 0;}),r("fill",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--fill","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)}]),n("stroke-none",[["stroke","none"]]),t.functional("stroke",t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??G(r,["color","number","length","percentage"])){case"number":case"length":case"percentage":return t.modifier?void 0:[y("stroke-width",r)];default:return r=je(t.value.value,t.modifier,e1),null===r?void 0:[y("stroke",r)];}}{let r=Te(t,e1,["--stroke","--color"]);if(r)return[y("stroke",r)];}{let r=e1.resolve(t.value.value,["--stroke-width"]);if(r)return[y("stroke-width",r)];if(de(t.value.value))return[y("stroke-width",t.value.value)];}}}),r("stroke",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--stroke","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:["0","1","2","3"],valueThemeKeys:["--stroke-width"]}]),n("object-contain",[["object-fit","contain"]]),n("object-cover",[["object-fit","cover"]]),n("object-fill",[["object-fit","fill"]]),n("object-none",[["object-fit","none"]]),n("object-scale-down",[["object-fit","scale-down"]]),n("object-top",[["object-position","top"]]),n("object-top-left",[["object-position","left top"]]),n("object-top-right",[["object-position","right top"]]),n("object-bottom",[["object-position","bottom"]]),n("object-bottom-left",[["object-position","left bottom"]]),n("object-bottom-right",[["object-position","right bottom"]]),n("object-left",[["object-position","left"]]),n("object-right",[["object-position","right"]]),n("object-center",[["object-position","center"]]),o("object",{themeKeys:["--object-position"],handle:e1=>[y("object-position",e1)]});for(let[e1,t]of[["p","padding"],["px","padding-inline"],["py","padding-block"],["ps","padding-inline-start"],["pe","padding-inline-end"],["pt","padding-top"],["pr","padding-right"],["pb","padding-bottom"],["pl","padding-left"]])i(e1,["--padding","--spacing"],e1=>[y(t,e1)]);n("text-left",[["text-align","left"]]),n("text-center",[["text-align","center"]]),n("text-right",[["text-align","right"]]),n("text-justify",[["text-align","justify"]]),n("text-start",[["text-align","start"]]),n("text-end",[["text-align","end"]]),i("indent",["--text-indent","--spacing"],e1=>[y("text-indent",e1)],{supportsNegative:!0}),n("align-baseline",[["vertical-align","baseline"]]),n("align-top",[["vertical-align","top"]]),n("align-middle",[["vertical-align","middle"]]),n("align-bottom",[["vertical-align","bottom"]]),n("align-text-top",[["vertical-align","text-top"]]),n("align-text-bottom",[["vertical-align","text-bottom"]]),n("align-sub",[["vertical-align","sub"]]),n("align-super",[["vertical-align","super"]]),o("align",{themeKeys:[],handle:e1=>[y("vertical-align",e1)]}),t.functional("font",t=>{if(t.value&&!t.modifier){if("arbitrary"===t.value.kind){let e1=t.value.value;switch(t.value.dataType??G(e1,["number","generic-name","family-name"])){case"generic-name":case"family-name":return[y("font-family",e1)];default:return[z([$e("--tw-font-weight")]),y("--tw-font-weight",e1),y("font-weight",e1)];}}{let r=e1.resolveWith(t.value.value,["--font"],["--font-feature-settings","--font-variation-settings"]);if(r){let[e1,t={}]=r;return[y("font-family",e1),y("font-feature-settings",t["--font-feature-settings"]),y("font-variation-settings",t["--font-variation-settings"])];}}{let r=e1.resolve(t.value.value,["--font-weight"]);if(r)return[z([$e("--tw-font-weight")]),y("--tw-font-weight",r),y("font-weight",r)];}}}),r("font",()=>[{values:[],valueThemeKeys:["--font"]},{values:[],valueThemeKeys:["--font-weight"]}]),n("uppercase",[["text-transform","uppercase"]]),n("lowercase",[["text-transform","lowercase"]]),n("capitalize",[["text-transform","capitalize"]]),n("normal-case",[["text-transform","none"]]),n("italic",[["font-style","italic"]]),n("not-italic",[["font-style","normal"]]),n("underline",[["text-decoration-line","underline"]]),n("overline",[["text-decoration-line","overline"]]),n("line-through",[["text-decoration-line","line-through"]]),n("no-underline",[["text-decoration-line","none"]]),n("font-stretch-normal",[["font-stretch","normal"]]),n("font-stretch-ultra-condensed",[["font-stretch","ultra-condensed"]]),n("font-stretch-extra-condensed",[["font-stretch","extra-condensed"]]),n("font-stretch-condensed",[["font-stretch","condensed"]]),n("font-stretch-semi-condensed",[["font-stretch","semi-condensed"]]),n("font-stretch-semi-expanded",[["font-stretch","semi-expanded"]]),n("font-stretch-expanded",[["font-stretch","expanded"]]),n("font-stretch-extra-expanded",[["font-stretch","extra-expanded"]]),n("font-stretch-ultra-expanded",[["font-stretch","ultra-expanded"]]),o("font-stretch",{handleBareValue:({value:e1})=>{if(!e1.endsWith("%"))return null;let t=Number(e1.slice(0,-1));return!de(t)||Number.isNaN(t)||t<50||t>200?null:e1;},handle:e1=>[y("font-stretch",e1)]}),r("font-stretch",()=>[{values:["50%","75%","90%","95%","100%","105%","110%","125%","150%","200%"]}]),a("placeholder",{themeKeys:["--background-color","--color"],handle:e1=>[w("&::placeholder",[y("--tw-sort","placeholder-color"),y("color",e1)])]}),n("decoration-solid",[["text-decoration-style","solid"]]),n("decoration-double",[["text-decoration-style","double"]]),n("decoration-dotted",[["text-decoration-style","dotted"]]),n("decoration-dashed",[["text-decoration-style","dashed"]]),n("decoration-wavy",[["text-decoration-style","wavy"]]),n("decoration-auto",[["text-decoration-thickness","auto"]]),n("decoration-from-font",[["text-decoration-thickness","from-font"]]),t.functional("decoration",t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??G(r,["color","length","percentage"])){case"length":case"percentage":return t.modifier?void 0:[y("text-decoration-thickness",r)];default:return r=je(r,t.modifier,e1),null===r?void 0:[y("text-decoration-color",r)];}}{let r=e1.resolve(t.value.value,["--text-decoration-thickness"]);if(r)return t.modifier?void 0:[y("text-decoration-thickness",r)];if(de(t.value.value))return t.modifier?void 0:[y("text-decoration-thickness",`${t.value.value}px`)];}{let r=Te(t,e1,["--text-decoration-color","--color"]);if(r)return[y("text-decoration-color",r)];}}}),r("decoration",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--text-decoration-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:["0","1","2"],valueThemeKeys:["--text-decoration-thickness"]}]),n("animate-none",[["animation","none"]]),o("animate",{themeKeys:["--animate"],handle:e1=>[y("animation",e1)]});{let a=["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,)"].join(" "),i=["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,)"].join(" "),l=()=>z([$e("--tw-blur"),$e("--tw-brightness"),$e("--tw-contrast"),$e("--tw-grayscale"),$e("--tw-hue-rotate"),$e("--tw-invert"),$e("--tw-opacity"),$e("--tw-saturate"),$e("--tw-sepia"),$e("--tw-drop-shadow"),$e("--tw-drop-shadow-color"),$e("--tw-drop-shadow-alpha","100%",""),$e("--tw-drop-shadow-size")]),s=()=>z([$e("--tw-backdrop-blur"),$e("--tw-backdrop-brightness"),$e("--tw-backdrop-contrast"),$e("--tw-backdrop-grayscale"),$e("--tw-backdrop-hue-rotate"),$e("--tw-backdrop-invert"),$e("--tw-backdrop-opacity"),$e("--tw-backdrop-saturate"),$e("--tw-backdrop-sepia")]);t.functional("filter",e1=>{if(!e1.modifier){if(null===e1.value)return[l(),y("filter",a)];if("arbitrary"===e1.value.kind)return[y("filter",e1.value.value)];if("none"===e1.value.value)return[y("filter","none")];}}),t.functional("backdrop-filter",e1=>{if(!e1.modifier){if(null===e1.value)return[s(),y("-webkit-backdrop-filter",i),y("backdrop-filter",i)];if("arbitrary"===e1.value.kind)return[y("-webkit-backdrop-filter",e1.value.value),y("backdrop-filter",e1.value.value)];if("none"===e1.value.value)return[y("-webkit-backdrop-filter","none"),y("backdrop-filter","none")];}}),o("blur",{themeKeys:["--blur"],handle:e1=>[l(),y("--tw-blur",`blur(${e1})`),y("filter",a)]}),n("blur-none",[l,["--tw-blur"," "],["filter",a]]),o("backdrop-blur",{themeKeys:["--backdrop-blur","--blur"],handle:e1=>[s(),y("--tw-backdrop-blur",`blur(${e1})`),y("-webkit-backdrop-filter",i),y("backdrop-filter",i)]}),n("backdrop-blur-none",[s,["--tw-backdrop-blur"," "],["-webkit-backdrop-filter",i],["backdrop-filter",i]]),o("brightness",{themeKeys:["--brightness"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,handle:e1=>[l(),y("--tw-brightness",`brightness(${e1})`),y("filter",a)]}),o("backdrop-brightness",{themeKeys:["--backdrop-brightness","--brightness"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,handle:e1=>[s(),y("--tw-backdrop-brightness",`brightness(${e1})`),y("-webkit-backdrop-filter",i),y("backdrop-filter",i)]}),r("brightness",()=>[{values:["0","50","75","90","95","100","105","110","125","150","200"],valueThemeKeys:["--brightness"]}]),r("backdrop-brightness",()=>[{values:["0","50","75","90","95","100","105","110","125","150","200"],valueThemeKeys:["--backdrop-brightness","--brightness"]}]),o("contrast",{themeKeys:["--contrast"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,handle:e1=>[l(),y("--tw-contrast",`contrast(${e1})`),y("filter",a)]}),o("backdrop-contrast",{themeKeys:["--backdrop-contrast","--contrast"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,handle:e1=>[s(),y("--tw-backdrop-contrast",`contrast(${e1})`),y("-webkit-backdrop-filter",i),y("backdrop-filter",i)]}),r("contrast",()=>[{values:["0","50","75","100","125","150","200"],valueThemeKeys:["--contrast"]}]),r("backdrop-contrast",()=>[{values:["0","50","75","100","125","150","200"],valueThemeKeys:["--backdrop-contrast","--contrast"]}]),o("grayscale",{themeKeys:["--grayscale"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,defaultValue:"100%",handle:e1=>[l(),y("--tw-grayscale",`grayscale(${e1})`),y("filter",a)]}),o("backdrop-grayscale",{themeKeys:["--backdrop-grayscale","--grayscale"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,defaultValue:"100%",handle:e1=>[s(),y("--tw-backdrop-grayscale",`grayscale(${e1})`),y("-webkit-backdrop-filter",i),y("backdrop-filter",i)]}),r("grayscale",()=>[{values:["0","25","50","75","100"],valueThemeKeys:["--grayscale"],hasDefaultValue:!0}]),r("backdrop-grayscale",()=>[{values:["0","25","50","75","100"],valueThemeKeys:["--backdrop-grayscale","--grayscale"],hasDefaultValue:!0}]),o("hue-rotate",{supportsNegative:!0,themeKeys:["--hue-rotate"],handleBareValue:({value:e1})=>de(e1)?`${e1}deg`:null,handle:e1=>[l(),y("--tw-hue-rotate",`hue-rotate(${e1})`),y("filter",a)]}),o("backdrop-hue-rotate",{supportsNegative:!0,themeKeys:["--backdrop-hue-rotate","--hue-rotate"],handleBareValue:({value:e1})=>de(e1)?`${e1}deg`:null,handle:e1=>[s(),y("--tw-backdrop-hue-rotate",`hue-rotate(${e1})`),y("-webkit-backdrop-filter",i),y("backdrop-filter",i)]}),r("hue-rotate",()=>[{values:["0","15","30","60","90","180"],valueThemeKeys:["--hue-rotate"]}]),r("backdrop-hue-rotate",()=>[{values:["0","15","30","60","90","180"],valueThemeKeys:["--backdrop-hue-rotate","--hue-rotate"]}]),o("invert",{themeKeys:["--invert"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,defaultValue:"100%",handle:e1=>[l(),y("--tw-invert",`invert(${e1})`),y("filter",a)]}),o("backdrop-invert",{themeKeys:["--backdrop-invert","--invert"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,defaultValue:"100%",handle:e1=>[s(),y("--tw-backdrop-invert",`invert(${e1})`),y("-webkit-backdrop-filter",i),y("backdrop-filter",i)]}),r("invert",()=>[{values:["0","25","50","75","100"],valueThemeKeys:["--invert"],hasDefaultValue:!0}]),r("backdrop-invert",()=>[{values:["0","25","50","75","100"],valueThemeKeys:["--backdrop-invert","--invert"],hasDefaultValue:!0}]),o("saturate",{themeKeys:["--saturate"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,handle:e1=>[l(),y("--tw-saturate",`saturate(${e1})`),y("filter",a)]}),o("backdrop-saturate",{themeKeys:["--backdrop-saturate","--saturate"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,handle:e1=>[s(),y("--tw-backdrop-saturate",`saturate(${e1})`),y("-webkit-backdrop-filter",i),y("backdrop-filter",i)]}),r("saturate",()=>[{values:["0","50","100","150","200"],valueThemeKeys:["--saturate"]}]),r("backdrop-saturate",()=>[{values:["0","50","100","150","200"],valueThemeKeys:["--backdrop-saturate","--saturate"]}]),o("sepia",{themeKeys:["--sepia"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,defaultValue:"100%",handle:e1=>[l(),y("--tw-sepia",`sepia(${e1})`),y("filter",a)]}),o("backdrop-sepia",{themeKeys:["--backdrop-sepia","--sepia"],handleBareValue:({value:e1})=>de(e1)?`${e1}%`:null,defaultValue:"100%",handle:e1=>[s(),y("--tw-backdrop-sepia",`sepia(${e1})`),y("-webkit-backdrop-filter",i),y("backdrop-filter",i)]}),r("sepia",()=>[{values:["0","50","100"],valueThemeKeys:["--sepia"],hasDefaultValue:!0}]),r("backdrop-sepia",()=>[{values:["0","50","100"],valueThemeKeys:["--backdrop-sepia","--sepia"],hasDefaultValue:!0}]),n("drop-shadow-none",[l,["--tw-drop-shadow"," "],["filter",a]]),t.functional("drop-shadow",t=>{let r;if(t.modifier&&("arbitrary"===t.modifier.kind?r=t.modifier.value:de(t.modifier.value)&&(r=`${t.modifier.value}%`)),!t.value){let t=e1.get(["--drop-shadow"]),n=e1.resolve(null,["--drop-shadow"]);return null===t||null===n?void 0:[l(),y("--tw-drop-shadow-alpha",r),...Ee("--tw-drop-shadow-size",t,r,e1=>`var(--tw-drop-shadow-color, ${e1})`),y("--tw-drop-shadow",R(n,",").map(e1=>`drop-shadow(${e1})`).join(" ")),y("filter",a)];}if("arbitrary"===t.value.kind){let n=t.value.value;return"color"===(t.value.dataType??G(n,["color"]))?(n=je(n,t.modifier,e1),null===n?void 0:[l(),y("--tw-drop-shadow-color",ze(n,"var(--tw-drop-shadow-alpha)")),y("--tw-drop-shadow","var(--tw-drop-shadow-size)")]):t.modifier&&!r?void 0:[l(),y("--tw-drop-shadow-alpha",r),...Ee("--tw-drop-shadow-size",n,r,e1=>`var(--tw-drop-shadow-color, ${e1})`),y("--tw-drop-shadow","var(--tw-drop-shadow-size)"),y("filter",a)];}{let n=e1.get([`--drop-shadow-${t.value.value}`]),o=e1.resolve(t.value.value,["--drop-shadow"]);if(n&&o)return t.modifier&&!r?void 0:r?[l(),y("--tw-drop-shadow-alpha",r),...Ee("--tw-drop-shadow-size",n,r,e1=>`var(--tw-drop-shadow-color, ${e1})`),y("--tw-drop-shadow","var(--tw-drop-shadow-size)"),y("filter",a)]:[l(),y("--tw-drop-shadow-alpha",r),...Ee("--tw-drop-shadow-size",n,r,e1=>`var(--tw-drop-shadow-color, ${e1})`),y("--tw-drop-shadow",R(o,",").map(e1=>`drop-shadow(${e1})`).join(" ")),y("filter",a)];}{let r=Te(t,e1,["--drop-shadow-color","--color"]);if(r)return[l(),y("--tw-drop-shadow-color",ze(r,"var(--tw-drop-shadow-alpha)")),y("--tw-drop-shadow","var(--tw-drop-shadow-size)")];}}),r("drop-shadow",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--drop-shadow-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{valueThemeKeys:["--drop-shadow"]}]),o("backdrop-opacity",{themeKeys:["--backdrop-opacity","--opacity"],handleBareValue:({value:e1})=>he(e1)?`${e1}%`:null,handle:e1=>[s(),y("--tw-backdrop-opacity",`opacity(${e1})`),y("-webkit-backdrop-filter",i),y("backdrop-filter",i)]}),r("backdrop-opacity",()=>[{values:Array.from({length:21},(e1,t)=>""+5*t),valueThemeKeys:["--backdrop-opacity","--opacity"]}]);}{let a=`var(--tw-ease, ${e1.resolve(null,["--default-transition-timing-function"])??"ease"})`,i=`var(--tw-duration, ${e1.resolve(null,["--default-transition-duration"])??"0s"})`;n("transition-none",[["transition-property","none"]]),n("transition-all",[["transition-property","all"],["transition-timing-function",a],["transition-duration",i]]),n("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",a],["transition-duration",i]]),n("transition-opacity",[["transition-property","opacity"],["transition-timing-function",a],["transition-duration",i]]),n("transition-shadow",[["transition-property","box-shadow"],["transition-timing-function",a],["transition-duration",i]]),n("transition-transform",[["transition-property","transform, translate, scale, rotate"],["transition-timing-function",a],["transition-duration",i]]),o("transition",{defaultValue:"color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter",themeKeys:["--transition-property"],handle:e1=>[y("transition-property",e1),y("transition-timing-function",a),y("transition-duration",i)]}),n("transition-discrete",[["transition-behavior","allow-discrete"]]),n("transition-normal",[["transition-behavior","normal"]]),o("delay",{handleBareValue:({value:e1})=>de(e1)?`${e1}ms`:null,themeKeys:["--transition-delay"],handle:e1=>[y("transition-delay",e1)]});{let r=()=>z([$e("--tw-duration")]);n("duration-initial",[r,["--tw-duration","initial"]]),t.functional("duration",t=>{if(t.modifier||!t.value)return;let n=null;return"arbitrary"===t.value.kind?n=t.value.value:(n=e1.resolve(t.value.fraction??t.value.value,["--transition-duration"]),null===n&&de(t.value.value)&&(n=`${t.value.value}ms`)),null!==n?[r(),y("--tw-duration",n),y("transition-duration",n)]:void 0;});}r("delay",()=>[{values:["75","100","150","200","300","500","700","1000"],valueThemeKeys:["--transition-delay"]}]),r("duration",()=>[{values:["75","100","150","200","300","500","700","1000"],valueThemeKeys:["--transition-duration"]}]);}{let e1=()=>z([$e("--tw-ease")]);n("ease-initial",[e1,["--tw-ease","initial"]]),n("ease-linear",[e1,["--tw-ease","linear"],["transition-timing-function","linear"]]),o("ease",{themeKeys:["--ease"],handle:t=>[e1(),y("--tw-ease",t),y("transition-timing-function",t)]});}n("will-change-auto",[["will-change","auto"]]),n("will-change-scroll",[["will-change","scroll-position"]]),n("will-change-contents",[["will-change","contents"]]),n("will-change-transform",[["will-change","transform"]]),o("will-change",{themeKeys:[],handle:e1=>[y("will-change",e1)]}),n("content-none",[["--tw-content","none"],["content","none"]]),o("content",{themeKeys:[],handle:e1=>[z([$e("--tw-content",'""')]),y("--tw-content",e1),y("content","var(--tw-content)")]});{let e1="var(--tw-contain-size,) var(--tw-contain-layout,) var(--tw-contain-paint,) var(--tw-contain-style,)",t=()=>z([$e("--tw-contain-size"),$e("--tw-contain-layout"),$e("--tw-contain-paint"),$e("--tw-contain-style")]);n("contain-none",[["contain","none"]]),n("contain-content",[["contain","content"]]),n("contain-strict",[["contain","strict"]]),n("contain-size",[t,["--tw-contain-size","size"],["contain",e1]]),n("contain-inline-size",[t,["--tw-contain-size","inline-size"],["contain",e1]]),n("contain-layout",[t,["--tw-contain-layout","layout"],["contain",e1]]),n("contain-paint",[t,["--tw-contain-paint","paint"],["contain",e1]]),n("contain-style",[t,["--tw-contain-style","style"],["contain",e1]]),o("contain",{themeKeys:[],handle:e1=>[y("contain",e1)]});}n("forced-color-adjust-none",[["forced-color-adjust","none"]]),n("forced-color-adjust-auto",[["forced-color-adjust","auto"]]),n("leading-none",[()=>z([$e("--tw-leading")]),["--tw-leading","1"],["line-height","1"]]),i("leading",["--leading","--spacing"],e1=>[z([$e("--tw-leading")]),y("--tw-leading",e1),y("line-height",e1)]),o("tracking",{supportsNegative:!0,themeKeys:["--tracking"],handle:e1=>[z([$e("--tw-tracking")]),y("--tw-tracking",e1),y("letter-spacing",e1)]}),n("antialiased",[["-webkit-font-smoothing","antialiased"],["-moz-osx-font-smoothing","grayscale"]]),n("subpixel-antialiased",[["-webkit-font-smoothing","auto"],["-moz-osx-font-smoothing","auto"]]);{let e1="var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)",t=()=>z([$e("--tw-ordinal"),$e("--tw-slashed-zero"),$e("--tw-numeric-figure"),$e("--tw-numeric-spacing"),$e("--tw-numeric-fraction")]);n("normal-nums",[["font-variant-numeric","normal"]]),n("ordinal",[t,["--tw-ordinal","ordinal"],["font-variant-numeric",e1]]),n("slashed-zero",[t,["--tw-slashed-zero","slashed-zero"],["font-variant-numeric",e1]]),n("lining-nums",[t,["--tw-numeric-figure","lining-nums"],["font-variant-numeric",e1]]),n("oldstyle-nums",[t,["--tw-numeric-figure","oldstyle-nums"],["font-variant-numeric",e1]]),n("proportional-nums",[t,["--tw-numeric-spacing","proportional-nums"],["font-variant-numeric",e1]]),n("tabular-nums",[t,["--tw-numeric-spacing","tabular-nums"],["font-variant-numeric",e1]]),n("diagonal-fractions",[t,["--tw-numeric-fraction","diagonal-fractions"],["font-variant-numeric",e1]]),n("stacked-fractions",[t,["--tw-numeric-fraction","stacked-fractions"],["font-variant-numeric",e1]]);}{let a=()=>z([$e("--tw-outline-style","solid")]);t.static("outline-hidden",()=>[y("--tw-outline-style","none"),y("outline-style","none"),k("@media","(forced-colors: active)",[y("outline","2px solid transparent"),y("outline-offset","2px")])]),n("outline-none",[["--tw-outline-style","none"],["outline-style","none"]]),n("outline-solid",[["--tw-outline-style","solid"],["outline-style","solid"]]),n("outline-dashed",[["--tw-outline-style","dashed"],["outline-style","dashed"]]),n("outline-dotted",[["--tw-outline-style","dotted"],["outline-style","dotted"]]),n("outline-double",[["--tw-outline-style","double"],["outline-style","double"]]),t.functional("outline",t=>{if(null===t.value){if(t.modifier)return;let r=e1.get(["--default-outline-width"])??"1px";return[a(),y("outline-style","var(--tw-outline-style)"),y("outline-width",r)];}if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??G(r,["color","length","number","percentage"])){case"length":case"number":case"percentage":return t.modifier?void 0:[a(),y("outline-style","var(--tw-outline-style)"),y("outline-width",r)];default:return r=je(r,t.modifier,e1),null===r?void 0:[y("outline-color",r)];}}{let r=Te(t,e1,["--outline-color","--color"]);if(r)return[y("outline-color",r)];}{if(t.modifier)return;let r=e1.resolve(t.value.value,["--outline-width"]);if(r)return[a(),y("outline-style","var(--tw-outline-style)"),y("outline-width",r)];if(de(t.value.value))return[a(),y("outline-style","var(--tw-outline-style)"),y("outline-width",`${t.value.value}px`)];}}),r("outline",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--outline-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t),hasDefaultValue:!0},{values:["0","1","2","4","8"],valueThemeKeys:["--outline-width"]}]),o("outline-offset",{supportsNegative:!0,themeKeys:["--outline-offset"],handleBareValue:({value:e1})=>de(e1)?`${e1}px`:null,handle:e1=>[y("outline-offset",e1)]}),r("outline-offset",()=>[{supportsNegative:!0,values:["0","1","2","4","8"],valueThemeKeys:["--outline-offset"]}]);}o("opacity",{themeKeys:["--opacity"],handleBareValue:({value:e1})=>he(e1)?`${e1}%`:null,handle:e1=>[y("opacity",e1)]}),r("opacity",()=>[{values:Array.from({length:21},(e1,t)=>""+5*t),valueThemeKeys:["--opacity"]}]),n("underline-offset-auto",[["text-underline-offset","auto"]]),o("underline-offset",{supportsNegative:!0,themeKeys:["--text-underline-offset"],handleBareValue:({value:e1})=>de(e1)?`${e1}px`:null,handle:e1=>[y("text-underline-offset",e1)]}),r("underline-offset",()=>[{supportsNegative:!0,values:["0","1","2","4","8"],valueThemeKeys:["--text-underline-offset"]}]),t.functional("text",t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??G(r,["color","length","percentage","absolute-size","relative-size"])){case"size":case"length":case"percentage":case"absolute-size":case"relative-size":if(t.modifier){let n="arbitrary"===t.modifier.kind?t.modifier.value:e1.resolve(t.modifier.value,["--leading"]);if(!n&&pe(t.modifier.value)){let r=e1.resolve(null,["--spacing"]);if(!r)return null;n=`calc(${r} * ${t.modifier.value})`;}return!n&&"none"===t.modifier.value&&(n="1"),n?[y("font-size",r),y("line-height",n)]:null;}return[y("font-size",r)];default:return r=je(r,t.modifier,e1),null===r?void 0:[y("color",r)];}}{let r=Te(t,e1,["--text-color","--color"]);if(r)return[y("color",r)];}{let r=e1.resolveWith(t.value.value,["--text"],["--line-height","--letter-spacing","--font-weight"]);if(r){let[n,o={}]=Array.isArray(r)?r:[r];if(t.modifier){let r="arbitrary"===t.modifier.kind?t.modifier.value:e1.resolve(t.modifier.value,["--leading"]);if(!r&&pe(t.modifier.value)){let n=e1.resolve(null,["--spacing"]);if(!n)return null;r=`calc(${n} * ${t.modifier.value})`;}if(!r&&"none"===t.modifier.value&&(r="1"),!r)return null;let o=[y("font-size",n)];return r&&o.push(y("line-height",r)),o;}return"string"==typeof o?[y("font-size",n),y("line-height",o)]:[y("font-size",n),y("line-height",o["--line-height"]?`var(--tw-leading, ${o["--line-height"]})`:void 0),y("letter-spacing",o["--letter-spacing"]?`var(--tw-tracking, ${o["--letter-spacing"]})`:void 0),y("font-weight",o["--font-weight"]?`var(--tw-font-weight, ${o["--font-weight"]})`:void 0)];}}}}),r("text",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--text-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:[],valueThemeKeys:["--text"],modifiers:[],modifierThemeKeys:["--leading"]}]);let C=()=>z([$e("--tw-text-shadow-color"),$e("--tw-text-shadow-alpha","100%","")]);n("text-shadow-initial",[C,["--tw-text-shadow-color","initial"]]),t.functional("text-shadow",t=>{let r;if(t.modifier&&("arbitrary"===t.modifier.kind?r=t.modifier.value:de(t.modifier.value)&&(r=`${t.modifier.value}%`)),!t.value){let t=e1.get(["--text-shadow"]);return null===t?void 0:[C(),y("--tw-text-shadow-alpha",r),...Ke("text-shadow",t,r,e1=>`var(--tw-text-shadow-color, ${e1})`)];}if("arbitrary"===t.value.kind){let n=t.value.value;return"color"===(t.value.dataType??G(n,["color"]))?(n=je(n,t.modifier,e1),null===n?void 0:[C(),y("--tw-text-shadow-color",ze(n,"var(--tw-text-shadow-alpha)"))]):[C(),y("--tw-text-shadow-alpha",r),...Ke("text-shadow",n,r,e1=>`var(--tw-text-shadow-color, ${e1})`)];}if("none"===t.value.value)return t.modifier?void 0:[C(),y("text-shadow","none")];{let n=e1.get([`--text-shadow-${t.value.value}`]);if(n)return[C(),y("--tw-text-shadow-alpha",r),...Ke("text-shadow",n,r,e1=>`var(--tw-text-shadow-color, ${e1})`)];}{let r=Te(t,e1,["--text-shadow-color","--color"]);if(r)return[C(),y("--tw-text-shadow-color",ze(r,"var(--tw-text-shadow-alpha)"))];}}),r("text-shadow",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--text-shadow-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:["none"]},{valueThemeKeys:["--text-shadow"],modifiers:Array.from({length:21},(e1,t)=>""+5*t),hasDefaultValue:!0}]);{let o=function(e1){return`var(--tw-ring-inset,) 0 0 0 calc(${e1} + var(--tw-ring-offset-width)) var(--tw-ring-color, ${c})`;},a=function(e1){return`inset 0 0 0 ${e1} var(--tw-inset-ring-color, currentcolor)`;},i=["var(--tw-inset-shadow)","var(--tw-inset-ring-shadow)","var(--tw-ring-offset-shadow)","var(--tw-ring-shadow)","var(--tw-shadow)"].join(", "),l="0 0 #0000",s=()=>z([$e("--tw-shadow",l),$e("--tw-shadow-color"),$e("--tw-shadow-alpha","100%",""),$e("--tw-inset-shadow",l),$e("--tw-inset-shadow-color"),$e("--tw-inset-shadow-alpha","100%",""),$e("--tw-ring-color"),$e("--tw-ring-shadow",l),$e("--tw-inset-ring-color"),$e("--tw-inset-ring-shadow",l),$e("--tw-ring-inset"),$e("--tw-ring-offset-width","0px",""),$e("--tw-ring-offset-color","#fff"),$e("--tw-ring-offset-shadow",l)]);n("shadow-initial",[s,["--tw-shadow-color","initial"]]),t.functional("shadow",t=>{let r;if(t.modifier&&("arbitrary"===t.modifier.kind?r=t.modifier.value:de(t.modifier.value)&&(r=`${t.modifier.value}%`)),!t.value){let t=e1.get(["--shadow"]);return null===t?void 0:[s(),y("--tw-shadow-alpha",r),...Ke("--tw-shadow",t,r,e1=>`var(--tw-shadow-color, ${e1})`),y("box-shadow",i)];}if("arbitrary"===t.value.kind){let n=t.value.value;return"color"===(t.value.dataType??G(n,["color"]))?(n=je(n,t.modifier,e1),null===n?void 0:[s(),y("--tw-shadow-color",ze(n,"var(--tw-shadow-alpha)"))]):[s(),y("--tw-shadow-alpha",r),...Ke("--tw-shadow",n,r,e1=>`var(--tw-shadow-color, ${e1})`),y("box-shadow",i)];}if("none"===t.value.value)return t.modifier?void 0:[s(),y("--tw-shadow",l),y("box-shadow",i)];{let n=e1.get([`--shadow-${t.value.value}`]);if(n)return[s(),y("--tw-shadow-alpha",r),...Ke("--tw-shadow",n,r,e1=>`var(--tw-shadow-color, ${e1})`),y("box-shadow",i)];}{let r=Te(t,e1,["--box-shadow-color","--color"]);if(r)return[s(),y("--tw-shadow-color",ze(r,"var(--tw-shadow-alpha)"))];}}),r("shadow",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--box-shadow-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:["none"]},{valueThemeKeys:["--shadow"],modifiers:Array.from({length:21},(e1,t)=>""+5*t),hasDefaultValue:!0}]),n("inset-shadow-initial",[s,["--tw-inset-shadow-color","initial"]]),t.functional("inset-shadow",t=>{let r;if(t.modifier&&("arbitrary"===t.modifier.kind?r=t.modifier.value:de(t.modifier.value)&&(r=`${t.modifier.value}%`)),!t.value){let t=e1.get(["--inset-shadow"]);return null===t?void 0:[s(),y("--tw-inset-shadow-alpha",r),...Ke("--tw-inset-shadow",t,r,e1=>`var(--tw-inset-shadow-color, ${e1})`),y("box-shadow",i)];}if("arbitrary"===t.value.kind){let n=t.value.value;return"color"===(t.value.dataType??G(n,["color"]))?(n=je(n,t.modifier,e1),null===n?void 0:[s(),y("--tw-inset-shadow-color",ze(n,"var(--tw-inset-shadow-alpha)"))]):[s(),y("--tw-inset-shadow-alpha",r),...Ke("--tw-inset-shadow",n,r,e1=>`var(--tw-inset-shadow-color, ${e1})`,"inset "),y("box-shadow",i)];}if("none"===t.value.value)return t.modifier?void 0:[s(),y("--tw-inset-shadow",l),y("box-shadow",i)];{let n=e1.get([`--inset-shadow-${t.value.value}`]);if(n)return[s(),y("--tw-inset-shadow-alpha",r),...Ke("--tw-inset-shadow",n,r,e1=>`var(--tw-inset-shadow-color, ${e1})`),y("box-shadow",i)];}{let r=Te(t,e1,["--box-shadow-color","--color"]);if(r)return[s(),y("--tw-inset-shadow-color",ze(r,"var(--tw-inset-shadow-alpha)"))];}}),r("inset-shadow",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--box-shadow-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:["none"]},{valueThemeKeys:["--inset-shadow"],modifiers:Array.from({length:21},(e1,t)=>""+5*t),hasDefaultValue:!0}]),n("ring-inset",[s,["--tw-ring-inset","inset"]]);let c=e1.get(["--default-ring-color"])??"currentcolor";t.functional("ring",t=>{if(!t.value){if(t.modifier)return;let r=e1.get(["--default-ring-width"])??"1px";return[s(),y("--tw-ring-shadow",o(r)),y("box-shadow",i)];}if("arbitrary"===t.value.kind){let r=t.value.value;return"length"===(t.value.dataType??G(r,["color","length"]))?t.modifier?void 0:[s(),y("--tw-ring-shadow",o(r)),y("box-shadow",i)]:(r=je(r,t.modifier,e1),null===r?void 0:[y("--tw-ring-color",r)]);}{let r=Te(t,e1,["--ring-color","--color"]);if(r)return[y("--tw-ring-color",r)];}{if(t.modifier)return;let r=e1.resolve(t.value.value,["--ring-width"]);if(null===r&&de(t.value.value)&&(r=`${t.value.value}px`),r)return[s(),y("--tw-ring-shadow",o(r)),y("box-shadow",i)];}}),r("ring",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--ring-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:["0","1","2","4","8"],valueThemeKeys:["--ring-width"],hasDefaultValue:!0}]),t.functional("inset-ring",t=>{if(!t.value)return t.modifier?void 0:[s(),y("--tw-inset-ring-shadow",a("1px")),y("box-shadow",i)];if("arbitrary"===t.value.kind){let r=t.value.value;return"length"===(t.value.dataType??G(r,["color","length"]))?t.modifier?void 0:[s(),y("--tw-inset-ring-shadow",a(r)),y("box-shadow",i)]:(r=je(r,t.modifier,e1),null===r?void 0:[y("--tw-inset-ring-color",r)]);}{let r=Te(t,e1,["--ring-color","--color"]);if(r)return[y("--tw-inset-ring-color",r)];}{if(t.modifier)return;let r=e1.resolve(t.value.value,["--ring-width"]);if(null===r&&de(t.value.value)&&(r=`${t.value.value}px`),r)return[s(),y("--tw-inset-ring-shadow",a(r)),y("box-shadow",i)];}}),r("inset-ring",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--ring-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:["0","1","2","4","8"],valueThemeKeys:["--ring-width"],hasDefaultValue:!0}]);let u="var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)";t.functional("ring-offset",t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;return"length"===(t.value.dataType??G(r,["color","length"]))?t.modifier?void 0:[y("--tw-ring-offset-width",r),y("--tw-ring-offset-shadow",u)]:(r=je(r,t.modifier,e1),null===r?void 0:[y("--tw-ring-offset-color",r)]);}{let r=e1.resolve(t.value.value,["--ring-offset-width"]);if(r)return t.modifier?void 0:[y("--tw-ring-offset-width",r),y("--tw-ring-offset-shadow",u)];if(de(t.value.value))return t.modifier?void 0:[y("--tw-ring-offset-width",`${t.value.value}px`),y("--tw-ring-offset-shadow",u)];}{let r=Te(t,e1,["--ring-offset-color","--color"]);if(r)return[y("--tw-ring-offset-color",r)];}}});}return r("ring-offset",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--ring-offset-color","--color"],modifiers:Array.from({length:21},(e1,t)=>""+5*t)},{values:["0","1","2","4","8"],valueThemeKeys:["--ring-offset-width"]}]),t.functional("@container",e1=>{let t=null;if(null===e1.value?t="inline-size":"arbitrary"===e1.value.kind?t=e1.value.value:"named"===e1.value.kind&&"normal"===e1.value.value&&(t="normal"),null!==t)return e1.modifier?[y("container-type",t),y("container-name",e1.modifier.value)]:[y("container-type",t)];}),r("@container",()=>[{values:["normal"],valueThemeKeys:[],hasDefaultValue:!0}]),t;}(e1),r=function(e1){let t=new _e;function r(e1,r1,{compounds:n}={}){n=n??Le(r1),t.static(e1,e1=>{e1.nodes=r1.map(t=>b(t,e1.nodes));},{compounds:n});}function n(e1,t){return t.map(t=>{let r=R(t=t.trim()," ");return"not"===r[0]?r.slice(1).join(" "):"@container"===e1?"("===r[0][0]?`not ${t}`:"not"===r[1]?`${r[0]} ${r.slice(2).join(" ")}`:`${r[0]} not ${r.slice(1).join(" ")}`:`not ${t}`;});}r("*",[":is(& > *)"],{compounds:0}),r("**",[":is(& *)"],{compounds:0});let o=["@media","@supports","@container"];function a(e1){for(let t of o){if(t!==e1.name)continue;let r=R(e1.params,",");return r.length>1?null:(r=n(e1.name,r),k(e1.name,r.join(", ")));}return null;}function i(e1){return e1.includes("::")?null:`&:not(${R(e1,",").map(e1=>e1.replaceAll("&","*")).join(", ")})`;}t.compound("not",3,(e1,t)=>{if("arbitrary"===t.variant.kind&&t.variant.relative||t.modifier)return null;let r=!1;return A([e1],(t,{path:n})=>{if("rule"!==t.kind&&"at-rule"!==t.kind)return 0;if(t.nodes.length>0)return 0;let o=[],l=[];for(let e1 of n)"at-rule"===e1.kind?o.push(e1):"rule"===e1.kind&&l.push(e1);if(o.length>1)return 2;if(l.length>1)return 2;let s=[];for(let e1 of l){let t=i(e1.selector);if(!t)return r=!1,2;s.push(w(t,[]));}for(let e1 of o){let t=a(e1);if(!t)return r=!1,2;s.push(t);}return Object.assign(e1,w("&",s)),r=!0,1;}),"rule"===e1.kind&&"&"===e1.selector&&1===e1.nodes.length&&Object.assign(e1,e1.nodes[0]),r?void 0:null;}),t.suggest("not",()=>Array.from(t.keys()).filter(e1=>t.compoundsWith("not",e1))),t.compound("group",2,(t,r)=>{if("arbitrary"===r.variant.kind&&r.variant.relative)return null;let n=r.modifier?`:where(.${e1.prefix?`${e1.prefix}\\:`:""}group\\/${r.modifier.value})`:`:where(.${e1.prefix?`${e1.prefix}\\:`:""}group)`,o=!1;return A([t],(e1,{path:t})=>{if("rule"!==e1.kind)return 0;for(let e1 of t.slice(0,-1))if("rule"===e1.kind)return o=!1,2;let r=e1.selector.replaceAll("&",n);R(r,",").length>1&&(r=`:is(${r})`),e1.selector=`&:is(${r} *)`,o=!0;}),o?void 0:null;}),t.suggest("group",()=>Array.from(t.keys()).filter(e1=>t.compoundsWith("group",e1))),t.compound("peer",2,(t,r)=>{if("arbitrary"===r.variant.kind&&r.variant.relative)return null;let n=r.modifier?`:where(.${e1.prefix?`${e1.prefix}\\:`:""}peer\\/${r.modifier.value})`:`:where(.${e1.prefix?`${e1.prefix}\\:`:""}peer)`,o=!1;return A([t],(e1,{path:t})=>{if("rule"!==e1.kind)return 0;for(let e1 of t.slice(0,-1))if("rule"===e1.kind)return o=!1,2;let r=e1.selector.replaceAll("&",n);R(r,",").length>1&&(r=`:is(${r})`),e1.selector=`&:is(${r} ~ *)`,o=!0;}),o?void 0:null;}),t.suggest("peer",()=>Array.from(t.keys()).filter(e1=>t.compoundsWith("peer",e1))),r("first-letter",["&::first-letter"]),r("first-line",["&::first-line"]),r("marker",["& *::marker","&::marker","& *::-webkit-details-marker","&::-webkit-details-marker"]),r("selection",["& *::selection","&::selection"]),r("file",["&::file-selector-button"]),r("placeholder",["&::placeholder"]),r("backdrop",["&::backdrop"]),r("details-content",["&::details-content"]);{let e1=function(){return z([k("@property","--tw-content",[y("syntax",'"*"'),y("initial-value",'""'),y("inherits","false")])]);};t.static("before",t=>{t.nodes=[w("&::before",[e1(),y("content","var(--tw-content)"),...t.nodes])];},{compounds:0}),t.static("after",t=>{t.nodes=[w("&::after",[e1(),y("content","var(--tw-content)"),...t.nodes])];},{compounds:0});}r("first",["&:first-child"]),r("last",["&:last-child"]),r("only",["&:only-child"]),r("odd",["&:nth-child(odd)"]),r("even",["&:nth-child(even)"]),r("first-of-type",["&:first-of-type"]),r("last-of-type",["&:last-of-type"]),r("only-of-type",["&:only-of-type"]),r("visited",["&:visited"]),r("target",["&:target"]),r("open",["&:is([open], :popover-open, :open)"]),r("default",["&:default"]),r("checked",["&:checked"]),r("indeterminate",["&:indeterminate"]),r("placeholder-shown",["&:placeholder-shown"]),r("autofill",["&:autofill"]),r("optional",["&:optional"]),r("required",["&:required"]),r("valid",["&:valid"]),r("invalid",["&:invalid"]),r("user-valid",["&:user-valid"]),r("user-invalid",["&:user-invalid"]),r("in-range",["&:in-range"]),r("out-of-range",["&:out-of-range"]),r("read-only",["&:read-only"]),r("empty",["&:empty"]),r("focus-within",["&:focus-within"]),t.static("hover",e1=>{e1.nodes=[w("&:hover",[k("@media","(hover: hover)",e1.nodes)])];}),r("focus",["&:focus"]),r("focus-visible",["&:focus-visible"]),r("active",["&:active"]),r("enabled",["&:enabled"]),r("disabled",["&:disabled"]),r("inert",["&:is([inert], [inert] *)"]),t.compound("in",2,(e1,t)=>{if(t.modifier)return null;let r=!1;return A([e1],(e1,{path:t})=>{if("rule"!==e1.kind)return 0;for(let e1 of t.slice(0,-1))if("rule"===e1.kind)return r=!1,2;e1.selector=`:where(${e1.selector.replaceAll("&","*")}) &`,r=!0;}),r?void 0:null;}),t.suggest("in",()=>Array.from(t.keys()).filter(e1=>t.compoundsWith("in",e1))),t.compound("has",2,(e1,t)=>{if(t.modifier)return null;let r=!1;return A([e1],(e1,{path:t})=>{if("rule"!==e1.kind)return 0;for(let e1 of t.slice(0,-1))if("rule"===e1.kind)return r=!1,2;e1.selector=`&:has(${e1.selector.replaceAll("&","*")})`,r=!0;}),r?void 0:null;}),t.suggest("has",()=>Array.from(t.keys()).filter(e1=>t.compoundsWith("has",e1))),t.functional("aria",(e1,t)=>{if(!t.value||t.modifier)return null;"arbitrary"===t.value.kind?e1.nodes=[w(`&[aria-${Me(t.value.value)}]`,e1.nodes)]:e1.nodes=[w(`&[aria-${t.value.value}="true"]`,e1.nodes)];}),t.suggest("aria",()=>["busy","checked","disabled","expanded","hidden","pressed","readonly","required","selected"]),t.functional("data",(e1,t)=>{if(!t.value||t.modifier)return null;e1.nodes=[w(`&[data-${Me(t.value.value)}]`,e1.nodes)];}),t.functional("nth",(e1,t)=>{if(!t.value||t.modifier||"named"===t.value.kind&&!de(t.value.value))return null;e1.nodes=[w(`&:nth-child(${t.value.value})`,e1.nodes)];}),t.functional("nth-last",(e1,t)=>{if(!t.value||t.modifier||"named"===t.value.kind&&!de(t.value.value))return null;e1.nodes=[w(`&:nth-last-child(${t.value.value})`,e1.nodes)];}),t.functional("nth-of-type",(e1,t)=>{if(!t.value||t.modifier||"named"===t.value.kind&&!de(t.value.value))return null;e1.nodes=[w(`&:nth-of-type(${t.value.value})`,e1.nodes)];}),t.functional("nth-last-of-type",(e1,t)=>{if(!t.value||t.modifier||"named"===t.value.kind&&!de(t.value.value))return null;e1.nodes=[w(`&:nth-last-of-type(${t.value.value})`,e1.nodes)];}),t.functional("supports",(e1,t)=>{if(!t.value||t.modifier)return null;let r=t.value.value;if(null===r)return null;if(/^[\w-]*\s*\(/.test(r)){let t=r.replace(/\b(and|or|not)\b/g," $1 ");e1.nodes=[k("@supports",t,e1.nodes)];}else r.includes(":")||(r=`${r}: var(--tw)`),("("!==r[0]||")"!==r[r.length-1])&&(r=`(${r})`),e1.nodes=[k("@supports",r,e1.nodes)];},{compounds:1}),r("motion-safe",["@media (prefers-reduced-motion: no-preference)"]),r("motion-reduce",["@media (prefers-reduced-motion: reduce)"]),r("contrast-more",["@media (prefers-contrast: more)"]),r("contrast-less",["@media (prefers-contrast: less)"]);{let r=function(e1,t,r,n){if(e1===t)return 0;let o=n.get(e1);if(null===o)return"asc"===r?-1:1;let a=n.get(t);return null===a?"asc"===r?1:-1:P(o,a,r);};{let n=e1.namespace("--breakpoint"),o=new c(t=>{switch(t.kind){case"static":return e1.resolveValue(t.root,["--breakpoint"])??null;case"functional":{if(!t.value||t.modifier)return null;let r=null;return"arbitrary"===t.value.kind?r=t.value.value:"named"===t.value.kind&&(r=e1.resolveValue(t.value.value,["--breakpoint"])),!r||r.includes("var(")?null:r;}case"arbitrary":case"compound":return null;}});t.group(()=>{t.functional("max",(e1,t)=>{if(t.modifier)return null;let r=o.get(t);if(null===r)return null;e1.nodes=[k("@media",`(width < ${r})`,e1.nodes)];},{compounds:1});},(e1,t)=>r(e1,t,"desc",o)),t.suggest("max",()=>Array.from(n.keys()).filter(e1=>null!==e1)),t.group(()=>{for(let[r,n]of e1.namespace("--breakpoint"))null!==r&&t.static(r,e1=>{e1.nodes=[k("@media",`(width >= ${n})`,e1.nodes)];},{compounds:1});t.functional("min",(e1,t)=>{if(t.modifier)return null;let r=o.get(t);if(null===r)return null;e1.nodes=[k("@media",`(width >= ${r})`,e1.nodes)];},{compounds:1});},(e1,t)=>r(e1,t,"asc",o)),t.suggest("min",()=>Array.from(n.keys()).filter(e1=>null!==e1));}{let n=e1.namespace("--container"),o=new c(t=>{switch(t.kind){case"functional":{if(null===t.value)return null;let r=null;return"arbitrary"===t.value.kind?r=t.value.value:"named"===t.value.kind&&(r=e1.resolveValue(t.value.value,["--container"])),!r||r.includes("var(")?null:r;}case"static":case"arbitrary":case"compound":return null;}});t.group(()=>{t.functional("@max",(e1,t)=>{let r=o.get(t);if(null===r)return null;e1.nodes=[k("@container",t.modifier?`${t.modifier.value} (width < ${r})`:`(width < ${r})`,e1.nodes)];},{compounds:1});},(e1,t)=>r(e1,t,"desc",o)),t.suggest("@max",()=>Array.from(n.keys()).filter(e1=>null!==e1)),t.group(()=>{t.functional("@",(e1,t)=>{let r=o.get(t);if(null===r)return null;e1.nodes=[k("@container",t.modifier?`${t.modifier.value} (width >= ${r})`:`(width >= ${r})`,e1.nodes)];},{compounds:1}),t.functional("@min",(e1,t)=>{let r=o.get(t);if(null===r)return null;e1.nodes=[k("@container",t.modifier?`${t.modifier.value} (width >= ${r})`:`(width >= ${r})`,e1.nodes)];},{compounds:1});},(e1,t)=>r(e1,t,"asc",o)),t.suggest("@min",()=>Array.from(n.keys()).filter(e1=>null!==e1)),t.suggest("@",()=>Array.from(n.keys()).filter(e1=>null!==e1));}}return r("portrait",["@media (orientation: portrait)"]),r("landscape",["@media (orientation: landscape)"]),r("ltr",['&:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *)']),r("rtl",['&:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *)']),r("dark",["@media (prefers-color-scheme: dark)"]),r("starting",["@starting-style"]),r("print",["@media print"]),r("forced-colors",["@media (forced-colors: active)"]),r("inverted-colors",["@media (inverted-colors: inverted)"]),r("pointer-none",["@media (pointer: none)"]),r("pointer-coarse",["@media (pointer: coarse)"]),r("pointer-fine",["@media (pointer: fine)"]),r("any-pointer-none",["@media (any-pointer: none)"]),r("any-pointer-coarse",["@media (any-pointer: coarse)"]),r("any-pointer-fine",["@media (any-pointer: fine)"]),r("noscript",["@media (scripting: none)"]),t;}(e1),n=new c(e1=>(function(e1,t){if("["===e1[0]&&"]"===e1[e1.length-1]){if("@"===e1[1]&&e1.includes("&"))return null;let t=W(e1.slice(1,-1));if(!L(t)||0===t.length||0===t.trim().length)return null;let r=">"===t[0]||"+"===t[0]||"~"===t[0];return!r&&"@"!==t[0]&&!t.includes("&")&&(t=`&:is(${t})`),{kind:"arbitrary",selector:t,relative:r};}{let[r,n=null,o]=R(e1,"/");if(o)return null;let a=q(r,e1=>t.variants.has(e1));for(let[e1,r]of a)switch(t.variants.kind(e1)){case"static":return null!==r||null!==n?null:{kind:"static",root:e1};case"functional":{let t=null===n?null:I(n);if(null!==n&&null===t)return null;if(null===r)return{kind:"functional",root:e1,modifier:t,value:null};if("]"===r[r.length-1]){if("["!==r[0])continue;let n=W(r.slice(1,-1));return L(n)&&0!==n.length&&0!==n.trim().length?{kind:"functional",root:e1,modifier:t,value:{kind:"arbitrary",value:n}}:null;}if(")"===r[r.length-1]){if("("!==r[0])continue;let n=W(r.slice(1,-1));return!L(n)||0===n.length||0===n.trim().length||"-"!==n[0]&&"-"!==n[1]?null:{kind:"functional",root:e1,modifier:t,value:{kind:"arbitrary",value:`var(${n})`}};}return{kind:"functional",root:e1,modifier:t,value:{kind:"named",value:r}};}case"compound":{if(null===r)return null;let o=t.parseVariant(r);if(null===o||!t.variants.compoundsWith(e1,o))return null;let a=null===n?null:I(n);return null!==n&&null===a?null:{kind:"compound",root:e1,modifier:a,variant:o};}}}return null;})(e1,s)),a=new c(e1=>Array.from(function*(e1,t){let r=R(e1,":");if(t.theme.prefix){if(1===r.length||r[0]!==t.theme.prefix)return null;r.shift();}let n=r.pop(),o=[];for(let e1=r.length-1;e1>=0;--e1){let n=t.parseVariant(r[e1]);if(null===n)return;o.push(n);}let a=!1;"!"===n[n.length-1]?(a=!0,n=n.slice(0,-1)):"!"===n[0]&&(a=!0,n=n.slice(1)),t.utilities.has(n,"static")&&!n.includes("[")&&(yield{kind:"static",root:n,variants:o,important:a,raw:e1});let[i,l=null,s]=R(n,"/");if(s)return;let c,u=null===l?null:I(l);if(null===l||null!==u)if("["!==i[0]){if("]"===i[i.length-1]){let e1=i.indexOf("-[");if(-1===e1)return;let r=i.slice(0,e1);if(!t.utilities.has(r,"functional"))return;c=[[r,i.slice(e1+1)]];}else if(")"===i[i.length-1]){let e1=i.indexOf("-(");if(-1===e1)return;let r=i.slice(0,e1);if(!t.utilities.has(r,"functional"))return;let n=i.slice(e1+2,-1),o=R(n,":"),a=null;if(2===o.length&&(a=o[0],n=o[1]),"-"!==n[0]&&"-"!==n[1])return;c=[[r,null===a?`[var(${n})]`:`[${a}:var(${n})]`]];}else c=q(i,e1=>t.utilities.has(e1,"functional"));for(let[t,r]of c){let n={kind:"functional",root:t,modifier:u,value:null,variants:o,important:a,raw:e1};if(null!==r){{let e1=r.indexOf("[");if(-1!==e1){if("]"!==r[r.length-1])return;let t=W(r.slice(e1+1,-1));if(!L(t))continue;let o="";for(let e1=0;e1=97&&r<=122))break;}if(0===t.length||0===t.trim().length)continue;n.value={kind:"arbitrary",dataType:o||null,value:t};}else{let e1=null===l||"arbitrary"===n.modifier?.kind?null:`${r}/${l}`;n.value={kind:"named",value:r,fraction:e1};}}yield n;}else yield n;}}else{if("]"!==i[i.length-1])return;let t=i.charCodeAt(1);if(45!==t&&!(t>=97&&t<=122))return;i=i.slice(1,-1);let r=i.indexOf(":");if(-1===r||0===r||r===i.length-1)return;let n=i.slice(0,r),l=W(i.slice(r+1));if(!L(l))return;yield{kind:"arbitrary",property:n,value:l,modifier:u,variants:o,important:a,raw:e1};}}(e1,s))),i=new c(e1=>{let t=function(e1,t){let r=function(e1,t){if("arbitrary"===e1.kind){let r=e1.value;return e1.modifier&&(r=je(r,e1.modifier,t.theme)),null===r?[]:[[y(e1.property,r)]];}let r=t.utilities.get(e1.root)??[],n=[],o=r.filter(e1=>!Ye(e1));for(let t of o){if(t.kind!==e1.kind)continue;let r=t.compileFn(e1);if(void 0!==r){if(null===r)return n;n.push(r);}}if(n.length>0)return n;let a=r.filter(e1=>Ye(e1));for(let t of a){if(t.kind!==e1.kind)continue;let r=t.compileFn(e1);if(void 0!==r){if(null===r)return n;n.push(r);}}return n;}(e1,t);if(0===r.length)return[];let n=[],a=`.${o(e1.raw)}`;for(let o of r){let r=Ge(o);(e1.important||t.important)&&Ze(o);let i={kind:"rule",selector:a,nodes:o};for(let r of e1.variants)if(null===He(i,r,t.variants))return[];n.push({node:i,propertySort:r});}return n;}(e1,s);try{Oe(t.map(({node:e1})=>e1),s);}catch{return[];}return t;}),l=new c(t=>{for(let r of g(t))e1.markUsedVariable(r);}),s={theme:e1,utilities:t,variants:r,invalidCandidates:new Set,important:!1,candidatesToCss(e1){let t=[];for(let r of e1){let e1=!1,{astNodes:n}=Pe([r],this,{onInvalidCandidate(){e1=!0;}});n=T(n,s,0),0===n.length||e1?t.push(null):t.push(C(n));}return t;},getClassOrder(e1){return function(e1,t){let{astNodes:r,nodeSorting:n}=Pe(Array.from(t),e1),o=new Map(t.map(e1=>[e1,null])),a=0n;for(let e1 of r){let t=n.get(e1)?.candidate;t&&o.set(t,o.get(t)??a++);}return t.map(e1=>[e1,o.get(e1)??null]);}(this,e1);},getClassList(){return De(this);},getVariants(){return function(e1){let t=[];for(let[r,n]of e1.variants.entries()){let o=function({value:t,modifier:n}={}){let o=r;t&&(o+=a?`-${t}`:t),n&&(o+=`/${n}`);let i=e1.parseVariant(o);if(!i)return[];let l=w(".__placeholder__",[]);if(null===He(l,i,e1.variants))return[];let s=[];return j(l.nodes,(e1,{path:t})=>{if("rule"!==e1.kind&&"at-rule"!==e1.kind||e1.nodes.length>0)return;t.sort((e1,t)=>{let r="at-rule"===e1.kind,n="at-rule"===t.kind;return r&&!n?-1:!r&&n?1:0;});let r=t.flatMap(e1=>"rule"===e1.kind?"&"===e1.selector?[]:[e1.selector]:"at-rule"===e1.kind?[`${e1.name} ${e1.params}`]:[]),n="";for(let e1=r.length-1;e1>=0;e1--)n=""===n?r[e1]:`${r[e1]} { ${n} }`;s.push(n);}),s;};if("arbitrary"===n.kind)continue;let a="@"!==r,i=e1.variants.getCompletions(r);switch(n.kind){case"static":t.push({name:r,values:i,isArbitrary:!1,hasDash:a,selectors:o});break;case"functional":case"compound":t.push({name:r,values:i,isArbitrary:!0,hasDash:a,selectors:o});}}return t;}(this);},parseCandidate:e1=>a.get(e1),parseVariant:e1=>n.get(e1),compileAstNodes:e1=>i.get(e1),getVariantOrder(){let e1=Array.from(n.values());e1.sort((e1,t)=>this.variants.compare(e1,t));let t,r=new Map,o=0;for(let n of e1)null!==n&&(void 0!==t&&0!==this.variants.compare(t,n)&&o++,r.set(n,o),t=n);return r;},resolveThemeValue(t,r=!0){let n=t.lastIndexOf("/"),o=null;-1!==n&&(o=t.slice(n+1).trim(),t=t.slice(0,n).trim());let a=e1.resolve(null,[t],r?1:0)??void 0;return o&&a?ze(a,o):a;},trackUsedVariables(e1){l.get(e1);}};return s;}var qe=["container-type","pointer-events","visibility","position","inset","inset-inline","inset-block","inset-inline-start","inset-inline-end","top","right","bottom","left","isolation","z-index","order","grid-column","grid-column-start","grid-column-end","grid-row","grid-row-start","grid-row-end","float","clear","--tw-container-component","margin","margin-inline","margin-block","margin-inline-start","margin-inline-end","margin-top","margin-right","margin-bottom","margin-left","box-sizing","display","field-sizing","aspect-ratio","height","max-height","min-height","width","max-width","min-width","flex","flex-shrink","flex-grow","flex-basis","table-layout","caption-side","border-collapse","border-spacing","transform-origin","translate","--tw-translate-x","--tw-translate-y","--tw-translate-z","scale","--tw-scale-x","--tw-scale-y","--tw-scale-z","rotate","--tw-rotate-x","--tw-rotate-y","--tw-rotate-z","--tw-skew-x","--tw-skew-y","transform","animation","cursor","touch-action","--tw-pan-x","--tw-pan-y","--tw-pinch-zoom","resize","scroll-snap-type","--tw-scroll-snap-strictness","scroll-snap-align","scroll-snap-stop","scroll-margin","scroll-margin-inline","scroll-margin-block","scroll-margin-inline-start","scroll-margin-inline-end","scroll-margin-top","scroll-margin-right","scroll-margin-bottom","scroll-margin-left","scroll-padding","scroll-padding-inline","scroll-padding-block","scroll-padding-inline-start","scroll-padding-inline-end","scroll-padding-top","scroll-padding-right","scroll-padding-bottom","scroll-padding-left","list-style-position","list-style-type","list-style-image","appearance","columns","break-before","break-inside","break-after","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-template-columns","grid-template-rows","flex-direction","flex-wrap","place-content","place-items","align-content","align-items","justify-content","justify-items","gap","column-gap","row-gap","--tw-space-x-reverse","--tw-space-y-reverse","divide-x-width","divide-y-width","--tw-divide-y-reverse","divide-style","divide-color","place-self","align-self","justify-self","overflow","overflow-x","overflow-y","overscroll-behavior","overscroll-behavior-x","overscroll-behavior-y","scroll-behavior","border-radius","border-start-radius","border-end-radius","border-top-radius","border-right-radius","border-bottom-radius","border-left-radius","border-start-start-radius","border-start-end-radius","border-end-end-radius","border-end-start-radius","border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius","border-width","border-inline-width","border-block-width","border-inline-start-width","border-inline-end-width","border-top-width","border-right-width","border-bottom-width","border-left-width","border-style","border-inline-style","border-block-style","border-inline-start-style","border-inline-end-style","border-top-style","border-right-style","border-bottom-style","border-left-style","border-color","border-inline-color","border-block-color","border-inline-start-color","border-inline-end-color","border-top-color","border-right-color","border-bottom-color","border-left-color","background-color","background-image","--tw-gradient-position","--tw-gradient-stops","--tw-gradient-via-stops","--tw-gradient-from","--tw-gradient-from-position","--tw-gradient-via","--tw-gradient-via-position","--tw-gradient-to","--tw-gradient-to-position","mask-image","--tw-mask-top","--tw-mask-top-from-color","--tw-mask-top-from-position","--tw-mask-top-to-color","--tw-mask-top-to-position","--tw-mask-right","--tw-mask-right-from-color","--tw-mask-right-from-position","--tw-mask-right-to-color","--tw-mask-right-to-position","--tw-mask-bottom","--tw-mask-bottom-from-color","--tw-mask-bottom-from-position","--tw-mask-bottom-to-color","--tw-mask-bottom-to-position","--tw-mask-left","--tw-mask-left-from-color","--tw-mask-left-from-position","--tw-mask-left-to-color","--tw-mask-left-to-position","--tw-mask-linear","--tw-mask-linear-position","--tw-mask-linear-from-color","--tw-mask-linear-from-position","--tw-mask-linear-to-color","--tw-mask-linear-to-position","--tw-mask-radial","--tw-mask-radial-shape","--tw-mask-radial-size","--tw-mask-radial-position","--tw-mask-radial-from-color","--tw-mask-radial-from-position","--tw-mask-radial-to-color","--tw-mask-radial-to-position","--tw-mask-conic","--tw-mask-conic-position","--tw-mask-conic-from-color","--tw-mask-conic-from-position","--tw-mask-conic-to-color","--tw-mask-conic-to-position","box-decoration-break","background-size","background-attachment","background-clip","background-position","background-repeat","background-origin","mask-composite","mask-mode","mask-type","mask-size","mask-clip","mask-position","mask-repeat","mask-origin","fill","stroke","stroke-width","object-fit","object-position","padding","padding-inline","padding-block","padding-inline-start","padding-inline-end","padding-top","padding-right","padding-bottom","padding-left","text-align","text-indent","vertical-align","font-family","font-size","line-height","font-weight","letter-spacing","text-wrap","overflow-wrap","word-break","text-overflow","hyphens","white-space","color","text-transform","font-style","font-stretch","font-variant-numeric","text-decoration-line","text-decoration-color","text-decoration-style","text-decoration-thickness","text-underline-offset","-webkit-font-smoothing","placeholder-color","caret-color","accent-color","color-scheme","opacity","background-blend-mode","mix-blend-mode","box-shadow","--tw-shadow","--tw-shadow-color","--tw-ring-shadow","--tw-ring-color","--tw-inset-shadow","--tw-inset-shadow-color","--tw-inset-ring-shadow","--tw-inset-ring-color","--tw-ring-offset-width","--tw-ring-offset-color","outline","outline-width","outline-offset","outline-color","--tw-blur","--tw-brightness","--tw-contrast","--tw-drop-shadow","--tw-grayscale","--tw-hue-rotate","--tw-invert","--tw-saturate","--tw-sepia","filter","--tw-backdrop-blur","--tw-backdrop-brightness","--tw-backdrop-contrast","--tw-backdrop-grayscale","--tw-backdrop-hue-rotate","--tw-backdrop-invert","--tw-backdrop-opacity","--tw-backdrop-saturate","--tw-backdrop-sepia","backdrop-filter","transition-property","transition-behavior","transition-delay","transition-duration","transition-timing-function","will-change","contain","content","forced-color-adjust"];function Pe(e1,t,{onInvalidCandidate:r}={}){let n=new Map,o=[],a=new Map;for(let n of e1){if(t.invalidCandidates.has(n)){r?.(n);continue;}let e1=t.parseCandidate(n);0!==e1.length?a.set(n,e1):r?.(n);}let i=t.getVariantOrder();for(let[e1,l]of a){let a=!1;for(let r of l){let l=t.compileAstNodes(r);if(0!==l.length){a=!0;for(let{node:t,propertySort:a}of l){let l=0n;for(let e1 of r.variants)l|=1n<{let r=n.get(e1),o=n.get(t);if(r.variants-o.variants!==0n)return Number(r.variants-o.variants);let a=0;for(;a1)return null;for(let e1 of a.nodes)if("rule"!==e1.kind&&"at-rule"!==e1.kind||null===o(e1,t))return null;return A(a.nodes,t=>{if(("rule"===t.kind||"at-rule"===t.kind)&&t.nodes.length<=0)return t.nodes=e1.nodes,1;}),void(e1.nodes=a.nodes);}return null===o(e1,t)?null:void 0;}function Ye(e1){let t=e1.options?.types??[];return t.length>1&&t.includes("any");}function Ze(e1){for(let t of e1)"at-root"!==t.kind&&("declaration"===t.kind?t.important=!0:("rule"===t.kind||"at-rule"===t.kind)&&Ze(t.nodes));}function Ge(e1){let t=new Set,r=0,n=e1.slice(),o=!1;for(;n.length>0;){let e1=n.shift();if("declaration"===e1.kind){if(void 0===e1.value||(r++,o))continue;if("--tw-sort"===e1.property){let r=qe.indexOf(e1.value??"");if(-1!==r){t.add(r),o=!0;continue;}}let n=qe.indexOf(e1.property);-1!==n&&t.add(n);}else if("rule"===e1.kind||"at-rule"===e1.kind)for(let t of e1.nodes)n.push(t);}return{order:Array.from(t).sort((e1,t)=>e1-t),count:r};}function Xe(e1,t){let r=0,n=b("&",e1),o=new Set,a=new c(()=>new Set),i=new c(()=>new Set);A([n],(e1,{parent:n})=>{if("at-rule"===e1.kind){if("@keyframes"===e1.name)return A(e1.nodes,e1=>{if("at-rule"===e1.kind&&"@apply"===e1.name)throw new Error("You cannot use `@apply` inside `@keyframes`.");}),1;if("@utility"===e1.name){let r=e1.params.replace(/-\*$/,"");return i.get(r).add(e1),void A(e1.nodes,r=>{if("at-rule"===r.kind&&"@apply"===r.name){o.add(e1);for(let n of Je(r,t))a.get(e1).add(n);}});}if("@apply"===e1.name){if(null===n)return;r|=1,o.add(n);for(let r of Je(e1,t))a.get(n).add(r);}}});let l=new Set,s=[],u=new Set;function d(e1,r=[]){if(!l.has(e1)){if(u.has(e1)){let n=r[(r.indexOf(e1)+1)%r.length];throw"at-rule"===e1.kind&&"@utility"===e1.name&&"at-rule"===n.kind&&"@utility"===n.name&&A(e1.nodes,e1=>{if("at-rule"!==e1.kind||"@apply"!==e1.name)return;let r=e1.params.split(/\s+/g);for(let e1 of r)for(let r of t.parseCandidate(e1))switch(r.kind){case"arbitrary":break;case"static":case"functional":if(n.params.replace(/-\*$/,"")===r.root)throw new Error(`You cannot \`@apply\` the \`${e1}\` utility here because it creates a circular dependency.`);}}),new Error(`Circular dependency detected: - -${C([e1])} -Relies on: - -${C([n])}`);}u.add(e1);for(let t of a.get(e1))for(let n of i.get(t))r.push(e1),d(n,r),r.pop();l.add(e1),u.delete(e1),s.push(e1);}}for(let e1 of o)d(e1);for(let e1 of s)if("nodes"in e1)for(let r=0;r{throw new Error(`Cannot apply unknown utility class: ${e1}`);}}).astNodes,a=[];for(let e1 of o)if("rule"===e1.kind)for(let t of e1.nodes)a.push(t);else a.push(e1);e1.nodes.splice(r,1,...a);}}return r;}function*Je(e1,t){for(let r of e1.params.split(/\s+/g))for(let e1 of t.parseCandidate(r))switch(e1.kind){case"arbitrary":break;case"static":case"functional":yield e1.root;}}async function Qe(e1,r,n,o=0){let a=0,i=[];return A(e1,(e1,{replaceWith:l})=>{if("at-rule"===e1.kind&&("@import"===e1.name||"@reference"===e1.name)){let s=function(e1){let t,r=null,n=null,o=null;for(let a=0;a{if(o>100)throw new Error(`Exceeded maximum recursion depth while resolving \`${c}\` in \`${r}\`)`);let e1=await n(c,r),a=t(e1.content);await Qe(a,e1.base,n,o+1),p.nodes=function(e1,t,r,n){let o=e1;return null!==t&&(o=[k("@layer",t,o)]),null!==r&&(o=[k("@media",r,o)]),null!==n&&(o=[k("@supports","("===n[0]?n:`(${n})`,o)]),o;}([$({base:e1.base},a)],u,d,f);})()),l(p),1;}}),i.length>0&&await Promise.all(i),a;}function et(e1,t=null){return Array.isArray(e1)&&2===e1.length&&"object"==typeof e1[1]&&null!==typeof e1[1]?t?e1[1][t]??null:e1[0]:Array.isArray(e1)&&null===t?e1.join(", "):"string"==typeof e1&&null===t?e1:null;}function tt(e1,{theme:t},r){for(let t of r){let r=nt([t]);r&&e1.theme.clearNamespace(`--${r}`,4);}for(let[r,n]of function(e1){let t=[];return ot(e1,[],(e1,r)=>{if(function(e1){return"number"==typeof e1||"string"==typeof e1;}(e1))return t.push([r,e1]),1;if(function(e1){if(!Array.isArray(e1)||2!==e1.length||"string"!=typeof e1[0]&&"number"!=typeof e1[0]||void 0===e1[1]||null===e1[1]||"object"!=typeof e1[1])return!1;for(let t of Reflect.ownKeys(e1[1]))if("string"!=typeof t||"string"!=typeof e1[1][t]&&"number"!=typeof e1[1][t])return!1;return!0;}(e1)){t.push([r,e1[0]]);for(let n of Reflect.ownKeys(e1[1]))t.push([[...r,`-${n}`],e1[1][n]]);return 1;}return Array.isArray(e1)&&e1.every(e1=>"string"==typeof e1)?(t.push([r,e1.join(", ")]),1):void 0;}),t;}(t)){if("string"!=typeof n&&"number"!=typeof n)continue;if("string"==typeof n&&(n=n.replace(//g,"1")),"opacity"===r[0]&&("number"==typeof n||"string"==typeof n)){let e1="string"==typeof n?parseFloat(n):n;e1>=0&&e1<=1&&(n=100*e1+"%");}let t=nt(r);t&&e1.theme.add(`--${t}`,""+n,7);}if(Object.hasOwn(t,"fontFamily")){let r=5;{let n=et(t.fontFamily.sans);n&&e1.theme.hasDefault("--font-sans")&&(e1.theme.add("--default-font-family",n,r),e1.theme.add("--default-font-feature-settings",et(t.fontFamily.sans,"fontFeatureSettings")??"normal",r),e1.theme.add("--default-font-variation-settings",et(t.fontFamily.sans,"fontVariationSettings")??"normal",r));}{let n=et(t.fontFamily.mono);n&&e1.theme.hasDefault("--font-mono")&&(e1.theme.add("--default-mono-font-family",n,r),e1.theme.add("--default-mono-font-feature-settings",et(t.fontFamily.mono,"fontFeatureSettings")??"normal",r),e1.theme.add("--default-mono-font-variation-settings",et(t.fontFamily.mono,"fontVariationSettings")??"normal",r));}}return t;}var rt=/^[a-zA-Z0-9-_%/\.]+$/;function nt(e1){if("container"===e1[0])return null;"animation"===(e1=structuredClone(e1))[0]&&(e1[0]="animate"),"aspectRatio"===e1[0]&&(e1[0]="aspect"),"borderRadius"===e1[0]&&(e1[0]="radius"),"boxShadow"===e1[0]&&(e1[0]="shadow"),"colors"===e1[0]&&(e1[0]="color"),"containers"===e1[0]&&(e1[0]="container"),"fontFamily"===e1[0]&&(e1[0]="font"),"fontSize"===e1[0]&&(e1[0]="text"),"letterSpacing"===e1[0]&&(e1[0]="tracking"),"lineHeight"===e1[0]&&(e1[0]="leading"),"maxWidth"===e1[0]&&(e1[0]="container"),"screens"===e1[0]&&(e1[0]="breakpoint"),"transitionTimingFunction"===e1[0]&&(e1[0]="ease");for(let t of e1)if(!rt.test(t))return null;return e1.map((e1,t,r)=>"1"===e1&&t!==r.length-1?"":e1).map(e1=>e1.replaceAll(".","_").replace(/([a-z])([A-Z])/g,(e1,t,r)=>`${t}-${r.toLowerCase()}`)).filter((t,r)=>"DEFAULT"!==t||r!==e1.length-1).join("-");}function ot(e1,t=[],r){for(let n of Reflect.ownKeys(e1)){let o=e1[n];if(null==o)continue;let a=[...t,n],i=r(o,a)??0;if(1!==i){if(2===i)return 2;if((Array.isArray(o)||"object"==typeof o)&&2===ot(o,a,r))return 2;}}}function at(e1){let t=[];for(let r of R(e1,".")){if(!r.includes("[")){t.push(r);continue;}let e1=0;for(;;){let n=r.indexOf("[",e1),o=r.indexOf("]",n);if(-1===n||-1===o)break;n>e1&&t.push(r.slice(e1,n)),t.push(r.slice(n+1,o)),e1=o+1;}e1<=r.length-1&&t.push(r.slice(e1));}return t;}function it(e1){if("[object Object]"!==Object.prototype.toString.call(e1))return!1;let t=Object.getPrototypeOf(e1);return null===t||null===Object.getPrototypeOf(t);}function lt(e1,t,r,n=[]){for(let o of t)if(null!=o)for(let t of Reflect.ownKeys(o)){n.push(t);let a=r(e1[t],o[t],n);void 0!==a?e1[t]=a:it(e1[t])&&it(o[t])?e1[t]=lt({},[e1[t],o[t]],r,n):e1[t]=o[t],n.pop();}return e1;}function st(e1,t,r){return function(n,o){let i=n.lastIndexOf("/"),l=null;-1!==i&&(l=n.slice(i+1).trim(),n=n.slice(0,i).trim());let s=(()=>{let o=at(n),[i,l]=function(e1,t){if(1===t.length&&t[0].startsWith("--"))return[e1.get([t[0]]),e1.getOptions(t[0])];let r=nt(t),n=new Map,o=new c(()=>new Map),a=e1.namespace(`--${r}`);if(0===a.size)return[null,0];let i=new Map;for(let[t,l]of a){if(!t||!t.includes("--")){n.set(t,l),i.set(t,e1.getOptions(t?`--${r}-${t}`:`--${r}`));continue;}let a=t.indexOf("--"),s=t.slice(0,a),c=t.slice(a+2);c=c.replace(/-([a-z])/g,(e1,t)=>t.toUpperCase()),o.get(""===s?null:s).set(c,[l,e1.getOptions(`--${r}${t}`)]);}let l=e1.getOptions(`--${r}`);for(let[e1,t]of o){let r=n.get(e1);if("string"!=typeof r)continue;let o={},a={};for(let[e1,[r,n]]of t)o[e1]=r,a[e1]=n;n.set(e1,[r,o]),i.set(e1,[l,a]);}let s={},u={};for(let[e1,t]of n)ut(s,[e1??"DEFAULT"],t);for(let[e1,t]of i)ut(u,[e1??"DEFAULT"],t);return"DEFAULT"===t[t.length-1]?[s?.DEFAULT??null,u.DEFAULT??0]:"DEFAULT"in s&&1===Object.keys(s).length?[s.DEFAULT,u.DEFAULT??0]:(s.__CSS_VALUES__=u,[s,u]);}(e1.theme,o),s=r(ct(t()??{},o)??null);if("string"==typeof s&&(s=s.replace("","1")),"object"!=typeof i)return"object"!=typeof l&&4&l?s??i:i;if(null!==s&&"object"==typeof s&&!Array.isArray(s)){let e1=lt({},[s],(e1,t)=>t);if(null===i&&Object.hasOwn(s,"__CSS_VALUES__")){let t={};for(let r in s.__CSS_VALUES__)t[r]=s[r],delete e1[r];i=t;}for(let t in i)"__CSS_VALUES__"!==t&&(4&s?.__CSS_VALUES__?.[t]&&void 0!==ct(e1,t.split("-"))||(e1[a(t)]=i[t]));return e1;}if(Array.isArray(i)&&Array.isArray(l)&&Array.isArray(s)){let e1=i[0],t=i[1];4&l[0]&&(e1=s[0]??e1);for(let e1 of Object.keys(t))4&l[1][e1]&&(t[e1]=s[1][e1]??t[e1]);return[e1,t];}return i??s;})();return l&&"string"==typeof s&&(s=ze(s,l)),s??o;};}function ct(e1,t){for(let r=0;r0){let e1=pt(a);o?o.nodes.push(e1):r.push(e1),a="";}let n=i,l=i+1;for(;l0){let t=pt(a);e1.nodes.push(t),a="";}o=n.length>0?n[n.length-1]:null;break;}case 46:case 58:case 35:if(a.length>0){let e1=pt(a);o?o.nodes.push(e1):r.push(e1);}a=String.fromCharCode(l);break;case 91:{if(a.length>0){let e1=pt(a);o?o.nodes.push(e1):r.push(e1);}a="";let n=i,l=0;for(let r=i+1;r0&&r.push(pt(a)),r;}var kt=/^[a-z@][a-zA-Z0-9/%._-]*$/;function bt({designSystem:e1,ast:t,resolvedConfig:r,featuresRef:n,referenceMode:o}){let a={addBase(r){if(o)return;let a=yt(r);n.current|=Oe(a,e1),t.push(k("@layer","base",a));},addVariant(t,r){if(!Be.test(t))throw new Error(`\`addVariant('${t}')\` defines an invalid variant name. Variants should only contain alphanumeric, dashes or underscore characters.`);"string"==typeof r||Array.isArray(r)?e1.variants.static(t,e1=>{e1.nodes=xt(r,e1.nodes);},{compounds:Le("string"==typeof r?[r]:r)}):"object"==typeof r&&e1.variants.fromAst(t,yt(r));},matchVariant(t,r,n){function o(e1,t,n){return xt(r(e1,{modifier:t?.value??null}),n);}let a=Object.keys(n?.values??{});e1.variants.group(()=>{e1.variants.functional(t,(e1,t)=>{if(!t.value)return n?.values&&"DEFAULT"in n.values?void(e1.nodes=o(n.values.DEFAULT,t.modifier,e1.nodes)):null;if("arbitrary"===t.value.kind)e1.nodes=o(t.value.value,t.modifier,e1.nodes);else if("named"===t.value.kind&&n?.values){let r=n.values[t.value.value];if("string"!=typeof r)return;e1.nodes=o(r,t.modifier,e1.nodes);}});},(e1,t)=>{if("functional"!==e1.kind||"functional"!==t.kind)return 0;let r=e1.value?e1.value.value:"DEFAULT",o=t.value?t.value.value:"DEFAULT",i=n?.values?.[r]??r,l=n?.values?.[o]??o;if(n&&"function"==typeof n.sort)return n.sort({value:i,modifier:e1.modifier?.value??null},{value:l,modifier:t.modifier?.value??null});let s=a.indexOf(r),c=a.indexOf(o);return s=-1===s?a.length:s,c=-1===c?a.length:c,s!==c?s-c:iObject.entries(e1));a=a.flatMap(([e1,t])=>R(e1,",").map(e1=>[e1.trim(),t]));let i=new c(()=>[]);for(let[e1,r]of a){if(e1.startsWith("@keyframes ")){o||t.push(b(e1,yt(r)));continue;}let n=wt(e1),a=!1;if(gt(n,e1=>{if("selector"===e1.kind&&"."===e1.value[0]&&kt.test(e1.value.slice(1))){let t=e1.value;e1.value="&";let o=vt(n),l=t.slice(1),s="&"===o?yt(r):[b(o,yt(r))];return i.get(l).push(...s),a=!0,void(e1.value=t);}if("function"===e1.kind&&":not"===e1.value)return 1;}),!a)throw new Error(`\`addUtilities({ '${e1}' : … })\` defines an invalid utility selector. Utilities must be a single class name and start with a lowercase letter, eg. \`.scrollbar-none\`.`);}for(let[t,r]of i)e1.theme.prefix&&A(r,t=>{if("rule"===t.kind){let r=wt(t.selector);gt(r,t=>{"selector"===t.kind&&"."===t.value[0]&&(t.value=`.${e1.theme.prefix}\\:${t.value.slice(1)}`);}),t.selector=vt(r);}}),e1.utilities.static(t,o=>{let a=structuredClone(r);return $t(a,t,o.raw),n.current|=Xe(a,e1),a;});},matchUtilities(t,r){let o=r?.type?Array.isArray(r?.type)?r.type:[r.type]:["any"];for(let[a,i]of Object.entries(t)){let t=function({negative:t}){return l=>{if("arbitrary"===l.value?.kind&&o.length>0&&!o.includes("any")&&(l.value.dataType&&!o.includes(l.value.dataType)||!l.value.dataType&&!G(l.value.value,o)))return;let s,c=o.includes("color"),u=null,d=!1;{let e1=r?.values??{};c&&(e1=Object.assign({inherit:"inherit",transparent:"transparent",current:"currentcolor"},e1)),l.value?"arbitrary"===l.value.kind?u=l.value.value:l.value.fraction&&e1[l.value.fraction]?(u=e1[l.value.fraction],d=!0):e1[l.value.value]?u=e1[l.value.value]:e1.__BARE_VALUE__&&(u=e1.__BARE_VALUE__(l.value)??null,d=(null!==l.value.fraction&&u?.includes("/"))??!1):u=e1.DEFAULT??null;}if(null===u)return;{let e1=r?.modifiers??null;s=l.modifier?"any"===e1||"arbitrary"===l.modifier.kind?l.modifier.value:e1?.[l.modifier.value]?e1[l.modifier.value]:c&&!Number.isNaN(Number(l.modifier.value))?`${l.modifier.value}%`:null:null;}if(l.modifier&&null===s&&!d)return"arbitrary"===l.value?.kind?null:void 0;c&&null!==s&&(u=ze(u,s)),t&&(u=`calc(${u} * -1)`);let f=yt(i(u,{modifier:s}));return $t(f,a,l.raw),n.current|=Xe(f,e1),f;};};if(!kt.test(a))throw new Error(`\`matchUtilities({ '${a}' : … })\` defines an invalid utility name. Utilities should be alphanumeric and start with a lowercase letter, eg. \`scrollbar\`.`);r?.supportsNegativeValues&&e1.utilities.functional(`-${a}`,t({negative:!0}),{types:o}),e1.utilities.functional(a,t({negative:!1}),{types:o}),e1.utilities.suggest(a,()=>{let e1=r?.values??{},t=new Set(Object.keys(e1));t.delete("__BARE_VALUE__"),t.has("DEFAULT")&&(t.delete("DEFAULT"),t.add(null));let n=r?.modifiers??{},o="any"===n?[]:Object.keys(n);return[{supportsNegative:r?.supportsNegativeValues??!1,values:Array.from(t),modifiers:o}];});}},addComponents(e1,t){this.addUtilities(e1,t);},matchComponents(e1,t){this.matchUtilities(e1,t);},theme:st(e1,()=>r.theme??{},e1=>e1),prefix:e1=>e1,config(e1,t){let n=r;if(!e1)return n;let o=at(e1);for(let e1=0;e1Object.entries(e1));for(let[e1,n]of r)if("object"!=typeof n){if(!e1.startsWith("--")){if("@slot"===n){t.push(b(e1,[k("@slot")]));continue;}e1=e1.replace(/([A-Z])/g,"-$1").toLowerCase();}t.push(y(e1,String(n)));}else if(Array.isArray(n))for(let r of n)"string"==typeof r?t.push(y(e1,r)):t.push(b(e1,yt(r)));else null!==n&&t.push(b(e1,yt(n)));return t;}function xt(e1,r){return("string"==typeof e1?[e1]:e1).flatMap(e1=>{if(e1.trim().endsWith("}")){let n=t(e1.replace("}","{@slot}}"));return Re(n,r),n;}return b(e1,r);});}function $t(e1,t,r){A(e1,e1=>{if("rule"===e1.kind){let n=wt(e1.selector);gt(n,e1=>{"selector"===e1.kind&&e1.value===`.${t}`&&(e1.value=`.${o(r)}`);}),e1.selector=vt(n);}});}function zt(e1,t,r){for(let r of function(e1){let t=[];if("keyframes"in e1.theme)for(let[r,n]of Object.entries(e1.theme.keyframes))t.push(k("@keyframes",r,yt(n)));return t;}(t))e1.theme.addKeyframes(r);}var At={inherit:"inherit",current:"currentcolor",transparent:"transparent",black:"#000",white:"#fff",slate:{50:"oklch(98.4% 0.003 247.858)",100:"oklch(96.8% 0.007 247.896)",200:"oklch(92.9% 0.013 255.508)",300:"oklch(86.9% 0.022 252.894)",400:"oklch(70.4% 0.04 256.788)",500:"oklch(55.4% 0.046 257.417)",600:"oklch(44.6% 0.043 257.281)",700:"oklch(37.2% 0.044 257.287)",800:"oklch(27.9% 0.041 260.031)",900:"oklch(20.8% 0.042 265.755)",950:"oklch(12.9% 0.042 264.695)"},gray:{50:"oklch(98.5% 0.002 247.839)",100:"oklch(96.7% 0.003 264.542)",200:"oklch(92.8% 0.006 264.531)",300:"oklch(87.2% 0.01 258.338)",400:"oklch(70.7% 0.022 261.325)",500:"oklch(55.1% 0.027 264.364)",600:"oklch(44.6% 0.03 256.802)",700:"oklch(37.3% 0.034 259.733)",800:"oklch(27.8% 0.033 256.848)",900:"oklch(21% 0.034 264.665)",950:"oklch(13% 0.028 261.692)"},zinc:{50:"oklch(98.5% 0 0)",100:"oklch(96.7% 0.001 286.375)",200:"oklch(92% 0.004 286.32)",300:"oklch(87.1% 0.006 286.286)",400:"oklch(70.5% 0.015 286.067)",500:"oklch(55.2% 0.016 285.938)",600:"oklch(44.2% 0.017 285.786)",700:"oklch(37% 0.013 285.805)",800:"oklch(27.4% 0.006 286.033)",900:"oklch(21% 0.006 285.885)",950:"oklch(14.1% 0.005 285.823)"},neutral:{50:"oklch(98.5% 0 0)",100:"oklch(97% 0 0)",200:"oklch(92.2% 0 0)",300:"oklch(87% 0 0)",400:"oklch(70.8% 0 0)",500:"oklch(55.6% 0 0)",600:"oklch(43.9% 0 0)",700:"oklch(37.1% 0 0)",800:"oklch(26.9% 0 0)",900:"oklch(20.5% 0 0)",950:"oklch(14.5% 0 0)"},stone:{50:"oklch(98.5% 0.001 106.423)",100:"oklch(97% 0.001 106.424)",200:"oklch(92.3% 0.003 48.717)",300:"oklch(86.9% 0.005 56.366)",400:"oklch(70.9% 0.01 56.259)",500:"oklch(55.3% 0.013 58.071)",600:"oklch(44.4% 0.011 73.639)",700:"oklch(37.4% 0.01 67.558)",800:"oklch(26.8% 0.007 34.298)",900:"oklch(21.6% 0.006 56.043)",950:"oklch(14.7% 0.004 49.25)"},red:{50:"oklch(97.1% 0.013 17.38)",100:"oklch(93.6% 0.032 17.717)",200:"oklch(88.5% 0.062 18.334)",300:"oklch(80.8% 0.114 19.571)",400:"oklch(70.4% 0.191 22.216)",500:"oklch(63.7% 0.237 25.331)",600:"oklch(57.7% 0.245 27.325)",700:"oklch(50.5% 0.213 27.518)",800:"oklch(44.4% 0.177 26.899)",900:"oklch(39.6% 0.141 25.723)",950:"oklch(25.8% 0.092 26.042)"},orange:{50:"oklch(98% 0.016 73.684)",100:"oklch(95.4% 0.038 75.164)",200:"oklch(90.1% 0.076 70.697)",300:"oklch(83.7% 0.128 66.29)",400:"oklch(75% 0.183 55.934)",500:"oklch(70.5% 0.213 47.604)",600:"oklch(64.6% 0.222 41.116)",700:"oklch(55.3% 0.195 38.402)",800:"oklch(47% 0.157 37.304)",900:"oklch(40.8% 0.123 38.172)",950:"oklch(26.6% 0.079 36.259)"},amber:{50:"oklch(98.7% 0.022 95.277)",100:"oklch(96.2% 0.059 95.617)",200:"oklch(92.4% 0.12 95.746)",300:"oklch(87.9% 0.169 91.605)",400:"oklch(82.8% 0.189 84.429)",500:"oklch(76.9% 0.188 70.08)",600:"oklch(66.6% 0.179 58.318)",700:"oklch(55.5% 0.163 48.998)",800:"oklch(47.3% 0.137 46.201)",900:"oklch(41.4% 0.112 45.904)",950:"oklch(27.9% 0.077 45.635)"},yellow:{50:"oklch(98.7% 0.026 102.212)",100:"oklch(97.3% 0.071 103.193)",200:"oklch(94.5% 0.129 101.54)",300:"oklch(90.5% 0.182 98.111)",400:"oklch(85.2% 0.199 91.936)",500:"oklch(79.5% 0.184 86.047)",600:"oklch(68.1% 0.162 75.834)",700:"oklch(55.4% 0.135 66.442)",800:"oklch(47.6% 0.114 61.907)",900:"oklch(42.1% 0.095 57.708)",950:"oklch(28.6% 0.066 53.813)"},lime:{50:"oklch(98.6% 0.031 120.757)",100:"oklch(96.7% 0.067 122.328)",200:"oklch(93.8% 0.127 124.321)",300:"oklch(89.7% 0.196 126.665)",400:"oklch(84.1% 0.238 128.85)",500:"oklch(76.8% 0.233 130.85)",600:"oklch(64.8% 0.2 131.684)",700:"oklch(53.2% 0.157 131.589)",800:"oklch(45.3% 0.124 130.933)",900:"oklch(40.5% 0.101 131.063)",950:"oklch(27.4% 0.072 132.109)"},green:{50:"oklch(98.2% 0.018 155.826)",100:"oklch(96.2% 0.044 156.743)",200:"oklch(92.5% 0.084 155.995)",300:"oklch(87.1% 0.15 154.449)",400:"oklch(79.2% 0.209 151.711)",500:"oklch(72.3% 0.219 149.579)",600:"oklch(62.7% 0.194 149.214)",700:"oklch(52.7% 0.154 150.069)",800:"oklch(44.8% 0.119 151.328)",900:"oklch(39.3% 0.095 152.535)",950:"oklch(26.6% 0.065 152.934)"},emerald:{50:"oklch(97.9% 0.021 166.113)",100:"oklch(95% 0.052 163.051)",200:"oklch(90.5% 0.093 164.15)",300:"oklch(84.5% 0.143 164.978)",400:"oklch(76.5% 0.177 163.223)",500:"oklch(69.6% 0.17 162.48)",600:"oklch(59.6% 0.145 163.225)",700:"oklch(50.8% 0.118 165.612)",800:"oklch(43.2% 0.095 166.913)",900:"oklch(37.8% 0.077 168.94)",950:"oklch(26.2% 0.051 172.552)"},teal:{50:"oklch(98.4% 0.014 180.72)",100:"oklch(95.3% 0.051 180.801)",200:"oklch(91% 0.096 180.426)",300:"oklch(85.5% 0.138 181.071)",400:"oklch(77.7% 0.152 181.912)",500:"oklch(70.4% 0.14 182.503)",600:"oklch(60% 0.118 184.704)",700:"oklch(51.1% 0.096 186.391)",800:"oklch(43.7% 0.078 188.216)",900:"oklch(38.6% 0.063 188.416)",950:"oklch(27.7% 0.046 192.524)"},cyan:{50:"oklch(98.4% 0.019 200.873)",100:"oklch(95.6% 0.045 203.388)",200:"oklch(91.7% 0.08 205.041)",300:"oklch(86.5% 0.127 207.078)",400:"oklch(78.9% 0.154 211.53)",500:"oklch(71.5% 0.143 215.221)",600:"oklch(60.9% 0.126 221.723)",700:"oklch(52% 0.105 223.128)",800:"oklch(45% 0.085 224.283)",900:"oklch(39.8% 0.07 227.392)",950:"oklch(30.2% 0.056 229.695)"},sky:{50:"oklch(97.7% 0.013 236.62)",100:"oklch(95.1% 0.026 236.824)",200:"oklch(90.1% 0.058 230.902)",300:"oklch(82.8% 0.111 230.318)",400:"oklch(74.6% 0.16 232.661)",500:"oklch(68.5% 0.169 237.323)",600:"oklch(58.8% 0.158 241.966)",700:"oklch(50% 0.134 242.749)",800:"oklch(44.3% 0.11 240.79)",900:"oklch(39.1% 0.09 240.876)",950:"oklch(29.3% 0.066 243.157)"},blue:{50:"oklch(97% 0.014 254.604)",100:"oklch(93.2% 0.032 255.585)",200:"oklch(88.2% 0.059 254.128)",300:"oklch(80.9% 0.105 251.813)",400:"oklch(70.7% 0.165 254.624)",500:"oklch(62.3% 0.214 259.815)",600:"oklch(54.6% 0.245 262.881)",700:"oklch(48.8% 0.243 264.376)",800:"oklch(42.4% 0.199 265.638)",900:"oklch(37.9% 0.146 265.522)",950:"oklch(28.2% 0.091 267.935)"},indigo:{50:"oklch(96.2% 0.018 272.314)",100:"oklch(93% 0.034 272.788)",200:"oklch(87% 0.065 274.039)",300:"oklch(78.5% 0.115 274.713)",400:"oklch(67.3% 0.182 276.935)",500:"oklch(58.5% 0.233 277.117)",600:"oklch(51.1% 0.262 276.966)",700:"oklch(45.7% 0.24 277.023)",800:"oklch(39.8% 0.195 277.366)",900:"oklch(35.9% 0.144 278.697)",950:"oklch(25.7% 0.09 281.288)"},violet:{50:"oklch(96.9% 0.016 293.756)",100:"oklch(94.3% 0.029 294.588)",200:"oklch(89.4% 0.057 293.283)",300:"oklch(81.1% 0.111 293.571)",400:"oklch(70.2% 0.183 293.541)",500:"oklch(60.6% 0.25 292.717)",600:"oklch(54.1% 0.281 293.009)",700:"oklch(49.1% 0.27 292.581)",800:"oklch(43.2% 0.232 292.759)",900:"oklch(38% 0.189 293.745)",950:"oklch(28.3% 0.141 291.089)"},purple:{50:"oklch(97.7% 0.014 308.299)",100:"oklch(94.6% 0.033 307.174)",200:"oklch(90.2% 0.063 306.703)",300:"oklch(82.7% 0.119 306.383)",400:"oklch(71.4% 0.203 305.504)",500:"oklch(62.7% 0.265 303.9)",600:"oklch(55.8% 0.288 302.321)",700:"oklch(49.6% 0.265 301.924)",800:"oklch(43.8% 0.218 303.724)",900:"oklch(38.1% 0.176 304.987)",950:"oklch(29.1% 0.149 302.717)"},fuchsia:{50:"oklch(97.7% 0.017 320.058)",100:"oklch(95.2% 0.037 318.852)",200:"oklch(90.3% 0.076 319.62)",300:"oklch(83.3% 0.145 321.434)",400:"oklch(74% 0.238 322.16)",500:"oklch(66.7% 0.295 322.15)",600:"oklch(59.1% 0.293 322.896)",700:"oklch(51.8% 0.253 323.949)",800:"oklch(45.2% 0.211 324.591)",900:"oklch(40.1% 0.17 325.612)",950:"oklch(29.3% 0.136 325.661)"},pink:{50:"oklch(97.1% 0.014 343.198)",100:"oklch(94.8% 0.028 342.258)",200:"oklch(89.9% 0.061 343.231)",300:"oklch(82.3% 0.12 346.018)",400:"oklch(71.8% 0.202 349.761)",500:"oklch(65.6% 0.241 354.308)",600:"oklch(59.2% 0.249 0.584)",700:"oklch(52.5% 0.223 3.958)",800:"oklch(45.9% 0.187 3.815)",900:"oklch(40.8% 0.153 2.432)",950:"oklch(28.4% 0.109 3.907)"},rose:{50:"oklch(96.9% 0.015 12.422)",100:"oklch(94.1% 0.03 12.58)",200:"oklch(89.2% 0.058 10.001)",300:"oklch(81% 0.117 11.638)",400:"oklch(71.2% 0.194 13.428)",500:"oklch(64.5% 0.246 16.439)",600:"oklch(58.6% 0.253 17.585)",700:"oklch(51.4% 0.222 16.935)",800:"oklch(45.5% 0.188 13.697)",900:"oklch(41% 0.159 10.272)",950:"oklch(27.1% 0.105 12.094)"}};function jt(e1){return{__BARE_VALUE__:e1};}var Tt=jt(e1=>{if(de(e1.value))return e1.value;}),Ct=jt(e1=>{if(de(e1.value))return`${e1.value}%`;}),St=jt(e1=>{if(de(e1.value))return`${e1.value}px`;}),Kt=jt(e1=>{if(de(e1.value))return`${e1.value}ms`;}),Et=jt(e1=>{if(de(e1.value))return`${e1.value}deg`;}),Vt=jt(e1=>{if(null===e1.fraction)return;let[t,r]=R(e1.fraction,"/");return de(t)&&de(r)?e1.fraction:void 0;}),Nt=jt(e1=>{if(de(Number(e1.value)))return`repeat(${e1.value}, minmax(0, 1fr))`;}),Ot={accentColor:({theme:e1})=>e1("colors"),animation:{none:"none",spin:"spin 1s linear infinite",ping:"ping 1s cubic-bezier(0, 0, 0.2, 1) infinite",pulse:"pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",bounce:"bounce 1s infinite"},aria:{busy:'busy="true"',checked:'checked="true"',disabled:'disabled="true"',expanded:'expanded="true"',hidden:'hidden="true"',pressed:'pressed="true"',readonly:'readonly="true"',required:'required="true"',selected:'selected="true"'},aspectRatio:{auto:"auto",square:"1 / 1",video:"16 / 9",...Vt},backdropBlur:({theme:e1})=>e1("blur"),backdropBrightness:({theme:e1})=>({...e1("brightness"),...Ct}),backdropContrast:({theme:e1})=>({...e1("contrast"),...Ct}),backdropGrayscale:({theme:e1})=>({...e1("grayscale"),...Ct}),backdropHueRotate:({theme:e1})=>({...e1("hueRotate"),...Et}),backdropInvert:({theme:e1})=>({...e1("invert"),...Ct}),backdropOpacity:({theme:e1})=>({...e1("opacity"),...Ct}),backdropSaturate:({theme:e1})=>({...e1("saturate"),...Ct}),backdropSepia:({theme:e1})=>({...e1("sepia"),...Ct}),backgroundColor:({theme:e1})=>e1("colors"),backgroundImage:{none:"none","gradient-to-t":"linear-gradient(to top, var(--tw-gradient-stops))","gradient-to-tr":"linear-gradient(to top right, var(--tw-gradient-stops))","gradient-to-r":"linear-gradient(to right, var(--tw-gradient-stops))","gradient-to-br":"linear-gradient(to bottom right, var(--tw-gradient-stops))","gradient-to-b":"linear-gradient(to bottom, var(--tw-gradient-stops))","gradient-to-bl":"linear-gradient(to bottom left, var(--tw-gradient-stops))","gradient-to-l":"linear-gradient(to left, var(--tw-gradient-stops))","gradient-to-tl":"linear-gradient(to top left, var(--tw-gradient-stops))"},backgroundOpacity:({theme:e1})=>e1("opacity"),backgroundPosition:{bottom:"bottom",center:"center",left:"left","left-bottom":"left bottom","left-top":"left top",right:"right","right-bottom":"right bottom","right-top":"right top",top:"top"},backgroundSize:{auto:"auto",cover:"cover",contain:"contain"},blur:{0:"0",none:"",sm:"4px",DEFAULT:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"40px","3xl":"64px"},borderColor:({theme:e1})=>({DEFAULT:"currentcolor",...e1("colors")}),borderOpacity:({theme:e1})=>e1("opacity"),borderRadius:{none:"0px",sm:"0.125rem",DEFAULT:"0.25rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem","3xl":"1.5rem",full:"9999px"},borderSpacing:({theme:e1})=>e1("spacing"),borderWidth:{DEFAULT:"1px",0:"0px",2:"2px",4:"4px",8:"8px",...St},boxShadow:{sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",DEFAULT:"0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)",inner:"inset 0 2px 4px 0 rgb(0 0 0 / 0.05)",none:"none"},boxShadowColor:({theme:e1})=>e1("colors"),brightness:{0:"0",50:".5",75:".75",90:".9",95:".95",100:"1",105:"1.05",110:"1.1",125:"1.25",150:"1.5",200:"2",...Ct},caretColor:({theme:e1})=>e1("colors"),colors:()=>({...At}),columns:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12","3xs":"16rem","2xs":"18rem",xs:"20rem",sm:"24rem",md:"28rem",lg:"32rem",xl:"36rem","2xl":"42rem","3xl":"48rem","4xl":"56rem","5xl":"64rem","6xl":"72rem","7xl":"80rem",...Tt},container:{},content:{none:"none"},contrast:{0:"0",50:".5",75:".75",100:"1",125:"1.25",150:"1.5",200:"2",...Ct},cursor:{auto:"auto",default:"default",pointer:"pointer",wait:"wait",text:"text",move:"move",help:"help","not-allowed":"not-allowed",none:"none","context-menu":"context-menu",progress:"progress",cell:"cell",crosshair:"crosshair","vertical-text":"vertical-text",alias:"alias",copy:"copy","no-drop":"no-drop",grab:"grab",grabbing:"grabbing","all-scroll":"all-scroll","col-resize":"col-resize","row-resize":"row-resize","n-resize":"n-resize","e-resize":"e-resize","s-resize":"s-resize","w-resize":"w-resize","ne-resize":"ne-resize","nw-resize":"nw-resize","se-resize":"se-resize","sw-resize":"sw-resize","ew-resize":"ew-resize","ns-resize":"ns-resize","nesw-resize":"nesw-resize","nwse-resize":"nwse-resize","zoom-in":"zoom-in","zoom-out":"zoom-out"},divideColor:({theme:e1})=>e1("borderColor"),divideOpacity:({theme:e1})=>e1("borderOpacity"),divideWidth:({theme:e1})=>({...e1("borderWidth"),...St}),dropShadow:{sm:"0 1px 1px rgb(0 0 0 / 0.05)",DEFAULT:["0 1px 2px rgb(0 0 0 / 0.1)","0 1px 1px rgb(0 0 0 / 0.06)"],md:["0 4px 3px rgb(0 0 0 / 0.07)","0 2px 2px rgb(0 0 0 / 0.06)"],lg:["0 10px 8px rgb(0 0 0 / 0.04)","0 4px 3px rgb(0 0 0 / 0.1)"],xl:["0 20px 13px rgb(0 0 0 / 0.03)","0 8px 5px rgb(0 0 0 / 0.08)"],"2xl":"0 25px 25px rgb(0 0 0 / 0.15)",none:"0 0 #0000"},fill:({theme:e1})=>e1("colors"),flex:{1:"1 1 0%",auto:"1 1 auto",initial:"0 1 auto",none:"none"},flexBasis:({theme:e1})=>({auto:"auto","1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%","1/12":"8.333333%","2/12":"16.666667%","3/12":"25%","4/12":"33.333333%","5/12":"41.666667%","6/12":"50%","7/12":"58.333333%","8/12":"66.666667%","9/12":"75%","10/12":"83.333333%","11/12":"91.666667%",full:"100%",...e1("spacing")}),flexGrow:{0:"0",DEFAULT:"1",...Tt},flexShrink:{0:"0",DEFAULT:"1",...Tt},fontFamily:{sans:["ui-sans-serif","system-ui","sans-serif",'"Apple Color Emoji"','"Segoe UI Emoji"','"Segoe UI Symbol"','"Noto Color Emoji"'],serif:["ui-serif","Georgia","Cambria",'"Times New Roman"',"Times","serif"],mono:["ui-monospace","SFMono-Regular","Menlo","Monaco","Consolas",'"Liberation Mono"','"Courier New"',"monospace"]},fontSize:{xs:["0.75rem",{lineHeight:"1rem"}],sm:["0.875rem",{lineHeight:"1.25rem"}],base:["1rem",{lineHeight:"1.5rem"}],lg:["1.125rem",{lineHeight:"1.75rem"}],xl:["1.25rem",{lineHeight:"1.75rem"}],"2xl":["1.5rem",{lineHeight:"2rem"}],"3xl":["1.875rem",{lineHeight:"2.25rem"}],"4xl":["2.25rem",{lineHeight:"2.5rem"}],"5xl":["3rem",{lineHeight:"1"}],"6xl":["3.75rem",{lineHeight:"1"}],"7xl":["4.5rem",{lineHeight:"1"}],"8xl":["6rem",{lineHeight:"1"}],"9xl":["8rem",{lineHeight:"1"}]},fontWeight:{thin:"100",extralight:"200",light:"300",normal:"400",medium:"500",semibold:"600",bold:"700",extrabold:"800",black:"900"},gap:({theme:e1})=>e1("spacing"),gradientColorStops:({theme:e1})=>e1("colors"),gradientColorStopPositions:{"0%":"0%","5%":"5%","10%":"10%","15%":"15%","20%":"20%","25%":"25%","30%":"30%","35%":"35%","40%":"40%","45%":"45%","50%":"50%","55%":"55%","60%":"60%","65%":"65%","70%":"70%","75%":"75%","80%":"80%","85%":"85%","90%":"90%","95%":"95%","100%":"100%",...Ct},grayscale:{0:"0",DEFAULT:"100%",...Ct},gridAutoColumns:{auto:"auto",min:"min-content",max:"max-content",fr:"minmax(0, 1fr)"},gridAutoRows:{auto:"auto",min:"min-content",max:"max-content",fr:"minmax(0, 1fr)"},gridColumn:{auto:"auto","span-1":"span 1 / span 1","span-2":"span 2 / span 2","span-3":"span 3 / span 3","span-4":"span 4 / span 4","span-5":"span 5 / span 5","span-6":"span 6 / span 6","span-7":"span 7 / span 7","span-8":"span 8 / span 8","span-9":"span 9 / span 9","span-10":"span 10 / span 10","span-11":"span 11 / span 11","span-12":"span 12 / span 12","span-full":"1 / -1"},gridColumnEnd:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13",...Tt},gridColumnStart:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13",...Tt},gridRow:{auto:"auto","span-1":"span 1 / span 1","span-2":"span 2 / span 2","span-3":"span 3 / span 3","span-4":"span 4 / span 4","span-5":"span 5 / span 5","span-6":"span 6 / span 6","span-7":"span 7 / span 7","span-8":"span 8 / span 8","span-9":"span 9 / span 9","span-10":"span 10 / span 10","span-11":"span 11 / span 11","span-12":"span 12 / span 12","span-full":"1 / -1"},gridRowEnd:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13",...Tt},gridRowStart:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13",...Tt},gridTemplateColumns:{none:"none",subgrid:"subgrid",1:"repeat(1, minmax(0, 1fr))",2:"repeat(2, minmax(0, 1fr))",3:"repeat(3, minmax(0, 1fr))",4:"repeat(4, minmax(0, 1fr))",5:"repeat(5, minmax(0, 1fr))",6:"repeat(6, minmax(0, 1fr))",7:"repeat(7, minmax(0, 1fr))",8:"repeat(8, minmax(0, 1fr))",9:"repeat(9, minmax(0, 1fr))",10:"repeat(10, minmax(0, 1fr))",11:"repeat(11, minmax(0, 1fr))",12:"repeat(12, minmax(0, 1fr))",...Nt},gridTemplateRows:{none:"none",subgrid:"subgrid",1:"repeat(1, minmax(0, 1fr))",2:"repeat(2, minmax(0, 1fr))",3:"repeat(3, minmax(0, 1fr))",4:"repeat(4, minmax(0, 1fr))",5:"repeat(5, minmax(0, 1fr))",6:"repeat(6, minmax(0, 1fr))",7:"repeat(7, minmax(0, 1fr))",8:"repeat(8, minmax(0, 1fr))",9:"repeat(9, minmax(0, 1fr))",10:"repeat(10, minmax(0, 1fr))",11:"repeat(11, minmax(0, 1fr))",12:"repeat(12, minmax(0, 1fr))",...Nt},height:({theme:e1})=>({auto:"auto","1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%",full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content",...e1("spacing")}),hueRotate:{0:"0deg",15:"15deg",30:"30deg",60:"60deg",90:"90deg",180:"180deg",...Et},inset:({theme:e1})=>({auto:"auto","1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%",full:"100%",...e1("spacing")}),invert:{0:"0",DEFAULT:"100%",...Ct},keyframes:{spin:{to:{transform:"rotate(360deg)"}},ping:{"75%, 100%":{transform:"scale(2)",opacity:"0"}},pulse:{"50%":{opacity:".5"}},bounce:{"0%, 100%":{transform:"translateY(-25%)",animationTimingFunction:"cubic-bezier(0.8,0,1,1)"},"50%":{transform:"none",animationTimingFunction:"cubic-bezier(0,0,0.2,1)"}}},letterSpacing:{tighter:"-0.05em",tight:"-0.025em",normal:"0em",wide:"0.025em",wider:"0.05em",widest:"0.1em"},lineHeight:{none:"1",tight:"1.25",snug:"1.375",normal:"1.5",relaxed:"1.625",loose:"2",3:".75rem",4:"1rem",5:"1.25rem",6:"1.5rem",7:"1.75rem",8:"2rem",9:"2.25rem",10:"2.5rem"},listStyleType:{none:"none",disc:"disc",decimal:"decimal"},listStyleImage:{none:"none"},margin:({theme:e1})=>({auto:"auto",...e1("spacing")}),lineClamp:{1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",...Tt},maxHeight:({theme:e1})=>({none:"none",full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content",...e1("spacing")}),maxWidth:({theme:e1})=>({none:"none",xs:"20rem",sm:"24rem",md:"28rem",lg:"32rem",xl:"36rem","2xl":"42rem","3xl":"48rem","4xl":"56rem","5xl":"64rem","6xl":"72rem","7xl":"80rem",full:"100%",min:"min-content",max:"max-content",fit:"fit-content",prose:"65ch",...e1("spacing")}),minHeight:({theme:e1})=>({full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content",...e1("spacing")}),minWidth:({theme:e1})=>({full:"100%",min:"min-content",max:"max-content",fit:"fit-content",...e1("spacing")}),objectPosition:{bottom:"bottom",center:"center",left:"left","left-bottom":"left bottom","left-top":"left top",right:"right","right-bottom":"right bottom","right-top":"right top",top:"top"},opacity:{0:"0",5:"0.05",10:"0.1",15:"0.15",20:"0.2",25:"0.25",30:"0.3",35:"0.35",40:"0.4",45:"0.45",50:"0.5",55:"0.55",60:"0.6",65:"0.65",70:"0.7",75:"0.75",80:"0.8",85:"0.85",90:"0.9",95:"0.95",100:"1",...Ct},order:{first:"-9999",last:"9999",none:"0",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",...Tt},outlineColor:({theme:e1})=>e1("colors"),outlineOffset:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...St},outlineWidth:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...St},padding:({theme:e1})=>e1("spacing"),placeholderColor:({theme:e1})=>e1("colors"),placeholderOpacity:({theme:e1})=>e1("opacity"),ringColor:({theme:e1})=>({DEFAULT:"currentcolor",...e1("colors")}),ringOffsetColor:({theme:e1})=>e1("colors"),ringOffsetWidth:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...St},ringOpacity:({theme:e1})=>({DEFAULT:"0.5",...e1("opacity")}),ringWidth:{DEFAULT:"3px",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...St},rotate:{0:"0deg",1:"1deg",2:"2deg",3:"3deg",6:"6deg",12:"12deg",45:"45deg",90:"90deg",180:"180deg",...Et},saturate:{0:"0",50:".5",100:"1",150:"1.5",200:"2",...Ct},scale:{0:"0",50:".5",75:".75",90:".9",95:".95",100:"1",105:"1.05",110:"1.1",125:"1.25",150:"1.5",...Ct},screens:{sm:"40rem",md:"48rem",lg:"64rem",xl:"80rem","2xl":"96rem"},scrollMargin:({theme:e1})=>e1("spacing"),scrollPadding:({theme:e1})=>e1("spacing"),sepia:{0:"0",DEFAULT:"100%",...Ct},skew:{0:"0deg",1:"1deg",2:"2deg",3:"3deg",6:"6deg",12:"12deg",...Et},space:({theme:e1})=>e1("spacing"),spacing:{px:"1px",0:"0px",.5:"0.125rem",1:"0.25rem",1.5:"0.375rem",2:"0.5rem",2.5:"0.625rem",3:"0.75rem",3.5:"0.875rem",4:"1rem",5:"1.25rem",6:"1.5rem",7:"1.75rem",8:"2rem",9:"2.25rem",10:"2.5rem",11:"2.75rem",12:"3rem",14:"3.5rem",16:"4rem",20:"5rem",24:"6rem",28:"7rem",32:"8rem",36:"9rem",40:"10rem",44:"11rem",48:"12rem",52:"13rem",56:"14rem",60:"15rem",64:"16rem",72:"18rem",80:"20rem",96:"24rem"},stroke:({theme:e1})=>({none:"none",...e1("colors")}),strokeWidth:{0:"0",1:"1",2:"2",...Tt},supports:{},data:{},textColor:({theme:e1})=>e1("colors"),textDecorationColor:({theme:e1})=>e1("colors"),textDecorationThickness:{auto:"auto","from-font":"from-font",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...St},textIndent:({theme:e1})=>e1("spacing"),textOpacity:({theme:e1})=>e1("opacity"),textUnderlineOffset:{auto:"auto",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...St},transformOrigin:{center:"center",top:"top","top-right":"top right",right:"right","bottom-right":"bottom right",bottom:"bottom","bottom-left":"bottom left",left:"left","top-left":"top left"},transitionDelay:{0:"0s",75:"75ms",100:"100ms",150:"150ms",200:"200ms",300:"300ms",500:"500ms",700:"700ms",1e3:"1000ms",...Kt},transitionDuration:{DEFAULT:"150ms",0:"0s",75:"75ms",100:"100ms",150:"150ms",200:"200ms",300:"300ms",500:"500ms",700:"700ms",1e3:"1000ms",...Kt},transitionProperty:{none:"none",all:"all",DEFAULT:"color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter",colors:"color, background-color, border-color, outline-color, text-decoration-color, fill, stroke",opacity:"opacity",shadow:"box-shadow",transform:"transform"},transitionTimingFunction:{DEFAULT:"cubic-bezier(0.4, 0, 0.2, 1)",linear:"linear",in:"cubic-bezier(0.4, 0, 1, 1)",out:"cubic-bezier(0, 0, 0.2, 1)","in-out":"cubic-bezier(0.4, 0, 0.2, 1)"},translate:({theme:e1})=>({"1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%",full:"100%",...e1("spacing")}),size:({theme:e1})=>({auto:"auto","1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%","1/12":"8.333333%","2/12":"16.666667%","3/12":"25%","4/12":"33.333333%","5/12":"41.666667%","6/12":"50%","7/12":"58.333333%","8/12":"66.666667%","9/12":"75%","10/12":"83.333333%","11/12":"91.666667%",full:"100%",min:"min-content",max:"max-content",fit:"fit-content",...e1("spacing")}),width:({theme:e1})=>({auto:"auto","1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%","1/12":"8.333333%","2/12":"16.666667%","3/12":"25%","4/12":"33.333333%","5/12":"41.666667%","6/12":"50%","7/12":"58.333333%","8/12":"66.666667%","9/12":"75%","10/12":"83.333333%","11/12":"91.666667%",full:"100%",screen:"100vw",svw:"100svw",lvw:"100lvw",dvw:"100dvw",min:"min-content",max:"max-content",fit:"fit-content",...e1("spacing")}),willChange:{auto:"auto",scroll:"scroll-position",contents:"contents",transform:"transform"},zIndex:{auto:"auto",0:"0",10:"10",20:"20",30:"30",40:"40",50:"50",...Tt}};function Ft(e1){return{theme:{...Ot,colors:({theme:e1})=>e1("color",{}),extend:{fontSize:({theme:e1})=>({...e1("text",{})}),boxShadow:({theme:e1})=>({...e1("shadow",{})}),animation:({theme:e1})=>({...e1("animate",{})}),aspectRatio:({theme:e1})=>({...e1("aspect",{})}),borderRadius:({theme:e1})=>({...e1("radius",{})}),screens:({theme:e1})=>({...e1("breakpoint",{})}),letterSpacing:({theme:e1})=>({...e1("tracking",{})}),lineHeight:({theme:e1})=>({...e1("leading",{})}),transitionDuration:{DEFAULT:e1.get(["--default-transition-duration"])??null},transitionTimingFunction:{DEFAULT:e1.get(["--default-transition-timing-function"])??null},maxWidth:({theme:e1})=>({...e1("container",{})})}}};}var Wt={blocklist:[],future:{},prefix:"",important:!1,darkMode:null,theme:{},plugins:[],content:{files:[]}};function Ut(e1,t){let r={design:e1,configs:[],plugins:[],content:{files:[]},theme:{},extend:{},result:structuredClone(Wt)};for(let e1 of t)Bt(r,e1);for(let e1 of r.configs)"darkMode"in e1&&void 0!==e1.darkMode&&(r.result.darkMode=e1.darkMode??null),"prefix"in e1&&void 0!==e1.prefix&&(r.result.prefix=e1.prefix??""),"blocklist"in e1&&void 0!==e1.blocklist&&(r.result.blocklist=e1.blocklist??[]),"important"in e1&&void 0!==e1.important&&(r.result.important=e1.important??!1);let n=function(e1){let t=new Set,r=st(e1.design,()=>e1.theme,o),n=Object.assign(r,{theme:r,colors:At});function o(e1){return"function"==typeof e1?e1(n)??null:e1??null;}for(let r of e1.configs){let n=r.theme??{},o=n.extend??{};for(let e1 in n)"extend"!==e1&&t.add(e1);Object.assign(e1.theme,n);for(let t in o)e1.extend[t]??=[],e1.extend[t].push(o[t]);}delete e1.theme.extend;for(let t in e1.extend){let r=[e1.theme[t],...e1.extend[t]];e1.theme[t]=()=>lt({},r.map(o),Dt);}for(let t in e1.theme)e1.theme[t]=o(e1.theme[t]);if(e1.theme.screens&&"object"==typeof e1.theme.screens)for(let t of Object.keys(e1.theme.screens)){let r=e1.theme.screens[t];r&&"object"==typeof r&&("raw"in r||"max"in r||"min"in r&&(e1.theme.screens[t]=r.min));}return t;}(r);return{resolvedConfig:{...r.result,content:r.content,theme:r.theme,plugins:r.plugins},replacedThemeKeys:n};}function Dt(e1,t){return Array.isArray(e1)&&it(e1[0])?e1.concat(t):Array.isArray(t)&&it(t[0])&&it(e1)?[e1,...t]:Array.isArray(t)?t:void 0;}function Bt(e1,{config:t,base:r,path:n,reference:o}){let a=[];for(let e1 of t.plugins??[])"__isOptionsFunction"in e1?a.push({...e1(),reference:o}):"handler"in e1?a.push({...e1,reference:o}):a.push({handler:e1,reference:o});if(Array.isArray(t.presets)&&0===t.presets.length)throw new Error("Error in the config file/plugin/preset. An empty preset (`preset: []`) is not currently supported.");for(let a of t.presets??[])Bt(e1,{path:n,base:r,config:a,reference:o});for(let t of a)e1.plugins.push(t),t.config&&Bt(e1,{path:n,base:r,config:t.config,reference:!!t.reference});let i=t.content??[],l=Array.isArray(i)?i:i.files;for(let t of l)e1.content.files.push("object"==typeof t?t:{base:r,pattern:t});e1.configs.push(t);}function _t(e1,t){let r=e1.theme.container||{};if("object"!=typeof r||null===r)return;let n=function({center:e1,padding:t,screens:r},n){let o=[],a=null;if(e1&&o.push(y("margin-inline","auto")),("string"==typeof t||"object"==typeof t&&null!==t&&"DEFAULT"in t)&&o.push(y("padding-inline","string"==typeof t?t:t.DEFAULT)),"object"==typeof r&&null!==r){a=new Map;let e1=Array.from(n.theme.namespace("--breakpoint").entries());if(e1.sort((e1,t)=>P(e1[1],t[1],"asc")),e1.length>0){let[t]=e1[0];o.push(k("@media",`(width >= --theme(--breakpoint-${t}))`,[y("max-width","none")]));}for(let[e1,t]of Object.entries(r)){if("object"==typeof t){if(!("min"in t))continue;t=t.min;}a.set(e1,k("@media",`(width >= ${t})`,[y("max-width",t)]));}}if("object"==typeof t&&null!==t){let e1=Object.entries(t).filter(([e1])=>"DEFAULT"!==e1).map(([e1,t])=>[e1,n.theme.resolveValue(e1,["--breakpoint"]),t]).filter(Boolean);e1.sort((e1,t)=>P(e1[1],t[1],"asc"));for(let[t,,r]of e1)if(a&&a.has(t))a.get(t).nodes.push(y("padding-inline",r));else{if(a)continue;o.push(k("@media",`(width >= theme(--breakpoint-${t}))`,[y("padding-inline",r)]));}}if(a)for(let[,e1]of a)o.push(e1);return o;}(r,t);0!==n.length&&t.utilities.static("container",()=>structuredClone(n));}function Lt({addVariant:e1,config:t}){let r=t("darkMode",null),[n,o=".dark"]=Array.isArray(r)?r:[r];if("variant"===n){let e1;if(Array.isArray(o)||"function"==typeof o?e1=o:"string"==typeof o&&(e1=[o]),Array.isArray(e1))for(let t of e1)".dark"===t?(n=!1,console.warn('When using `variant` for `darkMode`, you must provide a selector.\nExample: `darkMode: ["variant", ".your-selector &"]`')):t.includes("&")||(n=!1,console.warn('When using `variant` for `darkMode`, your selector must contain `&`.\nExample `darkMode: ["variant", ".your-selector &"]`'));o=e1;}null===n||("selector"===n?e1("dark",`&:where(${o}, ${o} *)`):"media"===n?e1("dark","@media (prefers-color-scheme: dark)"):"variant"===n?e1("dark",o):"class"===n&&e1("dark",`&:is(${o} *)`));}function Mt(e1){return(Array.isArray(e1)?e1:[e1]).map(e1=>"string"==typeof e1?{min:e1}:e1&&"object"==typeof e1?e1:null).map(e1=>{if(null===e1)return null;if("raw"in e1)return e1.raw;let t="";return void 0!==e1.max&&(t+=`${e1.max} >= `),t+="width",void 0!==e1.min&&(t+=` >= ${e1.min}`),`(${t})`;}).filter(Boolean).join(", ");}var Rt=/^[a-z]+$/;async function It({designSystem:e1,base:t,ast:r,loadModule:n,sources:o}){let a=0,i=[],l=[];A(r,(e1,{parent:t,replaceWith:r,context:n})=>{if("at-rule"===e1.kind){if("@plugin"===e1.name){if(null!==t)throw new Error("`@plugin` cannot be nested.");let o=e1.params.slice(1,-1);if(0===o.length)throw new Error("`@plugin` must have a path.");let l={};for(let t of e1.nodes??[]){if("declaration"!==t.kind)throw new Error(`Unexpected \`@plugin\` option: - -${C([t])} - -\`@plugin\` options must be a flat list of declarations.`);if(void 0===t.value)continue;let e1=R(t.value,",").map(e1=>{if("null"===(e1=e1.trim()))return null;if("true"===e1)return!0;if("false"===e1)return!1;if(!Number.isNaN(Number(e1)))return Number(e1);if('"'===e1[0]&&'"'===e1[e1.length-1]||"'"===e1[0]&&"'"===e1[e1.length-1])return e1.slice(1,-1);if("{"===e1[0]&&"}"===e1[e1.length-1])throw new Error(`Unexpected \`@plugin\` option: Value of declaration \`${C([t]).trim()}\` is not supported. - -Using an object as a plugin option is currently only supported in JavaScript configuration files.`);return e1;});l[t.property]=1===e1.length?e1[0]:e1;}return i.push([{id:o,base:n.base,reference:!!n.reference},Object.keys(l).length>0?l:null]),r([]),void(a|=4);}if("@config"===e1.name){if(e1.nodes.length>0)throw new Error("`@config` cannot have a body.");if(null!==t)throw new Error("`@config` cannot be nested.");return l.push({id:e1.params.slice(1,-1),base:n.base,reference:!!n.reference}),r([]),void(a|=4);}}}),function(e1){for(let[t,r]of[["t","top"],["tr","top right"],["r","right"],["br","bottom right"],["b","bottom"],["bl","bottom left"],["l","left"],["tl","top left"]])e1.utilities.static(`bg-gradient-to-${t}`,()=>[y("--tw-gradient-position",`to ${r} in oklab`),y("background-image","linear-gradient(var(--tw-gradient-stops))")]);e1.utilities.static("bg-left-top",()=>[y("background-position","left top")]),e1.utilities.static("bg-right-top",()=>[y("background-position","right top")]),e1.utilities.static("bg-left-bottom",()=>[y("background-position","left bottom")]),e1.utilities.static("bg-right-bottom",()=>[y("background-position","right bottom")]),e1.utilities.static("object-left-top",()=>[y("object-position","left top")]),e1.utilities.static("object-right-top",()=>[y("object-position","right top")]),e1.utilities.static("object-left-bottom",()=>[y("object-position","left bottom")]),e1.utilities.static("object-right-bottom",()=>[y("object-position","right bottom")]),e1.utilities.functional("max-w-screen",t=>{if(!t.value||"arbitrary"===t.value.kind)return;let r=e1.theme.resolve(t.value.value,["--breakpoint"]);return r?[y("max-width",r)]:void 0;}),e1.utilities.static("overflow-ellipsis",()=>[y("text-overflow","ellipsis")]),e1.utilities.static("decoration-slice",()=>[y("-webkit-box-decoration-break","slice"),y("box-decoration-break","slice")]),e1.utilities.static("decoration-clone",()=>[y("-webkit-box-decoration-break","clone"),y("box-decoration-break","clone")]),e1.utilities.functional("flex-shrink",e1=>{if(!e1.modifier){if(!e1.value)return[y("flex-shrink","1")];if("arbitrary"===e1.value.kind)return[y("flex-shrink",e1.value.value)];if(de(e1.value.value))return[y("flex-shrink",e1.value.value)];}}),e1.utilities.functional("flex-grow",e1=>{if(!e1.modifier){if(!e1.value)return[y("flex-grow","1")];if("arbitrary"===e1.value.kind)return[y("flex-grow",e1.value.value)];if(de(e1.value.value))return[y("flex-grow",e1.value.value)];}});}(e1);let s=e1.resolveThemeValue;if(e1.resolveThemeValue=function(n,i){return n.startsWith("--")?s(n,i):(a|=qt({designSystem:e1,base:t,ast:r,sources:o,configs:[],pluginDetails:[]}),e1.resolveThemeValue(n,i));},!i.length&&!l.length)return 0;let[c,u]=await Promise.all([Promise.all(l.map(async({id:e1,base:t,reference:r})=>{let o=await n(e1,t,"config");return{path:e1,base:o.base,config:o.module,reference:r};})),Promise.all(i.map(async([{id:e1,base:t,reference:r},o])=>{let a=await n(e1,t,"plugin");return{path:e1,base:a.base,plugin:a.module,options:o,reference:r};}))]);return a|=qt({designSystem:e1,base:t,ast:r,sources:o,configs:c,pluginDetails:u}),a;}function qt({designSystem:e1,base:t,ast:r,sources:n,configs:o,pluginDetails:a}){let i=0,l=[...a.map(e1=>{if(!e1.options)return{config:{plugins:[e1.plugin]},base:e1.base,reference:e1.reference};if("__isOptionsFunction"in e1.plugin)return{config:{plugins:[e1.plugin(e1.options)]},base:e1.base,reference:e1.reference};throw new Error(`The plugin "${e1.path}" does not accept options`);}),...o],{resolvedConfig:s}=Ut(e1,[{config:Ft(e1.theme),base:t,reference:!0},...l,{config:{plugins:[Lt]},base:t,reference:!0}]),{resolvedConfig:c,replacedThemeKeys:u}=Ut(e1,l),d=e1.resolveThemeValue;e1.resolveThemeValue=function(e1,t){if("-"===e1[0]&&"-"===e1[1])return d(e1,t);let r=h.theme(e1,void 0);return Array.isArray(r)&&2===r.length?r[0]:Array.isArray(r)?r.join(", "):"string"==typeof r?r:void 0;};let f,p={designSystem:e1,ast:r,resolvedConfig:s,featuresRef:{set current(e){i|=e;}}},h=bt({...p,referenceMode:!1});for(let{handler:e1,reference:t}of s.plugins)t?(f||=bt({...p,referenceMode:!0}),e1(f)):e1(h);if(tt(e1,c,u),zt(e1,c),function(e1,t){let r=e1.theme.aria||{},n=e1.theme.supports||{},o=e1.theme.data||{};if(Object.keys(r).length>0){let e1=t.variants.get("aria"),n=e1?.applyFn,o=e1?.compounds;t.variants.functional("aria",(e1,t)=>{let o=t.value;return o&&"named"===o.kind&&o.value in r?n?.(e1,{...t,value:{kind:"arbitrary",value:r[o.value]}}):n?.(e1,t);},{compounds:o});}if(Object.keys(n).length>0){let e1=t.variants.get("supports"),r=e1?.applyFn,o=e1?.compounds;t.variants.functional("supports",(e1,t)=>{let o=t.value;return o&&"named"===o.kind&&o.value in n?r?.(e1,{...t,value:{kind:"arbitrary",value:n[o.value]}}):r?.(e1,t);},{compounds:o});}if(Object.keys(o).length>0){let e1=t.variants.get("data"),r=e1?.applyFn,n=e1?.compounds;t.variants.functional("data",(e1,t)=>{let n=t.value;return n&&"named"===n.kind&&n.value in o?r?.(e1,{...t,value:{kind:"arbitrary",value:o[n.value]}}):r?.(e1,t);},{compounds:n});}}(c,e1),function(e1,t){let r=e1.theme.screens||{},n=t.variants.get("min")?.order??0,o=[];for(let[e1,a]of Object.entries(r)){let r=function(r){t.variants.static(e1,e1=>{e1.nodes=[k("@media",c,e1.nodes)];},{order:r});},i=t.variants.get(e1),l=t.theme.resolveValue(e1,["--breakpoint"]);if(i&&l&&!t.theme.hasDefault(`--breakpoint-${e1}`))continue;let s=!0;"string"==typeof a&&(s=!1);let c=Mt(a);s?o.push(r):r(n);}if(0!==o.length){for(let[,e1]of t.variants.variants)e1.order>n&&(e1.order+=o.length);t.variants.compareFns=new Map(Array.from(t.variants.compareFns).map(([e1,t])=>(e1>n&&(e1+=o.length),[e1,t])));for(let[e1,t]of o.entries())t(n+e1+1);}}(c,e1),_t(c,e1),!e1.theme.prefix&&s.prefix){if(s.prefix.endsWith("-")&&(s.prefix=s.prefix.slice(0,-1),console.warn(`The prefix "${s.prefix}" is invalid. Prefixes must be lowercase ASCII letters (a-z) only and is written as a variant before all utilities. We have fixed up the prefix for you. Remove the trailing \`-\` to silence this warning.`)),!Rt.test(s.prefix))throw new Error(`The prefix "${s.prefix}" is invalid. Prefixes must be lowercase ASCII letters (a-z) only.`);e1.theme.prefix=s.prefix;}if(!e1.important&&!0===s.important&&(e1.important=!0),"string"==typeof s.important){let e1=s.important;A(r,(t,{replaceWith:r,parent:n})=>{if("at-rule"===t.kind&&"@tailwind"===t.name&&"utilities"===t.params)return"rule"===n?.kind&&n.selector===e1||r(w(e1,[t])),2;});}for(let t of s.blocklist)e1.invalidCandidates.add(t);for(let e1 of s.content.files){if("raw"in e1)throw new Error(`Error in the config file/plugin/preset. The \`content\` key contains a \`raw\` entry: - -${JSON.stringify(e1,null,2)} - -This feature is not currently supported.`);let t=!1;"!"==e1.pattern[0]&&(t=!0,e1.pattern=e1.pattern.slice(1)),n.push({...e1,negated:t});}return i;}var Pt=/^(-?\d+)\.\.(-?\d+)(?:\.\.(-?\d+))?$/;function Ht(e1){let t=e1.indexOf("{");if(-1===t)return[e1];let r=[],n=e1.slice(0,t),o=e1.slice(t),a=0,i=o.lastIndexOf("}");for(let e1=0;e10)for(let r=e1;r<=t;r+=a){let e1=r.toString();i.push(e1);}else for(let r=e1;r>=t;r+=a){let e1=r.toString();i.push(e1);}}return i;}(s):R(s,","),l=l.flatMap(e1=>Ht(e1));let u=Ht(c);for(let e1 of u)for(let t of l)r.push(n+t+e1);return r;}var Yt=/^[a-z]+$/;function Zt(){throw new Error("No `loadModule` function provided to `compile`");}function Gt(){throw new Error("No `loadStylesheet` function provided to `compile`");}async function Xt(e1,{base:t="",loadModule:r=Zt,loadStylesheet:n=Gt}={}){let i=0;e1=[$({base:t},e1)],i|=await Qe(e1,t,n);let l=null,c=new s,u=[],d=[],f=null,g=null,v=[],x=[],j=[],T=[],S=null;A(e1,(e1,{parent:t,replaceWith:r,context:n})=>{if("at-rule"===e1.kind){if("@tailwind"===e1.name&&("utilities"===e1.params||e1.params.startsWith("utilities"))){if(null!==g)return void r([]);let t=R(e1.params," ");for(let e1 of t)if(e1.startsWith("source(")){let t=e1.slice(7,-1);if("none"===t){S=t;continue;}if('"'===t[0]&&'"'!==t[t.length-1]||"'"===t[0]&&"'"!==t[t.length-1]||"'"!==t[0]&&'"'!==t[0])throw new Error("`source(…)` paths must be quoted.");S={base:n.sourceBase??n.base,pattern:t.slice(1,-1)};}g=e1,i|=16;}if("@utility"===e1.name){if(null!==t)throw new Error("`@utility` cannot be nested.");if(0===e1.nodes.length)throw new Error(`\`@utility ${e1.params}\` is empty. Utilities should include at least one property.`);let r=function(e1){let t=e1.params;return be.test(t)?r=>{let n={"--value":{usedSpacingInteger:!1,usedSpacingNumber:!1,themeKeys:new Set,literals:new Set},"--modifier":{usedSpacingInteger:!1,usedSpacingNumber:!1,themeKeys:new Set,literals:new Set}};A(e1.nodes,e1=>{if("declaration"!==e1.kind||!e1.value||!e1.value.includes("--value(")&&!e1.value.includes("--modifier("))return;let t=m(e1.value);p(t,e1=>{if("function"!==e1.kind)return;if(!("--spacing"!==e1.value||n["--modifier"].usedSpacingNumber&&n["--value"].usedSpacingNumber))return p(e1.nodes,e1=>{if("function"!==e1.kind||"--value"!==e1.value&&"--modifier"!==e1.value)return;let t=e1.value;for(let r of e1.nodes)if("word"===r.kind){if("integer"===r.value)n[t].usedSpacingInteger||=!0;else if("number"===r.value&&(n[t].usedSpacingNumber||=!0,n["--modifier"].usedSpacingNumber&&n["--value"].usedSpacingNumber))return 2;}}),0;if("--value"!==e1.value&&"--modifier"!==e1.value)return;let t=R(h(e1.nodes),",");for(let[e1,r]of t.entries())r=r.replace(/\\\*/g,"*"),r=r.replace(/--(.*?)\s--(.*?)/g,"--$1-*--$2"),r=r.replace(/\s+/g,""),r=r.replace(/(-\*){2,}/g,"-*"),"-"===r[0]&&"-"===r[1]&&!r.includes("-*")&&(r+="-*"),t[e1]=r;e1.nodes=m(t.join(","));for(let t of e1.nodes)if("word"!==t.kind||'"'!==t.value[0]&&"'"!==t.value[0]||t.value[0]!==t.value[t.value.length-1]){if("word"===t.kind&&"-"===t.value[0]&&"-"===t.value[1]){let r=t.value.replace(/-\*.*$/g,"");n[e1.value].themeKeys.add(r);}else if("word"===t.kind&&("["!==t.value[0]||"]"!==t.value[t.value.length-1])&&!Ce.includes(t.value)){console.warn(`Unsupported bare value data type: "${t.value}". -Only valid data types are: ${Ce.map(e1=>`"${e1}"`).join(", ")}. -`);let r=t.value,n=structuredClone(e1),o="¶";p(n.nodes,(e1,{replaceWith:t})=>{"word"===e1.kind&&e1.value===r&&t({kind:"word",value:o});});let a="^".repeat(h([t]).length),i=h([n]).indexOf(o),l=["```css",h([e1])," ".repeat(i)+a,"```"].join("\n");console.warn(l);}}else{let r=t.value.slice(1,-1);n[e1.value].literals.add(r);}}),e1.value=h(t);}),r.utilities.functional(t.slice(0,-2),t=>{let n=structuredClone(e1),o=t.value,a=t.modifier;if(null===o)return;let i=!1,l=!1,s=!1,c=!1,u=new Map,d=!1;if(A([n],(e1,{parent:t,replaceWith:n})=>{if("rule"!==t?.kind&&"at-rule"!==t?.kind||"declaration"!==e1.kind||!e1.value)return;let f=m(e1.value);0===(p(f,(f,{replaceWith:p})=>{if("function"===f.kind){if("--value"===f.value){i=!0;let a=Se(o,f,r);return a?(l=!0,a.ratio?d=!0:u.set(e1,t),p(a.nodes),1):(i||=!1,n([]),2);}if("--modifier"===f.value){if(null===a)return n([]),2;s=!0;let e1=Se(a,f,r);return e1?(c=!0,p(e1.nodes),1):(s||=!1,n([]),2);}}})??0)&&(e1.value=h(f));}),i&&!l||s&&!c||d&&c||a&&!d&&!c)return null;if(d)for(let[e1,t]of u){let r=t.nodes.indexOf(e1);-1!==r&&t.nodes.splice(r,1);}return n.nodes;}),r.utilities.suggest(t.slice(0,-2),()=>{let e1=[],t=[];for(let[o,{literals:a,usedSpacingNumber:i,usedSpacingInteger:l,themeKeys:s}]of[[e1,n["--value"]],[t,n["--modifier"]]]){for(let e1 of a)o.push(e1);if(i)o.push(...ye);else if(l)for(let e1 of ye)de(e1)&&o.push(e1);for(let e1 of r.theme.keysInNamespaces(s))o.push(e1);}return[{values:e1,modifiers:t}];});}:ke.test(t)?r=>{r.utilities.static(t,()=>structuredClone(e1.nodes));}:null;}(e1);if(null===r)throw new Error(`\`@utility ${e1.params}\` defines an invalid utility name. Utilities should be alphanumeric and start with a lowercase letter.`);d.push(r);}if("@source"===e1.name){if(e1.nodes.length>0)throw new Error("`@source` cannot have a body.");if(null!==t)throw new Error("`@source` cannot be nested.");let o=!1,a=!1,i=e1.params;if("n"===i[0]&&i.startsWith("not ")&&(o=!0,i=i.slice(4)),"i"===i[0]&&i.startsWith("inline(")&&(a=!0,i=i.slice(7,-1)),'"'===i[0]&&'"'!==i[i.length-1]||"'"===i[0]&&"'"!==i[i.length-1]||"'"!==i[0]&&'"'!==i[0])throw new Error("`@source` paths must be quoted.");let l=i.slice(1,-1);if(a){let e1=o?T:j,t=R(l," ");for(let r of t)for(let t of Ht(r))e1.push(t);}else x.push({base:n.base,pattern:l,negated:o});return void r([]);}if("@variant"===e1.name&&(null===t?0===e1.nodes.length?e1.name="@custom-variant":(A(e1.nodes,t=>{if("at-rule"===t.kind&&"@slot"===t.name)return e1.name="@custom-variant",2;}),"@variant"===e1.name&&v.push(e1)):v.push(e1)),"@custom-variant"===e1.name){if(null!==t)throw new Error("`@custom-variant` cannot be nested.");r([]);let[n,o]=R(e1.params," ");if(!Be.test(n))throw new Error(`\`@custom-variant ${n}\` defines an invalid variant name. Variants should only contain alphanumeric, dashes or underscore characters.`);if(e1.nodes.length>0&&o)throw new Error(`\`@custom-variant ${n}\` cannot have both a selector and a body.`);if(0===e1.nodes.length){if(!o)throw new Error(`\`@custom-variant ${n}\` has no selector or body.`);let e1=R(o.slice(1,-1),",");if(0===e1.length||e1.some(e1=>""===e1.trim()))throw new Error(`\`@custom-variant ${n} (${e1.join(",")})\` selector is invalid.`);let t=[],r=[];for(let n of e1)n=n.trim(),"@"===n[0]?t.push(n):r.push(n);return void u.push(e1=>{e1.variants.static(n,e1=>{let n=[];r.length>0&&n.push(w(r.join(", "),e1.nodes));for(let r of t)n.push(b(r,e1.nodes));e1.nodes=n;},{compounds:Le([...r,...t])});});}return void u.push(t=>{t.variants.fromAst(n,e1.nodes);});}if("@media"===e1.name){let t=R(e1.params," "),o=[];for(let r of t)if(r.startsWith("source(")){let t=r.slice(7,-1);A(e1.nodes,(e1,{replaceWith:r})=>{if("at-rule"===e1.kind&&"@tailwind"===e1.name&&"utilities"===e1.params)return e1.params+=` source(${t})`,r([$({sourceBase:n.base},[e1])]),2;});}else if(r.startsWith("theme(")){let t=r.slice(6,-1),n=t.includes("reference");A(e1.nodes,e1=>{if("at-rule"!==e1.kind){if(n)throw new Error('Files imported with `@import "…" theme(reference)` must only contain `@theme` blocks.\nUse `@reference "…";` instead.');return 0;}if("@theme"===e1.name)return e1.params+=" "+t,1;});}else if(r.startsWith("prefix(")){let t=r.slice(7,-1);A(e1.nodes,e1=>{if("at-rule"===e1.kind&&"@theme"===e1.name)return e1.params+=` prefix(${t})`,1;});}else"important"===r?l=!0:"reference"===r?e1.nodes=[$({reference:!0},e1.nodes)]:o.push(r);o.length>0?e1.params=o.join(" "):t.length>0&&r(e1.nodes);}if("@theme"===e1.name){let[t,o]=function(e1){let t=0,r=null;for(let n of R(e1," "))"reference"===n?t|=2:"inline"===n?t|=1:"default"===n?t|=4:"static"===n?t|=8:n.startsWith("prefix(")&&n.endsWith(")")&&(r=n.slice(7,-1));return[t,r];}(e1.params);if(n.reference&&(t|=2),o){if(!Yt.test(o))throw new Error(`The prefix "${o}" is invalid. Prefixes must be lowercase ASCII letters (a-z) only.`);c.prefix=o;}return A(e1.nodes,r=>{if("at-rule"===r.kind&&"@keyframes"===r.name)return c.addKeyframes(r),1;if("comment"===r.kind)return;if("declaration"===r.kind&&r.property.startsWith("--"))return void c.add(a(r.property),r.value??"",t);let n=C([k(e1.name,e1.params,[r])]).split("\n").map((e1,t,r)=>`${0===t||t>=r.length-2?" ":">"} ${e1}`).join("\n");throw new Error(`\`@theme\` blocks must only contain custom properties or \`@keyframes\`. - -${n}`);}),f?r([]):(f=w(":root, :host",[]),r([f])),1;}}});let K=Ie(c);if(l&&(K.important=l),T.length>0)for(let e1 of T)K.invalidCandidates.add(e1);i|=await It({designSystem:K,base:t,ast:e1,loadModule:r,sources:x});for(let e1 of u)e1(K);for(let e1 of d)e1(K);if(f){let t=[];for(let[e1,r]of K.theme.entries())2&r.options||t.push(y(o(e1),r.value));let r=K.theme.getKeyframes();for(let t of r)e1.push($({theme:!0},[z([t])]));f.nodes=[$({theme:!0},t)];}if(g){let e1=g;e1.kind="context",e1.context={};}if(v.length>0){for(let e1 of v){let t=w("&",e1.nodes),r=e1.params,n=K.parseVariant(r);if(null===n)throw new Error(`Cannot use \`@variant\` with unknown variant: ${r}`);if(null===He(t,n,K.variants))throw new Error(`Cannot use \`@variant\` with variant: ${r}`);Object.assign(e1,t);}i|=32;}return i|=Oe(e1,K),i|=Xe(e1,K),A(e1,(e1,{replaceWith:t})=>{if("at-rule"===e1.kind)return"@utility"===e1.name&&t([]),1;}),{designSystem:K,ast:e1,sources:x,root:S,utilitiesNode:g,features:i,inlineCandidates:j};}async function Jt(e1,r={}){let n=t(e1),o=await async function(e1,t={}){let{designSystem:r,ast:n,sources:o,root:a,utilitiesNode:i,features:l,inlineCandidates:s}=await Xt(e1,t);function c(e1){r.invalidCandidates.add(e1);}n.unshift(x("! tailwindcss v4.1.3 | MIT License | https://tailwindcss.com "));let u=new Set,d=null,f=0,p=!1;for(let e1 of s)r.invalidCandidates.has(e1)||(u.add(e1),p=!0);return{sources:o,root:a,features:l,build(o){if(0===l)return e1;if(!i)return d??=T(n,r,t.polyfills),d;let a=p,s=!1;p=!1;let h=u.size;for(let e1 of o)if(!r.invalidCandidates.has(e1))if("-"===e1[0]&&"-"===e1[1]){let t=r.theme.markUsedVariable(e1);a||=t,s||=t;}else u.add(e1),a||=u.size!==h;if(!a)return d??=T(n,r,t.polyfills),d;let m=Pe(u,r,{onInvalidCandidate:c}).astNodes;return s||f!==m.length?(f=m.length,i.nodes=m,d=T(n,r,t.polyfills),d):(d??=T(n,r,t.polyfills),d);}};}(n,r),a=n,i=e1;return{...o,build(e1){let t=o.build(e1);return t===a||(i=C(t),a=t),i;}};}var Qt={index:"@layer theme, base, components, utilities;\n\n@import './theme.css' layer(theme);\n@import './preflight.css' layer(base);\n@import './utilities.css' layer(utilities);\n",preflight:"/*\n 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)\n 2. Remove default margins and padding\n 3. Reset all borders.\n*/\n\n*,\n::after,\n::before,\n::backdrop,\n::file-selector-button {\n box-sizing: border-box; /* 1 */\n margin: 0; /* 2 */\n padding: 0; /* 2 */\n border: 0 solid; /* 3 */\n}\n\n/*\n 1. Use a consistent sensible line-height in all browsers.\n 2. Prevent adjustments of font size after orientation changes in iOS.\n 3. Use a more readable tab size.\n 4. Use the user's configured `sans` font-family by default.\n 5. Use the user's configured `sans` font-feature-settings by default.\n 6. Use the user's configured `sans` font-variation-settings by default.\n 7. Disable tap highlights on iOS.\n*/\n\nhtml,\n:host {\n line-height: 1.5; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n tab-size: 4; /* 3 */\n font-family: --theme(\n --default-font-family,\n ui-sans-serif,\n system-ui,\n sans-serif,\n 'Apple Color Emoji',\n 'Segoe UI Emoji',\n 'Segoe UI Symbol',\n 'Noto Color Emoji'\n ); /* 4 */\n font-feature-settings: --theme(--default-font-feature-settings, normal); /* 5 */\n font-variation-settings: --theme(--default-font-variation-settings, normal); /* 6 */\n -webkit-tap-highlight-color: transparent; /* 7 */\n}\n\n/*\n 1. Add the correct height in Firefox.\n 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)\n 3. Reset the default border style to a 1px solid border.\n*/\n\nhr {\n height: 0; /* 1 */\n color: inherit; /* 2 */\n border-top-width: 1px; /* 3 */\n}\n\n/*\n Add the correct text decoration in Chrome, Edge, and Safari.\n*/\n\nabbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n}\n\n/*\n Remove the default font size and weight for headings.\n*/\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n font-size: inherit;\n font-weight: inherit;\n}\n\n/*\n Reset links to optimize for opt-in styling instead of opt-out.\n*/\n\na {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n}\n\n/*\n Add the correct font weight in Edge and Safari.\n*/\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/*\n 1. Use the user's configured `mono` font-family by default.\n 2. Use the user's configured `mono` font-feature-settings by default.\n 3. Use the user's configured `mono` font-variation-settings by default.\n 4. Correct the odd `em` font sizing in all browsers.\n*/\n\ncode,\nkbd,\nsamp,\npre {\n font-family: --theme(\n --default-mono-font-family,\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n 'Liberation Mono',\n 'Courier New',\n monospace\n ); /* 1 */\n font-feature-settings: --theme(--default-mono-font-feature-settings, normal); /* 2 */\n font-variation-settings: --theme(--default-mono-font-variation-settings, normal); /* 3 */\n font-size: 1em; /* 4 */\n}\n\n/*\n Add the correct font size in all browsers.\n*/\n\nsmall {\n font-size: 80%;\n}\n\n/*\n Prevent `sub` and `sup` elements from affecting the line height in all browsers.\n*/\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/*\n 1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)\n 2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)\n 3. Remove gaps between table borders by default.\n*/\n\ntable {\n text-indent: 0; /* 1 */\n border-color: inherit; /* 2 */\n border-collapse: collapse; /* 3 */\n}\n\n/*\n Use the modern Firefox focus style for all focusable elements.\n*/\n\n:-moz-focusring {\n outline: auto;\n}\n\n/*\n Add the correct vertical alignment in Chrome and Firefox.\n*/\n\nprogress {\n vertical-align: baseline;\n}\n\n/*\n Add the correct display in Chrome and Safari.\n*/\n\nsummary {\n display: list-item;\n}\n\n/*\n Make lists unstyled by default.\n*/\n\nol,\nul,\nmenu {\n list-style: none;\n}\n\n/*\n 1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)\n 2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)\n This can trigger a poorly considered lint error in some tools but is included by design.\n*/\n\nimg,\nsvg,\nvideo,\ncanvas,\naudio,\niframe,\nembed,\nobject {\n display: block; /* 1 */\n vertical-align: middle; /* 2 */\n}\n\n/*\n Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)\n*/\n\nimg,\nvideo {\n max-width: 100%;\n height: auto;\n}\n\n/*\n 1. Inherit font styles in all browsers.\n 2. Remove border radius in all browsers.\n 3. Remove background color in all browsers.\n 4. Ensure consistent opacity for disabled states in all browsers.\n*/\n\nbutton,\ninput,\nselect,\noptgroup,\ntextarea,\n::file-selector-button {\n font: inherit; /* 1 */\n font-feature-settings: inherit; /* 1 */\n font-variation-settings: inherit; /* 1 */\n letter-spacing: inherit; /* 1 */\n color: inherit; /* 1 */\n border-radius: 0; /* 2 */\n background-color: transparent; /* 3 */\n opacity: 1; /* 4 */\n}\n\n/*\n Restore default font weight.\n*/\n\n:where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n}\n\n/*\n Restore indentation.\n*/\n\n:where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n}\n\n/*\n Restore space after button.\n*/\n\n::file-selector-button {\n margin-inline-end: 4px;\n}\n\n/*\n Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)\n*/\n\n::placeholder {\n opacity: 1;\n}\n\n/*\n Set the default placeholder color to a semi-transparent version of the current text color in browsers that do not\n crash when using `color-mix(…)` with `currentcolor`. (https://github.com/tailwindlabs/tailwindcss/issues/17194)\n*/\n\n@supports (not (-webkit-appearance: -apple-pay-button)) /* Not Safari */ or\n (contain-intrinsic-size: 1px) /* Safari 17+ */ {\n ::placeholder {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n}\n\n/*\n Prevent resizing textareas horizontally by default.\n*/\n\ntextarea {\n resize: vertical;\n}\n\n/*\n Remove the inner padding in Chrome and Safari on macOS.\n*/\n\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/*\n 1. Ensure date/time inputs have the same height when empty in iOS Safari.\n 2. Ensure text alignment can be changed on date/time inputs in iOS Safari.\n*/\n\n::-webkit-date-and-time-value {\n min-height: 1lh; /* 1 */\n text-align: inherit; /* 2 */\n}\n\n/*\n Prevent height from changing on date/time inputs in macOS Safari when the input is set to `display: block`.\n*/\n\n::-webkit-datetime-edit {\n display: inline-flex;\n}\n\n/*\n Remove excess padding from pseudo-elements in date/time inputs to ensure consistent height across browsers.\n*/\n\n::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n}\n\n::-webkit-datetime-edit,\n::-webkit-datetime-edit-year-field,\n::-webkit-datetime-edit-month-field,\n::-webkit-datetime-edit-day-field,\n::-webkit-datetime-edit-hour-field,\n::-webkit-datetime-edit-minute-field,\n::-webkit-datetime-edit-second-field,\n::-webkit-datetime-edit-millisecond-field,\n::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n}\n\n/*\n Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)\n*/\n\n:-moz-ui-invalid {\n box-shadow: none;\n}\n\n/*\n Correct the inability to style the border radius in iOS Safari.\n*/\n\nbutton,\ninput:where([type='button'], [type='reset'], [type='submit']),\n::file-selector-button {\n appearance: button;\n}\n\n/*\n Correct the cursor style of increment and decrement buttons in Safari.\n*/\n\n::-webkit-inner-spin-button,\n::-webkit-outer-spin-button {\n height: auto;\n}\n\n/*\n Make elements with the HTML hidden attribute stay hidden by default.\n*/\n\n[hidden]:where(:not([hidden='until-found'])) {\n display: none !important;\n}\n",theme:"@theme default {\n --font-sans:\n ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',\n 'Noto Color Emoji';\n --font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;\n --font-mono:\n ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',\n monospace;\n\n --color-red-50: oklch(97.1% 0.013 17.38);\n --color-red-100: oklch(93.6% 0.032 17.717);\n --color-red-200: oklch(88.5% 0.062 18.334);\n --color-red-300: oklch(80.8% 0.114 19.571);\n --color-red-400: oklch(70.4% 0.191 22.216);\n --color-red-500: oklch(63.7% 0.237 25.331);\n --color-red-600: oklch(57.7% 0.245 27.325);\n --color-red-700: oklch(50.5% 0.213 27.518);\n --color-red-800: oklch(44.4% 0.177 26.899);\n --color-red-900: oklch(39.6% 0.141 25.723);\n --color-red-950: oklch(25.8% 0.092 26.042);\n\n --color-orange-50: oklch(98% 0.016 73.684);\n --color-orange-100: oklch(95.4% 0.038 75.164);\n --color-orange-200: oklch(90.1% 0.076 70.697);\n --color-orange-300: oklch(83.7% 0.128 66.29);\n --color-orange-400: oklch(75% 0.183 55.934);\n --color-orange-500: oklch(70.5% 0.213 47.604);\n --color-orange-600: oklch(64.6% 0.222 41.116);\n --color-orange-700: oklch(55.3% 0.195 38.402);\n --color-orange-800: oklch(47% 0.157 37.304);\n --color-orange-900: oklch(40.8% 0.123 38.172);\n --color-orange-950: oklch(26.6% 0.079 36.259);\n\n --color-amber-50: oklch(98.7% 0.022 95.277);\n --color-amber-100: oklch(96.2% 0.059 95.617);\n --color-amber-200: oklch(92.4% 0.12 95.746);\n --color-amber-300: oklch(87.9% 0.169 91.605);\n --color-amber-400: oklch(82.8% 0.189 84.429);\n --color-amber-500: oklch(76.9% 0.188 70.08);\n --color-amber-600: oklch(66.6% 0.179 58.318);\n --color-amber-700: oklch(55.5% 0.163 48.998);\n --color-amber-800: oklch(47.3% 0.137 46.201);\n --color-amber-900: oklch(41.4% 0.112 45.904);\n --color-amber-950: oklch(27.9% 0.077 45.635);\n\n --color-yellow-50: oklch(98.7% 0.026 102.212);\n --color-yellow-100: oklch(97.3% 0.071 103.193);\n --color-yellow-200: oklch(94.5% 0.129 101.54);\n --color-yellow-300: oklch(90.5% 0.182 98.111);\n --color-yellow-400: oklch(85.2% 0.199 91.936);\n --color-yellow-500: oklch(79.5% 0.184 86.047);\n --color-yellow-600: oklch(68.1% 0.162 75.834);\n --color-yellow-700: oklch(55.4% 0.135 66.442);\n --color-yellow-800: oklch(47.6% 0.114 61.907);\n --color-yellow-900: oklch(42.1% 0.095 57.708);\n --color-yellow-950: oklch(28.6% 0.066 53.813);\n\n --color-lime-50: oklch(98.6% 0.031 120.757);\n --color-lime-100: oklch(96.7% 0.067 122.328);\n --color-lime-200: oklch(93.8% 0.127 124.321);\n --color-lime-300: oklch(89.7% 0.196 126.665);\n --color-lime-400: oklch(84.1% 0.238 128.85);\n --color-lime-500: oklch(76.8% 0.233 130.85);\n --color-lime-600: oklch(64.8% 0.2 131.684);\n --color-lime-700: oklch(53.2% 0.157 131.589);\n --color-lime-800: oklch(45.3% 0.124 130.933);\n --color-lime-900: oklch(40.5% 0.101 131.063);\n --color-lime-950: oklch(27.4% 0.072 132.109);\n\n --color-green-50: oklch(98.2% 0.018 155.826);\n --color-green-100: oklch(96.2% 0.044 156.743);\n --color-green-200: oklch(92.5% 0.084 155.995);\n --color-green-300: oklch(87.1% 0.15 154.449);\n --color-green-400: oklch(79.2% 0.209 151.711);\n --color-green-500: oklch(72.3% 0.219 149.579);\n --color-green-600: oklch(62.7% 0.194 149.214);\n --color-green-700: oklch(52.7% 0.154 150.069);\n --color-green-800: oklch(44.8% 0.119 151.328);\n --color-green-900: oklch(39.3% 0.095 152.535);\n --color-green-950: oklch(26.6% 0.065 152.934);\n\n --color-emerald-50: oklch(97.9% 0.021 166.113);\n --color-emerald-100: oklch(95% 0.052 163.051);\n --color-emerald-200: oklch(90.5% 0.093 164.15);\n --color-emerald-300: oklch(84.5% 0.143 164.978);\n --color-emerald-400: oklch(76.5% 0.177 163.223);\n --color-emerald-500: oklch(69.6% 0.17 162.48);\n --color-emerald-600: oklch(59.6% 0.145 163.225);\n --color-emerald-700: oklch(50.8% 0.118 165.612);\n --color-emerald-800: oklch(43.2% 0.095 166.913);\n --color-emerald-900: oklch(37.8% 0.077 168.94);\n --color-emerald-950: oklch(26.2% 0.051 172.552);\n\n --color-teal-50: oklch(98.4% 0.014 180.72);\n --color-teal-100: oklch(95.3% 0.051 180.801);\n --color-teal-200: oklch(91% 0.096 180.426);\n --color-teal-300: oklch(85.5% 0.138 181.071);\n --color-teal-400: oklch(77.7% 0.152 181.912);\n --color-teal-500: oklch(70.4% 0.14 182.503);\n --color-teal-600: oklch(60% 0.118 184.704);\n --color-teal-700: oklch(51.1% 0.096 186.391);\n --color-teal-800: oklch(43.7% 0.078 188.216);\n --color-teal-900: oklch(38.6% 0.063 188.416);\n --color-teal-950: oklch(27.7% 0.046 192.524);\n\n --color-cyan-50: oklch(98.4% 0.019 200.873);\n --color-cyan-100: oklch(95.6% 0.045 203.388);\n --color-cyan-200: oklch(91.7% 0.08 205.041);\n --color-cyan-300: oklch(86.5% 0.127 207.078);\n --color-cyan-400: oklch(78.9% 0.154 211.53);\n --color-cyan-500: oklch(71.5% 0.143 215.221);\n --color-cyan-600: oklch(60.9% 0.126 221.723);\n --color-cyan-700: oklch(52% 0.105 223.128);\n --color-cyan-800: oklch(45% 0.085 224.283);\n --color-cyan-900: oklch(39.8% 0.07 227.392);\n --color-cyan-950: oklch(30.2% 0.056 229.695);\n\n --color-sky-50: oklch(97.7% 0.013 236.62);\n --color-sky-100: oklch(95.1% 0.026 236.824);\n --color-sky-200: oklch(90.1% 0.058 230.902);\n --color-sky-300: oklch(82.8% 0.111 230.318);\n --color-sky-400: oklch(74.6% 0.16 232.661);\n --color-sky-500: oklch(68.5% 0.169 237.323);\n --color-sky-600: oklch(58.8% 0.158 241.966);\n --color-sky-700: oklch(50% 0.134 242.749);\n --color-sky-800: oklch(44.3% 0.11 240.79);\n --color-sky-900: oklch(39.1% 0.09 240.876);\n --color-sky-950: oklch(29.3% 0.066 243.157);\n\n --color-blue-50: oklch(97% 0.014 254.604);\n --color-blue-100: oklch(93.2% 0.032 255.585);\n --color-blue-200: oklch(88.2% 0.059 254.128);\n --color-blue-300: oklch(80.9% 0.105 251.813);\n --color-blue-400: oklch(70.7% 0.165 254.624);\n --color-blue-500: oklch(62.3% 0.214 259.815);\n --color-blue-600: oklch(54.6% 0.245 262.881);\n --color-blue-700: oklch(48.8% 0.243 264.376);\n --color-blue-800: oklch(42.4% 0.199 265.638);\n --color-blue-900: oklch(37.9% 0.146 265.522);\n --color-blue-950: oklch(28.2% 0.091 267.935);\n\n --color-indigo-50: oklch(96.2% 0.018 272.314);\n --color-indigo-100: oklch(93% 0.034 272.788);\n --color-indigo-200: oklch(87% 0.065 274.039);\n --color-indigo-300: oklch(78.5% 0.115 274.713);\n --color-indigo-400: oklch(67.3% 0.182 276.935);\n --color-indigo-500: oklch(58.5% 0.233 277.117);\n --color-indigo-600: oklch(51.1% 0.262 276.966);\n --color-indigo-700: oklch(45.7% 0.24 277.023);\n --color-indigo-800: oklch(39.8% 0.195 277.366);\n --color-indigo-900: oklch(35.9% 0.144 278.697);\n --color-indigo-950: oklch(25.7% 0.09 281.288);\n\n --color-violet-50: oklch(96.9% 0.016 293.756);\n --color-violet-100: oklch(94.3% 0.029 294.588);\n --color-violet-200: oklch(89.4% 0.057 293.283);\n --color-violet-300: oklch(81.1% 0.111 293.571);\n --color-violet-400: oklch(70.2% 0.183 293.541);\n --color-violet-500: oklch(60.6% 0.25 292.717);\n --color-violet-600: oklch(54.1% 0.281 293.009);\n --color-violet-700: oklch(49.1% 0.27 292.581);\n --color-violet-800: oklch(43.2% 0.232 292.759);\n --color-violet-900: oklch(38% 0.189 293.745);\n --color-violet-950: oklch(28.3% 0.141 291.089);\n\n --color-purple-50: oklch(97.7% 0.014 308.299);\n --color-purple-100: oklch(94.6% 0.033 307.174);\n --color-purple-200: oklch(90.2% 0.063 306.703);\n --color-purple-300: oklch(82.7% 0.119 306.383);\n --color-purple-400: oklch(71.4% 0.203 305.504);\n --color-purple-500: oklch(62.7% 0.265 303.9);\n --color-purple-600: oklch(55.8% 0.288 302.321);\n --color-purple-700: oklch(49.6% 0.265 301.924);\n --color-purple-800: oklch(43.8% 0.218 303.724);\n --color-purple-900: oklch(38.1% 0.176 304.987);\n --color-purple-950: oklch(29.1% 0.149 302.717);\n\n --color-fuchsia-50: oklch(97.7% 0.017 320.058);\n --color-fuchsia-100: oklch(95.2% 0.037 318.852);\n --color-fuchsia-200: oklch(90.3% 0.076 319.62);\n --color-fuchsia-300: oklch(83.3% 0.145 321.434);\n --color-fuchsia-400: oklch(74% 0.238 322.16);\n --color-fuchsia-500: oklch(66.7% 0.295 322.15);\n --color-fuchsia-600: oklch(59.1% 0.293 322.896);\n --color-fuchsia-700: oklch(51.8% 0.253 323.949);\n --color-fuchsia-800: oklch(45.2% 0.211 324.591);\n --color-fuchsia-900: oklch(40.1% 0.17 325.612);\n --color-fuchsia-950: oklch(29.3% 0.136 325.661);\n\n --color-pink-50: oklch(97.1% 0.014 343.198);\n --color-pink-100: oklch(94.8% 0.028 342.258);\n --color-pink-200: oklch(89.9% 0.061 343.231);\n --color-pink-300: oklch(82.3% 0.12 346.018);\n --color-pink-400: oklch(71.8% 0.202 349.761);\n --color-pink-500: oklch(65.6% 0.241 354.308);\n --color-pink-600: oklch(59.2% 0.249 0.584);\n --color-pink-700: oklch(52.5% 0.223 3.958);\n --color-pink-800: oklch(45.9% 0.187 3.815);\n --color-pink-900: oklch(40.8% 0.153 2.432);\n --color-pink-950: oklch(28.4% 0.109 3.907);\n\n --color-rose-50: oklch(96.9% 0.015 12.422);\n --color-rose-100: oklch(94.1% 0.03 12.58);\n --color-rose-200: oklch(89.2% 0.058 10.001);\n --color-rose-300: oklch(81% 0.117 11.638);\n --color-rose-400: oklch(71.2% 0.194 13.428);\n --color-rose-500: oklch(64.5% 0.246 16.439);\n --color-rose-600: oklch(58.6% 0.253 17.585);\n --color-rose-700: oklch(51.4% 0.222 16.935);\n --color-rose-800: oklch(45.5% 0.188 13.697);\n --color-rose-900: oklch(41% 0.159 10.272);\n --color-rose-950: oklch(27.1% 0.105 12.094);\n\n --color-slate-50: oklch(98.4% 0.003 247.858);\n --color-slate-100: oklch(96.8% 0.007 247.896);\n --color-slate-200: oklch(92.9% 0.013 255.508);\n --color-slate-300: oklch(86.9% 0.022 252.894);\n --color-slate-400: oklch(70.4% 0.04 256.788);\n --color-slate-500: oklch(55.4% 0.046 257.417);\n --color-slate-600: oklch(44.6% 0.043 257.281);\n --color-slate-700: oklch(37.2% 0.044 257.287);\n --color-slate-800: oklch(27.9% 0.041 260.031);\n --color-slate-900: oklch(20.8% 0.042 265.755);\n --color-slate-950: oklch(12.9% 0.042 264.695);\n\n --color-gray-50: oklch(98.5% 0.002 247.839);\n --color-gray-100: oklch(96.7% 0.003 264.542);\n --color-gray-200: oklch(92.8% 0.006 264.531);\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-500: oklch(55.1% 0.027 264.364);\n --color-gray-600: oklch(44.6% 0.03 256.802);\n --color-gray-700: oklch(37.3% 0.034 259.733);\n --color-gray-800: oklch(27.8% 0.033 256.848);\n --color-gray-900: oklch(21% 0.034 264.665);\n --color-gray-950: oklch(13% 0.028 261.692);\n\n --color-zinc-50: oklch(98.5% 0 0);\n --color-zinc-100: oklch(96.7% 0.001 286.375);\n --color-zinc-200: oklch(92% 0.004 286.32);\n --color-zinc-300: oklch(87.1% 0.006 286.286);\n --color-zinc-400: oklch(70.5% 0.015 286.067);\n --color-zinc-500: oklch(55.2% 0.016 285.938);\n --color-zinc-600: oklch(44.2% 0.017 285.786);\n --color-zinc-700: oklch(37% 0.013 285.805);\n --color-zinc-800: oklch(27.4% 0.006 286.033);\n --color-zinc-900: oklch(21% 0.006 285.885);\n --color-zinc-950: oklch(14.1% 0.005 285.823);\n\n --color-neutral-50: oklch(98.5% 0 0);\n --color-neutral-100: oklch(97% 0 0);\n --color-neutral-200: oklch(92.2% 0 0);\n --color-neutral-300: oklch(87% 0 0);\n --color-neutral-400: oklch(70.8% 0 0);\n --color-neutral-500: oklch(55.6% 0 0);\n --color-neutral-600: oklch(43.9% 0 0);\n --color-neutral-700: oklch(37.1% 0 0);\n --color-neutral-800: oklch(26.9% 0 0);\n --color-neutral-900: oklch(20.5% 0 0);\n --color-neutral-950: oklch(14.5% 0 0);\n\n --color-stone-50: oklch(98.5% 0.001 106.423);\n --color-stone-100: oklch(97% 0.001 106.424);\n --color-stone-200: oklch(92.3% 0.003 48.717);\n --color-stone-300: oklch(86.9% 0.005 56.366);\n --color-stone-400: oklch(70.9% 0.01 56.259);\n --color-stone-500: oklch(55.3% 0.013 58.071);\n --color-stone-600: oklch(44.4% 0.011 73.639);\n --color-stone-700: oklch(37.4% 0.01 67.558);\n --color-stone-800: oklch(26.8% 0.007 34.298);\n --color-stone-900: oklch(21.6% 0.006 56.043);\n --color-stone-950: oklch(14.7% 0.004 49.25);\n\n --color-black: #000;\n --color-white: #fff;\n\n --spacing: 0.25rem;\n\n --breakpoint-sm: 40rem;\n --breakpoint-md: 48rem;\n --breakpoint-lg: 64rem;\n --breakpoint-xl: 80rem;\n --breakpoint-2xl: 96rem;\n\n --container-3xs: 16rem;\n --container-2xs: 18rem;\n --container-xs: 20rem;\n --container-sm: 24rem;\n --container-md: 28rem;\n --container-lg: 32rem;\n --container-xl: 36rem;\n --container-2xl: 42rem;\n --container-3xl: 48rem;\n --container-4xl: 56rem;\n --container-5xl: 64rem;\n --container-6xl: 72rem;\n --container-7xl: 80rem;\n\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --text-3xl: 1.875rem;\n --text-3xl--line-height: calc(2.25 / 1.875);\n --text-4xl: 2.25rem;\n --text-4xl--line-height: calc(2.5 / 2.25);\n --text-5xl: 3rem;\n --text-5xl--line-height: 1;\n --text-6xl: 3.75rem;\n --text-6xl--line-height: 1;\n --text-7xl: 4.5rem;\n --text-7xl--line-height: 1;\n --text-8xl: 6rem;\n --text-8xl--line-height: 1;\n --text-9xl: 8rem;\n --text-9xl--line-height: 1;\n\n --font-weight-thin: 100;\n --font-weight-extralight: 200;\n --font-weight-light: 300;\n --font-weight-normal: 400;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --font-weight-extrabold: 800;\n --font-weight-black: 900;\n\n --tracking-tighter: -0.05em;\n --tracking-tight: -0.025em;\n --tracking-normal: 0em;\n --tracking-wide: 0.025em;\n --tracking-wider: 0.05em;\n --tracking-widest: 0.1em;\n\n --leading-tight: 1.25;\n --leading-snug: 1.375;\n --leading-normal: 1.5;\n --leading-relaxed: 1.625;\n --leading-loose: 2;\n\n --radius-xs: 0.125rem;\n --radius-sm: 0.25rem;\n --radius-md: 0.375rem;\n --radius-lg: 0.5rem;\n --radius-xl: 0.75rem;\n --radius-2xl: 1rem;\n --radius-3xl: 1.5rem;\n --radius-4xl: 2rem;\n\n --shadow-2xs: 0 1px rgb(0 0 0 / 0.05);\n --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n\n --inset-shadow-2xs: inset 0 1px rgb(0 0 0 / 0.05);\n --inset-shadow-xs: inset 0 1px 1px rgb(0 0 0 / 0.05);\n --inset-shadow-sm: inset 0 2px 4px rgb(0 0 0 / 0.05);\n\n --drop-shadow-xs: 0 1px 1px rgb(0 0 0 / 0.05);\n --drop-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.15);\n --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12);\n --drop-shadow-lg: 0 4px 4px rgb(0 0 0 / 0.15);\n --drop-shadow-xl: 0 9px 7px rgb(0 0 0 / 0.1);\n --drop-shadow-2xl: 0 25px 25px rgb(0 0 0 / 0.15);\n\n --text-shadow-2xs: 0px 1px 0px rgb(0 0 0 / 0.15);\n --text-shadow-xs: 0px 1px 1px rgb(0 0 0 / 0.2);\n --text-shadow-sm:\n 0px 1px 0px rgb(0 0 0 / 0.075), 0px 1px 1px rgb(0 0 0 / 0.075), 0px 2px 2px rgb(0 0 0 / 0.075);\n --text-shadow-md:\n 0px 1px 1px rgb(0 0 0 / 0.1), 0px 1px 2px rgb(0 0 0 / 0.1), 0px 2px 4px rgb(0 0 0 / 0.1);\n --text-shadow-lg:\n 0px 1px 2px rgb(0 0 0 / 0.1), 0px 3px 2px rgb(0 0 0 / 0.1), 0px 4px 8px rgb(0 0 0 / 0.1);\n\n --ease-in: cubic-bezier(0.4, 0, 1, 1);\n --ease-out: cubic-bezier(0, 0, 0.2, 1);\n --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);\n\n --animate-spin: spin 1s linear infinite;\n --animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;\n --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n --animate-bounce: bounce 1s infinite;\n\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n @keyframes ping {\n 75%,\n 100% {\n transform: scale(2);\n opacity: 0;\n }\n }\n\n @keyframes pulse {\n 50% {\n opacity: 0.5;\n }\n }\n\n @keyframes bounce {\n 0%,\n 100% {\n transform: translateY(-25%);\n animation-timing-function: cubic-bezier(0.8, 0, 1, 1);\n }\n\n 50% {\n transform: none;\n animation-timing-function: cubic-bezier(0, 0, 0.2, 1);\n }\n }\n\n --blur-xs: 4px;\n --blur-sm: 8px;\n --blur-md: 12px;\n --blur-lg: 16px;\n --blur-xl: 24px;\n --blur-2xl: 40px;\n --blur-3xl: 64px;\n\n --perspective-dramatic: 100px;\n --perspective-near: 300px;\n --perspective-normal: 500px;\n --perspective-midrange: 800px;\n --perspective-distant: 1200px;\n\n --aspect-video: 16 / 9;\n\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: --theme(--font-sans, initial);\n --default-font-feature-settings: --theme(--font-sans--font-feature-settings, initial);\n --default-font-variation-settings: --theme(--font-sans--font-variation-settings, initial);\n --default-mono-font-family: --theme(--font-mono, initial);\n --default-mono-font-feature-settings: --theme(--font-mono--font-feature-settings, initial);\n --default-mono-font-variation-settings: --theme(--font-mono--font-variation-settings, initial);\n}\n\n/* Deprecated */\n@theme default inline reference {\n --blur: 8px;\n --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);\n --drop-shadow: 0 1px 2px rgb(0 0 0 / 0.1), 0 1px 1px rgb(0 0 0 / 0.06);\n --radius: 0.25rem;\n --max-width-prose: 65ch;\n}\n",utilities:"@tailwind utilities;\n"};console.warn("The browser build of Tailwind CSS should not be used in production. To use Tailwind CSS in production, use the Tailwind CLI, Vite plugin, or PostCSS plugin: https://tailwindcss.com/docs/installation");var er,tr="text/tailwindcss",rr=new Set,nr="",or=document.createElement("style"),ar=Promise.resolve(),ir=1,lr=new class{start(e1){performance.mark(`${e1} (start)`);}end(e1,t){performance.mark(`${e1} (end)`),performance.measure(e1,{start:`${e1} (start)`,end:`${e1} (end)`,detail:t});}hit(e1,t){performance.mark(e1,{detail:t});}error(e1){throw performance.mark("(error)",{detail:{error:`${e1}`}}),e1;}};async function sr(e1,t){try{let r=function(){if("tailwindcss"===e1)return{base:t,content:Qt.index};if("tailwindcss/preflight"===e1||"tailwindcss/preflight.css"===e1||"./preflight.css"===e1)return{base:t,content:Qt.preflight};if("tailwindcss/theme"===e1||"tailwindcss/theme.css"===e1||"./theme.css"===e1)return{base:t,content:Qt.theme};if("tailwindcss/utilities"===e1||"tailwindcss/utilities.css"===e1||"./utilities.css"===e1)return{base:t,content:Qt.utilities};throw new Error(`The browser build does not support @import for "${e1}"`);}();return lr.hit("Loaded stylesheet",{id:e1,base:t,size:r.content.length}),r;}catch(r){throw lr.hit("Failed to load stylesheet",{id:e1,base:t,error:r.message??r}),r;}}async function cr(){throw new Error("The browser build does not support plugins or config files.");}function ur(e1){ar=ar.then(async function(){if(!er&&"full"!==e1)return;let t=ir++;lr.start(`Build #${t} (${e1})`),"full"===e1&&await async function(){lr.start("Create compiler"),lr.start("Reading Stylesheets");let e1=document.querySelectorAll(`style[type="${tr}"]`),t="";for(let r of e1)fr(r),t+=r.textContent+"\n";if(t.includes("@import")||(t=`@import "tailwindcss";${t}`),lr.end("Reading Stylesheets",{size:t.length,changed:nr!==t}),nr!==t){nr=t,lr.start("Compile CSS");try{er=await Jt(t,{base:"/",loadStylesheet:sr,loadModule:cr});}finally{lr.end("Compile CSS"),lr.end("Create compiler");}rr.clear();}}(),lr.start("Build"),await async function(e1){if(!er)return;let t=new Set;lr.start("Collect classes");for(let e1 of document.querySelectorAll("[class]"))for(let r of e1.classList)rr.has(r)||(rr.add(r),t.add(r));lr.end("Collect classes",{count:t.size}),(0!==t.size||"incremental"!==e1)&&(lr.start("Build utilities"),or.textContent=er.build(Array.from(t)),lr.end("Build utilities"));}(e1),lr.end("Build"),lr.end(`Build #${t} (${e1})`);}).catch(e1=>lr.error(e1));}var dr=new MutationObserver(()=>ur("full"));function fr(e1){dr.observe(e1,{attributes:!0,attributeFilter:["type"],characterData:!0,subtree:!0,childList:!0});}new MutationObserver(e1=>{let t=0,r=0;for(let n of e1){for(let e1 of n.addedNodes)e1.nodeType===Node.ELEMENT_NODE&&"STYLE"===e1.tagName&&e1.getAttribute("type")===tr&&(fr(e1),t++);for(let e1 of n.addedNodes)1===e1.nodeType&&e1!==or&&r++;"attributes"===n.type&&r++;}return t>0?ur("full"):r>0?ur("incremental"):void 0;}).observe(document.documentElement,{attributes:!0,attributeFilter:["class"],childList:!0,subtree:!0}),ur("full"),document.head.append(or);})(); \ No newline at end of file diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/tailwind.js.br b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/tailwind.js.br deleted file mode 100644 index 3fcb990c..00000000 Binary files a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/assets/tailwind.js.br and /dev/null differ diff --git a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/index.html b/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/index.html deleted file mode 100644 index 850f6d79..00000000 --- a/services/core/blueprint/web-client/target/dx/blueprint-pwa/release/web/public/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - {blueprint} - - - - - - - - - - -
- - - - - diff --git a/services/core/catalyst/broker/atomicMap.go b/services/core/catalyst/broker/atomicMap.go index 34aaf456..8294c99c 100644 --- a/services/core/catalyst/broker/atomicMap.go +++ b/services/core/catalyst/broker/atomicMap.go @@ -1,6 +1,7 @@ package broker import ( + "context" "encoding/base64" "sync" @@ -15,14 +16,17 @@ type ( m map[string][]*connect.ServerStream[acv1.ConsumeResponse] // yield the client connection to a thread, and then send events to it n map[string]chan *acv1.CloudEvent + // registrations maps event_type → []consumer_source_names for topology tracking + registrations map[string][]string } ) func newAtomicMap() *atomicMap { return &atomicMap{ - mu: sync.RWMutex{}, - m: make(map[string][]*connect.ServerStream[acv1.ConsumeResponse]), - n: make(map[string]chan *acv1.CloudEvent), + mu: sync.RWMutex{}, + m: make(map[string][]*connect.ServerStream[acv1.ConsumeResponse]), + n: make(map[string]chan *acv1.CloudEvent), + registrations: make(map[string][]string), } } @@ -33,24 +37,12 @@ func (am *atomicMap) hash(msgKindName string) string { } func (am *atomicMap) Insert(key string, resStream *connect.ServerStream[acv1.ConsumeResponse]) { - // TODO: Figure out how to start with a read lock? - am.mu.RLock() - defer am.mu.RUnlock() - list, ok := am.m[key] - if !ok { - am.mu.RUnlock() - am.mu.Lock() - defer am.mu.Unlock() - var list []*connect.ServerStream[acv1.ConsumeResponse] - list = append(list, resStream) - am.m[key] = list - } else { - list = append(list, resStream) - am.m[key] = list - } + am.mu.Lock() + defer am.mu.Unlock() + am.m[key] = append(am.m[key], resStream) } -func (am *atomicMap) Broker(key string, resStream *connect.ServerStream[acv1.ConsumeResponse]) { +func (am *atomicMap) Broker(ctx context.Context, key string, resStream *connect.ServerStream[acv1.ConsumeResponse]) { am.mu.RLock() ch, found := am.n[key] if !found { @@ -62,36 +54,93 @@ func (am *atomicMap) Broker(key string, resStream *connect.ServerStream[acv1.Con am.n[key] = ch am.mu.Unlock() // now start a new routine and keep it open as long as the `ch` channel has connected clients - go am.send(ch, resStream) + go am.send(ctx, ch, resStream) return } else { // the channel is already made and shared with other consumers, and producers so we can just use `ch` - go am.send(ch, resStream) + go am.send(ctx, ch, resStream) am.mu.RUnlock() } } -func (am *atomicMap) send(ch chan *acv1.CloudEvent, stream *connect.ServerStream[acv1.ConsumeResponse]) { - // when the channel receives a message send to the stream the client is holding onto +func (am *atomicMap) send(ctx context.Context, ch chan *acv1.CloudEvent, stream *connect.ServerStream[acv1.ConsumeResponse]) { for { - m := <-ch - msg := &acv1.ConsumeResponse{ - Message: m, + select { + case <-ctx.Done(): + return + case m := <-ch: + if err := stream.Send(&acv1.ConsumeResponse{Message: m}); err != nil { + return + } } - stream.Send(msg) } } func (am *atomicMap) Broadcast(key string, msg *acv1.CloudEvent) { + am.mu.RLock() ch, ok := am.n[key] + am.mu.RUnlock() if ok { ch <- msg - } else { - // we don't have any consumers that will listen to the message so as of right now - // the message is not worth sending + } + // No consumers registered for this key — drop silently. + // TODO: consider a dead-letter queue. +} - // TODO: We might consider a dead letter queue - return +// AddRegistration records that source is subscribed to eventType. +// Duplicate entries for the same (eventType, source) pair are ignored. +func (am *atomicMap) AddRegistration(eventType, source string) { + am.mu.Lock() + defer am.mu.Unlock() + for _, s := range am.registrations[eventType] { + if s == source { + return + } + } + am.registrations[eventType] = append(am.registrations[eventType], source) +} + +// RemoveRegistration removes source from the subscriber list for eventType. +func (am *atomicMap) RemoveRegistration(eventType, source string) { + am.mu.Lock() + defer am.mu.Unlock() + list := am.registrations[eventType] + for i, s := range list { + if s == source { + updated := append(list[:i], list[i+1:]...) + if len(updated) == 0 { + delete(am.registrations, eventType) + } else { + am.registrations[eventType] = updated + } + return + } + } +} + +// ConsumerCount returns the number of distinct consumer sources currently registered. +func (am *atomicMap) ConsumerCount() int { + am.mu.RLock() + defer am.mu.RUnlock() + seen := make(map[string]bool) + for _, srcs := range am.registrations { + for _, s := range srcs { + seen[s] = true + } + } + return len(seen) +} + +// Registrations returns a snapshot copy of the full event_type → consumers map. +func (am *atomicMap) Registrations() map[string][]string { + am.mu.RLock() + defer am.mu.RUnlock() + out := make(map[string][]string, len(am.registrations)) + for k, v := range am.registrations { + cp := make([]string, len(v)) + copy(cp, v) + out[k] = cp } + return out } diff --git a/services/core/catalyst/broker/consumer.go b/services/core/catalyst/broker/consumer.go index 63aa082c..b89066ca 100644 --- a/services/core/catalyst/broker/consumer.go +++ b/services/core/catalyst/broker/consumer.go @@ -27,7 +27,8 @@ func NewConsumer(consumerRegistrationChan chan register) Consumer { func (c *consumer) Consume(ctx context.Context, msg *acv1.CloudEvent, stream *connect.ServerStream[acv1.ConsumeResponse]) error { // fling the consumer stream into the controller c.consumerRegistrationChan <- register{ - CloudEvent: msg, + ctx: ctx, + CloudEvent: msg, ServerStream: stream, } diff --git a/services/core/catalyst/broker/controller.go b/services/core/catalyst/broker/controller.go index f2e8d502..5ba483a5 100644 --- a/services/core/catalyst/broker/controller.go +++ b/services/core/catalyst/broker/controller.go @@ -1,108 +1,359 @@ package broker import ( + "context" + "sort" + "sync" + "sync/atomic" + "time" + "connectrpc.com/connect" acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" "github.com/steady-bytes/draft/pkg/chassis" + "google.golang.org/protobuf/types/known/timestamppb" ) type ( Controller interface { Consumer Producer + Query(ctx context.Context, req *acv1.QueryRequest) ([]*acv1.CloudEvent, error) + QueryStream(ctx context.Context, req *acv1.QueryRequest, stream *connect.ServerStream[acv1.QueryStreamResponse]) error + GetTopology(ctx context.Context) (*acv1.GetTopologyResponse, error) + WatchTopology(ctx context.Context, stream *connect.ServerStream[acv1.WatchTopologyResponse]) error + GetMetrics(ctx context.Context, windowSecs int32) (*acv1.GetMetricsResponse, error) + GetResourceMetrics(ctx context.Context) (*acv1.GetResourceMetricsResponse, error) + GetTopicSeries(ctx context.Context, eventType string, windowSecs int32) (*acv1.GetTopicSeriesResponse, error) } controller struct { Producer Consumer - logger chassis.Logger - - state *atomicMap + logger chassis.Logger + state *atomicMap + storer Storer + observers *observerRegistry + topology *topologyRegistry + publishedTotal atomic.Uint64 } register struct { + ctx context.Context *acv1.CloudEvent *connect.ServerStream[acv1.ConsumeResponse] } + + // observerRegistry manages live-event channels for QueryStream subscribers. + observerRegistry struct { + mu sync.RWMutex + subs map[uint64]chan *acv1.CloudEvent + counter uint64 + } ) -func NewController(logger chassis.Logger) Controller { +func NewController(logger chassis.Logger, storer Storer) Controller { var ( producerMsgChan = make(chan *acv1.CloudEvent) consumerRegistrationChan = make(chan register) ) ctr := &controller{ - NewProducer(producerMsgChan), - NewConsumer(consumerRegistrationChan), - logger, - newAtomicMap(), + Producer: NewProducer(producerMsgChan), + Consumer: NewConsumer(consumerRegistrationChan), + logger: logger, + state: newAtomicMap(), + storer: storer, + observers: newObserverRegistry(), + topology: newTopologyRegistry(), } - // TODO: This could contain more configuration. Like maybe reading the number - // of cpu cores to spread the works over? - go ctr.produce(producerMsgChan) go ctr.consume(consumerRegistrationChan) return ctr } -const ( - LOG_KEY_TO_CH = "key to channel" -) +func newObserverRegistry() *observerRegistry { + return &observerRegistry{subs: make(map[uint64]chan *acv1.CloudEvent)} +} + +func (r *observerRegistry) subscribe() (uint64, chan *acv1.CloudEvent) { + ch := make(chan *acv1.CloudEvent, 64) + r.mu.Lock() + id := r.counter + r.counter++ + r.subs[id] = ch + r.mu.Unlock() + return id, ch +} + +func (r *observerRegistry) unsubscribe(id uint64) { + r.mu.Lock() + delete(r.subs, id) + r.mu.Unlock() +} + +// broadcast sends event to every active QueryStream subscriber. Slow consumers +// are skipped rather than blocking the producer goroutine. +func (r *observerRegistry) broadcast(event *acv1.CloudEvent) { + r.mu.RLock() + defer r.mu.RUnlock() + for _, ch := range r.subs { + select { + case ch <- event: + default: + } + } +} + func (c *controller) produce(producerMsgChan chan *acv1.CloudEvent) { for { msg := <-producerMsgChan - c.logger.WithField("msg: ", msg).Info("produce massage received") - - // make hash of - key := c.state.hash(string(msg.ProtoReflect().Descriptor().FullName())) + receivedAt := time.Now() - // do I save to blueprint? - // - default config is to be durable - // - the producer can also add configuration to say not to store + // Stamp forwarded_at before broadcasting so live QueryStream subscribers + // receive the attribute alongside the event payload. + forwardedAt := time.Now() + if msg.Attributes == nil { + msg.Attributes = make(map[string]*acv1.CloudEvent_CloudEventAttributeValue) + } + msg.Attributes["forwarded_at"] = &acv1.CloudEvent_CloudEventAttributeValue{ + Attr: &acv1.CloudEvent_CloudEventAttributeValue_CeTimestamp{ + CeTimestamp: timestamppb.New(forwardedAt), + }, + } - // send the received `Message` to all `Consumers` for the same key - c.logger.WithField("key", key).Info(LOG_KEY_TO_CH) + c.publishedTotal.Add(1) + key := c.state.hash(string(msg.ProtoReflect().Descriptor().FullName())) c.state.Broadcast(key, msg) + c.observers.broadcast(msg) + c.topology.ObserveProducer(msg.GetSource()) + + if err := c.storer.Save(context.Background(), msg, receivedAt, forwardedAt); err != nil { + c.logger.WithField("error", err.Error()).Error("failed to persist event") + } } } -// consume - Will create a hash of the message domain, and typeUrl then save the msg.ServerStream to `atomicMap.m` -// that can be used to `Broadcast` messages to when a message is produced. Con's to this approach are a `RWMutex` -// has to be used to `Broadcast` the message so the connected stream. -// func (c *controller) consume(reg chan register) { -// for { -// msg := <-reg -// fmt.Print("Receive a request to setup a consumer", msg) - -// // make hash of -// key := c.hash(msg.GetDomain(), msg.GetKind().GetTypeUrl()) - -// // use hash as key if the hash does not exist, then create a slice of connections -// // and append the connection to the slice -// c.state.Insert(key, msg.ServerStream) -// } -// } - -// consume - Will create a hash of the message domain, and typeUrl to use as a key to a tx, and rx sides of a channel -// the `tx` or transmitter will be used when a producer produces an event to send the event to each client that is consuming -// events of the domain, and typeUrl. func (c *controller) consume(registerChan chan register) { for { - // create a shared channel that will receive any kind of message of that domain, and typeUrl - // add the receiver to a go routine that will keep the `ServerStream` open and send any messages - // received up to the client connect. - msg := <-registerChan - c.logger.WithField("msg", msg).Info("consume channel registration") + reg := <-registerChan - key := c.state.hash(string(msg.ProtoReflect().Descriptor().FullName())) + key := c.state.hash(string(reg.ProtoReflect().Descriptor().FullName())) + c.state.Broker(reg.ctx, key, reg.ServerStream) + + // Track consumer identity declared via ConsumeRequest.message.source/type. + // A cleanup goroutine removes the registration when the RPC context is cancelled + // (i.e. the client disconnects). + src := reg.GetSource() + typ := reg.GetType() + if src != "" && typ != "" { + c.state.AddRegistration(typ, src) + c.topology.NotifyConsumerConnected(src) + go func(ctx context.Context, src, typ string) { + <-ctx.Done() + c.state.RemoveRegistration(typ, src) + c.topology.NotifyConsumerDisconnected(src) + }(reg.ctx, src, typ) + } + } +} + +func (c *controller) Query(ctx context.Context, req *acv1.QueryRequest) ([]*acv1.CloudEvent, error) { + descending := req.GetOrderBy() == acv1.OrderDirection_ORDER_DIRECTION_DESC + candidates, err := c.storer.Query(ctx, req.GetLimit(), req.GetAfter(), descending) + if err != nil { + return nil, err + } + + expr := req.GetExpression() + if expr == nil { + return candidates, nil + } + + matched := make([]*acv1.CloudEvent, 0, len(candidates)) + for _, event := range candidates { + if ok, _ := matchesExpression(expr, event); ok { + matched = append(matched, event) + } + } + return matched, nil +} + +func (c *controller) QueryStream(ctx context.Context, req *acv1.QueryRequest, stream *connect.ServerStream[acv1.QueryStreamResponse]) error { + expr := req.GetExpression() + + // Phase 1: replay historical events from ClickHouse. + descending := req.GetOrderBy() == acv1.OrderDirection_ORDER_DIRECTION_DESC + historical, err := c.storer.Query(ctx, req.GetLimit(), req.GetAfter(), descending) + if err != nil { + return err + } + for _, event := range historical { + if ok, _ := matchesExpression(expr, event); ok { + if err := stream.Send(&acv1.QueryStreamResponse{Event: event}); err != nil { + return err + } + } + } + + // Phase 2: stream live events as they arrive. + id, ch := c.observers.subscribe() + defer c.observers.unsubscribe(id) + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case event := <-ch: + if ok, _ := matchesExpression(expr, event); ok { + if err := stream.Send(&acv1.QueryStreamResponse{Event: event}); err != nil { + return err + } + } + } + } +} + +func (c *controller) GetTopology(ctx context.Context) (*acv1.GetTopologyResponse, error) { + producers, sourcesByType, err := c.storer.QueryDistinctSources(ctx) + if err != nil { + return nil, err + } + + producerNodes := make([]*acv1.TopologyNode, len(producers)) + for i, src := range producers { + producerNodes[i] = &acv1.TopologyNode{Id: src, Name: src} + } + + regs := c.state.Registrations() + consumerSet := make(map[string]bool) + var edges []*acv1.TopologyEdge + + for eventType, consumers := range regs { + producerSrcs := sourcesByType[eventType] + for _, consumerSrc := range consumers { + consumerSet[consumerSrc] = true + for _, producerSrc := range producerSrcs { + edges = append(edges, &acv1.TopologyEdge{ + ProducerSource: producerSrc, + ConsumerSource: consumerSrc, + EventType: eventType, + }) + } + } + } + + // Enrich edges with per-minute vol counts from ClickHouse (60-second window). + vols, _ := c.storer.QueryVolumes(ctx, 60) + volIdx := make(map[string]map[string]uint32) + for _, v := range vols { + if volIdx[v.Source] == nil { + volIdx[v.Source] = make(map[string]uint32) + } + volIdx[v.Source][v.EventType] += v.Count + } + for _, e := range edges { + if byType, ok := volIdx[e.ProducerSource]; ok { + e.Vol = byType[e.EventType] + } + } + + consumerNodes := make([]*acv1.TopologyNode, 0, len(consumerSet)) + for src := range consumerSet { + consumerNodes = append(consumerNodes, &acv1.TopologyNode{Id: src, Name: src}) + } + sort.Slice(consumerNodes, func(i, j int) bool { + return consumerNodes[i].Id < consumerNodes[j].Id + }) + + return &acv1.GetTopologyResponse{ + Producers: producerNodes, + Consumers: consumerNodes, + Edges: edges, + }, nil +} + +func (c *controller) WatchTopology(ctx context.Context, stream *connect.ServerStream[acv1.WatchTopologyResponse]) error { + obs, cleanup := c.topology.subscribe() + defer cleanup() - // key := c.state.hash(msg.GetDomain(), msg.GetKind().GetTypeUrl()) - c.logger.WithField("key", key).Info(LOG_KEY_TO_CH) - c.state.Broker(key, msg.ServerStream) + for { + select { + case <-ctx.Done(): + return ctx.Err() + case resp := <-obs.ch: + if err := stream.Send(resp); err != nil { + return err + } + } + } +} + +func (c *controller) GetTopicSeries(ctx context.Context, eventType string, windowSecs int32) (*acv1.GetTopicSeriesResponse, error) { + pts, bucket, err := c.storer.QueryTopicSeries(ctx, eventType, windowSecs) + if err != nil { + return nil, err + } + protoPoints := make([]*acv1.SeriesPoint, len(pts)) + for i, p := range pts { + protoPoints[i] = &acv1.SeriesPoint{TimestampMs: p.TimestampMs, Count: p.Count} + } + return &acv1.GetTopicSeriesResponse{Points: protoPoints, BucketSecs: bucket}, nil +} + +func (c *controller) GetResourceMetrics(_ context.Context) (*acv1.GetResourceMetricsResponse, error) { + stats := c.storer.StoreStats() + return &acv1.GetResourceMetricsResponse{ + MessagesPublishedTotal: c.publishedTotal.Load(), + MessagesDroppedTotal: stats.DroppedTotal, + QueueDepth: stats.QueueDepth, + QueueCapacity: stats.QueueCapacity, + ActiveConsumers: uint32(c.state.ConsumerCount()), + ActiveProducers: uint32(c.topology.ProducerCount()), + StoreFlushP95Ms: stats.FlushP95Ms, + StoreFlushCount: stats.FlushCount, + }, nil +} + +func (c *controller) GetMetrics(ctx context.Context, windowSecs int32) (*acv1.GetMetricsResponse, error) { + volumes, err := c.storer.QueryVolumes(ctx, windowSecs) + if err != nil { + return nil, err + } + + latency, err := c.storer.QueryLatency(ctx, windowSecs) + if err != nil { + // Non-fatal: return what we have without latency. + latency = LatencyStats{} + } + + // Compute total messages/min from the volume counts. + var totalCount uint32 + for _, v := range volumes { + totalCount += v.Count } + windowMins := float64(windowSecs) / 60.0 + var msgsPerMin uint32 + if windowMins > 0 { + msgsPerMin = uint32(float64(totalCount) / windowMins) + } + + edgeVols := make([]*acv1.EdgeVolume, 0, len(volumes)) + for _, v := range volumes { + edgeVols = append(edgeVols, &acv1.EdgeVolume{ + Source: v.Source, + EventType: v.EventType, + Count: v.Count, + }) + } + + return &acv1.GetMetricsResponse{ + EdgeVolumes: edgeVols, + MedianLatencyMs: latency.MedianMs, + P95LatencyMs: latency.P95Ms, + TotalMessagesPerMin: msgsPerMin, + }, nil } diff --git a/services/core/catalyst/broker/evaluator.go b/services/core/catalyst/broker/evaluator.go new file mode 100644 index 00000000..cbf3a853 --- /dev/null +++ b/services/core/catalyst/broker/evaluator.go @@ -0,0 +1,529 @@ +package broker + +import ( + "encoding/base64" + "fmt" + "regexp" + "strconv" + "strings" + "time" + + acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" +) + +// ceKind represents one of the three CESQL primitive types. +type ceKind int + +const ( + kindString ceKind = iota + kindInt + kindBool +) + +// ceVal is a dynamically-typed CESQL value. +type ceVal struct { + kind ceKind + strVal string + intVal int32 + boolVal bool +} + +func sv(s string) ceVal { return ceVal{kind: kindString, strVal: s} } +func iv(i int32) ceVal { return ceVal{kind: kindInt, intVal: i} } +func bv(b bool) ceVal { return ceVal{kind: kindBool, boolVal: b} } + +// matchesExpression evaluates expr against event and returns true when the +// expression is satisfied. A nil expression matches every event. +func matchesExpression(expr *acv1.Expression, event *acv1.CloudEvent) (bool, error) { + if expr == nil { + return true, nil + } + val, err := eval(expr, event) + if err != nil { + return false, err + } + b, _ := toBool(val) + return b, nil +} + +func eval(expr *acv1.Expression, event *acv1.CloudEvent) (ceVal, error) { + if expr == nil { + return bv(false), nil + } + switch e := expr.GetExpr().(type) { + case *acv1.Expression_Literal: + return evalLiteral(e.Literal), nil + case *acv1.Expression_Attribute: + return evalAttribute(e.Attribute, event), nil + case *acv1.Expression_Unary: + return evalUnary(e.Unary, event) + case *acv1.Expression_Binary: + return evalBinary(e.Binary, event) + case *acv1.Expression_Like: + return evalLike(e.Like, event) + case *acv1.Expression_Exists: + return evalExists(e.Exists, event), nil + case *acv1.Expression_In: + return evalIn(e.In, event) + case *acv1.Expression_FunctionCall: + return evalFunction(e.FunctionCall, event) + default: + return bv(false), nil + } +} + +func evalLiteral(lit *acv1.Literal) ceVal { + switch v := lit.GetValue().(type) { + case *acv1.Literal_IntegerValue: + return iv(v.IntegerValue) + case *acv1.Literal_BoolValue: + return bv(v.BoolValue) + case *acv1.Literal_StringValue: + return sv(v.StringValue) + default: + return sv("") + } +} + +func evalAttribute(ref *acv1.AttributeRef, event *acv1.CloudEvent) ceVal { + switch ref.GetName() { + case "id": + return sv(event.GetId()) + case "source": + return sv(event.GetSource()) + case "specversion": + return sv(event.GetSpecVersion()) + case "type": + return sv(event.GetType()) + default: + attrs := event.GetAttributes() + if attrs == nil { + return sv("") + } + v, ok := attrs[ref.GetName()] + if !ok { + return sv("") + } + return ceAttrToVal(v) + } +} + +func ceAttrToVal(v *acv1.CloudEvent_CloudEventAttributeValue) ceVal { + switch a := v.GetAttr().(type) { + case *acv1.CloudEvent_CloudEventAttributeValue_CeBoolean: + return bv(a.CeBoolean) + case *acv1.CloudEvent_CloudEventAttributeValue_CeInteger: + return iv(a.CeInteger) + case *acv1.CloudEvent_CloudEventAttributeValue_CeString: + return sv(a.CeString) + case *acv1.CloudEvent_CloudEventAttributeValue_CeUri: + return sv(a.CeUri) + case *acv1.CloudEvent_CloudEventAttributeValue_CeUriRef: + return sv(a.CeUriRef) + case *acv1.CloudEvent_CloudEventAttributeValue_CeBytes: + return sv(base64.StdEncoding.EncodeToString(a.CeBytes)) + case *acv1.CloudEvent_CloudEventAttributeValue_CeTimestamp: + return sv(a.CeTimestamp.AsTime().Format(time.RFC3339Nano)) + default: + return sv("") + } +} + +func evalUnary(u *acv1.UnaryExpr, event *acv1.CloudEvent) (ceVal, error) { + operand, err := eval(u.GetOperand(), event) + if err != nil { + return bv(false), err + } + switch u.GetOp() { + case acv1.UnaryOp_UNARY_OP_NOT: + b, _ := toBool(operand) + return bv(!b), nil + case acv1.UnaryOp_UNARY_OP_NEGATE: + n, _ := toInt(operand) + return iv(-n), nil + default: + return bv(false), nil + } +} + +func evalBinary(b *acv1.BinaryExpr, event *acv1.CloudEvent) (ceVal, error) { + left, err := eval(b.GetLeft(), event) + if err != nil { + return bv(false), err + } + + // Short-circuit AND and OR before evaluating the right side. + switch b.GetOp() { + case acv1.BinaryOp_BINARY_OP_AND: + lb, _ := toBool(left) + if !lb { + return bv(false), nil + } + right, err := eval(b.GetRight(), event) + if err != nil { + return bv(false), err + } + rb, _ := toBool(right) + return bv(rb), nil + + case acv1.BinaryOp_BINARY_OP_OR: + lb, _ := toBool(left) + if lb { + return bv(true), nil + } + right, err := eval(b.GetRight(), event) + if err != nil { + return bv(false), err + } + rb, _ := toBool(right) + return bv(rb), nil + } + + right, err := eval(b.GetRight(), event) + if err != nil { + return bv(false), err + } + + switch b.GetOp() { + case acv1.BinaryOp_BINARY_OP_XOR: + lb, _ := toBool(left) + rb, _ := toBool(right) + return bv(lb != rb), nil + + case acv1.BinaryOp_BINARY_OP_EQ: + return bv(cevalsEqual(left, right)), nil + case acv1.BinaryOp_BINARY_OP_NEQ: + return bv(!cevalsEqual(left, right)), nil + + case acv1.BinaryOp_BINARY_OP_LT: + li, _ := toInt(left) + ri, _ := toInt(right) + return bv(li < ri), nil + case acv1.BinaryOp_BINARY_OP_LTE: + li, _ := toInt(left) + ri, _ := toInt(right) + return bv(li <= ri), nil + case acv1.BinaryOp_BINARY_OP_GT: + li, _ := toInt(left) + ri, _ := toInt(right) + return bv(li > ri), nil + case acv1.BinaryOp_BINARY_OP_GTE: + li, _ := toInt(left) + ri, _ := toInt(right) + return bv(li >= ri), nil + + case acv1.BinaryOp_BINARY_OP_ADD: + li, _ := toInt(left) + ri, _ := toInt(right) + return iv(li + ri), nil + case acv1.BinaryOp_BINARY_OP_SUB: + li, _ := toInt(left) + ri, _ := toInt(right) + return iv(li - ri), nil + case acv1.BinaryOp_BINARY_OP_MUL: + li, _ := toInt(left) + ri, _ := toInt(right) + return iv(li * ri), nil + case acv1.BinaryOp_BINARY_OP_DIV: + li, _ := toInt(left) + ri, _ := toInt(right) + if ri == 0 { + return iv(0), fmt.Errorf("division by zero") + } + return iv(li / ri), nil + case acv1.BinaryOp_BINARY_OP_MOD: + li, _ := toInt(left) + ri, _ := toInt(right) + if ri == 0 { + return iv(0), fmt.Errorf("modulo by zero") + } + return iv(li % ri), nil + + default: + return bv(false), nil + } +} + +func evalLike(l *acv1.LikeExpr, event *acv1.CloudEvent) (ceVal, error) { + operand, err := eval(l.GetOperand(), event) + if err != nil { + return bv(false), err + } + s, _ := toString(operand) + matched, err := likeMatch(l.GetPattern(), s) + if err != nil { + return bv(false), err + } + if l.GetNegated() { + return bv(!matched), nil + } + return bv(matched), nil +} + +// likeMatch converts a CESQL LIKE pattern to a regexp and tests s against it. +// % matches any sequence of characters, _ matches exactly one character, +// and \ escapes the next character literally. +func likeMatch(pattern, s string) (bool, error) { + var re strings.Builder + re.WriteString("(?s)^") + for i := 0; i < len(pattern); i++ { + c := pattern[i] + switch c { + case '\\': + if i+1 < len(pattern) { + i++ + re.WriteString(regexp.QuoteMeta(string(pattern[i]))) + } else { + re.WriteString(regexp.QuoteMeta("\\")) + } + case '%': + re.WriteString(".*") + case '_': + re.WriteString(".") + default: + re.WriteString(regexp.QuoteMeta(string(c))) + } + } + re.WriteString("$") + return regexp.MatchString(re.String(), s) +} + +func evalExists(e *acv1.ExistsExpr, event *acv1.CloudEvent) ceVal { + switch e.GetAttribute() { + case "id", "source", "specversion", "type": + return bv(true) + default: + _, ok := event.GetAttributes()[e.GetAttribute()] + return bv(ok) + } +} + +func evalIn(in *acv1.InExpr, event *acv1.CloudEvent) (ceVal, error) { + operand, err := eval(in.GetOperand(), event) + if err != nil { + return bv(false), err + } + for _, valueExpr := range in.GetValues() { + v, err := eval(valueExpr, event) + if err != nil { + continue + } + if cevalsEqual(operand, v) { + return bv(!in.GetNegated()), nil + } + } + return bv(in.GetNegated()), nil +} + +func evalFunction(fc *acv1.FunctionCall, event *acv1.CloudEvent) (ceVal, error) { + args := make([]ceVal, len(fc.GetArgs())) + for i, arg := range fc.GetArgs() { + v, err := eval(arg, event) + if err != nil { + return bv(false), err + } + args[i] = v + } + + switch fc.GetFunction() { + case acv1.BuiltinFunction_FUNCTION_LENGTH: + if len(args) != 1 { + return iv(0), fmt.Errorf("LENGTH requires 1 argument, got %d", len(args)) + } + s, _ := toString(args[0]) + return iv(int32(len([]rune(s)))), nil + + case acv1.BuiltinFunction_FUNCTION_CONCAT: + var sb strings.Builder + for _, a := range args { + s, _ := toString(a) + sb.WriteString(s) + } + return sv(sb.String()), nil + + case acv1.BuiltinFunction_FUNCTION_CONCAT_WS: + if len(args) < 1 { + return sv(""), fmt.Errorf("CONCAT_WS requires at least 1 argument") + } + sep, _ := toString(args[0]) + parts := make([]string, 0, len(args)-1) + for _, a := range args[1:] { + s, _ := toString(a) + parts = append(parts, s) + } + return sv(strings.Join(parts, sep)), nil + + case acv1.BuiltinFunction_FUNCTION_LOWER: + if len(args) != 1 { + return sv(""), fmt.Errorf("LOWER requires 1 argument") + } + s, _ := toString(args[0]) + return sv(strings.ToLower(s)), nil + + case acv1.BuiltinFunction_FUNCTION_UPPER: + if len(args) != 1 { + return sv(""), fmt.Errorf("UPPER requires 1 argument") + } + s, _ := toString(args[0]) + return sv(strings.ToUpper(s)), nil + + case acv1.BuiltinFunction_FUNCTION_TRIM: + if len(args) != 1 { + return sv(""), fmt.Errorf("TRIM requires 1 argument") + } + s, _ := toString(args[0]) + return sv(strings.TrimSpace(s)), nil + + case acv1.BuiltinFunction_FUNCTION_LEFT: + if len(args) != 2 { + return sv(""), fmt.Errorf("LEFT requires 2 arguments") + } + s, _ := toString(args[0]) + n, _ := toInt(args[1]) + runes := []rune(s) + if n < 0 { + return sv(s), fmt.Errorf("LEFT: n must be >= 0") + } + if int(n) >= len(runes) { + return sv(s), nil + } + return sv(string(runes[:n])), nil + + case acv1.BuiltinFunction_FUNCTION_RIGHT: + if len(args) != 2 { + return sv(""), fmt.Errorf("RIGHT requires 2 arguments") + } + s, _ := toString(args[0]) + n, _ := toInt(args[1]) + runes := []rune(s) + if n < 0 { + return sv(s), fmt.Errorf("RIGHT: n must be >= 0") + } + if int(n) >= len(runes) { + return sv(s), nil + } + return sv(string(runes[len(runes)-int(n):])), nil + + case acv1.BuiltinFunction_FUNCTION_SUBSTRING: + if len(args) < 2 || len(args) > 3 { + return sv(""), fmt.Errorf("SUBSTRING requires 2 or 3 arguments, got %d", len(args)) + } + s, _ := toString(args[0]) + pos, _ := toInt(args[1]) + runes := []rune(s) + l := int32(len(runes)) + var start int32 + switch { + case pos > 0: + start = pos - 1 + case pos < 0: + start = l + pos + default: + return sv(""), nil + } + if start < 0 || start >= l { + return sv(""), fmt.Errorf("SUBSTRING: position out of range") + } + if len(args) == 2 { + return sv(string(runes[start:])), nil + } + length, _ := toInt(args[2]) + if length < 0 { + return sv(""), fmt.Errorf("SUBSTRING: length must be >= 0") + } + end := start + length + if end > l { + end = l + } + return sv(string(runes[start:end])), nil + + case acv1.BuiltinFunction_FUNCTION_ABS: + if len(args) != 1 { + return iv(0), fmt.Errorf("ABS requires 1 argument") + } + n, _ := toInt(args[0]) + if n == -2147483648 { + return iv(2147483647), fmt.Errorf("ABS: integer overflow for min int32") + } + if n < 0 { + return iv(-n), nil + } + return iv(n), nil + + default: + return bv(false), fmt.Errorf("unknown function: %v", fc.GetFunction()) + } +} + +// ─── Type coercion ───────────────────────────────────────────────────────────── + +func toBool(v ceVal) (bool, error) { + switch v.kind { + case kindBool: + return v.boolVal, nil + case kindInt: + return v.intVal != 0, nil + case kindString: + switch strings.ToLower(strings.TrimSpace(v.strVal)) { + case "true": + return true, nil + case "false": + return false, nil + default: + return false, fmt.Errorf("cast error: %q is not a boolean", v.strVal) + } + } + return false, nil +} + +func toInt(v ceVal) (int32, error) { + switch v.kind { + case kindInt: + return v.intVal, nil + case kindBool: + if v.boolVal { + return 1, nil + } + return 0, nil + case kindString: + n, err := strconv.ParseInt(strings.TrimSpace(v.strVal), 10, 32) + if err != nil { + return 0, fmt.Errorf("cast error: %q is not an integer", v.strVal) + } + return int32(n), nil + } + return 0, nil +} + +func toString(v ceVal) (string, error) { + switch v.kind { + case kindString: + return v.strVal, nil + case kindInt: + return strconv.FormatInt(int64(v.intVal), 10), nil + case kindBool: + if v.boolVal { + return "true", nil + } + return "false", nil + } + return "", nil +} + +// cevalsEqual compares two ceVal values. Same-kind values compare directly; +// cross-kind values are coerced to string per the CESQL spec. +func cevalsEqual(a, b ceVal) bool { + if a.kind == b.kind { + switch a.kind { + case kindString: + return a.strVal == b.strVal + case kindInt: + return a.intVal == b.intVal + case kindBool: + return a.boolVal == b.boolVal + } + } + as, _ := toString(a) + bs, _ := toString(b) + return as == bs +} diff --git a/services/core/catalyst/broker/query.go b/services/core/catalyst/broker/query.go new file mode 100644 index 00000000..23434e36 --- /dev/null +++ b/services/core/catalyst/broker/query.go @@ -0,0 +1,25 @@ +package broker + +import ( + "context" + + acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + + "connectrpc.com/connect" +) + +// Query executes a CESQL expression against stored events and returns all matches. +func (h *rpc) Query(ctx context.Context, req *connect.Request[acv1.QueryRequest]) (*connect.Response[acv1.QueryResponse], error) { + events, err := h.controller.Query(ctx, req.Msg) + if err != nil { + h.logger.Error(err.Error()) + return nil, err + } + + return connect.NewResponse(&acv1.QueryResponse{Events: events}), nil +} + +// QueryStream replays stored events then streams live events as they arrive. +func (h *rpc) QueryStream(ctx context.Context, req *connect.Request[acv1.QueryRequest], stream *connect.ServerStream[acv1.QueryStreamResponse]) error { + return h.controller.QueryStream(ctx, req.Msg, stream) +} diff --git a/services/core/catalyst/broker/rpc.go b/services/core/catalyst/broker/rpc.go index ff56d144..2c7e20ce 100644 --- a/services/core/catalyst/broker/rpc.go +++ b/services/core/catalyst/broker/rpc.go @@ -2,8 +2,6 @@ package broker import ( "context" - "errors" - "sync" acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" acConnect "github.com/steady-bytes/draft/api/core/message_broker/actors/v1/v1connect" @@ -20,6 +18,10 @@ type ( chassis.RPCRegistrar acConnect.ConsumerHandler acConnect.ProducerHandler + acConnect.QueryHandler + acConnect.TopologyHandler + acConnect.MetricsHandler + acConnect.ResourceMetricsHandler } rpc struct { @@ -36,13 +38,23 @@ func NewRPC(logger chassis.Logger, controller Controller) Rpc { } func (h *rpc) RegisterRPC(server chassis.Rpcer) { - // regiser the handler for the consumer service producerPattern, producerHandler := acConnect.NewProducerHandler(h) server.AddHandler(producerPattern, producerHandler, true) - // // regiser the handler for the producer service consumerPattern, consumerHandler := acConnect.NewConsumerHandler(h) server.AddHandler(consumerPattern, consumerHandler, true) + + queryPattern, queryHandler := acConnect.NewQueryHandler(h) + server.AddHandler(queryPattern, queryHandler, true) + + topologyPattern, topologyHandler := acConnect.NewTopologyHandler(h) + server.AddHandler(topologyPattern, topologyHandler, true) + + metricsPattern, metricsHandler := acConnect.NewMetricsHandler(h) + server.AddHandler(metricsPattern, metricsHandler, true) + + resourceMetricsPattern, resourceMetricsHandler := acConnect.NewResourceMetricsHandler(h) + server.AddHandler(resourceMetricsPattern, resourceMetricsHandler, true) } // Consume accepts a request containing a `Message` type to subscribe to @@ -52,26 +64,55 @@ func (h *rpc) RegisterRPC(server chassis.Rpcer) { // the `wg.Done()` method is called after the error is logged closing the // server connection with the client func (h *rpc) Consume(ctx context.Context, req *connect.Request[acv1.ConsumeRequest], stream *connect.ServerStream[acv1.ConsumeResponse]) error { - h.logger.Info("consume request") - - var ( - msg = req.Msg.GetMessage() - wg sync.WaitGroup - ) + msg := req.Msg.GetMessage() - wg.Add(1) if err := h.controller.Consume(ctx, msg, stream); err != nil { h.logger.Error(err.Error()) - wg.Done() return err } - wg.Wait() + <-ctx.Done() - return errors.New("closed") + return ctx.Err() } func (h *rpc) Produce(ctx context.Context, inputStream *connect.BidiStream[acv1.ProduceRequest, acv1.ProduceResponse]) error { - h.logger.Info("produce request") return h.controller.Produce(ctx, inputStream) } + +func (h *rpc) GetTopology(ctx context.Context, _ *connect.Request[acv1.GetTopologyRequest]) (*connect.Response[acv1.GetTopologyResponse], error) { + resp, err := h.controller.GetTopology(ctx) + if err != nil { + return nil, err + } + return connect.NewResponse(resp), nil +} + +func (h *rpc) WatchTopology(ctx context.Context, _ *connect.Request[acv1.WatchTopologyRequest], stream *connect.ServerStream[acv1.WatchTopologyResponse]) error { + return h.controller.WatchTopology(ctx, stream) +} + +func (h *rpc) GetMetrics(ctx context.Context, req *connect.Request[acv1.GetMetricsRequest]) (*connect.Response[acv1.GetMetricsResponse], error) { + resp, err := h.controller.GetMetrics(ctx, req.Msg.GetWindowSeconds()) + if err != nil { + return nil, err + } + return connect.NewResponse(resp), nil +} + +func (h *rpc) GetResourceMetrics(ctx context.Context, _ *connect.Request[acv1.GetResourceMetricsRequest]) (*connect.Response[acv1.GetResourceMetricsResponse], error) { + resp, err := h.controller.GetResourceMetrics(ctx) + if err != nil { + return nil, err + } + return connect.NewResponse(resp), nil +} + +func (h *rpc) GetTopicSeries(ctx context.Context, req *connect.Request[acv1.GetTopicSeriesRequest]) (*connect.Response[acv1.GetTopicSeriesResponse], error) { + resp, err := h.controller.GetTopicSeries(ctx, req.Msg.GetEventType(), req.Msg.GetWindowSeconds()) + if err != nil { + return nil, err + } + return connect.NewResponse(resp), nil +} + diff --git a/services/core/catalyst/broker/store.go b/services/core/catalyst/broker/store.go new file mode 100644 index 00000000..4f4a7143 --- /dev/null +++ b/services/core/catalyst/broker/store.go @@ -0,0 +1,529 @@ +package broker + +import ( + "context" + "encoding/base64" + "fmt" + "sort" + "sync" + "sync/atomic" + "time" + + "github.com/ClickHouse/clickhouse-go/v2" + "github.com/ClickHouse/clickhouse-go/v2/lib/driver" + acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" +) + +const ( + // batchSize is the maximum number of events accumulated before a flush is + // forced, regardless of the flush interval. + batchSize = 5_000 + + // flushInterval is the maximum time an event may sit in the buffer before + // it is written to ClickHouse, even if the batch is not yet full. + flushInterval = 500 * time.Millisecond + + // chanCapacity is the depth of the ingest channel. It is sized well above + // the largest expected burst so Save never blocks the produce goroutine. + chanCapacity = 100_000 +) + +type ( + ClickHouseConfig struct { + Enabled bool `mapstructure:"enabled"` + Address string `mapstructure:"address"` + Database string `mapstructure:"database"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + } + + // EdgeVolume is a (source, event_type, count) tuple returned by QueryVolumes. + EdgeVolume struct { + Source string + EventType string + Count uint32 + } + + // LatencyStats holds pre-computed median and P95 dispatch latency in milliseconds. + LatencyStats struct { + MedianMs float64 + P95Ms float64 + } + + // TopicSeriesPoint is one time-bucketed count for QueryTopicSeries. + TopicSeriesPoint struct { + TimestampMs int64 + Count uint32 + } + + // StoreResourceStats contains point-in-time resource metrics read directly + // from the store's in-process state rather than from ClickHouse. + StoreResourceStats struct { + DroppedTotal uint64 + QueueDepth uint32 + QueueCapacity uint32 + FlushP95Ms float64 + FlushCount uint32 + } + + Storer interface { + Save(ctx context.Context, event *acv1.CloudEvent, receivedAt, forwardedAt time.Time) error + Query(ctx context.Context, limit int32, after string, descending bool) ([]*acv1.CloudEvent, error) + // QueryDistinctSources returns the list of distinct producer source names and + // a map of event_type → []source_names for edge derivation in GetTopology. + QueryDistinctSources(ctx context.Context) ([]string, map[string][]string, error) + // QueryVolumes returns per-(source, event_type) event counts over the last windowSecs seconds. + QueryVolumes(ctx context.Context, windowSecs int32) ([]EdgeVolume, error) + // QueryLatency returns median and P95 dispatch latency over the last windowSecs seconds. + QueryLatency(ctx context.Context, windowSecs int32) (LatencyStats, error) + // StoreStats returns live resource counters from the store's in-process state. + StoreStats() StoreResourceStats + // QueryTopicSeries returns time-bucketed event counts for one event_type. + // Pass windowSecs = -1 to query all stored data. Returns the points and + // the bucket size in seconds that was chosen. + QueryTopicSeries(ctx context.Context, eventType string, windowSecs int32) ([]TopicSeriesPoint, int32, error) + } + + // flushRing is a fixed-size ring buffer that tracks store flush durations for + // P95 computation without requiring an external dependency. + flushRing struct { + mu sync.Mutex + ring [128]float64 + pos int + total atomic.Uint64 + } + + noopStore struct{} + + // pendingEvent captures both the time the event arrived at Catalyst (receivedAt) + // and the time it was dispatched to consumers (forwardedAt). Both come from the + // same Go clock so latency (forwardedAt - receivedAt) is always non-negative, + // unlike ClickHouse's now64() which fires at batch-flush time after forwardedAt. + pendingEvent struct { + event *acv1.CloudEvent + receivedAt time.Time + forwardedAt time.Time + } + + clickhouseStore struct { + conn driver.Conn + ch chan pendingEvent + droppedTotal atomic.Uint64 + flushes flushRing + } +) + +func (r *flushRing) record(ms float64) { + r.mu.Lock() + r.ring[r.pos%128] = ms + r.pos++ + r.mu.Unlock() + r.total.Add(1) +} + +func (r *flushRing) p95Ms() float64 { + r.mu.Lock() + n := r.pos + if n > 128 { + n = 128 + } + buf := make([]float64, n) + copy(buf, r.ring[:n]) + r.mu.Unlock() + if n == 0 { + return 0 + } + sort.Float64s(buf) + return buf[int(float64(n-1)*0.95)] +} + +func NewNoopStore() Storer { return &noopStore{} } + +func (n *noopStore) Save(_ context.Context, _ *acv1.CloudEvent, _, _ time.Time) error { return nil } + +func (n *noopStore) Query(_ context.Context, _ int32, _ string, _ bool) ([]*acv1.CloudEvent, error) { + return nil, nil +} + +func (n *noopStore) QueryDistinctSources(_ context.Context) ([]string, map[string][]string, error) { + return nil, nil, nil +} + +func (n *noopStore) QueryVolumes(_ context.Context, _ int32) ([]EdgeVolume, error) { + return nil, nil +} + +func (n *noopStore) QueryLatency(_ context.Context, _ int32) (LatencyStats, error) { + return LatencyStats{}, nil +} + +func (n *noopStore) StoreStats() StoreResourceStats { return StoreResourceStats{} } + +func (n *noopStore) QueryTopicSeries(_ context.Context, _ string, _ int32) ([]TopicSeriesPoint, int32, error) { + return nil, 60, nil +} + +func NewClickHouseStore(cfg ClickHouseConfig) (Storer, error) { + conn, err := clickhouse.Open(&clickhouse.Options{ + Addr: []string{cfg.Address}, + Auth: clickhouse.Auth{ + Database: cfg.Database, + Username: cfg.Username, + Password: cfg.Password, + }, + }) + if err != nil { + return nil, fmt.Errorf("open clickhouse: %w", err) + } + store := &clickhouseStore{ + conn: conn, + ch: make(chan pendingEvent, chanCapacity), + } + if err := store.migrate(context.Background()); err != nil { + return nil, fmt.Errorf("migrate: %w", err) + } + go store.flusher() + return store, nil +} + +const createEventsTable = ` +CREATE TABLE IF NOT EXISTS events ( + id String, + source String, + spec_version String, + type String, + body String, + inserted_at DateTime64(9) DEFAULT now64(), + forwarded_at DateTime64(9) DEFAULT toDateTime64(0, 9), + raw String +) ENGINE = MergeTree() +ORDER BY (type, inserted_at) +PARTITION BY toYYYYMM(inserted_at) +` + +func (s *clickhouseStore) migrate(ctx context.Context) error { + if err := s.conn.Exec(ctx, createEventsTable); err != nil { + return err + } + if err := s.conn.Exec(ctx, `ALTER TABLE events ADD COLUMN IF NOT EXISTS body String DEFAULT ''`); err != nil { + return err + } + return s.conn.Exec(ctx, `ALTER TABLE events ADD COLUMN IF NOT EXISTS forwarded_at DateTime64(9) DEFAULT toDateTime64(0, 9)`) +} + +// Save enqueues the event for batch insertion. It never blocks the caller — if +// the channel is full the event is dropped rather than stalling the produce loop. +func (s *clickhouseStore) Save(_ context.Context, event *acv1.CloudEvent, receivedAt, forwardedAt time.Time) error { + select { + case s.ch <- pendingEvent{event: event, receivedAt: receivedAt, forwardedAt: forwardedAt}: + default: + s.droppedTotal.Add(1) + } + return nil +} + +func (s *clickhouseStore) StoreStats() StoreResourceStats { + return StoreResourceStats{ + DroppedTotal: s.droppedTotal.Load(), + QueueDepth: uint32(len(s.ch)), + QueueCapacity: chanCapacity, + FlushP95Ms: s.flushes.p95Ms(), + FlushCount: uint32(s.flushes.total.Load()), + } +} + +// flusher drains the ingest channel and writes events to ClickHouse in batches. +// It flushes whenever the buffer reaches batchSize or flushInterval elapses. +func (s *clickhouseStore) flusher() { + ticker := time.NewTicker(flushInterval) + defer ticker.Stop() + + buf := make([]pendingEvent, 0, batchSize) + + flush := func() { + if len(buf) == 0 { + return + } + start := time.Now() + if err := s.insertBatch(context.Background(), buf); err != nil { + // Non-fatal: log and continue. Individual event loss is acceptable + // over stalling the pipeline. + _ = err + } + s.flushes.record(float64(time.Since(start).Milliseconds())) + buf = buf[:0] + } + + for { + select { + case pe := <-s.ch: + buf = append(buf, pe) + if len(buf) >= batchSize { + flush() + } + case <-ticker.C: + flush() + } + } +} + +func (s *clickhouseStore) insertBatch(ctx context.Context, events []pendingEvent) error { + batch, err := s.conn.PrepareBatch(ctx, + "INSERT INTO events (id, source, spec_version, type, body, inserted_at, forwarded_at, raw)", + ) + if err != nil { + return fmt.Errorf("prepare batch: %w", err) + } + for _, pe := range events { + b, err := proto.Marshal(pe.event) + if err != nil { + continue + } + if err := batch.Append( + pe.event.GetId(), + pe.event.GetSource(), + pe.event.GetSpecVersion(), + pe.event.GetType(), + pe.event.GetTextData(), + pe.receivedAt, + pe.forwardedAt, + base64.StdEncoding.EncodeToString(b), + ); err != nil { + return fmt.Errorf("append row: %w", err) + } + } + return batch.Send() +} + +func (s *clickhouseStore) Query(ctx context.Context, limit int32, after string, descending bool) ([]*acv1.CloudEvent, error) { + if limit <= 0 { + limit = 100 + } + + order := "ASC" + if descending { + order = "DESC" + } + + var ( + rows driver.Rows + err error + ) + if after != "" { + t, parseErr := time.Parse(time.RFC3339, after) + if parseErr != nil { + return nil, fmt.Errorf("parse after timestamp: %w", parseErr) + } + rows, err = s.conn.Query(ctx, + "SELECT raw, forwarded_at FROM events WHERE inserted_at > ? ORDER BY inserted_at "+order+" LIMIT ?", + t, limit, + ) + } else { + rows, err = s.conn.Query(ctx, + "SELECT raw, forwarded_at FROM events ORDER BY inserted_at "+order+" LIMIT ?", + limit, + ) + } + if err != nil { + return nil, fmt.Errorf("query events: %w", err) + } + defer rows.Close() + + epochZero := time.Unix(0, 0) + + var result []*acv1.CloudEvent + for rows.Next() { + var raw string + var forwardedAt time.Time + if err := rows.Scan(&raw, &forwardedAt); err != nil { + return nil, fmt.Errorf("scan row: %w", err) + } + b, err := base64.StdEncoding.DecodeString(raw) + if err != nil { + return nil, fmt.Errorf("decode event: %w", err) + } + event := &acv1.CloudEvent{} + if err := proto.Unmarshal(b, event); err != nil { + return nil, fmt.Errorf("unmarshal event: %w", err) + } + // For rows stored before forwarded_at was injected into the proto, + // back-fill the attribute from the dedicated ClickHouse column. + if _, ok := event.Attributes["forwarded_at"]; !ok && forwardedAt.After(epochZero) { + if event.Attributes == nil { + event.Attributes = make(map[string]*acv1.CloudEvent_CloudEventAttributeValue) + } + event.Attributes["forwarded_at"] = &acv1.CloudEvent_CloudEventAttributeValue{ + Attr: &acv1.CloudEvent_CloudEventAttributeValue_CeTimestamp{ + CeTimestamp: timestamppb.New(forwardedAt), + }, + } + } + result = append(result, event) + } + return result, rows.Err() +} + +// QueryDistinctSources returns the distinct producer names and a map of +// event_type → []producer_names derived from the events table. +func (s *clickhouseStore) QueryDistinctSources(ctx context.Context) ([]string, map[string][]string, error) { + rows, err := s.conn.Query(ctx, + "SELECT DISTINCT source, type FROM events ORDER BY source, type LIMIT 2000", + ) + if err != nil { + return nil, nil, fmt.Errorf("query distinct sources: %w", err) + } + defer rows.Close() + + seenSources := make(map[string]bool) + sourcesByType := make(map[string][]string) + + for rows.Next() { + var src, typ string + if err := rows.Scan(&src, &typ); err != nil { + return nil, nil, fmt.Errorf("scan distinct sources: %w", err) + } + seenSources[src] = true + already := false + for _, s := range sourcesByType[typ] { + if s == src { + already = true + break + } + } + if !already { + sourcesByType[typ] = append(sourcesByType[typ], src) + } + } + if err := rows.Err(); err != nil { + return nil, nil, err + } + + producers := make([]string, 0, len(seenSources)) + for src := range seenSources { + producers = append(producers, src) + } + sort.Strings(producers) + return producers, sourcesByType, nil +} + +// QueryVolumes returns event counts grouped by (source, event_type) over the last windowSecs seconds. +// Pass windowSecs = -1 to query all stored events without a time filter. +func (s *clickhouseStore) QueryVolumes(ctx context.Context, windowSecs int32) ([]EdgeVolume, error) { + var ( + rows driver.Rows + err error + ) + if windowSecs > 0 { + rows, err = s.conn.Query(ctx, + "SELECT source, type, toUInt32(count()) AS cnt FROM events WHERE inserted_at >= now() - INTERVAL ? SECOND GROUP BY source, type ORDER BY cnt DESC LIMIT 2000", + windowSecs, + ) + } else { + rows, err = s.conn.Query(ctx, + "SELECT source, type, toUInt32(count()) AS cnt FROM events GROUP BY source, type ORDER BY cnt DESC LIMIT 2000", + ) + } + if err != nil { + return nil, fmt.Errorf("query volumes: %w", err) + } + defer rows.Close() + + var result []EdgeVolume + for rows.Next() { + var src, typ string + var cnt uint32 + if err := rows.Scan(&src, &typ, &cnt); err != nil { + return nil, fmt.Errorf("scan volume row: %w", err) + } + result = append(result, EdgeVolume{Source: src, EventType: typ, Count: cnt}) + } + return result, rows.Err() +} + +// QueryLatency returns median and P95 dispatch latency in milliseconds over the last windowSecs seconds. +// Rows where forwarded_at is epoch zero (not yet stamped) are excluded. +// Pass windowSecs = -1 to query all stored events without a time filter. +// bucketSecs returns the bucket interval for the given window. +func bucketSecs(windowSecs int32) int32 { + switch { + case windowSecs <= 0: + return 60 // all time: 1-min buckets + case windowSecs <= 900: + return 1 // 15 min: 1-sec buckets + case windowSecs <= 3600: + return 5 // 1 h: 5-sec buckets + case windowSecs <= 10800: + return 10 // 3 h: 10-sec buckets + default: + return 30 // 24 h: 30-sec buckets + } +} + +// QueryTopicSeries returns time-bucketed event counts for one event_type. +func (s *clickhouseStore) QueryTopicSeries(ctx context.Context, eventType string, windowSecs int32) ([]TopicSeriesPoint, int32, error) { + bucket := bucketSecs(windowSecs) + var ( + rows driver.Rows + err error + ) + if windowSecs > 0 { + rows, err = s.conn.Query(ctx, + fmt.Sprintf(`SELECT + toInt64(toUnixTimestamp(toStartOfInterval(inserted_at, toIntervalSecond(%d)))) * 1000 AS ts, + toUInt32(count()) AS cnt + FROM events + WHERE type = ? + AND inserted_at >= now() - INTERVAL %d SECOND + GROUP BY ts ORDER BY ts ASC`, bucket, windowSecs), + eventType, + ) + } else { + rows, err = s.conn.Query(ctx, + fmt.Sprintf(`SELECT + toInt64(toUnixTimestamp(toStartOfInterval(inserted_at, toIntervalSecond(%d)))) * 1000 AS ts, + toUInt32(count()) AS cnt + FROM events + WHERE type = ? + GROUP BY ts ORDER BY ts ASC LIMIT 10080`, bucket), + eventType, + ) + } + if err != nil { + return nil, 0, fmt.Errorf("query topic series: %w", err) + } + defer rows.Close() + + var result []TopicSeriesPoint + for rows.Next() { + var ts int64 + var cnt uint32 + if err := rows.Scan(&ts, &cnt); err != nil { + return nil, 0, fmt.Errorf("scan series row: %w", err) + } + result = append(result, TopicSeriesPoint{TimestampMs: ts, Count: cnt}) + } + return result, bucket, rows.Err() +} + +func (s *clickhouseStore) QueryLatency(ctx context.Context, windowSecs int32) (LatencyStats, error) { + const baseQuery = `SELECT + quantile(0.5)(toFloat64(toUnixTimestamp64Nano(forwarded_at) - toUnixTimestamp64Nano(inserted_at))) / 1e6, + quantile(0.95)(toFloat64(toUnixTimestamp64Nano(forwarded_at) - toUnixTimestamp64Nano(inserted_at))) / 1e6 + FROM events + WHERE forwarded_at > toDateTime64(0, 9)` + + var row driver.Row + if windowSecs > 0 { + row = s.conn.QueryRow(ctx, baseQuery+" AND inserted_at >= now() - INTERVAL ? SECOND", windowSecs) + } else { + row = s.conn.QueryRow(ctx, baseQuery) + } + + var stats LatencyStats + if err := row.Scan(&stats.MedianMs, &stats.P95Ms); err != nil { + return LatencyStats{}, fmt.Errorf("query latency: %w", err) + } + return stats, nil +} diff --git a/services/core/catalyst/broker/topology.go b/services/core/catalyst/broker/topology.go new file mode 100644 index 00000000..9f12e899 --- /dev/null +++ b/services/core/catalyst/broker/topology.go @@ -0,0 +1,100 @@ +package broker + +import ( + "sync" + + acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" +) + +// topologyObserver holds a buffered channel for one WatchTopology subscriber. +type topologyObserver struct { + ch chan *acv1.WatchTopologyResponse +} + +// topologyRegistry tracks WatchTopology subscribers and the set of producer +// sources that have been observed at least once. It is safe for concurrent use. +type topologyRegistry struct { + mu sync.RWMutex + observers []*topologyObserver + seen map[string]bool // producer sources seen in the produce loop +} + +func newTopologyRegistry() *topologyRegistry { + return &topologyRegistry{ + observers: make([]*topologyObserver, 0), + seen: make(map[string]bool), + } +} + +// subscribe registers a new WatchTopology stream and returns the observer plus +// a cleanup function that must be called (typically via defer) to deregister it. +func (r *topologyRegistry) subscribe() (*topologyObserver, func()) { + obs := &topologyObserver{ch: make(chan *acv1.WatchTopologyResponse, 64)} + r.mu.Lock() + r.observers = append(r.observers, obs) + r.mu.Unlock() + return obs, func() { + r.mu.Lock() + defer r.mu.Unlock() + for i, o := range r.observers { + if o == obs { + r.observers = append(r.observers[:i], r.observers[i+1:]...) + return + } + } + } +} + +// broadcast sends resp to every active subscriber. Slow consumers are skipped +// rather than blocking the caller. +func (r *topologyRegistry) broadcast(resp *acv1.WatchTopologyResponse) { + r.mu.RLock() + defer r.mu.RUnlock() + for _, obs := range r.observers { + select { + case obs.ch <- resp: + default: + } + } +} + +// NotifyConsumerConnected broadcasts a consumer_connected delta. +func (r *topologyRegistry) NotifyConsumerConnected(source string) { + r.broadcast(&acv1.WatchTopologyResponse{ + Event: &acv1.WatchTopologyResponse_ConsumerConnected{ + ConsumerConnected: &acv1.TopologyNode{Id: source, Name: source}, + }, + }) +} + +// NotifyConsumerDisconnected broadcasts a consumer_disconnected delta. +func (r *topologyRegistry) NotifyConsumerDisconnected(source string) { + r.broadcast(&acv1.WatchTopologyResponse{ + Event: &acv1.WatchTopologyResponse_ConsumerDisconnected{ + ConsumerDisconnected: &acv1.TopologyNode{Id: source, Name: source}, + }, + }) +} + +// ProducerCount returns the number of distinct producer sources seen since start. +func (r *topologyRegistry) ProducerCount() int { + r.mu.RLock() + defer r.mu.RUnlock() + return len(r.seen) +} + +// ObserveProducer broadcasts producer_appeared the first time source is seen. +func (r *topologyRegistry) ObserveProducer(source string) { + r.mu.Lock() + if r.seen[source] { + r.mu.Unlock() + return + } + r.seen[source] = true + r.mu.Unlock() + r.broadcast(&acv1.WatchTopologyResponse{ + Event: &acv1.WatchTopologyResponse_ProducerAppeared{ + ProducerAppeared: &acv1.TopologyNode{Id: source, Name: source}, + }, + }) +} diff --git a/services/core/catalyst/config.yaml b/services/core/catalyst/config.yaml index c711d6e4..1f32ebb0 100644 --- a/services/core/catalyst/config.yaml +++ b/services/core/catalyst/config.yaml @@ -11,3 +11,10 @@ service: internal: host: localhost port: 2220 + +clickhouse: + enabled: true + address: "localhost:9000" + database: "catalyst" + username: "default" + password: "" diff --git a/services/core/catalyst/docker-compose.yaml b/services/core/catalyst/docker-compose.yaml new file mode 100644 index 00000000..4f805260 --- /dev/null +++ b/services/core/catalyst/docker-compose.yaml @@ -0,0 +1,24 @@ +name: catalyst-dev + +services: + clickhouse: + image: clickhouse/clickhouse-server:24.8 + restart: unless-stopped + ports: + - "9000:9000" # native protocol (used by the Go driver) + - "8123:8123" # HTTP interface (useful for the web UI / curl queries) + environment: + CLICKHOUSE_DB: catalyst + CLICKHOUSE_USER: default + CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1 + CLICKHOUSE_PASSWORD: "" + volumes: + - clickhouse_data:/var/lib/clickhouse + healthcheck: + test: ["CMD", "clickhouse-client", "--query", "SELECT 1"] + interval: 5s + timeout: 5s + retries: 10 + +volumes: + clickhouse_data: diff --git a/services/core/catalyst/go.mod b/services/core/catalyst/go.mod index 733d8820..4a120144 100644 --- a/services/core/catalyst/go.mod +++ b/services/core/catalyst/go.mod @@ -1,22 +1,32 @@ module github.com/steady-bytes/draft/services/core/catalyst -go 1.23.2 +go 1.24.1 + +replace github.com/steady-bytes/draft/api => ../../../api require ( connectrpc.com/connect v1.16.2 + github.com/ClickHouse/clickhouse-go/v2 v2.46.0 github.com/steady-bytes/draft/api v1.0.0 github.com/steady-bytes/draft/pkg/chassis v0.4.5 github.com/steady-bytes/draft/pkg/loggers v0.2.4 + google.golang.org/protobuf v1.36.3 ) require ( connectrpc.com/grpcreflect v1.2.0 // indirect + github.com/ClickHouse/ch-go v0.71.0 // indirect + github.com/andybalholm/brotli v1.2.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/boltdb/bolt v1.3.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 // indirect github.com/envoyproxy/go-control-plane v0.12.0 // indirect github.com/fatih/color v1.14.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-faster/city v1.0.1 // indirect + github.com/go-faster/errors v0.7.1 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect @@ -24,15 +34,20 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/raft v1.6.0 // indirect github.com/hashicorp/raft-boltdb/v2 v2.3.0 // indirect - github.com/magiconair/properties v1.8.7 // indirect + github.com/klauspost/compress v1.18.3 // indirect + github.com/magiconair/properties v1.8.10 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/paulmach/orb v0.12.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pierrec/lz4/v4 v4.1.25 // indirect github.com/rs/cors v1.10.1 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/segmentio/asm v1.2.1 // indirect + github.com/shopspring/decimal v1.4.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect @@ -40,15 +55,17 @@ require ( github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.etcd.io/bbolt v1.3.7 // indirect + go.opentelemetry.io/otel v1.41.0 // indirect + go.opentelemetry.io/otel/trace v1.41.0 // indirect go.uber.org/multierr v1.11.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/net v0.50.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.34.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/services/core/catalyst/go.sum b/services/core/catalyst/go.sum index 369fe2d6..b3687abd 100644 --- a/services/core/catalyst/go.sum +++ b/services/core/catalyst/go.sum @@ -2,11 +2,17 @@ connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +github.com/ClickHouse/ch-go v0.71.0 h1:bUdZ/EZj/LcVHsMqaRUP2holqygrPWQKeMjc6nZoyRM= +github.com/ClickHouse/ch-go v0.71.0/go.mod h1:NwbNc+7jaqfY58dmdDUbG4Jl22vThgx1cYjBw0vtgXw= +github.com/ClickHouse/clickhouse-go/v2 v2.46.0 h1:s3eRy+hYmu5uzotB6ZhDofgHu8kDgGN/fpmjxRkqSpk= +github.com/ClickHouse/clickhouse-go/v2 v2.46.0/go.mod h1:giJfUVlMkcfUEPVfRpt51zZaGEx9i17gCos8gBl392c= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ= +github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -15,6 +21,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 h1:VIG8z8W5EDy5cIbv2mH5TufcdZm7p/Nn73GZ6nJaXcQ= @@ -33,6 +41,10 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= +github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw= +github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg= +github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -40,14 +52,21 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= @@ -76,6 +95,11 @@ github.com/hashicorp/raft-boltdb/v2 v2.3.0/go.mod h1:YHukhB04ChJsLHLJEUD6vjFyLX2 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw= +github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -85,8 +109,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -104,11 +128,17 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/paulmach/orb v0.12.0 h1:z+zOwjmG3MyEEqzv92UN49Lg1JFYx0L9GpGKNVDKk1s= +github.com/paulmach/orb v0.12.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= +github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pierrec/lz4/v4 v4.1.25 h1:kocOqRffaIbU5djlIBr7Wh+cx82C0vtFb0fOurZHqD0= +github.com/pierrec/lz4/v4 v4.1.25/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -137,6 +167,10 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0= +github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= @@ -149,8 +183,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= -github.com/steady-bytes/draft/api v1.0.0 h1:QIvboAJgU0fBOV6BKChLMhHYIjBTR53+LJaR3w3g0NY= -github.com/steady-bytes/draft/api v1.0.0/go.mod h1:mlwxjvRiqvwySGdzVmF8voFhMffWq2F7dyd+xt6kENA= github.com/steady-bytes/draft/pkg/chassis v0.4.5 h1:UQ2+2vsy/lsOkGk904SCthkwZcqD8ZBnLpHn2Cgts0Y= github.com/steady-bytes/draft/pkg/chassis v0.4.5/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM= github.com/steady-bytes/draft/pkg/loggers v0.2.4 h1:cRzJaqnJ2VSekiJpYBAl64yaKoaTOhdp42F/CSKNWsc= @@ -162,58 +194,108 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= +github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= +go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c= +go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE= +go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0= +go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= +golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/services/core/catalyst/main.go b/services/core/catalyst/main.go index 01b026fa..6dc71f2d 100644 --- a/services/core/catalyst/main.go +++ b/services/core/catalyst/main.go @@ -8,12 +8,30 @@ import ( ) func main() { - var ( - logger = zerolog.New() + logger := zerolog.New() - cnt = broker.NewController(logger) - rpc = broker.NewRPC(logger, cnt) - ) + cfg := chassis.GetConfig() + + var chCfg broker.ClickHouseConfig + if err := cfg.UnmarshalKey("clickhouse", &chCfg); err != nil { + logger.WithField("error", err.Error()).Error("failed to read clickhouse config") + } + + var storer broker.Storer + if chCfg.Enabled { + s, err := broker.NewClickHouseStore(chCfg) + if err != nil { + logger.WithField("error", err.Error()).Error("failed to connect to clickhouse — falling back to noop store") + storer = broker.NewNoopStore() + } else { + storer = s + } + } else { + storer = broker.NewNoopStore() + } + + cnt := broker.NewController(logger, storer) + rpc := broker.NewRPC(logger, cnt) defer chassis.New(logger). Register(chassis.RegistrationOptions{ diff --git a/services/core/fuse/control_plane/controller.go b/services/core/fuse/control_plane/controller.go index 5c9bf3aa..fa01b4d7 100644 --- a/services/core/fuse/control_plane/controller.go +++ b/services/core/fuse/control_plane/controller.go @@ -5,7 +5,10 @@ import ( "context" "errors" "net/http" + "net/url" "slices" + "strconv" + "strings" "time" ntv1 "github.com/steady-bytes/draft/api/core/control_plane/networking/v1" @@ -17,6 +20,7 @@ import ( endpoint "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" route "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + extauthzv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3" router "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3" hcm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" upstreams "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" @@ -39,6 +43,7 @@ type ( LoadCache() UpdateCacheWithNewRoute(route *ntv1.Route) error + ListRoutes(ctx context.Context) ([]*ntv1.Route, error) Increment() string } @@ -62,6 +67,11 @@ const ( LISTENER_PORT_CONFIG_KEY = "fuse.listener.port" DEFAULT_ROUTE_CONFIG_NAME = "route_config" + + // auth service discovery + AuthServiceBlueprintKey = "auth_service_address" + AUTH_CLUSTER_NAME = "auth-service" + AUTH_FILTER_NAME = "envoy.filters.http.ext_authz" ) var ( @@ -150,6 +160,30 @@ func (cp *controlPlane) UpdateCacheWithNewRoute(route *ntv1.Route) error { return cp.apply(ctx, client) } +func (cp *controlPlane) ListRoutes(ctx context.Context) ([]*ntv1.Route, error) { + client := kvv1Connect.NewKeyValueServiceClient(http.DefaultClient, chassis.GetConfig().Entrypoint()) + + routeModel, err := anypb.New(&ntv1.Route{}) + if err != nil { + return nil, ErrFailedRouteMarshal + } + + resp, err := client.List(ctx, connect.NewRequest(&kvv1.ListRequest{Value: routeModel})) + if err != nil { + return nil, ErrUnableToSaveRoute + } + + routes := make([]*ntv1.Route, 0, len(resp.Msg.GetValues())) + for _, v := range resp.Msg.GetValues() { + r := &ntv1.Route{} + if err := v.UnmarshalTo(r); err != nil { + return nil, ErrFailedRouteMarshal + } + routes = append(routes, r) + } + return routes, nil +} + func (cp *controlPlane) apply(ctx context.Context, client kvv1Connect.KeyValueServiceClient) error { routeModel, err := anypb.New(&ntv1.Route{}) @@ -168,6 +202,11 @@ func (cp *controlPlane) apply(ctx context.Context, client kvv1Connect.KeyValueSe return ErrUnableToSaveRoute } + // Discover the auth service address. Empty string means auth is not deployed; + // routes are treated as public and no ext_authz filter is added. + authAddr := cp.getAuthServiceAddress(ctx, client) + authEnabled := authAddr != "" + var snapshot *cache.Snapshot var clusters []types.Resource var systemRoutes []types.Resource @@ -186,7 +225,18 @@ func (cp *controlPlane) apply(ctx context.Context, client kvv1Connect.KeyValueSe clusters = append(clusters, makeCluster(newRoute, clusterLoadAssignment)) } - systemRoutes = append(systemRoutes, makeRouterConfig(routes.Msg.GetValues())) + // Add the auth service cluster when auth is enabled so Envoy can reach it. + if authEnabled { + authCluster, err := makeAuthCluster(authAddr) + if err != nil { + cp.logger.WithError(err).Warn("invalid auth_service_address — running without auth") + authEnabled = false + } else { + clusters = append(clusters, authCluster) + } + } + + systemRoutes = append(systemRoutes, makeRouterConfig(routes.Msg.GetValues(), authEnabled)) newRouter := &router.Router{} @@ -196,6 +246,21 @@ func (cp *controlPlane) apply(ctx context.Context, client kvv1Connect.KeyValueSe return err } + // Build the ordered HttpFilter chain. ext_authz must come before the router. + httpFilters := []*hcm.HttpFilter{} + if authEnabled { + extAuthzFilter, err := makeExtAuthzFilter(authAddr) + if err != nil { + cp.logger.WithError(err).Error("failed to build ext_authz filter") + return err + } + httpFilters = append(httpFilters, extAuthzFilter) + } + httpFilters = append(httpFilters, &hcm.HttpFilter{ + Name: "fuse-http-router", + ConfigType: &hcm.HttpFilter_TypedConfig{TypedConfig: routerConfig}, + }) + // HTTP filter configuration manager := &hcm.HttpConnectionManager{ CodecType: hcm.HttpConnectionManager_AUTO, @@ -206,10 +271,7 @@ func (cp *controlPlane) apply(ctx context.Context, client kvv1Connect.KeyValueSe RouteConfigName: routeConfigName(), }, }, - HttpFilters: []*hcm.HttpFilter{{ - Name: "fuse-http-router", - ConfigType: &hcm.HttpFilter_TypedConfig{TypedConfig: routerConfig}, - }}, + HttpFilters: httpFilters, UpgradeConfigs: []*hcm.HttpConnectionManager_UpgradeConfig{ { UpgradeType: "websocket", @@ -266,6 +328,27 @@ func (cp *controlPlane) apply(ctx context.Context, client kvv1Connect.KeyValueSe return nil } +// getAuthServiceAddress reads the auth service address from Blueprint KV. +// Returns an empty string if the auth service is not registered. +func (cp *controlPlane) getAuthServiceAddress(ctx context.Context, client kvv1Connect.KeyValueServiceClient) string { + val, err := anypb.New(&kvv1.Value{}) + if err != nil { + return "" + } + resp, err := client.Get(ctx, connect.NewRequest(&kvv1.GetRequest{ + Key: AuthServiceBlueprintKey, + Value: val, + })) + if err != nil { + return "" + } + value := &kvv1.Value{} + if err := resp.Msg.GetValue().UnmarshalTo(value); err != nil { + return "" + } + return value.Data +} + // Increase the version of the snapshot. At this point we are just generating a random UUID. // // TODO: Keep track of the version in `blueprint` to load historical routing configurations. @@ -304,10 +387,118 @@ func makeCluster(r *ntv1.Route, loadAssignment *endpoint.ClusterLoadAssignment) return c } +// makeAuthCluster builds an Envoy cluster that points to the auth service. +func makeAuthCluster(rawURL string) (*cluster.Cluster, error) { + host, port, err := parseAuthServiceURL(rawURL) + if err != nil { + return nil, err + } + la := &endpoint.ClusterLoadAssignment{ + ClusterName: AUTH_CLUSTER_NAME, + Endpoints: []*endpoint.LocalityLbEndpoints{{ + LbEndpoints: []*endpoint.LbEndpoint{{ + HostIdentifier: &endpoint.LbEndpoint_Endpoint{ + Endpoint: &endpoint.Endpoint{ + Address: &core.Address{ + Address: &core.Address_SocketAddress{ + SocketAddress: &core.SocketAddress{ + Protocol: core.SocketAddress_TCP, + Address: host, + PortSpecifier: &core.SocketAddress_PortValue{PortValue: port}, + }, + }, + }, + }, + }, + }}, + }}, + } + return &cluster.Cluster{ + Name: AUTH_CLUSTER_NAME, + ConnectTimeout: durationpb.New(5 * time.Second), + ClusterDiscoveryType: &cluster.Cluster_Type{Type: cluster.Cluster_LOGICAL_DNS}, + LbPolicy: cluster.Cluster_ROUND_ROBIN, + LoadAssignment: la, + DnsLookupFamily: cluster.Cluster_V4_ONLY, + }, nil +} + +// makeExtAuthzFilter builds the ext_authz HttpFilter that points to the auth service cluster. +func makeExtAuthzFilter(rawURL string) (*hcm.HttpFilter, error) { + extAuthzConfig := &extauthzv3.ExtAuthz{ + Services: &extauthzv3.ExtAuthz_HttpService{ + HttpService: &extauthzv3.HttpService{ + ServerUri: &core.HttpUri{ + Uri: rawURL, + HttpUpstreamType: &core.HttpUri_Cluster{ + Cluster: AUTH_CLUSTER_NAME, + }, + Timeout: durationpb.New(250 * time.Millisecond), + }, + }, + }, + TransportApiVersion: resource.DefaultAPIVersion, + // deny the request if the auth service is unavailable + FailureModeAllow: false, + } + extAuthzAny, err := anypb.New(extAuthzConfig) + if err != nil { + return nil, err + } + return &hcm.HttpFilter{ + Name: AUTH_FILTER_NAME, + ConfigType: &hcm.HttpFilter_TypedConfig{TypedConfig: extAuthzAny}, + }, nil +} + +// makePerRouteAuthConfig returns the typed_per_filter_config for the ext_authz filter on +// a single route. When authEnabled is false (no auth service registered) nil is returned. +func makePerRouteAuthConfig(r *ntv1.Route, authEnabled bool) *anypb.Any { + if !authEnabled { + return nil + } + + auth := r.GetAuth() + + // No auth field, disabled auth, or explicit bypass → disable the check for this route. + if auth == nil || !auth.Enabled || auth.Policy == ntv1.AuthPolicy_AUTH_POLICY_BYPASS { + perRoute := &extauthzv3.ExtAuthzPerRoute{ + Override: &extauthzv3.ExtAuthzPerRoute_Disabled{Disabled: true}, + } + a, _ := anypb.New(perRoute) + return a + } + + // Build context extensions carrying the policy requirements so the auth service + // can enforce them without needing its own route table. + contextExtensions := map[string]string{} + switch auth.Policy { + case ntv1.AuthPolicy_AUTH_POLICY_GROUPS: + if len(auth.RequiredGroups) > 0 { + contextExtensions["required_groups"] = strings.Join(auth.RequiredGroups, ",") + } + case ntv1.AuthPolicy_AUTH_POLICY_SCOPES: + if len(auth.RequiredScopes) > 0 { + contextExtensions["required_scopes"] = strings.Join(auth.RequiredScopes, " ") + } + } + + perRoute := &extauthzv3.ExtAuthzPerRoute{ + Override: &extauthzv3.ExtAuthzPerRoute_CheckSettings{ + CheckSettings: &extauthzv3.CheckSettings{ + ContextExtensions: contextExtensions, + }, + }, + } + a, _ := anypb.New(perRoute) + return a +} + // `makeRoute` creates a route for the given cluster, and a virtual host for the process that is attempting to add the route. // // `nt_route` :route configuration that is being added to the snapshot. -func makeRouterConfig(routes map[string]*anypb.Any) *route.RouteConfiguration { +// `authEnabled` :whether the auth service is registered; controls per-route ext_authz config generation. +func makeRouterConfig(routes map[string]*anypb.Any, authEnabled bool) *route.RouteConfiguration { var ( virtualHosts []*route.VirtualHost defaultVirtualHost = &route.VirtualHost{ @@ -324,46 +515,38 @@ func makeRouterConfig(routes map[string]*anypb.Any) *route.RouteConfiguration { return nil } - // if no host is requested, add to default host - if r.Match.Host == "" { - defaultVirtualHost.Routes = append(defaultVirtualHost.Routes, &route.Route{ - Match: &route.RouteMatch{ - PathSpecifier: &route.RouteMatch_Prefix{ - Prefix: r.Match.Prefix, - }, + perRouteConfig := map[string]*anypb.Any{} + if authCfg := makePerRouteAuthConfig(r, authEnabled); authCfg != nil { + perRouteConfig[AUTH_FILTER_NAME] = authCfg + } + + envoyRoute := &route.Route{ + Match: &route.RouteMatch{ + PathSpecifier: &route.RouteMatch_Prefix{ + Prefix: r.Match.Prefix, }, - Action: &route.Route_Route{ - Route: &route.RouteAction{ - ClusterSpecifier: &route.RouteAction_Cluster{ - Cluster: clusterName(r), - }, - // disable with 0 value - Timeout: &durationpb.Duration{}, + }, + Action: &route.Route_Route{ + Route: &route.RouteAction{ + ClusterSpecifier: &route.RouteAction_Cluster{ + Cluster: clusterName(r), }, + // disable with 0 value + Timeout: &durationpb.Duration{}, }, - TypedPerFilterConfig: map[string]*anypb.Any{}, - }) + }, + TypedPerFilterConfig: perRouteConfig, + } + + // if no host is requested, add to default host + if r.Match.Host == "" { + defaultVirtualHost.Routes = append(defaultVirtualHost.Routes, envoyRoute) } else { virtualHosts = append(virtualHosts, &route.VirtualHost{ Name: r.Name, Domains: []string{r.Match.Host}, - Routes: []*route.Route{{ - Match: &route.RouteMatch{ - PathSpecifier: &route.RouteMatch_Prefix{ - Prefix: r.Match.Prefix, - }, - }, - Action: &route.Route_Route{ - Route: &route.RouteAction{ - ClusterSpecifier: &route.RouteAction_Cluster{ - Cluster: clusterName(r), - }, - // disable with 0 value - Timeout: &durationpb.Duration{}, - }, - }, - TypedPerFilterConfig: map[string]*anypb.Any{}, - }}}) + Routes: []*route.Route{envoyRoute}, + }) } } @@ -450,3 +633,20 @@ func routeConfigName() string { func clusterName(r *ntv1.Route) string { return r.Name } + +func parseAuthServiceURL(rawURL string) (host string, port uint32, err error) { + u, err := url.Parse(rawURL) + if err != nil { + return "", 0, err + } + host = u.Hostname() + portStr := u.Port() + if portStr == "" { + portStr = "80" + } + p, err := strconv.ParseUint(portStr, 10, 32) + if err != nil { + return "", 0, err + } + return host, uint32(p), nil +} diff --git a/services/core/fuse/control_plane/rpc.go b/services/core/fuse/control_plane/rpc.go index 40cea0fc..17a0b71c 100644 --- a/services/core/fuse/control_plane/rpc.go +++ b/services/core/fuse/control_plane/rpc.go @@ -130,8 +130,12 @@ func (h *rpc) DeleteRoute(context.Context, *connect.Request[ntv1.DeleteRouteRequ } // ListRoutes implements Rpc. -func (h *rpc) ListRoutes(context.Context, *connect.Request[ntv1.ListRoutesRequest]) (*connect.Response[ntv1.ListRoutesResponse], error) { - return nil, ErrNotImplemented +func (h *rpc) ListRoutes(ctx context.Context, req *connect.Request[ntv1.ListRoutesRequest]) (*connect.Response[ntv1.ListRoutesResponse], error) { + routes, err := h.controlPlane.ListRoutes(ctx) + if err != nil { + return nil, connect.NewError(connect.CodeInternal, err) + } + return connect.NewResponse(&ntv1.ListRoutesResponse{Routes: routes}), nil } /////////////////////// diff --git a/services/core/fuse/go.mod b/services/core/fuse/go.mod index 35d1578f..b08cc7e4 100644 --- a/services/core/fuse/go.mod +++ b/services/core/fuse/go.mod @@ -2,6 +2,8 @@ module github.com/steady-bytes/draft/services/core/fuse go 1.23.2 +replace github.com/steady-bytes/draft/api => ../../../api + require ( connectrpc.com/connect v1.16.2 github.com/envoyproxy/go-control-plane v0.12.0 @@ -9,7 +11,7 @@ require ( github.com/steady-bytes/draft/api v1.0.0 github.com/steady-bytes/draft/pkg/chassis v0.4.5 github.com/steady-bytes/draft/pkg/loggers v0.2.4 - google.golang.org/protobuf v1.34.2 + google.golang.org/protobuf v1.36.3 ) require ( @@ -20,7 +22,7 @@ require ( github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 // indirect github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect + github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect github.com/fatih/color v1.14.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -49,10 +51,10 @@ require ( go.etcd.io/bbolt v1.3.7 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect google.golang.org/grpc v1.65.0 // indirect diff --git a/services/core/fuse/go.sum b/services/core/fuse/go.sum index 084d4729..eec38384 100644 --- a/services/core/fuse/go.sum +++ b/services/core/fuse/go.sum @@ -32,8 +32,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= -github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= +github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= @@ -161,8 +161,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= -github.com/steady-bytes/draft/api v1.0.0 h1:QIvboAJgU0fBOV6BKChLMhHYIjBTR53+LJaR3w3g0NY= -github.com/steady-bytes/draft/api v1.0.0/go.mod h1:mlwxjvRiqvwySGdzVmF8voFhMffWq2F7dyd+xt6kENA= github.com/steady-bytes/draft/pkg/chassis v0.4.5 h1:UQ2+2vsy/lsOkGk904SCthkwZcqD8ZBnLpHn2Cgts0Y= github.com/steady-bytes/draft/pkg/chassis v0.4.5/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM= github.com/steady-bytes/draft/pkg/loggers v0.2.4 h1:cRzJaqnJ2VSekiJpYBAl64yaKoaTOhdp42F/CSKNWsc= @@ -192,13 +190,13 @@ golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjs golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -212,11 +210,11 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= @@ -224,8 +222,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/services/examples/auth/auth b/services/examples/auth/auth new file mode 100755 index 00000000..b1186a2a Binary files /dev/null and b/services/examples/auth/auth differ diff --git a/services/examples/auth/config.yaml b/services/examples/auth/config.yaml new file mode 100644 index 00000000..2c348b8c --- /dev/null +++ b/services/examples/auth/config.yaml @@ -0,0 +1,16 @@ +service: + name: auth-example + domain: examples + env: local + entrypoint: http://localhost:2221 + logging: + level: debug + + network: + bind_address: localhost + bind_port: 9092 + internal: + host: host.docker.internal + port: 9092 + external: + host: localhost:10000 diff --git a/services/examples/auth/go.mod b/services/examples/auth/go.mod new file mode 100644 index 00000000..6200ce77 --- /dev/null +++ b/services/examples/auth/go.mod @@ -0,0 +1,56 @@ +module github.com/steady-bytes/draft/services/examples/auth + +go 1.23.2 + +replace github.com/steady-bytes/draft/api => ../../../api + +require ( + connectrpc.com/connect v1.16.2 + github.com/steady-bytes/draft/api v1.0.0 + github.com/steady-bytes/draft/pkg/chassis v0.4.5 + github.com/steady-bytes/draft/pkg/loggers v0.2.4 +) + +require ( + connectrpc.com/grpcreflect v1.2.0 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/boltdb/bolt v1.3.1 // indirect + github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 // indirect + github.com/envoyproxy/go-control-plane v0.12.0 // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/raft v1.6.0 // indirect + github.com/hashicorp/raft-boltdb/v2 v2.3.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/rs/cors v1.10.1 // indirect + github.com/rs/zerolog v1.32.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.etcd.io/bbolt v1.3.7 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.36.3 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/services/examples/auth/go.sum b/services/examples/auth/go.sum new file mode 100644 index 00000000..3c22931a --- /dev/null +++ b/services/examples/auth/go.sum @@ -0,0 +1,226 @@ +connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= +connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= +connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= +connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 h1:VIG8z8W5EDy5cIbv2mH5TufcdZm7p/Nn73GZ6nJaXcQ= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0/go.mod h1:rMOW7HwKadbOR8W4sxYCaHS5TwK0mbpysmDINEfr5SE= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= +github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/raft v1.6.0 h1:tkIAORZy2GbJ2Trp5eUSggLXDPOJLXC+JJLNMMqtgtM= +github.com/hashicorp/raft v1.6.0/go.mod h1:Xil5pDgeGwRWuX4uPUmwa+7Vagg4N804dz6mhNi6S7o= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245 h1:NyeelmxyaUHfDdmhzlEVlrRk+1T9EnlCjvHenrusrfU= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0= +github.com/hashicorp/raft-boltdb/v2 v2.3.0 h1:fPpQR1iGEVYjZ2OELvUHX600VAK5qmdnDEv3eXOwZUA= +github.com/hashicorp/raft-boltdb/v2 v2.3.0/go.mod h1:YHukhB04ChJsLHLJEUD6vjFyLX2L3dsX3wPBZcX4tmc= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/steady-bytes/draft/pkg/chassis v0.4.5 h1:UQ2+2vsy/lsOkGk904SCthkwZcqD8ZBnLpHn2Cgts0Y= +github.com/steady-bytes/draft/pkg/chassis v0.4.5/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM= +github.com/steady-bytes/draft/pkg/loggers v0.2.4 h1:cRzJaqnJ2VSekiJpYBAl64yaKoaTOhdp42F/CSKNWsc= +github.com/steady-bytes/draft/pkg/loggers v0.2.4/go.mod h1:nXeOQ6lXhsVWHzRqVcJz0JIeSW75ORVN+0izJwwnH+Y= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/services/examples/auth/main.go b/services/examples/auth/main.go new file mode 100644 index 00000000..ed885541 --- /dev/null +++ b/services/examples/auth/main.go @@ -0,0 +1,82 @@ +package main + +import ( + "context" + + authv1 "github.com/steady-bytes/draft/api/examples/auth/v1" + authv1Connect "github.com/steady-bytes/draft/api/examples/auth/v1/v1connect" + ntv1 "github.com/steady-bytes/draft/api/core/control_plane/networking/v1" + "github.com/steady-bytes/draft/pkg/chassis" + "github.com/steady-bytes/draft/pkg/loggers/zerolog" + + "connectrpc.com/connect" +) + +func main() { + var ( + logger = zerolog.New() + ctrl = &controller{logger: logger} + ) + + defer chassis.New(logger). + Register(chassis.RegistrationOptions{ + Namespace: "examples", + }). + WithRPCHandler(ctrl). + // Public route — anyone can call Greet, no token required. + WithRoute(&ntv1.Route{ + Name: "auth-example-greet", + Match: &ntv1.RouteMatch{ + Prefix: "/examples.auth.v1.AuthExampleService/Greet", + }, + Auth: &ntv1.RouteAuth{ + Policy: ntv1.AuthPolicy_AUTH_POLICY_BYPASS, + }, + }). + // Protected route — caller must present a valid bearer token. + WithRoute(&ntv1.Route{ + Name: "auth-example-secret", + Match: &ntv1.RouteMatch{ + Prefix: "/examples.auth.v1.AuthExampleService/Secret", + }, + Auth: &ntv1.RouteAuth{ + Enabled: true, + Policy: ntv1.AuthPolicy_AUTH_POLICY_AUTHENTICATED, + }, + }). + Start() +} + +type controller struct { + logger chassis.Logger +} + +func (c *controller) RegisterRPC(server chassis.Rpcer) { + pattern, handler := authv1Connect.NewAuthExampleServiceHandler(c) + server.AddHandler(pattern, handler, true) +} + +// Greet is public — no auth required by Envoy so this always succeeds. +func (c *controller) Greet(ctx context.Context, req *connect.Request[authv1.GreetRequest]) (*connect.Response[authv1.GreetResponse], error) { + name := req.Msg.Name + if name == "" { + name = "stranger" + } + return connect.NewResponse(&authv1.GreetResponse{ + Message: "Hello, " + name + "! (public endpoint)", + }), nil +} + +// Secret requires a valid token. If the auth service is in bypass mode every +// request reaches here; in authentik mode only authenticated callers do. +// The X-Authentik-Username header is set by the auth service on allow. +func (c *controller) Secret(ctx context.Context, req *connect.Request[authv1.SecretRequest]) (*connect.Response[authv1.SecretResponse], error) { + caller := req.Header().Get("X-Authentik-Username") + if caller == "" { + caller = "anonymous (auth bypass mode)" + } + return connect.NewResponse(&authv1.SecretResponse{ + Caller: caller, + Secret: "the launch codes are: draft-auth-works", + }), nil +} diff --git a/services/examples/consumer/config.yaml b/services/examples/consumer/config.yaml new file mode 100644 index 00000000..8634dfa7 --- /dev/null +++ b/services/examples/consumer/config.yaml @@ -0,0 +1,19 @@ +service: + name: consumer + domain: examples + env: local + entrypoint: http://localhost:2221 + logging: + level: debug + + network: + bind_address: localhost + bind_port: 9092 + internal: + host: localhost + port: 9092 + external: + host: localhost:10000 + +catalyst: + address: http://localhost:2220 diff --git a/services/examples/consumer/consumer b/services/examples/consumer/consumer new file mode 100755 index 00000000..dd5a1889 Binary files /dev/null and b/services/examples/consumer/consumer differ diff --git a/services/examples/consumer/go.mod b/services/examples/consumer/go.mod new file mode 100644 index 00000000..e40349f8 --- /dev/null +++ b/services/examples/consumer/go.mod @@ -0,0 +1,56 @@ +module github.com/steady-bytes/draft/services/examples/consumer + +go 1.23.2 + +replace github.com/steady-bytes/draft/api => ../../../api + +require ( + connectrpc.com/connect v1.16.2 + github.com/steady-bytes/draft/api v1.0.0 + github.com/steady-bytes/draft/pkg/chassis v0.4.4 + github.com/steady-bytes/draft/pkg/loggers v0.2.1 + golang.org/x/net v0.25.0 + google.golang.org/protobuf v1.36.3 +) + +require ( + connectrpc.com/grpcreflect v1.2.0 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/boltdb/bolt v1.3.1 // indirect + github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 // indirect + github.com/envoyproxy/go-control-plane v0.12.0 // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/raft v1.6.0 // indirect + github.com/hashicorp/raft-boltdb/v2 v2.3.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/rs/cors v1.10.1 // indirect + github.com/rs/zerolog v1.32.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.etcd.io/bbolt v1.3.7 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/grpc v1.65.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/services/examples/consumer/go.sum b/services/examples/consumer/go.sum new file mode 100644 index 00000000..801ecc80 --- /dev/null +++ b/services/examples/consumer/go.sum @@ -0,0 +1,226 @@ +connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= +connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= +connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= +connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 h1:VIG8z8W5EDy5cIbv2mH5TufcdZm7p/Nn73GZ6nJaXcQ= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0/go.mod h1:rMOW7HwKadbOR8W4sxYCaHS5TwK0mbpysmDINEfr5SE= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= +github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/raft v1.6.0 h1:tkIAORZy2GbJ2Trp5eUSggLXDPOJLXC+JJLNMMqtgtM= +github.com/hashicorp/raft v1.6.0/go.mod h1:Xil5pDgeGwRWuX4uPUmwa+7Vagg4N804dz6mhNi6S7o= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245 h1:NyeelmxyaUHfDdmhzlEVlrRk+1T9EnlCjvHenrusrfU= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0= +github.com/hashicorp/raft-boltdb/v2 v2.3.0 h1:fPpQR1iGEVYjZ2OELvUHX600VAK5qmdnDEv3eXOwZUA= +github.com/hashicorp/raft-boltdb/v2 v2.3.0/go.mod h1:YHukhB04ChJsLHLJEUD6vjFyLX2L3dsX3wPBZcX4tmc= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/steady-bytes/draft/pkg/chassis v0.4.4 h1:bG139PqiqMRLMh4+NWlB1eHztsIKQX+dSYBL2qhvIkY= +github.com/steady-bytes/draft/pkg/chassis v0.4.4/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM= +github.com/steady-bytes/draft/pkg/loggers v0.2.1 h1:9ng9X87CwuFGvahuKvMTJxUoUQYzqH23EA18YNTVJH0= +github.com/steady-bytes/draft/pkg/loggers v0.2.1/go.mod h1:nXeOQ6lXhsVWHzRqVcJz0JIeSW75ORVN+0izJwwnH+Y= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/services/examples/consumer/main.go b/services/examples/consumer/main.go new file mode 100644 index 00000000..86ed3e2e --- /dev/null +++ b/services/examples/consumer/main.go @@ -0,0 +1,161 @@ +package main + +import ( + "context" + "crypto/tls" + "net" + "net/http" + + acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + acConnect "github.com/steady-bytes/draft/api/core/message_broker/actors/v1/v1connect" + crudv1 "github.com/steady-bytes/draft/api/examples/crud/v1" + userv1 "github.com/steady-bytes/draft/api/examples/user/v1" + "github.com/steady-bytes/draft/pkg/chassis" + "github.com/steady-bytes/draft/pkg/loggers/zerolog" + + "connectrpc.com/connect" + "golang.org/x/net/http2" + "google.golang.org/protobuf/encoding/protojson" +) + +const serviceName = "examples-consumer" + +// eventTypes is the exhaustive list of event types this service processes. +// One Consume stream is opened per type so that each (consumer, event_type) pair +// appears as a distinct edge in the topology view once Phase 4 registration +// tracking is deployed. The broker broadcasts all events to all streams; each +// goroutine filters to its declared type so events are never double-processed. +var eventTypes = []string{ + "examples.crud.v1.DatabaseModelSaved", + "examples.user.v1.UserCreated", + "examples.user.v1.UserLoggedIn", +} + +func main() { + logger := zerolog.New() + + defer chassis.New(logger). + Register(chassis.RegistrationOptions{ + Namespace: "examples", + }). + WithRunner(func() { + run(logger) + }). + Start() +} + +func run(logger chassis.Logger) { + cfg := chassis.GetConfig() + catalystAddr := cfg.GetString("catalyst.address") + if catalystAddr == "" { + catalystAddr = "http://localhost:2220" + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + go func() { + <-chassis.Closer() + cancel() + }() + + client := acConnect.NewConsumerClient(h2cClient(), catalystAddr, connect.WithGRPC()) + + done := make(chan struct{}, len(eventTypes)) + for _, et := range eventTypes { + et := et + go func() { + defer func() { done <- struct{}{} }() + consumeType(ctx, logger, client, et) + }() + } + + for range eventTypes { + <-done + } +} + +func consumeType(ctx context.Context, logger chassis.Logger, client acConnect.ConsumerClient, eventType string) { + req := connect.NewRequest(&acv1.ConsumeRequest{ + Message: &acv1.CloudEvent{ + Source: serviceName, + Type: eventType, + }, + }) + + stream, err := client.Consume(ctx, req) + if err != nil { + logger.WithField("error", err.Error()).WithField("type", eventType).Error("failed to open consume stream") + return + } + + logger.WithField("type", eventType).Info("consumer stream open") + + for stream.Receive() { + event := stream.Msg().GetMessage() + if event == nil || event.Type != eventType { + continue + } + handle(logger, event) + } + + if err := stream.Err(); err != nil && ctx.Err() == nil { + logger.WithField("error", err.Error()).WithField("type", eventType).Error("consume stream ended with error") + } +} + +func handle(logger chassis.Logger, event *acv1.CloudEvent) { + body := []byte(event.GetTextData()) + + switch event.Type { + case "examples.crud.v1.DatabaseModelSaved": + var payload crudv1.DatabaseModelSaved + if err := protojson.Unmarshal(body, &payload); err != nil { + logger.WithField("error", err.Error()).Error("failed to unmarshal DatabaseModelSaved") + return + } + // logger. + // WithField("model_id", payload.ModelId). + // WithField("model_name", payload.ModelName). + // WithField("operation", payload.Operation.String()). + // Info("DatabaseModelSaved received") + + case "examples.user.v1.UserCreated": + var payload userv1.UserCreated + if err := protojson.Unmarshal(body, &payload); err != nil { + logger.WithField("error", err.Error()).Error("failed to unmarshal UserCreated") + return + } + // logger. + // WithField("user_id", payload.UserId). + // WithField("email", payload.Email). + // WithField("name", payload.Name). + // Info("UserCreated received") + + case "examples.user.v1.UserLoggedIn": + var payload userv1.UserLoggedIn + if err := protojson.Unmarshal(body, &payload); err != nil { + logger.WithField("error", err.Error()).Error("failed to unmarshal UserLoggedIn") + return + } + // logger. + // WithField("user_id", payload.UserId). + // WithField("email", payload.Email). + // WithField("login_at", payload.LoginAt.AsTime().String()). + // Info("UserLoggedIn received") + + } +} + +// h2cClient returns an HTTP client that speaks HTTP/2 cleartext (h2c), which +// is required for gRPC streaming against catalyst's plain-TCP server. +func h2cClient() *http.Client { + return &http.Client{ + Transport: &http2.Transport{ + AllowHTTP: true, + DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) { + return net.Dial(network, addr) + }, + }, + } +} diff --git a/services/examples/consumer2/config.yaml b/services/examples/consumer2/config.yaml new file mode 100644 index 00000000..5656667f --- /dev/null +++ b/services/examples/consumer2/config.yaml @@ -0,0 +1,19 @@ +service: + name: consumer2 + domain: examples + env: local + entrypoint: http://localhost:2221 + logging: + level: debug + + network: + bind_address: localhost + bind_port: 9094 + internal: + host: localhost + port: 9094 + external: + host: localhost:10000 + +catalyst: + address: http://localhost:2220 diff --git a/services/examples/consumer2/consumer2 b/services/examples/consumer2/consumer2 new file mode 100755 index 00000000..0f07fa52 Binary files /dev/null and b/services/examples/consumer2/consumer2 differ diff --git a/services/examples/consumer2/go.mod b/services/examples/consumer2/go.mod new file mode 100644 index 00000000..289227a5 --- /dev/null +++ b/services/examples/consumer2/go.mod @@ -0,0 +1,56 @@ +module github.com/steady-bytes/draft/services/examples/consumer2 + +go 1.23.2 + +replace github.com/steady-bytes/draft/api => ../../../api + +require ( + connectrpc.com/connect v1.16.2 + github.com/steady-bytes/draft/api v1.0.0 + github.com/steady-bytes/draft/pkg/chassis v0.4.4 + github.com/steady-bytes/draft/pkg/loggers v0.2.1 + golang.org/x/net v0.25.0 + google.golang.org/protobuf v1.36.3 +) + +require ( + connectrpc.com/grpcreflect v1.2.0 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/boltdb/bolt v1.3.1 // indirect + github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 // indirect + github.com/envoyproxy/go-control-plane v0.12.0 // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/raft v1.6.0 // indirect + github.com/hashicorp/raft-boltdb/v2 v2.3.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/rs/cors v1.10.1 // indirect + github.com/rs/zerolog v1.32.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.etcd.io/bbolt v1.3.7 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/grpc v1.65.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/services/examples/consumer2/go.sum b/services/examples/consumer2/go.sum new file mode 100644 index 00000000..801ecc80 --- /dev/null +++ b/services/examples/consumer2/go.sum @@ -0,0 +1,226 @@ +connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= +connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= +connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= +connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 h1:VIG8z8W5EDy5cIbv2mH5TufcdZm7p/Nn73GZ6nJaXcQ= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0/go.mod h1:rMOW7HwKadbOR8W4sxYCaHS5TwK0mbpysmDINEfr5SE= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= +github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/raft v1.6.0 h1:tkIAORZy2GbJ2Trp5eUSggLXDPOJLXC+JJLNMMqtgtM= +github.com/hashicorp/raft v1.6.0/go.mod h1:Xil5pDgeGwRWuX4uPUmwa+7Vagg4N804dz6mhNi6S7o= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245 h1:NyeelmxyaUHfDdmhzlEVlrRk+1T9EnlCjvHenrusrfU= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0= +github.com/hashicorp/raft-boltdb/v2 v2.3.0 h1:fPpQR1iGEVYjZ2OELvUHX600VAK5qmdnDEv3eXOwZUA= +github.com/hashicorp/raft-boltdb/v2 v2.3.0/go.mod h1:YHukhB04ChJsLHLJEUD6vjFyLX2L3dsX3wPBZcX4tmc= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/steady-bytes/draft/pkg/chassis v0.4.4 h1:bG139PqiqMRLMh4+NWlB1eHztsIKQX+dSYBL2qhvIkY= +github.com/steady-bytes/draft/pkg/chassis v0.4.4/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM= +github.com/steady-bytes/draft/pkg/loggers v0.2.1 h1:9ng9X87CwuFGvahuKvMTJxUoUQYzqH23EA18YNTVJH0= +github.com/steady-bytes/draft/pkg/loggers v0.2.1/go.mod h1:nXeOQ6lXhsVWHzRqVcJz0JIeSW75ORVN+0izJwwnH+Y= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/services/examples/consumer2/main.go b/services/examples/consumer2/main.go new file mode 100644 index 00000000..2957512c --- /dev/null +++ b/services/examples/consumer2/main.go @@ -0,0 +1,139 @@ +package main + +import ( + "context" + "crypto/tls" + "net" + "net/http" + + acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + acConnect "github.com/steady-bytes/draft/api/core/message_broker/actors/v1/v1connect" + echov1 "github.com/steady-bytes/draft/api/examples/echo/v1" + "github.com/steady-bytes/draft/pkg/chassis" + "github.com/steady-bytes/draft/pkg/loggers/zerolog" + + "connectrpc.com/connect" + "golang.org/x/net/http2" + "google.golang.org/protobuf/encoding/protojson" +) + +const serviceName = "examples-consumer2" + +var eventTypes = []string{ + "examples.echo.v1.HelloWorld", + "examples.echo.v1.Ping", + "examples.echo.v1.Pong", +} + +func main() { + logger := zerolog.New() + + defer chassis.New(logger). + Register(chassis.RegistrationOptions{ + Namespace: "examples", + }). + WithRunner(func() { + run(logger) + }). + Start() +} + +func run(logger chassis.Logger) { + cfg := chassis.GetConfig() + catalystAddr := cfg.GetString("catalyst.address") + if catalystAddr == "" { + catalystAddr = "http://localhost:2220" + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + go func() { + <-chassis.Closer() + cancel() + }() + + client := acConnect.NewConsumerClient(h2cClient(), catalystAddr, connect.WithGRPC()) + + done := make(chan struct{}, len(eventTypes)) + for _, et := range eventTypes { + et := et + // Create a goroutine-local logger here (sequential) so that the goroutine + // never shares a logger instance with another goroutine. Concurrent + // WithField chains on a shared logger race on the zerolog context byte + // slice's underlying array in Go 1.24+. + etLogger := logger.WithField("event_type", et) + go func() { + defer func() { done <- struct{}{} }() + consumeType(ctx, etLogger, client, et) + }() + } + + for range eventTypes { + <-done + } +} + +func consumeType(ctx context.Context, logger chassis.Logger, client acConnect.ConsumerClient, eventType string) { + req := connect.NewRequest(&acv1.ConsumeRequest{ + Message: &acv1.CloudEvent{ + Source: serviceName, + Type: eventType, + }, + }) + + stream, err := client.Consume(ctx, req) + if err != nil { + logger.WithField("error", err.Error()).WithField("type", eventType).Error("failed to open consume stream") + return + } + + logger.WithField("type", eventType).Info("consumer stream open") + + for stream.Receive() { + event := stream.Msg().GetMessage() + if event == nil || event.Type != eventType { + continue + } + handle(logger, event) + } + + if err := stream.Err(); err != nil && ctx.Err() == nil { + logger.WithField("error", err.Error()).WithField("type", eventType).Error("consume stream ended with error") + } +} + +func handle(logger chassis.Logger, event *acv1.CloudEvent) { + body := []byte(event.GetTextData()) + + switch event.Type { + case "examples.echo.v1.HelloWorld": + var payload echov1.HelloWorld + if err := protojson.Unmarshal(body, &payload); err != nil { + logger.WithField("error", err.Error()).Error("failed to unmarshal HelloWorld") + } + + case "examples.echo.v1.Ping": + var payload echov1.Ping + if err := protojson.Unmarshal(body, &payload); err != nil { + logger.WithField("error", err.Error()).Error("failed to unmarshal Ping") + } + + case "examples.echo.v1.Pong": + var payload echov1.Pong + if err := protojson.Unmarshal(body, &payload); err != nil { + logger.WithField("error", err.Error()).Error("failed to unmarshal Pong") + } + } +} + +func h2cClient() *http.Client { + return &http.Client{ + Transport: &http2.Transport{ + AllowHTTP: true, + DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) { + return net.Dial(network, addr) + }, + }, + } +} diff --git a/services/examples/producer/config.yaml b/services/examples/producer/config.yaml new file mode 100644 index 00000000..5c751552 --- /dev/null +++ b/services/examples/producer/config.yaml @@ -0,0 +1,19 @@ +service: + name: producer + domain: examples + env: local + entrypoint: http://localhost:2221 + logging: + level: debug + + network: + bind_address: localhost + bind_port: 9091 + internal: + host: localhost + port: 9091 + external: + host: localhost:10000 + +catalyst: + address: http://localhost:2220 diff --git a/services/examples/producer/events/events.go b/services/examples/producer/events/events.go new file mode 100644 index 00000000..393679fe --- /dev/null +++ b/services/examples/producer/events/events.go @@ -0,0 +1,178 @@ +package events + +import ( + "math/rand/v2" + "time" + + "github.com/google/uuid" + acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + crudv1 "github.com/steady-bytes/draft/api/examples/crud/v1" + userv1 "github.com/steady-bytes/draft/api/examples/user/v1" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/types/known/timestamppb" +) + +// ─── Pools ──────────────────────────────────────────────────────────────────── + +type modelKind struct { + name string + source string +} + +var modelPool = []modelKind{ + {"User", "/services/user-service"}, + {"Product", "/services/catalog-service"}, + {"Order", "/services/order-service"}, + {"Cart", "/services/cart-service"}, + {"Invoice", "/services/billing-service"}, + {"Payment", "/services/payment-service"}, + {"Shipment", "/services/fulfillment-service"}, + {"Review", "/services/review-service"}, +} + +type fakeUser struct { + name string + email string +} + +var userPool = []fakeUser{ + {"Alice Martin", "alice.martin@example.com"}, + {"Bob Chen", "bob.chen@example.com"}, + {"Carol Davis", "carol.davis@example.com"}, + {"Daniel Kim", "daniel.kim@example.com"}, + {"Emma Wilson", "emma.wilson@example.com"}, + {"Frank Torres", "frank.torres@example.com"}, + {"Grace Lee", "grace.lee@example.com"}, + {"Henry Brown", "henry.brown@example.com"}, + {"Isabel Garcia", "isabel.garcia@example.com"}, + {"Jack Murphy", "jack.murphy@example.com"}, +} + +// operations weighted toward CREATE and UPDATE since deletes are rarer. +var weightedOps = []crudv1.Operation{ + crudv1.Operation_OPERATION_CREATE, + crudv1.Operation_OPERATION_CREATE, + crudv1.Operation_OPERATION_CREATE, + crudv1.Operation_OPERATION_UPDATE, + crudv1.Operation_OPERATION_UPDATE, + crudv1.Operation_OPERATION_DELETE, +} + +// ─── Random generators ──────────────────────────────────────────────────────── + +// Random returns a randomly-selected CloudEvent drawn from the available event +// types. The distribution is weighted: 50 % DatabaseModelSaved, 30 % +// UserLoggedIn, 20 % UserCreated. +func Random() (*acv1.CloudEvent, error) { + n := rand.IntN(10) + switch { + case n < 5: + return RandomDatabaseModelSaved() + case n < 8: + return RandomUserLoggedIn() + default: + return RandomUserCreated() + } +} + +func RandomDatabaseModelSaved() (*acv1.CloudEvent, error) { + m := modelPool[rand.IntN(len(modelPool))] + op := weightedOps[rand.IntN(len(weightedOps))] + return NewDatabaseModelSaved(uuid.NewString(), m.name, op, m.source) +} + +func RandomUserCreated() (*acv1.CloudEvent, error) { + u := userPool[rand.IntN(len(userPool))] + return NewUserCreated(uuid.NewString(), u.email, u.name) +} + +func RandomUserLoggedIn() (*acv1.CloudEvent, error) { + u := userPool[rand.IntN(len(userPool))] + return NewUserLoggedIn(uuid.NewString(), u.email) +} + +// ─── Explicit constructors ──────────────────────────────────────────────────── + +func NewDatabaseModelSaved(modelID, modelName string, op crudv1.Operation, source string) (*acv1.CloudEvent, error) { + b, err := protojson.Marshal(&crudv1.DatabaseModelSaved{ + ModelId: modelID, + ModelName: modelName, + Operation: op, + }) + if err != nil { + return nil, err + } + return &acv1.CloudEvent{ + Id: uuid.NewString(), + Source: source, + SpecVersion: "1.0", + Type: "examples.crud.v1.DatabaseModelSaved", + Data: &acv1.CloudEvent_TextData{TextData: string(b)}, + Attributes: map[string]*acv1.CloudEvent_CloudEventAttributeValue{ + "time": timeAttr(), + "subject": subjectAttr(modelID), + }, + }, nil +} + +func NewUserCreated(userID, email, name string) (*acv1.CloudEvent, error) { + b, err := protojson.Marshal(&userv1.UserCreated{ + UserId: userID, + Email: email, + Name: name, + }) + if err != nil { + return nil, err + } + return &acv1.CloudEvent{ + Id: uuid.NewString(), + Source: "/services/user-service", + SpecVersion: "1.0", + Type: "examples.user.v1.UserCreated", + Data: &acv1.CloudEvent_TextData{TextData: string(b)}, + Attributes: map[string]*acv1.CloudEvent_CloudEventAttributeValue{ + "time": timeAttr(), + "subject": subjectAttr(userID), + }, + }, nil +} + +func NewUserLoggedIn(userID, email string) (*acv1.CloudEvent, error) { + b, err := protojson.Marshal(&userv1.UserLoggedIn{ + UserId: userID, + Email: email, + LoginAt: timestamppb.New(time.Now()), + }) + if err != nil { + return nil, err + } + return &acv1.CloudEvent{ + Id: uuid.NewString(), + Source: "/services/user-service", + SpecVersion: "1.0", + Type: "examples.user.v1.UserLoggedIn", + Data: &acv1.CloudEvent_TextData{TextData: string(b)}, + Attributes: map[string]*acv1.CloudEvent_CloudEventAttributeValue{ + "time": timeAttr(), + "subject": subjectAttr(userID), + }, + }, nil +} + +// ─── Attribute helpers ──────────────────────────────────────────────────────── + +func timeAttr() *acv1.CloudEvent_CloudEventAttributeValue { + return &acv1.CloudEvent_CloudEventAttributeValue{ + Attr: &acv1.CloudEvent_CloudEventAttributeValue_CeTimestamp{ + CeTimestamp: timestamppb.Now(), + }, + } +} + +func subjectAttr(s string) *acv1.CloudEvent_CloudEventAttributeValue { + return &acv1.CloudEvent_CloudEventAttributeValue{ + Attr: &acv1.CloudEvent_CloudEventAttributeValue_CeString{ + CeString: s, + }, + } +} diff --git a/services/examples/producer/go.mod b/services/examples/producer/go.mod new file mode 100644 index 00000000..02865b30 --- /dev/null +++ b/services/examples/producer/go.mod @@ -0,0 +1,57 @@ +module github.com/steady-bytes/draft/services/examples/producer + +go 1.23.2 + +replace github.com/steady-bytes/draft/api => ../../../api + +require ( + connectrpc.com/connect v1.16.2 + github.com/google/uuid v1.6.0 + github.com/steady-bytes/draft/api v1.0.0 + github.com/steady-bytes/draft/pkg/chassis v0.4.4 + github.com/steady-bytes/draft/pkg/loggers v0.2.1 + golang.org/x/net v0.25.0 + google.golang.org/protobuf v1.36.3 +) + +require ( + connectrpc.com/grpcreflect v1.2.0 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/boltdb/bolt v1.3.1 // indirect + github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 // indirect + github.com/envoyproxy/go-control-plane v0.12.0 // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/raft v1.6.0 // indirect + github.com/hashicorp/raft-boltdb/v2 v2.3.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/rs/cors v1.10.1 // indirect + github.com/rs/zerolog v1.32.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.etcd.io/bbolt v1.3.7 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/grpc v1.65.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/services/examples/producer/go.sum b/services/examples/producer/go.sum new file mode 100644 index 00000000..93b96b2e --- /dev/null +++ b/services/examples/producer/go.sum @@ -0,0 +1,228 @@ +connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= +connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= +connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= +connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 h1:VIG8z8W5EDy5cIbv2mH5TufcdZm7p/Nn73GZ6nJaXcQ= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0/go.mod h1:rMOW7HwKadbOR8W4sxYCaHS5TwK0mbpysmDINEfr5SE= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= +github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/raft v1.6.0 h1:tkIAORZy2GbJ2Trp5eUSggLXDPOJLXC+JJLNMMqtgtM= +github.com/hashicorp/raft v1.6.0/go.mod h1:Xil5pDgeGwRWuX4uPUmwa+7Vagg4N804dz6mhNi6S7o= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245 h1:NyeelmxyaUHfDdmhzlEVlrRk+1T9EnlCjvHenrusrfU= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0= +github.com/hashicorp/raft-boltdb/v2 v2.3.0 h1:fPpQR1iGEVYjZ2OELvUHX600VAK5qmdnDEv3eXOwZUA= +github.com/hashicorp/raft-boltdb/v2 v2.3.0/go.mod h1:YHukhB04ChJsLHLJEUD6vjFyLX2L3dsX3wPBZcX4tmc= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/steady-bytes/draft/pkg/chassis v0.4.4 h1:bG139PqiqMRLMh4+NWlB1eHztsIKQX+dSYBL2qhvIkY= +github.com/steady-bytes/draft/pkg/chassis v0.4.4/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM= +github.com/steady-bytes/draft/pkg/loggers v0.2.1 h1:9ng9X87CwuFGvahuKvMTJxUoUQYzqH23EA18YNTVJH0= +github.com/steady-bytes/draft/pkg/loggers v0.2.1/go.mod h1:nXeOQ6lXhsVWHzRqVcJz0JIeSW75ORVN+0izJwwnH+Y= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/services/examples/producer/main.go b/services/examples/producer/main.go new file mode 100644 index 00000000..a4c6903f --- /dev/null +++ b/services/examples/producer/main.go @@ -0,0 +1,111 @@ +package main + +import ( + "context" + "crypto/tls" + "math/rand/v2" + "net" + "net/http" + "time" + + acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + acConnect "github.com/steady-bytes/draft/api/core/message_broker/actors/v1/v1connect" + "github.com/steady-bytes/draft/pkg/chassis" + "github.com/steady-bytes/draft/pkg/loggers/zerolog" + "github.com/steady-bytes/draft/services/examples/producer/events" + + "connectrpc.com/connect" + "golang.org/x/net/http2" +) + +func main() { + logger := zerolog.New() + + defer chassis.New(logger). + Register(chassis.RegistrationOptions{ + Namespace: "examples", + }). + WithRunner(func() { + run(logger) + }). + Start() +} + +func run(logger chassis.Logger) { + cfg := chassis.GetConfig() + catalystAddr := cfg.GetString("catalyst.address") + if catalystAddr == "" { + catalystAddr = "http://localhost:2220" + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + go func() { + <-chassis.Closer() + cancel() + }() + + client := acConnect.NewProducerClient(h2cClient(), catalystAddr, connect.WithGRPC()) + stream := client.Produce(ctx) + + for { + delay, count := nextBurst() + + select { + case <-ctx.Done(): + return + case <-time.After(delay): + for range count { + emit(logger, stream, events.Random) + } + } + } +} + +// nextBurst returns a randomised (delay, eventCount) pair that models three +// traffic modes observed in real applications: +// +// - Normal (80 %): 100 ms – 1 s delay, 50 – 150 events — steady background activity +// - Quiet (15 %): 2 s – 8 s delay, 2 – 10 events — idle gaps between actions +// - Burst (5 %): 10 ms – 150 ms delay, 800 – 1 200 events — spikes from batch jobs / fan-out +func nextBurst() (time.Duration, int) { + n := rand.IntN(20) + switch { + case n < 1: // 5 %: burst + return randDuration(10, 150), rand.IntN(1500) + 800 + case n < 4: // 15 %: quiet + return randDuration(2000, 8000), rand.IntN(100) + 2 + default: // 80 %: normal + return randDuration(100, 1000), rand.IntN(1000) + 50 + } +} + +func randDuration(minMs, maxMs int) time.Duration { + return time.Duration(rand.IntN(maxMs-minMs)+minMs) * time.Millisecond +} + +func emit(logger chassis.Logger, stream *connect.BidiStreamForClient[acv1.ProduceRequest, acv1.ProduceResponse], build func() (*acv1.CloudEvent, error)) { + event, err := build() + if err != nil { + logger.WithField("error", err.Error()).Error("failed to build event") + return + } + if err := stream.Send(&acv1.ProduceRequest{Message: event}); err != nil { + logger.WithField("error", err.Error()).Error("failed to send event") + return + } +} + +// h2cClient returns an HTTP client that speaks HTTP/2 cleartext (h2c), which +// is required for gRPC streaming against catalyst's plain-TCP server. +func h2cClient() *http.Client { + return &http.Client{ + Transport: &http2.Transport{ + AllowHTTP: true, + DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) { + return net.Dial(network, addr) + }, + }, + } +} diff --git a/services/examples/producer2/config.yaml b/services/examples/producer2/config.yaml new file mode 100644 index 00000000..2fcc55ee --- /dev/null +++ b/services/examples/producer2/config.yaml @@ -0,0 +1,19 @@ +service: + name: producer2 + domain: examples + env: local + entrypoint: http://localhost:2221 + logging: + level: debug + + network: + bind_address: localhost + bind_port: 9093 + internal: + host: localhost + port: 9093 + external: + host: localhost:10000 + +catalyst: + address: http://localhost:2220 diff --git a/services/examples/producer2/events/events.go b/services/examples/producer2/events/events.go new file mode 100644 index 00000000..c48a22f1 --- /dev/null +++ b/services/examples/producer2/events/events.go @@ -0,0 +1,138 @@ +package events + +import ( + "math/rand/v2" + + "github.com/google/uuid" + acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + echov1 "github.com/steady-bytes/draft/api/examples/echo/v1" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/types/known/timestamppb" +) + +var senders = []string{ + "/services/gateway", + "/services/scheduler", + "/services/cli", + "/services/webhook", + "/services/mobile-app", +} + +var greetings = []string{ + "Hello from the other side", + "Greetings, world!", + "Hi there", + "Hey!", + "Salutations", + "Howdy", + "What's up", +} + +// Random returns a randomly-selected CloudEvent. Distribution: 40% HelloWorld, +// 30% Ping, 30% Pong. +func Random() (*acv1.CloudEvent, error) { + n := rand.IntN(10) + switch { + case n < 4: + return RandomHelloWorld() + case n < 7: + return RandomPing() + default: + return RandomPong() + } +} + +func RandomHelloWorld() (*acv1.CloudEvent, error) { + sender := senders[rand.IntN(len(senders))] + msg := greetings[rand.IntN(len(greetings))] + return NewHelloWorld(uuid.NewString(), msg, sender) +} + +func RandomPing() (*acv1.CloudEvent, error) { + sender := senders[rand.IntN(len(senders))] + return NewPing(uuid.NewString(), sender) +} + +func RandomPong() (*acv1.CloudEvent, error) { + responder := senders[rand.IntN(len(senders))] + return NewPong(uuid.NewString(), uuid.NewString(), responder) +} + +func NewHelloWorld(id, message, sender string) (*acv1.CloudEvent, error) { + b, err := protojson.Marshal(&echov1.HelloWorld{ + Message: message, + Sender: sender, + }) + if err != nil { + return nil, err + } + return &acv1.CloudEvent{ + Id: uuid.NewString(), + Source: sender, + SpecVersion: "1.0", + Type: "examples.echo.v1.HelloWorld", + Data: &acv1.CloudEvent_TextData{TextData: string(b)}, + Attributes: map[string]*acv1.CloudEvent_CloudEventAttributeValue{ + "time": timeAttr(), + "subject": subjectAttr(id), + }, + }, nil +} + +func NewPing(id, sender string) (*acv1.CloudEvent, error) { + b, err := protojson.Marshal(&echov1.Ping{ + Id: id, + Sender: sender, + }) + if err != nil { + return nil, err + } + return &acv1.CloudEvent{ + Id: uuid.NewString(), + Source: sender, + SpecVersion: "1.0", + Type: "examples.echo.v1.Ping", + Data: &acv1.CloudEvent_TextData{TextData: string(b)}, + Attributes: map[string]*acv1.CloudEvent_CloudEventAttributeValue{ + "time": timeAttr(), + "subject": subjectAttr(id), + }, + }, nil +} + +func NewPong(id, pingID, responder string) (*acv1.CloudEvent, error) { + b, err := protojson.Marshal(&echov1.Pong{ + PingId: pingID, + Responder: responder, + }) + if err != nil { + return nil, err + } + return &acv1.CloudEvent{ + Id: uuid.NewString(), + Source: responder, + SpecVersion: "1.0", + Type: "examples.echo.v1.Pong", + Data: &acv1.CloudEvent_TextData{TextData: string(b)}, + Attributes: map[string]*acv1.CloudEvent_CloudEventAttributeValue{ + "time": timeAttr(), + "subject": subjectAttr(id), + }, + }, nil +} + +func timeAttr() *acv1.CloudEvent_CloudEventAttributeValue { + return &acv1.CloudEvent_CloudEventAttributeValue{ + Attr: &acv1.CloudEvent_CloudEventAttributeValue_CeTimestamp{ + CeTimestamp: timestamppb.Now(), + }, + } +} + +func subjectAttr(s string) *acv1.CloudEvent_CloudEventAttributeValue { + return &acv1.CloudEvent_CloudEventAttributeValue{ + Attr: &acv1.CloudEvent_CloudEventAttributeValue_CeString{ + CeString: s, + }, + } +} diff --git a/services/examples/producer2/go.mod b/services/examples/producer2/go.mod new file mode 100644 index 00000000..383aa2b5 --- /dev/null +++ b/services/examples/producer2/go.mod @@ -0,0 +1,57 @@ +module github.com/steady-bytes/draft/services/examples/producer2 + +go 1.23.2 + +replace github.com/steady-bytes/draft/api => ../../../api + +require ( + connectrpc.com/connect v1.16.2 + github.com/google/uuid v1.6.0 + github.com/steady-bytes/draft/api v1.0.0 + github.com/steady-bytes/draft/pkg/chassis v0.4.4 + github.com/steady-bytes/draft/pkg/loggers v0.2.1 + golang.org/x/net v0.25.0 + google.golang.org/protobuf v1.36.3 +) + +require ( + connectrpc.com/grpcreflect v1.2.0 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/boltdb/bolt v1.3.1 // indirect + github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 // indirect + github.com/envoyproxy/go-control-plane v0.12.0 // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/raft v1.6.0 // indirect + github.com/hashicorp/raft-boltdb/v2 v2.3.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/rs/cors v1.10.1 // indirect + github.com/rs/zerolog v1.32.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.etcd.io/bbolt v1.3.7 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/grpc v1.65.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/services/examples/producer2/go.sum b/services/examples/producer2/go.sum new file mode 100644 index 00000000..93b96b2e --- /dev/null +++ b/services/examples/producer2/go.sum @@ -0,0 +1,228 @@ +connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= +connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= +connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U= +connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0 h1:VIG8z8W5EDy5cIbv2mH5TufcdZm7p/Nn73GZ6nJaXcQ= +github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.15.0/go.mod h1:rMOW7HwKadbOR8W4sxYCaHS5TwK0mbpysmDINEfr5SE= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= +github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/raft v1.6.0 h1:tkIAORZy2GbJ2Trp5eUSggLXDPOJLXC+JJLNMMqtgtM= +github.com/hashicorp/raft v1.6.0/go.mod h1:Xil5pDgeGwRWuX4uPUmwa+7Vagg4N804dz6mhNi6S7o= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245 h1:NyeelmxyaUHfDdmhzlEVlrRk+1T9EnlCjvHenrusrfU= +github.com/hashicorp/raft-boltdb v0.0.0-20231115180007-027066e4d245/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0= +github.com/hashicorp/raft-boltdb/v2 v2.3.0 h1:fPpQR1iGEVYjZ2OELvUHX600VAK5qmdnDEv3eXOwZUA= +github.com/hashicorp/raft-boltdb/v2 v2.3.0/go.mod h1:YHukhB04ChJsLHLJEUD6vjFyLX2L3dsX3wPBZcX4tmc= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/steady-bytes/draft/pkg/chassis v0.4.4 h1:bG139PqiqMRLMh4+NWlB1eHztsIKQX+dSYBL2qhvIkY= +github.com/steady-bytes/draft/pkg/chassis v0.4.4/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM= +github.com/steady-bytes/draft/pkg/loggers v0.2.1 h1:9ng9X87CwuFGvahuKvMTJxUoUQYzqH23EA18YNTVJH0= +github.com/steady-bytes/draft/pkg/loggers v0.2.1/go.mod h1:nXeOQ6lXhsVWHzRqVcJz0JIeSW75ORVN+0izJwwnH+Y= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/services/examples/producer2/main.go b/services/examples/producer2/main.go new file mode 100644 index 00000000..e22f5744 --- /dev/null +++ b/services/examples/producer2/main.go @@ -0,0 +1,105 @@ +package main + +import ( + "context" + "crypto/tls" + "math/rand/v2" + "net" + "net/http" + "time" + + acv1 "github.com/steady-bytes/draft/api/core/message_broker/actors/v1" + acConnect "github.com/steady-bytes/draft/api/core/message_broker/actors/v1/v1connect" + "github.com/steady-bytes/draft/pkg/chassis" + "github.com/steady-bytes/draft/pkg/loggers/zerolog" + "github.com/steady-bytes/draft/services/examples/producer2/events" + + "connectrpc.com/connect" + "golang.org/x/net/http2" +) + +func main() { + logger := zerolog.New() + + defer chassis.New(logger). + Register(chassis.RegistrationOptions{ + Namespace: "examples", + }). + WithRunner(func() { + run(logger) + }). + Start() +} + +func run(logger chassis.Logger) { + cfg := chassis.GetConfig() + catalystAddr := cfg.GetString("catalyst.address") + if catalystAddr == "" { + catalystAddr = "http://localhost:2220" + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + go func() { + <-chassis.Closer() + cancel() + }() + + client := acConnect.NewProducerClient(h2cClient(), catalystAddr, connect.WithGRPC()) + stream := client.Produce(ctx) + + for { + delay, count := nextBurst() + + select { + case <-ctx.Done(): + return + case <-time.After(delay): + for range count { + emit(logger, stream, events.Random) + } + } + } +} + +// nextBurst returns a randomised (delay, eventCount) pair modelling three +// traffic modes: Normal (80%), Quiet (15%), Burst (5%). +func nextBurst() (time.Duration, int) { + n := rand.IntN(20) + switch { + case n < 1: // 5%: burst + return randDuration(10, 150), rand.IntN(1500) + 800 + case n < 4: // 15%: quiet + return randDuration(2000, 8000), rand.IntN(100) + 2 + default: // 80%: normal + return randDuration(100, 1000), rand.IntN(1000) + 50 + } +} + +func randDuration(minMs, maxMs int) time.Duration { + return time.Duration(rand.IntN(maxMs-minMs)+minMs) * time.Millisecond +} + +func emit(logger chassis.Logger, stream *connect.BidiStreamForClient[acv1.ProduceRequest, acv1.ProduceResponse], build func() (*acv1.CloudEvent, error)) { + event, err := build() + if err != nil { + logger.WithField("error", err.Error()).Error("failed to build event") + return + } + if err := stream.Send(&acv1.ProduceRequest{Message: event}); err != nil { + logger.WithField("error", err.Error()).Error("failed to send event") + return + } +} + +func h2cClient() *http.Client { + return &http.Client{ + Transport: &http2.Transport{ + AllowHTTP: true, + DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) { + return net.Dial(network, addr) + }, + }, + } +} diff --git a/tools/dctl/cmd/broker/consume.go b/tools/dctl/cmd/broker/consume.go index 6a2941d3..2c7cfbbb 100644 --- a/tools/dctl/cmd/broker/consume.go +++ b/tools/dctl/cmd/broker/consume.go @@ -54,9 +54,9 @@ func Consume(cmd *cobra.Command, args []string) error { msg := &acv1.CloudEvent{ Id: uuid.NewString(), - Source: string(value.ProtoReflect().Descriptor().FullName()), + Source: "dctl", SpecVersion: "v1", - Type: string(value.ProtoReflect().Descriptor().Name()), + Type: "", Attributes: attrs, Data: &acv1.CloudEvent_ProtoData{ ProtoData: a, diff --git a/tools/dioxus-grpc/.editorconfig b/tools/dioxus-grpc/.editorconfig new file mode 100644 index 00000000..39928c6b --- /dev/null +++ b/tools/dioxus-grpc/.editorconfig @@ -0,0 +1,5 @@ +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +end_of_line = lf diff --git a/tools/dioxus-grpc/.gitignore b/tools/dioxus-grpc/.gitignore new file mode 100644 index 00000000..3f56a249 --- /dev/null +++ b/tools/dioxus-grpc/.gitignore @@ -0,0 +1,5 @@ +**/target +examples/src/hook/* +examples/src/proto/* +!examples/src/hook/mod.rs + diff --git a/tools/dioxus-grpc/Cargo.lock b/tools/dioxus-grpc/Cargo.lock new file mode 100644 index 00000000..55bed347 --- /dev/null +++ b/tools/dioxus-grpc/Cargo.lock @@ -0,0 +1,445 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "convert_case" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "dioxus-grpc" +version = "0.1.0" +dependencies = [ + "convert_case", + "tonic-build", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "multimap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "prettyplease" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +dependencies = [ + "heck", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "syn" +version = "2.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "tonic-build" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85f0383fadd15609306383a90e85eaed44169f931a5d2be1b42c76ceff1825e" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] diff --git a/tools/dioxus-grpc/Cargo.toml b/tools/dioxus-grpc/Cargo.toml new file mode 100644 index 00000000..8fc21485 --- /dev/null +++ b/tools/dioxus-grpc/Cargo.toml @@ -0,0 +1,143 @@ +[package] + categories = ["api-bindings", "gui", "wasm", "web-programming"] + description = "Easy interface for a gRPC client with Dioxus " + documentation = "" + edition = "2024" + exclude = ["/clippy.toml", "/examples", "/justfile", "/rustfmt.toml", "/taplo.toml"] + keywords = ["dioxus", "grpc", "wasm"] + license = "LGPL-3.0-or-later" + name = "dioxus-grpc" + readme = "README.md" + repository = "https://github.com/steady-bytes/draft/tools/dioxus-grpc" + version = "0.1.0" + +[features] + default = ["codegen"] + codegen = ["dep:convert_case", "dep:tonic-build"] + web = [] + +[dependencies] + convert_case = { version = "0.8.0", optional = true } + tonic-build = { version = "0.13", default-features = false, features = ["prost"], optional = true } + +# +[lints.clippy] + # Have false positives + borrow_deref_ref = "allow" + deref_addrof = "allow" + drain_collect = "allow" + + # Based + allow_attributes_without_reason = "warn" + clear_with_drain = "warn" + clone_on_ref_ptr = "warn" + cloned_instead_of_copied = "warn" + collection_is_never_read = "warn" + create_dir = "warn" + elidable_lifetime_names = "warn" + empty_drop = "warn" + empty_enum_variants_with_brackets = "warn" + empty_structs_with_brackets = "warn" + explicit_into_iter_loop = "warn" + filetype_is_file = "warn" + filter_map_next = "warn" + flat_map_option = "warn" + ignored_unit_patterns = "warn" + impl_trait_in_params = "warn" + index_refutable_slice = "warn" + inefficient_to_string = "warn" + iter_filter_is_ok = "warn" + iter_filter_is_some = "warn" + iter_on_empty_collections = "warn" + iter_with_drain = "warn" + manual_assert = "warn" + match_same_arms = "warn" + match_wildcard_for_single_variants = "warn" + mismatching_type_param_order = "warn" + mixed_read_write_in_expression = "warn" + mut_mut = "warn" + needless_collect = "warn" + needless_continue = "warn" + needless_raw_string_hashes = "warn" + non_std_lazy_statics = "warn" + nonstandard_macro_braces = "warn" + option_as_ref_cloned = "warn" + or_fun_call = "warn" + pub_without_shorthand = "deny" + redundant_closure_for_method_calls = "warn" + same_name_method = "warn" + self_named_module_files = "deny" + semicolon_if_nothing_returned = "warn" + significant_drop_in_scrutinee = "warn" + single_char_pattern = "warn" + str_split_at_newline = "warn" + string_to_string = "warn" + trait_duplication_in_bounds = "warn" + undocumented_unsafe_blocks = "warn" + unnested_or_patterns = "warn" + unreadable_literal = "warn" + unused_async = "warn" + unused_peekable = "warn" + unused_result_ok = "warn" + unused_rounding = "warn" + unused_self = "warn" + verbose_bit_mask = "warn" + verbose_file_reads = "warn" + + # Mid + branches_sharing_code = "warn" + cfg_not_test = "warn" + cognitive_complexity = "warn" + comparison_chain = "warn" + doc_link_with_quotes = "warn" + empty_enum = "warn" + equatable_if_let = "warn" + if_not_else = "warn" + iter_on_single_items = "warn" + large_digit_groups = "warn" + manual_midpoint = "warn" + match_on_vec_items = "warn" + negative_feature_names = "warn" + option_option = "warn" + path_buf_push_overwrite = "warn" + redundant_type_annotations = "warn" + rest_pat_in_fully_bound_structs = "warn" + string_lit_chars_any = "warn" + type_repetition_in_bounds = "warn" + uninlined_format_args = "warn" + + # Controversial + as_conversions = "deny" + assigning_clones = "warn" + bool_to_int_with_if = "warn" + decimal_literal_representation = "warn" # with clippy.toml `literal-representation-threshold` + default_trait_access = "warn" + derive_partial_eq_without_eq = "warn" + doc_link_code = "warn" + fallible_impl_from = "warn" + format_push_string = "warn" + from_iter_instead_of_collect = "warn" + implicit_clone = "warn" + items_after_statements = "warn" + literal_string_with_formatting_args = "warn" + manual_string_new = "warn" + map_unwrap_or = "warn" + map_with_unused_argument_over_ranges = "warn" + missing_const_for_fn = "warn" + needless_for_each = "warn" + needless_pass_by_ref_mut = "warn" + needless_pass_by_value = "warn" # Not true everytime tho + non_zero_suggestions = "warn" + ref_option_ref = "warn" + string_lit_as_bytes = "warn" + too_long_first_doc_paragraph = "warn" + trivial_regex = "warn" + unchecked_duration_subtraction = "warn" + unnecessary_join = "warn" + unwrap_used = "warn" # With clippy.toml `allow-unwrap-in-test` + + # Removing + enum_variant_names = "allow" + too_many_arguments = "allow" + type_complexity = "allow" + upper_case_acronyms = "allow" diff --git a/tools/dioxus-grpc/README.md b/tools/dioxus-grpc/README.md new file mode 100644 index 00000000..e523b5af --- /dev/null +++ b/tools/dioxus-grpc/README.md @@ -0,0 +1,69 @@ +

dioxus-grpc

+ +`dioxus-grpc` provides a convenient way to use `gRPC` with `Dioxus` + +## Example + +```rs +fn app() -> Element { + let req = use_signal(|| HelloRequest { name: String::new() }); + let greeter = use_greeter_service(); + + rsx! { + input { + value: "{req().name}", + oninput: move |event| req.write().name = event.value() + } + match &*greeter.say_hello(req).read() { + Some(Ok(resp)) => rsx!{"[{resp.message}] - From server"}, + Some(Err(err)) => rsx!{"Couldn't get the name {err:#?}"}, + None => rsx!{"..."}, + } + } +} +``` + +```proto +syntax = "proto3"; + +package helloworld; + +service Greeter { + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +message HelloRequest { + string name = 1; +} + +message HelloReply { + string message = 1; +} +``` + + +## How to use ? + +_By default, this is meant for `mobile` & `desktop`. But you can activate it for `web` with `feature = "web"`_ + +To use it, you will need to also use `tonic-build` (and disable the `transport` feature in case of `feature = "web`). Therefore, something like: + +```toml +[build-dependencies] + dioxus-grpc = "*" + tonic-build = "0.13" + # For web: + # tonic-build = { version = "0.13", default-features = false, features = ["prost"] } +``` + +But, you will also need to import some runtime dependencies: + +```toml +[dependencies] + dioxus = { version = "0.6", features = ["mobile"] } + tonic = "0.13" + prost = "0.13" + # For web: + # tonic = { version = "0.13", default-features = false, features = ["codegen", "prost"] } + # tonic-web-wasm-client = "0.7" +``` diff --git a/tools/dioxus-grpc/clippy.toml b/tools/dioxus-grpc/clippy.toml new file mode 100644 index 00000000..a2daf5bc --- /dev/null +++ b/tools/dioxus-grpc/clippy.toml @@ -0,0 +1,2 @@ +allow-unwrap-in-tests = true +literal-representation-threshold = 16384 diff --git a/tools/dioxus-grpc/examples/Cargo.lock b/tools/dioxus-grpc/examples/Cargo.lock new file mode 100644 index 00000000..9d20d4b3 --- /dev/null +++ b/tools/dioxus-grpc/examples/Cargo.lock @@ -0,0 +1,5805 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "ashpd" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093" +dependencies = [ + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.8.5", + "serde", + "serde_repr", + "tokio", + "url", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-io" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 0.38.44", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 0.38.44", + "tracing", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.44", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[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-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "axum" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +dependencies = [ + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa 1.0.15", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +dependencies = [ + "serde", +] + +[[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 = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" +dependencies = [ + "objc2 0.6.1", +] + +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.9.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 = "cc" +version = "1.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" +dependencies = [ + "shlex", +] + +[[package]] +name = "cesu8" +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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation 0.1.2", + "core-foundation 0.9.4", + "core-graphics 0.23.2", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2" +dependencies = [ + "bitflags 2.9.0", + "block", + "cocoa-foundation 0.2.0", + "core-foundation 0.10.0", + "core-graphics 0.24.0", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d" +dependencies = [ + "bitflags 2.9.0", + "block", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", + "libc", + "objc", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "const-serialize" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08259976d62c715c4826cb4a3d64a3a9e5c5f68f964ff6087319857f569f93a6" +dependencies = [ + "const-serialize-macro", + "serde", +] + +[[package]] +name = "const-serialize-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04382d0d9df7434af6b1b49ea1a026ef39df1b0738b1cc373368cf175354f6eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "const_format" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "convert_case" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.9.0", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.9.0", + "core-foundation 0.10.0", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa 0.4.8", + "matches", + "phf 0.8.0", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.101", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +dependencies = [ + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.101", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dioxus" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a247114500f1a78e87022defa8173de847accfada8e8809dfae23a118a580c" +dependencies = [ + "dioxus-cli-config", + "dioxus-config-macro", + "dioxus-core", + "dioxus-core-macro", + "dioxus-devtools", + "dioxus-document", + "dioxus-fullstack", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-logger", + "dioxus-mobile", + "dioxus-signals", + "dioxus-web", + "manganis", + "warnings", +] + +[[package]] +name = "dioxus-cli-config" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd16948f1ffdb068dd9a64812158073a4250e2af4e98ea31fdac0312e6bce86" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "dioxus-config-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75cbf582fbb1c32d34a1042ea675469065574109c95154468710a4d73ee98b49" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "dioxus-core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c03f451a119e47433c16e2d8eb5b15bf7d6e6734eb1a4c47574e6711dadff8d" +dependencies = [ + "const_format", + "dioxus-core-types", + "futures-channel", + "futures-util", + "generational-box", + "longest-increasing-subsequence", + "rustc-hash", + "rustversion", + "serde", + "slab", + "slotmap", + "tracing", + "warnings", +] + +[[package]] +name = "dioxus-core-macro" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "105c954caaaedf8cd10f3d1ba576b01e18aa8d33ad435182125eefe488cf0064" +dependencies = [ + "convert_case 0.6.0", + "dioxus-rsx", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "dioxus-core-types" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91a82fccfa48574eb7aa183e297769540904694844598433a9eb55896ad9f93b" +dependencies = [ + "once_cell", +] + +[[package]] +name = "dioxus-desktop" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b0cca3e7a10a4a3df37ea52c4cc7a53e5c9233489e03ee3f2829471fc3099a" +dependencies = [ + "async-trait", + "base64", + "cocoa 0.25.0", + "core-foundation 0.9.4", + "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", + "generational-box", + "global-hotkey", + "infer", + "jni", + "lazy-js-bundle", + "muda 0.11.5", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "objc_id", + "once_cell", + "rfd", + "rustc-hash", + "serde", + "serde_json", + "signal-hook", + "slab", + "tao", + "thiserror 1.0.69", + "tokio", + "tracing", + "tray-icon", + "urlencoding", + "webbrowser", + "wry", +] + +[[package]] +name = "dioxus-devtools" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a7300f1e8181218187b03502044157eef04e0a25b518117c5ef9ae1096880" +dependencies = [ + "dioxus-core", + "dioxus-devtools-types", + "dioxus-signals", + "serde", + "serde_json", + "tracing", + "tungstenite", + "warnings", +] + +[[package]] +name = "dioxus-devtools-types" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f62434973c0c9c5a3bc42e9cd5e7070401c2062a437fb5528f318c3e42ebf4ff" +dependencies = [ + "dioxus-core", + "serde", +] + +[[package]] +name = "dioxus-document" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "802a2014d1662b6615eec0a275745822ee4fc66aacd9d0f2fb33d6c8da79b8f2" +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.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe99b48a1348eec385b5c4bd3e80fd863b0d3b47257d34e2ddc58754dec5d128" +dependencies = [ + "base64", + "bytes", + "ciborium", + "dioxus-devtools", + "dioxus-history", + "dioxus-lib", + "dioxus-mobile", + "dioxus-web", + "dioxus_server_macro", + "futures-channel", + "futures-util", + "generational-box", + "once_cell", + "serde", + "server_fn", + "tracing", + "web-sys", +] + +[[package]] +name = "dioxus-grpc" +version = "0.1.0" +dependencies = [ + "convert_case 0.8.0", + "tonic-build", +] + +[[package]] +name = "dioxus-grpc-examples" +version = "0.0.1" +dependencies = [ + "dioxus", + "dioxus-grpc", + "prost 0.14.3", + "tokio", + "tonic", + "tonic-build", + "tonic-web", + "tonic-web-wasm-client", + "tower-http", +] + +[[package]] +name = "dioxus-history" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ae4e22616c698f35b60727313134955d885de2d32e83689258e586ebc9b7909" +dependencies = [ + "dioxus-core", + "tracing", +] + +[[package]] +name = "dioxus-hooks" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "948e2b3f20d9d4b2c300aaa60281b1755f3298684448920b27106da5841896d0" +dependencies = [ + "dioxus-core", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "rustversion", + "slab", + "tracing", + "warnings", +] + +[[package]] +name = "dioxus-html" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c9a40e6fee20ce7990095492dedb6a753eebe05e67d28271a249de74dc796d" +dependencies = [ + "async-trait", + "dioxus-core", + "dioxus-core-macro", + "dioxus-core-types", + "dioxus-hooks", + "dioxus-html-internal-macro", + "enumset", + "euclid", + "futures-channel", + "generational-box", + "keyboard-types", + "lazy-js-bundle", + "rustversion", + "serde", + "serde_json", + "serde_repr", + "tracing", +] + +[[package]] +name = "dioxus-html-internal-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43ba87b53688a2c9f619ecdf4b3b955bc1f08bd0570a80a0d626c405f6d14a76" +dependencies = [ + "convert_case 0.6.0", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "dioxus-interpreter-js" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330707b10ca75cb0eb05f9e5f8d80217cd0d7e62116a8277ae363c1a09b57a22" +dependencies = [ + "dioxus-core", + "dioxus-core-types", + "dioxus-html", + "js-sys", + "lazy-js-bundle", + "rustc-hash", + "serde", + "sledgehammer_bindgen", + "sledgehammer_utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "dioxus-lib" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5405b71aa9b8b0c3e0d22728f12f34217ca5277792bd315878cc6ecab7301b72" +dependencies = [ + "dioxus-config-macro", + "dioxus-core", + "dioxus-core-macro", + "dioxus-document", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-rsx", + "dioxus-signals", + "warnings", +] + +[[package]] +name = "dioxus-logger" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545961e752f6c8bf59c274951b3c8b18a106db6ad2f9e2035b29e1f2a3e899b1" +dependencies = [ + "console_error_panic_hook", + "dioxus-cli-config", + "tracing", + "tracing-subscriber", + "tracing-wasm", +] + +[[package]] +name = "dioxus-mobile" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1295388909f427758993f32a571e0f8698d6ce0f125fa0e81b8bfdec3fa952" +dependencies = [ + "dioxus-cli-config", + "dioxus-desktop", + "dioxus-lib", + "jni", + "libc", + "once_cell", +] + +[[package]] +name = "dioxus-rsx" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb588e05800b5a7eb90b2f40fca5bbd7626e823fb5e1ba21e011de649b45aa1" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "dioxus-signals" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10e032dbb3a2c0386ec8b8ee59bc20b5aeb67038147c855801237b45b13d72ac" +dependencies = [ + "dioxus-core", + "futures-channel", + "futures-util", + "generational-box", + "once_cell", + "parking_lot", + "rustc-hash", + "tracing", + "warnings", +] + +[[package]] +name = "dioxus-web" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7c12475c3d360058b8afe1b68eb6dfc9cbb7dcd760aed37c5f85c561c83ed1" +dependencies = [ + "async-trait", + "ciborium", + "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", + "js-sys", + "lazy-js-bundle", + "rustc-hash", + "serde", + "serde-wasm-bindgen", + "serde_json", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "dioxus_server_macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "371a5b21989a06b53c5092e977b3f75d0e60a65a4c15a2aa1d07014c3b2dda97" +dependencies = [ + "proc-macro2", + "quote", + "server_fn_macro", + "syn 2.0.101", +] + +[[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.59.0", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.0", + "objc2 0.6.1", +] + +[[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.101", +] + +[[package]] +name = "dlopen2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[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.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" + +[[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 = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "enumset" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "euclid" +version = "0.22.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "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 = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +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 = "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", +] + +[[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.101", +] + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[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.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "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" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe" +dependencies = [ + "gdk", + "gdkx11-sys", + "gio", + "glib", + "libc", + "x11", +] + +[[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.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a673cf4fb0ea6a91aa86c08695756dfe875277a912cdbf33db9a9f62d47ed82b" +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 = "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.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[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.9.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.101", +] + +[[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 = "global-hotkey" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b436093d1598b05e3b7fddc097b2bad32763f53a1beb25ab6f9718c6a60acd09" +dependencies = [ + "bitflags 2.9.0", + "cocoa 0.25.0", + "crossbeam-channel", + "keyboard-types", + "objc", + "once_cell", + "thiserror 1.0.69", + "windows-sys 0.52.0", + "x11-dl", +] + +[[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-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.101", +] + +[[package]] +name = "h2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.9.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" + +[[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 = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.15", +] + +[[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 = "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.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 1.0.15", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[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.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown 0.15.3", +] + +[[package]] +name = "infer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6c16b11a665b26aeeb9b1d7f954cdeb034be38dd00adab4f2ae921a8fee804" +dependencies = [ + "cfb", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[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 = [ + "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 = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +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.9.0", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "kuchikiki" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +dependencies = [ + "cssparser", + "html5ever", + "indexmap 1.9.3", + "matches", + "selectors", +] + +[[package]] +name = "lazy-js-bundle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49596223b9d9d4947a14a25c142a6e7d8ab3f27eb3ade269d238bb8b5c267e2" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[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", + "once_cell", +] + +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[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 = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.9.0", + "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.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "longest-increasing-subsequence" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[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.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317af44b15e7605b85f04525449a3bb631753040156c9b318e6cba8a3ea4ef73" +dependencies = [ + "const-serialize", + "manganis-core", + "manganis-macro", +] + +[[package]] +name = "manganis-core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c38bee65cc725b2bba23b5dbb290f57c8be8fadbe2043fb7e2ce73022ea06519" +dependencies = [ + "const-serialize", + "dioxus-cli-config", + "dioxus-core-types", + "serde", +] + +[[package]] +name = "manganis-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f4f71310913c40174d9f0cfcbcb127dad0329ecdb3945678a120db22d3d065" +dependencies = [ + "dunce", + "manganis-core", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[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.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "muda" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c47e7625990fc1af2226ea4f34fb2412b03c12639fcb91868581eb3a6893453" +dependencies = [ + "cocoa 0.25.0", + "crossbeam-channel", + "gtk", + "keyboard-types", + "libxdo", + "objc", + "once_cell", + "png", + "thiserror 1.0.69", + "windows-sys 0.52.0", +] + +[[package]] +name = "muda" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdae9c00e61cc0579bcac625e8ad22104c60548a025bfc972dc83868a28e1484" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "libxdo", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "once_cell", + "png", + "thiserror 1.0.69", + "windows-sys 0.59.0", +] + +[[package]] +name = "multimap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.9.0", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle 0.6.2", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.9.0", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate 2.0.2", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", + "objc_exception", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.9.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +dependencies = [ + "bitflags 2.9.0", + "objc2 0.6.1", + "objc2-core-foundation", + "objc2-foundation 0.3.1", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.9.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags 2.9.0", + "dispatch2", + "objc2 0.6.1", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" +dependencies = [ + "bitflags 2.9.0", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.9.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +dependencies = [ + "bitflags 2.9.0", + "block2 0.6.1", + "objc2 0.6.1", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.9.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.9.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[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" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap 2.9.0", +] + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_macros", + "phf_shared 0.8.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[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.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.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.1", +] + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +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 = "polling" +version = "3.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 0.38.44", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +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.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" +dependencies = [ + "proc-macro2", + "syn 2.0.101", +] + +[[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.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "version_check", +] + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive 0.13.5", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive 0.14.3", +] + +[[package]] +name = "prost-build" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +dependencies = [ + "heck 0.5.0", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost 0.13.5", + "prost-types", + "regex", + "syn 2.0.101", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "prost-types" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost 0.13.5", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +dependencies = [ + "bitflags 2.9.0", +] + +[[package]] +name = "redox_users" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 2.0.12", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +dependencies = [ + "base64", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-util", + "tower", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "windows-registry", +] + +[[package]] +name = "rfd" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a73a7337fc24366edfca76ec521f51877b114e42dab584008209cca6719251" +dependencies = [ + "ashpd", + "block", + "dispatch", + "js-sys", + "log", + "objc", + "objc-foundation", + "objc_id", + "pollster", + "raw-window-handle 0.6.2", + "urlencoding", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[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 = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.9.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.9.0", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustversion" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "selectors" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more", + "fxhash", + "log", + "matches", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", + "thin-slice", +] + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[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.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa 1.0.15", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_qs" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0431a35568651e363364210c91983c1da5eb29404d9f0928b67d4ebcfa7d330c" +dependencies = [ + "percent-encoding", + "serde", + "thiserror 1.0.69", +] + +[[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.101", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.15", + "ryu", + "serde", +] + +[[package]] +name = "server_fn" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fae7a3038a32e5a34ba32c6c45eb4852f8affaf8b794ebfcd4b1099e2d62ebe" +dependencies = [ + "bytes", + "const_format", + "dashmap", + "futures", + "gloo-net", + "http", + "js-sys", + "once_cell", + "reqwest", + "send_wrapper", + "serde", + "serde_json", + "serde_qs", + "server_fn_macro_default", + "thiserror 1.0.69", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "xxhash-rust", +] + +[[package]] +name = "server_fn_macro" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaaf648c6967aef78177c0610478abb5a3455811f401f3c62d10ae9bd3901a1" +dependencies = [ + "const_format", + "convert_case 0.6.0", + "proc-macro2", + "quote", + "syn 2.0.101", + "xxhash-rust", +] + +[[package]] +name = "server_fn_macro_default" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2aa8119b558a17992e0ac1fd07f080099564f24532858811ce04f742542440" +dependencies = [ + "server_fn_macro", + "syn 2.0.101", +] + +[[package]] +name = "servo_arc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f62f06db0370222f7f498ef478fce9f8df5828848d1d3517e3331936d7074f55" +dependencies = [ + "quote", + "syn 2.0.101", +] + +[[package]] +name = "sledgehammer_utils" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "debdd4b83524961983cea3c55383b3910fd2f24fd13a188f5b091d2d504a61ae" +dependencies = [ + "rustc-hash", +] + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "serde", + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" + +[[package]] +name = "socket2" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[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 = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.11.3", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] + +[[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.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[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.30.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da" +dependencies = [ + "bitflags 2.9.0", + "cocoa 0.26.0", + "core-foundation 0.10.0", + "core-graphics 0.24.0", + "crossbeam-channel", + "dispatch", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "instant", + "jni", + "lazy_static", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "scopeguard", + "tao-macros", + "unicode-segmentation", + "url", + "windows", + "windows-core", + "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.101", +] + +[[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.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +dependencies = [ + "fastrand", + "getrandom 0.3.2", + "once_cell", + "rustix 1.0.7", + "windows-sys 0.59.0", +] + +[[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 = "thin-slice" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.9.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.9.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tonic" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85839f0b32fd242bb3209262371d07feda6d780d16ee9d2bc88581b89da1549b" +dependencies = [ + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "prost 0.13.5", + "socket2", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85f0383fadd15609306383a90e85eaed44169f931a5d2be1b42c76ceff1825e" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "tonic-web" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8e4a5564e49598cbdefefb5b982c243b11009bdaf36ad59487c2253cb73379" +dependencies = [ + "base64", + "bytes", + "http", + "http-body", + "pin-project", + "tokio-stream", + "tonic", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-web-wasm-client" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12abe1160d2a9a3e4bf578e2e37fd8b4f65c5e64fca6037d6f1ed6c0e02a78ac" +dependencies = [ + "base64", + "byteorder", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "httparse", + "js-sys", + "pin-project", + "thiserror 2.0.12", + "tonic", + "tower-service", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 2.9.0", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697" +dependencies = [ + "bitflags 2.9.0", + "bytes", + "http", + "http-body", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[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.19.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadd75f5002e2513eaa19b2365f533090cc3e93abd38788452d9ea85cff7b48a" +dependencies = [ + "crossbeam-channel", + "dirs", + "libappindicator", + "muda 0.15.3", + "objc2 0.6.1", + "objc2-app-kit 0.3.1", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.1", + "once_cell", + "png", + "thiserror 2.0.12", + "windows-sys 0.59.0", +] + +[[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.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.8.5", + "sha1", + "thiserror 1.0.69", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +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.101", +] + +[[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.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.101", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[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 = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webbrowser" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" +dependencies = [ + "core-foundation 0.9.4", + "home", + "jni", + "log", + "ndk-context", + "objc", + "raw-window-handle 0.5.2", + "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 = "webview2-com" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61ff3d9d0ee4efcb461b14eb3acfda2702d10dc329f339303fc3e57215ae2c" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows", + "windows-core", + "windows-implement", + "windows-interface", +] + +[[package]] +name = "webview2-com-macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "webview2-com-sys" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886" +dependencies = [ + "thiserror 1.0.69", + "windows", + "windows-core", +] + +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[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.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result 0.2.0", + "windows-strings 0.1.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-registry" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +dependencies = [ + "windows-result 0.3.2", + "windows-strings 0.3.1", + "windows-targets 0.53.0", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +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-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows-version" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04a5c6627e310a23ad2358483286c7df260c964eb2d003d8efd6d0f4e79265c" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.0", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "wry" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac0099a336829fbf54c26b5f620c68980ebbe37196772aeaf6118df4931b5cb0" +dependencies = [ + "base64", + "block", + "cocoa 0.26.0", + "core-graphics 0.24.0", + "crossbeam-channel", + "dpi", + "dunce", + "gdkx11", + "gtk", + "html5ever", + "http", + "javascriptcore-rs", + "jni", + "kuchikiki", + "libc", + "ndk", + "objc", + "objc_id", + "once_cell", + "percent-encoding", + "raw-window-handle 0.6.2", + "sha2", + "soup3", + "tao-macros", + "thiserror 1.0.69", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows", + "windows-core", + "windows-version", + "x11-dl", +] + +[[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 = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[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.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "synstructure", +] + +[[package]] +name = "zbus" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b8e3d6ae3342792a6cc2340e4394334c7402f3d793b390d2c5494a4032b3030" +dependencies = [ + "async-broadcast", + "async-process", + "async-recursion", + "async-trait", + "derivative", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tokio", + "tracing", + "uds_windows", + "windows-sys 0.52.0", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7a3e850ff1e7217a3b7a07eba90d37fe9bb9e89a310f718afcde5885ca9b6d7" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "zvariant" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e09e8be97d44eeab994d752f341e67b3b0d80512a8b315a0671d47232ef1b65" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "url", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a5857e2856435331636a9fbb415b09243df4521a267c5bedcd5289b4d5799e" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] diff --git a/tools/dioxus-grpc/examples/Cargo.toml b/tools/dioxus-grpc/examples/Cargo.toml new file mode 100644 index 00000000..e05ad1b8 --- /dev/null +++ b/tools/dioxus-grpc/examples/Cargo.toml @@ -0,0 +1,59 @@ +[package] + edition = "2024" + name = "dioxus-grpc-examples" + version = "0.0.1" + +[dependencies] + dioxus = { version = "0.6" } + dioxus-grpc = { path = "../", default-features = false } + prost = "0.14.3" + tokio = { version = "1", optional = true, features = ["full"] } + tonic = { version = "0.13", default-features = false, features = ["codegen", "prost"] } + tonic-web = { version = "0.13" } + tonic-web-wasm-client = { version = "0.7", optional = true } + tower-http = { version = "0.6", features = ["cors", "trace"], optional = true } + +[build-dependencies] + dioxus-grpc = { path = "../", features = ["web"] } + tonic-build = { version = "0.13", default-features = false, features = ["prost"] } + +[features] + default = [] + # Client /server + clnt = [] + srv = [ + "dep:tokio", + "dep:tower-http", + "tonic-build/transport", + "tonic/router", + "tonic/server", + "tonic/transport", + ] + # Platforms + mobile = [ + "dep:tokio", + "dioxus/mobile", + "tonic-build/transport", + "tonic/router", + "tonic/server", + "tonic/transport", + ] + web = ["dep:tonic-web-wasm-client", "dioxus-grpc/web", "dioxus/web"] + + +[[bin]] + name = "helloworld" + path = "src/basic.rs" + + +[profile] + + [profile.wasm-dev] + inherits = "dev" + opt-level = 1 + + [profile.server-dev] + inherits = "dev" + + [profile.android-dev] + inherits = "dev" diff --git a/tools/dioxus-grpc/examples/README.md b/tools/dioxus-grpc/examples/README.md new file mode 100644 index 00000000..f649dcd1 --- /dev/null +++ b/tools/dioxus-grpc/examples/README.md @@ -0,0 +1,12 @@ +First, start server: + +```sh +cargo run --features srv +``` + + +After that, start client: + +```sh +dx serve --features clnt +``` diff --git a/tools/dioxus-grpc/examples/build.rs b/tools/dioxus-grpc/examples/build.rs new file mode 100644 index 00000000..f023196c --- /dev/null +++ b/tools/dioxus-grpc/examples/build.rs @@ -0,0 +1,67 @@ +use std::io::Result; + +fn main() -> Result<()> { + let protos_to_compile: Vec<_> = std::fs::read_dir("./proto/")? + .flatten() + .map(|entry| entry.path()) + .collect(); + + // Compile protos + tonic_build::configure().compile_protos(&protos_to_compile, &["./proto/"])?; + + // Add every file to mod.rs + std::fs::write( + format!( + "{}/src/proto/mod.rs", + std::env::current_dir()?.to_str().expect("build.rs"), + ), + protos_to_compile.iter().fold(String::new(), |acc, proto| { + acc + &format!( + "pub mod {};\n", + proto + .to_str() + .expect("build.rs") + .split('/') + .next_back() + .expect("build.rs") + .replace(".proto", "") + ) + }), + )?; + + dioxus_grpc::generate_hooks( + &protos_to_compile, + &["./proto/"], + &Some("./src/hook"), + Some("crate::proto"), + )?; + + // Move files to the correct place + for proto in protos_to_compile { + let file_name = proto + .to_str() + .expect("build.rs") + .split('/') + .next_back() + .expect("build.rs") + .replace(".proto", ".rs"); + + let mut proto_content = String::from("#![allow(warnings, unused, deny)]\n"); + println!("{proto:#?}"); + proto_content.push_str(&std::fs::read_to_string(format!( + "{}/{file_name}", + std::env::var("OUT_DIR").expect("build.rs") + ))?); + + std::fs::write( + format!( + "{}/src/proto/{file_name}", + std::env::current_dir()?.to_str().expect("build.rs") + ), + proto_content, + )?; + } + + + Ok(()) +} diff --git a/tools/dioxus-grpc/examples/proto/helloworld.proto b/tools/dioxus-grpc/examples/proto/helloworld.proto new file mode 100644 index 00000000..14a0d657 --- /dev/null +++ b/tools/dioxus-grpc/examples/proto/helloworld.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +import "messages.proto"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (messages.HelloRequest) returns (messages.HelloReply) {} +} diff --git a/tools/dioxus-grpc/examples/proto/messages.proto b/tools/dioxus-grpc/examples/proto/messages.proto new file mode 100644 index 00000000..40a7d142 --- /dev/null +++ b/tools/dioxus-grpc/examples/proto/messages.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +package messages; + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/tools/dioxus-grpc/examples/src/basic.rs b/tools/dioxus-grpc/examples/src/basic.rs new file mode 100644 index 00000000..8e73c3fe --- /dev/null +++ b/tools/dioxus-grpc/examples/src/basic.rs @@ -0,0 +1,90 @@ +#[cfg(feature = "clnt")] +mod hook; +mod proto; + +#[cfg(feature = "clnt")] +use dioxus::prelude::*; + +#[cfg(feature = "clnt")] +fn main() { + launch(app); +} + +#[cfg(feature = "clnt")] +fn app() -> Element { + use hook::{helloworld::use_greeter_service, messages::HelloRequest}; + + use_context_provider(|| dioxus_grpc::GrpcConfig { + host: "http://127.0.0.1:50051".to_string(), + }); + + let mut req = use_signal(|| { + HelloRequest { + name: String::new(), + } + }); + let greeter = use_greeter_service(); + + rsx! { + input { + value: "{req().name}", + oninput: move |event| req.write().name = event.value() + } + match &*greeter.say_hello(req).read() { + Some(Ok(resp)) => rsx!{"[{resp.message}] - From server"}, + Some(Err(err)) => rsx!{"Couldn't get the name: {err:#?}"}, + None => rsx!{"..."}, + } + } +} + + +#[cfg(feature = "srv")] +use { + proto::helloworld::greeter_server::Greeter, + proto::messages::{HelloReply, HelloRequest}, + tonic::{Request, Response, Status, transport::Server}, +}; + +#[cfg(feature = "srv")] +pub struct MyGreeter; + +#[cfg(feature = "srv")] +#[tonic::async_trait] +impl Greeter for MyGreeter { + async fn say_hello( + &self, + request: Request, + ) -> Result, Status> { + println!("Got a request from {:?}", request.remote_addr()); + + let reply = HelloReply { + message: format!("Hello {}!", request.into_inner().name), + }; + Ok(Response::new(reply)) + } +} + +#[cfg(feature = "srv")] +#[tokio::main] +async fn main() -> Result<(), Box> { + use {proto::helloworld::greeter_server::GreeterServer, tonic_web::GrpcWebLayer}; + + let addr = "127.0.0.1:50051".parse().unwrap(); + + println!("GreeterServer listening on {addr}"); + + let cors = tower_http::cors::CorsLayer::new() + .allow_methods(tower_http::cors::AllowMethods::any()) + .allow_origin(tower_http::cors::Any); + + Server::builder() + .accept_http1(true) + .layer(GrpcWebLayer::new()) + .layer(cors) + .add_service(GreeterServer::new(MyGreeter)) + .serve(addr) + .await?; + + Ok(()) +} diff --git a/tools/dioxus-grpc/examples/src/hook/mod.rs b/tools/dioxus-grpc/examples/src/hook/mod.rs new file mode 100644 index 00000000..ce200d24 --- /dev/null +++ b/tools/dioxus-grpc/examples/src/hook/mod.rs @@ -0,0 +1,4 @@ +#[path = "./helloworld.dx.rs"] +pub mod helloworld; +#[path = "./messages.dx.rs"] +pub mod messages; diff --git a/tools/dioxus-grpc/rustfmt.toml b/tools/dioxus-grpc/rustfmt.toml new file mode 100644 index 00000000..5e68b4b8 --- /dev/null +++ b/tools/dioxus-grpc/rustfmt.toml @@ -0,0 +1,18 @@ +# https://github.com/rust-lang/rustfmt +# Configuration: https://rust-lang.github.io/rustfmt + +# Stable +array_width = 50 +edition = "2024" +match_block_trailing_comma = true +newline_style = "Unix" + +# Nightly +binop_separator = "Back" +blank_lines_upper_bound = 3 +combine_control_expr = false +force_multiline_blocks = true +group_imports = "StdExternalCrate" +imports_granularity = "One" +imports_layout = "HorizontalVertical" +reorder_impl_items = true diff --git a/tools/dioxus-grpc/src/lib.rs b/tools/dioxus-grpc/src/lib.rs new file mode 100644 index 00000000..d536af52 --- /dev/null +++ b/tools/dioxus-grpc/src/lib.rs @@ -0,0 +1,147 @@ +#[cfg(feature = "codegen")] +use { + convert_case::{Case, Casing}, + std::{fmt::Write, path::Path}, + tonic_build::Config, +}; + +#[derive(Clone, Debug, PartialEq)] +pub struct GrpcConfig { + pub host: String, +} + +/// - to_path: Is the directory in which files should be written to. When [`None`], defaults to `OUT_DIR` +/// - prost_mod: If you moved the codegen of proto in a module +#[cfg(feature = "codegen")] +pub fn generate_hooks, P2: AsRef, P3: AsRef>( + protos: &[P], + includes: &[P2], + to_path: &Option, + prost_mod: Option<&str>, +) -> Result<(), std::io::Error> { + let mut config = Config::new(); + let file_descriptor_set = config.load_fds(protos, includes)?; + + for fd in file_descriptor_set.file { + if fd.service.is_empty() { + continue; + } + + let pkg_name = fd + .package + .as_ref() + .map_or_else(|| "_", |string| string.as_str()); + let filename = format!("{pkg_name}.dx.rs"); + let rust_pkg_name = pkg_name.replace('.', "_"); + + let mut str = format!( + "{mod_prost}\npub use proto::*;\nuse ::dioxus::prelude::*;\n", + mod_prost = if let Some(mod_path) = prost_mod { + format!("mod proto {{\n pub use {mod_path}::{rust_pkg_name}::*;\n}}") + } else { + format!( + "#[path = \"{out_dir}/{pkg_name}.rs\"]\nmod proto;", + out_dir = std::env::var("OUT_DIR").expect("build.rs"), + ) + }, + ); + + + for service in &fd.service { + let tonic_client = format!( + "proto::{}_client::{}Client", + service.name().to_case(Case::Snake), + service.name().to_case(Case::Pascal) + ); + + write!( + str, + "\npub struct {service_name}ServiceHook{tonic_client_ty};\n\npub fn use_{service_name_lowercase}_service() -> {service_name}ServiceHook {{\n {service_name}ServiceHook{new_tonic_client}\n}}\n\nimpl {service_name}ServiceHook {{\n", + service_name = service.name().to_case(Case::Pascal), + service_name_lowercase = service.name().to_case(Case::Snake), + tonic_client_ty = { + #[cfg(feature = "web")] + { + format!("({tonic_client}<::tonic_web_wasm_client::Client>)") + } + #[cfg(not(feature = "web"))] + { + format!("({tonic_client}<::tonic::transport::Channel>)") + } + }, + new_tonic_client = { + #[cfg(feature = "web")] + { + format!("({{ let config = use_context::<::dioxus_grpc::GrpcConfig>(); {tonic_client}::new(::tonic_web_wasm_client::Client::new(config.host.clone())) }})") + } + #[cfg(not(feature = "web"))] + { + format!("({{ let config = use_context::<::dioxus_grpc::GrpcConfig>(); {tonic_client}::new(::tonic::transport::Endpoint::new(config.host.clone()).unwrap().connect_lazy()) }})") + } + } + ) + .expect("write error"); + + for rpc in &service.method { + if rpc.client_streaming() || rpc.server_streaming() { + continue; + } + write!( + str, + " pub fn {rpc_name}(&self, req: Signal<{rpc_input}>) -> Resource> {{\n let client = self.0.to_owned();\n use_resource(move || {{\n let mut client = client.clone();\n async move {{ client.{rpc_name}(req()).await.map(|resp| resp.into_inner()) }}\n }})\n }}\n", + rpc_name = rpc.name().to_case(Case::Snake), + rpc_input = { + let mut full_path = rpc.input_type().split('.'); + let ty = full_path.next_back().expect("build.rs"); + let path = full_path.filter(|e| !e.is_empty()).collect::>().join("."); + + if path == pkg_name { + format!("proto::{ty}") + } else if let Some(mod_path) = prost_mod { + format!("{mod_path}::{path}::{ty}") + } else { + format!("super::{path}::{ty}") + } + }, + rpc_ouptut = { + let mut full_path = rpc.output_type().split('.'); + let ty = full_path.next_back().expect("build.rs"); + let path = full_path.filter(|e| !e.is_empty()).collect::>().join("."); + + if path == pkg_name { + format!("proto::{ty}") + } else if let Some(mod_path) = prost_mod { + format!("{mod_path}::{path}::{ty}") + } else { + format!("super::{path}::{ty}") + } + } + ).expect("write error"); + } + + str.push('}'); + } + + match to_path { + Some(p) => { + std::fs::write( + { + let mut path_to_file = p.as_ref().to_owned(); + path_to_file.push(filename); + path_to_file + }, + str, + ) + }, + None => { + std::fs::write( + format!("{}/{filename}", std::env::var("OUT_DIR").expect("build.rs")), + str, + ) + }, + }?; + } + + + Ok(()) +} diff --git a/tools/dioxus-grpc/taplo.toml b/tools/dioxus-grpc/taplo.toml new file mode 100644 index 00000000..80875651 --- /dev/null +++ b/tools/dioxus-grpc/taplo.toml @@ -0,0 +1,11 @@ +[formatting] + column_width = 100 + + indent_entries = true + indent_string = " " + indent_tables = true + + allowed_blank_lines = 3 + reoder_inline_tables = true + reorder_arrays = true + reorder_keys = true