diff --git a/.env.example b/.env.example index 1390efc..04a1dd8 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,5 @@ DATABASE_URL=postgres://postgres:postgres@localhost:5432/chattz PORT=3000 -APP_BASE_URL=http://localhost:3000 # Authentik OIDC app values OIDC_CLIENT_ID=replace-me @@ -17,9 +16,6 @@ TURN_URLS=turn:turn.example.com:3478?transport=udp,turn:turn.example.com:3478?tr TURN_USERNAME=replace-me TURN_PASSWORD=replace-me -# Cloudflare R2 media uploads -R2_ACCOUNT_ID=replace-me -R2_ACCESS_KEY_ID=replace-me -R2_SECRET_ACCESS_KEY=replace-me -R2_BUCKET=chattz-media -MEDIA_BASE_URL=https://media.example.com +# 32+ random chars; used to sign session cookies +SESSION_SECRET=replace-with-long-random-secret +COOKIE_SECURE=false diff --git a/.forgejo/workflows/pipeline.yaml b/.forgejo/workflows/pipeline.yaml index c76ae86..4adede5 100644 --- a/.forgejo/workflows/pipeline.yaml +++ b/.forgejo/workflows/pipeline.yaml @@ -11,51 +11,6 @@ jobs: with: node-version: 24 - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - name: Update version from tag - run: | - # Extract version from tag (e.g. v1.2.3 -> 1.2.3) - VERSION=${GITHUB_REF_NAME#v} - echo "Bumping version to $VERSION" - npm version $VERSION --no-git-tag-version - - run: npm ci - - run: npm run dist:linux - - name: Build Windows installer with 32-bit Wine prefix - run: | - export WINEARCH=win32 - export WINEPREFIX="$HOME/.wine32" - wineboot -u - npm run dist:win - - name: Copy installers into static folder - run: | - mkdir -p static/installers - find static/installers -mindepth 1 -maxdepth 1 -type f -delete - copy_first() { - pattern="$1" - out="$2" - file="$(find dist -maxdepth 1 -type f -name "$pattern" | head -n 1)" - if [ -n "$file" ]; then - cp "$file" "static/installers/$out" - fi - } - # Copy versioned artifacts for electron-updater - cp dist/*.AppImage static/installers/ || true - cp dist/*.exe static/installers/ || true - cp dist/*.rpm static/installers/ || true - cp dist/*.deb static/installers/ || true - cp dist/*.msi static/installers/ || true - - # Maintain generic names for stable website links - copy_first '*.rpm' 'chattz-linux.rpm' - copy_first '*.deb' 'chattz-linux.deb' - copy_first '*.AppImage' 'chattz-linux.AppImage' - copy_first '*.exe' 'chattz-windows.exe' - copy_first '*.msi' 'chattz-windows.msi' - - # Metadata files for electron-updater - copy_first 'latest-linux.yml' 'latest-linux.yml' - copy_first 'latest.yml' 'latest.yml' - name: Cache Cargo registry uses: actions/cache@v4 with: @@ -82,7 +37,7 @@ jobs: mkdir -p ~/discord cp target/release/chattz ~/discord/discord chmod +x ~/discord/discord - mkdir -p ~/discord/static/uploads - find ~/discord/static -mindepth 1 -maxdepth 1 ! -name 'uploads' -exec rm -rf {} + + mkdir -p ~/discord/static + rm -rf ~/discord/static/* cp -r static/* ~/discord/static/ - systemctl --user start discord + systemctl --user start discord \ No newline at end of file diff --git a/.gitignore b/.gitignore index a2feb2a..0b745e2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ /target -.env -node_modules -dist +.env \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index c44764d..bcfbb24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,418 +92,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "aws-config" -version = "1.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a8fc176d53d6fe85017f230405e3255cedb4a02221cb55ed6d76dccbbb099b2" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-sdk-sts", - "aws-smithy-async", - "aws-smithy-http 0.63.5", - "aws-smithy-json 0.62.4", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "http 1.4.0", - "time", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "aws-credential-types" -version = "1.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d203b0bf2626dcba8665f5cd0871d7c2c0930223d6b6be9097592fea21242d0" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "zeroize", -] - -[[package]] -name = "aws-lc-rs" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a7b350e3bb1767102698302bc37256cbd48422809984b98d292c40e2579aa9" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.37.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "aws-runtime" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede2ddc593e6c8acc6ce3358c28d6677a6dc49b65ba4b37a2befe14a11297e75" -dependencies = [ - "aws-credential-types", - "aws-sigv4", - "aws-smithy-async", - "aws-smithy-eventstream", - "aws-smithy-http 0.63.5", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "bytes-utils", - "fastrand", - "http 0.2.12", - "http 1.4.0", - "http-body 0.4.6", - "http-body 1.0.1", - "percent-encoding", - "pin-project-lite", - "tracing", - "uuid", -] - -[[package]] -name = "aws-sdk-s3" -version = "1.119.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d65fddc3844f902dfe1864acb8494db5f9342015ee3ab7890270d36fbd2e01c" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-sigv4", - "aws-smithy-async", - "aws-smithy-checksums", - "aws-smithy-eventstream", - "aws-smithy-http 0.62.6", - "aws-smithy-json 0.61.9", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-smithy-xml", - "aws-types", - "bytes", - "fastrand", - "hex", - "hmac", - "http 0.2.12", - "http 1.4.0", - "http-body 0.4.6", - "lru", - "percent-encoding", - "regex-lite", - "sha2", - "tracing", - "url", -] - -[[package]] -name = "aws-sdk-sts" -version = "1.99.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9acba7c62f3d4e2408fa998a3a8caacd8b9a5b5549cf36e2372fbdae329d5449" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http 0.63.5", - "aws-smithy-json 0.62.4", - "aws-smithy-observability", - "aws-smithy-query", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-smithy-xml", - "aws-types", - "fastrand", - "http 0.2.12", - "http 1.4.0", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sigv4" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37411f8e0f4bea0c3ca0958ce7f18f6439db24d555dbd809787262cd00926aa9" -dependencies = [ - "aws-credential-types", - "aws-smithy-eventstream", - "aws-smithy-http 0.63.5", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "form_urlencoded", - "hex", - "hmac", - "http 0.2.12", - "http 1.4.0", - "percent-encoding", - "sha2", - "time", - "tracing", -] - -[[package]] -name = "aws-smithy-async" -version = "1.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc50d0f63e714784b84223abd7abbc8577de8c35d699e0edd19f0a88a08ae13" -dependencies = [ - "futures-util", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "aws-smithy-checksums" -version = "0.63.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87294a084b43d649d967efe58aa1f9e0adc260e13a6938eb904c0ae9b45824ae" -dependencies = [ - "aws-smithy-http 0.62.6", - "aws-smithy-types", - "bytes", - "crc-fast", - "hex", - "http 0.2.12", - "http-body 0.4.6", - "md-5", - "pin-project-lite", - "sha1", - "sha2", - "tracing", -] - -[[package]] -name = "aws-smithy-eventstream" -version = "0.60.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c0b3e587fbaa5d7f7e870544508af8ce82ea47cd30376e69e1e37c4ac746f79" -dependencies = [ - "aws-smithy-types", - "bytes", - "crc32fast", -] - -[[package]] -name = "aws-smithy-http" -version = "0.62.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826141069295752372f8203c17f28e30c464d22899a43a0c9fd9c458d469c88b" -dependencies = [ - "aws-smithy-eventstream", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "bytes-utils", - "futures-core", - "futures-util", - "http 0.2.12", - "http 1.4.0", - "http-body 0.4.6", - "percent-encoding", - "pin-project-lite", - "pin-utils", - "tracing", -] - -[[package]] -name = "aws-smithy-http" -version = "0.63.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d619373d490ad70966994801bc126846afaa0d1ee920697a031f0cf63f2568e7" -dependencies = [ - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "bytes-utils", - "futures-core", - "futures-util", - "http 1.4.0", - "http-body 1.0.1", - "http-body-util", - "percent-encoding", - "pin-project-lite", - "pin-utils", - "tracing", -] - -[[package]] -name = "aws-smithy-http-client" -version = "1.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00ccbb08c10f6bcf912f398188e42ee2eab5f1767ce215a02a73bc5df1bbdd95" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "h2 0.3.27", - "h2 0.4.13", - "http 0.2.12", - "http 1.4.0", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper 1.8.1", - "hyper-rustls 0.24.2", - "hyper-rustls 0.27.7", - "hyper-util", - "pin-project-lite", - "rustls 0.21.12", - "rustls 0.23.36", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.26.4", - "tower", - "tracing", -] - -[[package]] -name = "aws-smithy-json" -version = "0.61.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fa1213db31ac95288d981476f78d05d9cbb0353d22cdf3472cc05bb02f6551" -dependencies = [ - "aws-smithy-types", -] - -[[package]] -name = "aws-smithy-json" -version = "0.62.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b3a779093e18cad88bbae08dc4261e1d95018c4c5b9356a52bcae7c0b6e9bb" -dependencies = [ - "aws-smithy-types", -] - -[[package]] -name = "aws-smithy-observability" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3f39d5bb871aaf461d59144557f16d5927a5248a983a40654d9cf3b9ba183b" -dependencies = [ - "aws-smithy-runtime-api", -] - -[[package]] -name = "aws-smithy-query" -version = "0.60.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f76a580e3d8f8961e5d48763214025a2af65c2fa4cd1fb7f270a0e107a71b0" -dependencies = [ - "aws-smithy-types", - "urlencoding", -] - -[[package]] -name = "aws-smithy-runtime" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ccf7f6eba8b2dcf8ce9b74806c6c185659c311665c4bf8d6e71ebd454db6bf" -dependencies = [ - "aws-smithy-async", - "aws-smithy-http 0.63.5", - "aws-smithy-http-client", - "aws-smithy-observability", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "fastrand", - "http 0.2.12", - "http 1.4.0", - "http-body 0.4.6", - "http-body 1.0.1", - "http-body-util", - "pin-project-lite", - "pin-utils", - "tokio", - "tracing", -] - -[[package]] -name = "aws-smithy-runtime-api" -version = "1.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4af6e5def28be846479bbeac55aa4603d6f7986fc5da4601ba324dd5d377516" -dependencies = [ - "aws-smithy-async", - "aws-smithy-types", - "bytes", - "http 0.2.12", - "http 1.4.0", - "pin-project-lite", - "tokio", - "tracing", - "zeroize", -] - -[[package]] -name = "aws-smithy-types" -version = "1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca2734c16913a45343b37313605d84e7d8b34a4611598ce1d25b35860a2bed3" -dependencies = [ - "base64-simd", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http 1.4.0", - "http-body 0.4.6", - "http-body 1.0.1", - "http-body-util", - "itoa", - "num-integer", - "pin-project-lite", - "pin-utils", - "ryu", - "serde", - "time", - "tokio", - "tokio-util", -] - -[[package]] -name = "aws-smithy-xml" -version = "0.60.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b53543b4b86ed43f051644f704a98c7291b3618b67adf057ee77a366fa52fcaa" -dependencies = [ - "xmlparser", -] - -[[package]] -name = "aws-types" -version = "1.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0470cc047657c6e286346bdf10a8719d26efd6a91626992e0e64481e44323e96" -dependencies = [ - "aws-credential-types", - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "rustc_version", - "tracing", -] - [[package]] name = "axum" version = "0.8.8" @@ -516,16 +104,15 @@ dependencies = [ "bytes", "form_urlencoded", "futures-util", - "http 1.4.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", - "hyper 1.8.1", + "hyper", "hyper-util", "itoa", "matchit", "memchr", "mime", - "multer", "percent-encoding", "pin-project-lite", "serde_core", @@ -550,8 +137,8 @@ checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes", "futures-core", - "http 1.4.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", @@ -578,16 +165,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64-simd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" -dependencies = [ - "outref", - "vsimd", -] - [[package]] name = "base64ct" version = "1.8.3" @@ -630,16 +207,6 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" -[[package]] -name = "bytes-utils" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" -dependencies = [ - "bytes", - "either", -] - [[package]] name = "cc" version = "1.2.56" @@ -647,8 +214,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", - "jobserver", - "libc", "shlex", ] @@ -669,20 +234,17 @@ name = "chattz" version = "0.1.0" dependencies = [ "anyhow", - "aws-config", - "aws-sdk-s3", "axum", "chrono", "dotenvy", "futures-util", + "jsonwebtoken", "reqwest", "sea-orm", "sea-orm-migration", "serde", "serde_json", - "sha2", "tokio", - "tower", "tower-http", "tracing", "tracing-subscriber", @@ -704,15 +266,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "cmake" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" -dependencies = [ - "cc", -] - [[package]] name = "concurrent-queue" version = "2.5.0" @@ -728,16 +281,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[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" @@ -768,28 +311,6 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" -[[package]] -name = "crc-fast" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ddc2d09feefeee8bd78101665bd8645637828fa9317f9f292496dbbd8c65ff3" -dependencies = [ - "crc", - "digest", - "rand 0.9.2", - "regex", - "rustversion", -] - -[[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-queue" version = "0.3.12" @@ -926,12 +447,6 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" -[[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" @@ -941,15 +456,6 @@ dependencies = [ "serde", ] -[[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 = "equivalent" version = "1.0.2" @@ -978,12 +484,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -1022,12 +522,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - [[package]] name = "futures" version = "0.3.31" @@ -1169,44 +663,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" -[[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", - "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", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "hashbrown" version = "0.15.5" @@ -1278,17 +734,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.4.0" @@ -1299,17 +744,6 @@ dependencies = [ "itoa", ] -[[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" @@ -1317,7 +751,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.4.0", + "http", ] [[package]] @@ -1328,8 +762,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.4.0", - "http-body 1.0.1", + "http", + "http-body", "pin-project-lite", ] @@ -1351,30 +785,6 @@ 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", - "pin-project-lite", - "socket2 0.5.10", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.8.1" @@ -1385,9 +795,8 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.13", - "http 1.4.0", - "http-body 1.0.1", + "http", + "http-body", "httparse", "httpdate", "itoa", @@ -1398,35 +807,19 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.32", - "log", - "rustls 0.21.12", - "tokio", - "tokio-rustls 0.24.1", -] - [[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.8.1", + "http", + "hyper", "hyper-util", - "rustls 0.23.36", - "rustls-native-certs", + "rustls", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tower-service", "webpki-roots 1.0.6", ] @@ -1441,14 +834,14 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.4.0", - "http-body 1.0.1", - "hyper 1.8.1", + "http", + "http-body", + "hyper", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.2", + "socket2", "tokio", "tower-service", "tracing", @@ -1629,16 +1022,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" -[[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.85" @@ -1649,6 +1032,21 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonwebtoken" +version = "9.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +dependencies = [ + "base64", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1712,15 +1110,6 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "lru" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" -dependencies = [ - "hashbrown 0.15.5", -] - [[package]] name = "lru-slab" version = "0.1.2" @@ -1785,23 +1174,6 @@ dependencies = [ "windows-sys 0.61.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 1.4.0", - "httparse", - "memchr", - "mime", - "spin", - "version_check", -] - [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1811,6 +1183,16 @@ dependencies = [ "windows-sys 0.61.2", ] +[[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-bigint-dig" version = "0.8.6" @@ -1869,12 +1251,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "openssl-probe" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" - [[package]] name = "ordered-float" version = "4.6.0" @@ -1908,12 +1284,6 @@ dependencies = [ "syn", ] -[[package]] -name = "outref" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" - [[package]] name = "parking" version = "2.2.1" @@ -1943,6 +1313,16 @@ dependencies = [ "windows-link", ] +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64", + "serde_core", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -2077,8 +1457,8 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.36", - "socket2 0.6.2", + "rustls", + "socket2", "thiserror", "tokio", "tracing", @@ -2097,7 +1477,7 @@ dependencies = [ "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.36", + "rustls", "rustls-pki-types", "slab", "thiserror", @@ -2115,7 +1495,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.2", + "socket2", "tracing", "windows-sys 0.60.2", ] @@ -2235,12 +1615,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "regex-lite" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" - [[package]] name = "regex-syntax" version = "0.8.9" @@ -2256,25 +1630,25 @@ dependencies = [ "base64", "bytes", "futures-core", - "http 1.4.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", - "hyper 1.8.1", - "hyper-rustls 0.27.7", + "hyper", + "hyper-rustls", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.36", + "rustls", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -2334,45 +1708,20 @@ dependencies = [ "semver", ] -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - [[package]] name = "rustls" version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ - "aws-lc-rs", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.9", + "rustls-webpki", "subtle", "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - [[package]] name = "rustls-pki-types" version = "1.14.0" @@ -2383,23 +1732,12 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "rustls-webpki" version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ - "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -2417,31 +1755,12 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" -[[package]] -name = "schannel" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" -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 = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sea-bae" version = "0.2.1" @@ -2589,29 +1908,6 @@ dependencies = [ "syn", ] -[[package]] -name = "security-framework" -version = "3.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38" -dependencies = [ - "bitflags", - "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 = "semver" version = "1.0.27" @@ -2731,6 +2027,18 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simple_asn1" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time", +] + [[package]] name = "slab" version = "0.4.12" @@ -2746,16 +2054,6 @@ dependencies = [ "serde", ] -[[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.2" @@ -2822,7 +2120,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rustls 0.23.36", + "rustls", "serde", "serde_json", "sha2", @@ -3085,6 +2383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", "serde_core", @@ -3143,7 +2442,7 @@ dependencies = [ "libc", "mio", "pin-project-lite", - "socket2 0.6.2", + "socket2", "tokio-macros", "windows-sys 0.61.2", ] @@ -3159,23 +2458,13 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.36", + "rustls", "tokio", ] @@ -3241,8 +2530,8 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http 1.4.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", "http-range-header", "httpdate", @@ -3347,7 +2636,7 @@ checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ "bytes", "data-encoding", - "http 1.4.0", + "http", "httparse", "log", "rand 0.9.2", @@ -3467,12 +2756,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "vsimd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" - [[package]] name = "want" version = "0.3.1" @@ -3903,12 +3186,6 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" -[[package]] -name = "xmlparser" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" - [[package]] name = "yansi" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 6dbd768..4d48561 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,20 +5,17 @@ edition = "2024" [dependencies] anyhow = "1" -aws-config = { version = "1", default-features = false, features = ["behavior-version-latest", "rt-tokio", "rustls"] } -aws-sdk-s3 = { version = "1", default-features = false, features = ["rt-tokio", "rustls"] } -axum = { version = "0.8", features = ["macros", "ws", "multipart"] } +axum = { version = "0.8", features = ["macros", "ws"] } chrono = { version = "0.4", features = ["serde"] } dotenvy = "0.15" +jsonwebtoken = "9" reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } -sea-orm = { version = "1.1", default-features = false, features = ["sqlx-postgres", "runtime-tokio-rustls", "macros", "with-chrono", "with-uuid", "mock"] } +sea-orm = { version = "1.1", default-features = false, features = ["sqlx-postgres", "runtime-tokio-rustls", "macros", "with-chrono", "with-uuid"] } sea-orm-migration = { version = "1.1", default-features = false, features = ["sqlx-postgres", "runtime-tokio-rustls"] } serde = { version = "1", features = ["derive"] } serde_json = "1" -sha2 = "0.10" futures-util = "0.3" -tokio = { version = "1", features = ["fs", "io-util", "macros", "rt-multi-thread"] } -tower = { version = "0.5", features = ["util"] } +tokio = { version = "1", features = ["macros", "rt-multi-thread"] } tower-http = { version = "0.6", features = ["trace", "fs"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } diff --git a/README.md b/README.md index 2708a60..af5e8f0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A simple single-instance Discord-style monolith in Rust using: ## What this includes - OIDC login flow (`/auth/login`, `/auth/callback`, `/auth/logout`) -- HttpOnly session cookie auth +- Signed session cookie auth - Channel voice chat over WebRTC (P2P mesh) with server WebSocket signaling - Guild invite codes (create + join) - Direct messages (DM) between users @@ -41,11 +41,6 @@ For voice reliability on restrictive networks, configure TURN in `.env`: - `TURN_USERNAME` - `TURN_PASSWORD` -For production deployments: -- `APP_BASE_URL` must be your public app origin and should use `https` -- `MEDIA_BASE_URL` should be a separate media origin for user uploads -- uploads and soundboard require R2/object storage to be configured - 3. Run app: ```bash @@ -60,7 +55,7 @@ Web UI is available at `http://localhost:${PORT}/`. ## Authentik setup notes Create an Authentik OAuth2/OIDC provider + application and set: -- Redirect URI: `${APP_BASE_URL}/auth/callback` +- Redirect URI: `http://localhost:3000/auth/callback` - Scopes including at least: `openid profile email` If you change `PORT`, update `OIDC_REDIRECT_URL` and this redirect URI to match. @@ -96,7 +91,6 @@ For Authentik these are commonly under `/application/o/...` for the app slug. - `GET /channels/:channel_id/voice/ws` (WebSocket signaling) All endpoints except health and auth flow require the session cookie from successful login. -Authenticated WebSocket connections (`/ws`, `/channels/:channel_id/voice/ws`) also use the same cookie session. ## Notes @@ -104,7 +98,6 @@ This is intentionally minimal and monolithic (single process, single Postgres in Voice is implemented as browser-to-browser WebRTC audio with signaling in this server. For two users behind strict NAT/firewall, you may need TURN for reliable connectivity. The web UI remembers the last selected guild in browser local storage and auto-selects it on reload. -User uploads are served from the configured media origin, not from `/static`. Mic filter modes in the UI: - `NSNet2 (Compat)`: always-on denoising mode (implemented using DeepFilterNet3 with lighter suppression preset) diff --git a/build/icon.png b/build/icon.png deleted file mode 100644 index 8169e48..0000000 Binary files a/build/icon.png and /dev/null differ diff --git a/desktop/app.js b/desktop/app.js deleted file mode 100644 index e0b9fa7..0000000 --- a/desktop/app.js +++ /dev/null @@ -1 +0,0 @@ -import "../static/shared/app-core.js"; diff --git a/desktop/index.html b/desktop/index.html deleted file mode 100644 index 1684077..0000000 --- a/desktop/index.html +++ /dev/null @@ -1,282 +0,0 @@ - - - - - - - - Chattz - - - - - - -
-
-
C
-

Chattz

-

Sign in to open your servers.

- -

-
-
- - - - - - - - - - - - - - - - - - - diff --git a/desktop/preload.js b/desktop/preload.js deleted file mode 100644 index f43670e..0000000 --- a/desktop/preload.js +++ /dev/null @@ -1,20 +0,0 @@ -const { contextBridge, ipcRenderer } = require('electron'); - -function onIpc(channel, callback) { - const listener = (_event, payload) => callback(payload); - ipcRenderer.on(channel, listener); - return () => ipcRenderer.removeListener(channel, listener); -} - -contextBridge.exposeInMainWorld('electronAPI', { - copyToClipboard: (text) => ipcRenderer.invoke('clipboard-write', text), - getUpdateState: () => ipcRenderer.invoke('get-update-state'), - checkForUpdatesNow: () => ipcRenderer.invoke('check-for-updates-now'), - checkForUpdates: () => ipcRenderer.send('check-for-updates'), - downloadUpdate: () => ipcRenderer.send('download-update'), - quitAndInstall: () => ipcRenderer.send('quit-and-install'), - onUpdateState: (callback) => onIpc('update-state', callback), - onUpdateAvailable: (callback) => onIpc('update-available', callback), - onUpdateDownloaded: (callback) => onIpc('update-downloaded', callback), - onUpdateError: (callback) => onIpc('update-error', callback) -}); diff --git a/desktop/vendor/deepfilternet3-noise-filter.esm.js b/desktop/vendor/deepfilternet3-noise-filter.esm.js deleted file mode 100644 index 7ad3ee9..0000000 --- a/desktop/vendor/deepfilternet3-noise-filter.esm.js +++ /dev/null @@ -1,249 +0,0 @@ -class AssetLoader { - constructor(config = {}) { - this.cdnUrl = config.cdnUrl ?? 'https://cdn.mezon.ai/AI/models/datas/noise_suppression/deepfilternet3'; - } - getCdnUrl(relativePath) { - return `${this.cdnUrl}/${relativePath}`; - } - getAssetUrls() { - return { - wasm: this.getCdnUrl('v2/pkg/df_bg.wasm'), - model: this.getCdnUrl('v2/models/DeepFilterNet3_onnx.tar.gz') - }; - } - async fetchAsset(url) { - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Failed to fetch asset: ${response.statusText}`); - } - return response.arrayBuffer(); - } -} -let defaultLoader = null; -function getAssetLoader(config) { - if (!defaultLoader || config) { - defaultLoader = new AssetLoader(config); - } - return defaultLoader; -} - -/** - * Creates a worklet module URL from inline code string - * This approach works with all bundlers without special configuration - */ -async function createWorkletModule(audioContext, workletCode) { - const blob = new Blob([workletCode], { type: 'application/javascript' }); - const blobUrl = URL.createObjectURL(blob); - await audioContext.audioWorklet.addModule(blobUrl); -} - -const WorkletMessageTypes = { - SET_SUPPRESSION_LEVEL: 'SET_SUPPRESSION_LEVEL', - SET_BYPASS: 'SET_BYPASS' -}; - -var workletCode = "(function () {\n 'use strict';\n\n let wasm;\n\n const heap = new Array(128).fill(undefined);\n\n heap.push(undefined, null, true, false);\n\n function getObject(idx) { return heap[idx]; }\n\n let heap_next = heap.length;\n\n function dropObject(idx) {\n if (idx < 132) return;\n heap[idx] = heap_next;\n heap_next = idx;\n }\n\n function takeObject(idx) {\n const ret = getObject(idx);\n dropObject(idx);\n return ret;\n }\n\n const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );\n\n if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }\n let cachedUint8Memory0 = null;\n\n function getUint8Memory0() {\n if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {\n cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);\n }\n return cachedUint8Memory0;\n }\n\n function getStringFromWasm0(ptr, len) {\n ptr = ptr >>> 0;\n return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));\n }\n\n function addHeapObject(obj) {\n if (heap_next === heap.length) heap.push(heap.length + 1);\n const idx = heap_next;\n heap_next = heap[idx];\n\n heap[idx] = obj;\n return idx;\n }\n /**\n * Set DeepFilterNet attenuation limit.\n *\n * Args:\n * - lim_db: New attenuation limit in dB.\n * @param {number} st\n * @param {number} lim_db\n */\n function df_set_atten_lim(st, lim_db) {\n wasm.df_set_atten_lim(st, lim_db);\n }\n\n /**\n * Get DeepFilterNet frame size in samples.\n * @param {number} st\n * @returns {number}\n */\n function df_get_frame_length(st) {\n const ret = wasm.df_get_frame_length(st);\n return ret >>> 0;\n }\n\n let WASM_VECTOR_LEN = 0;\n\n function passArray8ToWasm0(arg, malloc) {\n const ptr = malloc(arg.length * 1, 1) >>> 0;\n getUint8Memory0().set(arg, ptr / 1);\n WASM_VECTOR_LEN = arg.length;\n return ptr;\n }\n /**\n * Create a DeepFilterNet Model\n *\n * Args:\n * - path: File path to a DeepFilterNet tar.gz onnx model\n * - atten_lim: Attenuation limit in dB.\n *\n * Returns:\n * - DF state doing the full processing: stft, DNN noise reduction, istft.\n * @param {Uint8Array} model_bytes\n * @param {number} atten_lim\n * @returns {number}\n */\n function df_create(model_bytes, atten_lim) {\n const ptr0 = passArray8ToWasm0(model_bytes, wasm.__wbindgen_malloc);\n const len0 = WASM_VECTOR_LEN;\n const ret = wasm.df_create(ptr0, len0, atten_lim);\n return ret >>> 0;\n }\n\n let cachedFloat32Memory0 = null;\n\n function getFloat32Memory0() {\n if (cachedFloat32Memory0 === null || cachedFloat32Memory0.byteLength === 0) {\n cachedFloat32Memory0 = new Float32Array(wasm.memory.buffer);\n }\n return cachedFloat32Memory0;\n }\n\n function passArrayF32ToWasm0(arg, malloc) {\n const ptr = malloc(arg.length * 4, 4) >>> 0;\n getFloat32Memory0().set(arg, ptr / 4);\n WASM_VECTOR_LEN = arg.length;\n return ptr;\n }\n /**\n * Processes a chunk of samples.\n *\n * Args:\n * - df_state: Created via df_create()\n * - input: Input buffer of length df_get_frame_length()\n * - output: Output buffer of length df_get_frame_length()\n *\n * Returns:\n * - Local SNR of the current frame.\n * @param {number} st\n * @param {Float32Array} input\n * @returns {Float32Array}\n */\n function df_process_frame(st, input) {\n const ptr0 = passArrayF32ToWasm0(input, wasm.__wbindgen_malloc);\n const len0 = WASM_VECTOR_LEN;\n const ret = wasm.df_process_frame(st, ptr0, len0);\n return takeObject(ret);\n }\n\n function handleError(f, args) {\n try {\n return f.apply(this, args);\n } catch (e) {\n wasm.__wbindgen_exn_store(addHeapObject(e));\n }\n }\n\n (typeof FinalizationRegistry === 'undefined')\n ? { }\n : new FinalizationRegistry(ptr => wasm.__wbg_dfstate_free(ptr >>> 0));\n\n function __wbg_get_imports() {\n const imports = {};\n imports.wbg = {};\n imports.wbg.__wbindgen_object_drop_ref = function(arg0) {\n takeObject(arg0);\n };\n imports.wbg.__wbg_crypto_566d7465cdbb6b7a = function(arg0) {\n const ret = getObject(arg0).crypto;\n return addHeapObject(ret);\n };\n imports.wbg.__wbindgen_is_object = function(arg0) {\n const val = getObject(arg0);\n const ret = typeof(val) === 'object' && val !== null;\n return ret;\n };\n imports.wbg.__wbg_process_dc09a8c7d59982f6 = function(arg0) {\n const ret = getObject(arg0).process;\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_versions_d98c6400c6ca2bd8 = function(arg0) {\n const ret = getObject(arg0).versions;\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_node_caaf83d002149bd5 = function(arg0) {\n const ret = getObject(arg0).node;\n return addHeapObject(ret);\n };\n imports.wbg.__wbindgen_is_string = function(arg0) {\n const ret = typeof(getObject(arg0)) === 'string';\n return ret;\n };\n imports.wbg.__wbg_require_94a9da52636aacbf = function() { return handleError(function () {\n const ret = module.require;\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbindgen_is_function = function(arg0) {\n const ret = typeof(getObject(arg0)) === 'function';\n return ret;\n };\n imports.wbg.__wbindgen_string_new = function(arg0, arg1) {\n const ret = getStringFromWasm0(arg0, arg1);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_msCrypto_0b84745e9245cdf6 = function(arg0) {\n const ret = getObject(arg0).msCrypto;\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_randomFillSync_290977693942bf03 = function() { return handleError(function (arg0, arg1) {\n getObject(arg0).randomFillSync(takeObject(arg1));\n }, arguments) };\n imports.wbg.__wbg_getRandomValues_260cc23a41afad9a = function() { return handleError(function (arg0, arg1) {\n getObject(arg0).getRandomValues(getObject(arg1));\n }, arguments) };\n imports.wbg.__wbg_newnoargs_e258087cd0daa0ea = function(arg0, arg1) {\n const ret = new Function(getStringFromWasm0(arg0, arg1));\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_new_63b92bc8671ed464 = function(arg0) {\n const ret = new Uint8Array(getObject(arg0));\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_new_9efabd6b6d2ce46d = function(arg0) {\n const ret = new Float32Array(getObject(arg0));\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_buffer_12d079cc21e14bdb = function(arg0) {\n const ret = getObject(arg0).buffer;\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_newwithbyteoffsetandlength_aa4a17c33a06e5cb = function(arg0, arg1, arg2) {\n const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_newwithlength_e9b4878cebadb3d3 = function(arg0) {\n const ret = new Uint8Array(arg0 >>> 0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_set_a47bac70306a19a7 = function(arg0, arg1, arg2) {\n getObject(arg0).set(getObject(arg1), arg2 >>> 0);\n };\n imports.wbg.__wbg_subarray_a1f73cd4b5b42fe1 = function(arg0, arg1, arg2) {\n const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_newwithbyteoffsetandlength_4a659d079a1650e0 = function(arg0, arg1, arg2) {\n const ret = new Float32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_self_ce0dbfc45cf2f5be = function() { return handleError(function () {\n const ret = self.self;\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbg_window_c6fb939a7f436783 = function() { return handleError(function () {\n const ret = window.window;\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbg_globalThis_d1e6af4856ba331b = function() { return handleError(function () {\n const ret = globalThis.globalThis;\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbg_global_207b558942527489 = function() { return handleError(function () {\n const ret = global.global;\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbindgen_is_undefined = function(arg0) {\n const ret = getObject(arg0) === undefined;\n return ret;\n };\n imports.wbg.__wbg_call_27c0f87801dedf93 = function() { return handleError(function (arg0, arg1) {\n const ret = getObject(arg0).call(getObject(arg1));\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbindgen_object_clone_ref = function(arg0) {\n const ret = getObject(arg0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_call_b3ca7c6051f9bec1 = function() { return handleError(function (arg0, arg1, arg2) {\n const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbindgen_memory = function() {\n const ret = wasm.memory;\n return addHeapObject(ret);\n };\n imports.wbg.__wbindgen_throw = function(arg0, arg1) {\n throw new Error(getStringFromWasm0(arg0, arg1));\n };\n\n return imports;\n }\n\n function __wbg_finalize_init(instance, module) {\n wasm = instance.exports;\n cachedFloat32Memory0 = null;\n cachedUint8Memory0 = null;\n\n\n return wasm;\n }\n\n function initSync(module) {\n if (wasm !== undefined) return wasm;\n\n const imports = __wbg_get_imports();\n\n if (!(module instanceof WebAssembly.Module)) {\n module = new WebAssembly.Module(module);\n }\n\n const instance = new WebAssembly.Instance(module, imports);\n\n return __wbg_finalize_init(instance);\n }\n\n const WorkletMessageTypes = {\n SET_SUPPRESSION_LEVEL: 'SET_SUPPRESSION_LEVEL',\n SET_BYPASS: 'SET_BYPASS'\n };\n\n class DeepFilterAudioProcessor extends AudioWorkletProcessor {\n constructor(options) {\n super();\n this.dfModel = null;\n this.inputWritePos = 0;\n this.inputReadPos = 0;\n this.outputWritePos = 0;\n this.outputReadPos = 0;\n this.bypass = false;\n this.isInitialized = false;\n this.tempFrame = null;\n this.bufferSize = 8192;\n this.inputBuffer = new Float32Array(this.bufferSize);\n this.outputBuffer = new Float32Array(this.bufferSize);\n try {\n // Initialize WASM from pre-compiled module\n initSync(options.processorOptions.wasmModule);\n const modelBytes = new Uint8Array(options.processorOptions.modelBytes);\n const handle = df_create(modelBytes, options.processorOptions.suppressionLevel ?? 50);\n const frameLength = df_get_frame_length(handle);\n this.dfModel = { handle, frameLength };\n this.bufferSize = frameLength * 4;\n this.inputBuffer = new Float32Array(this.bufferSize);\n this.outputBuffer = new Float32Array(this.bufferSize);\n // Pre-allocate temp frame buffer for processing\n this.tempFrame = new Float32Array(frameLength);\n this.isInitialized = true;\n this.port.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n }\n catch (error) {\n console.error('Failed to initialize DeepFilter in AudioWorklet:', error);\n this.isInitialized = false;\n }\n }\n handleMessage(data) {\n switch (data.type) {\n case WorkletMessageTypes.SET_SUPPRESSION_LEVEL:\n if (this.dfModel && typeof data.value === 'number') {\n const level = Math.max(0, Math.min(100, Math.floor(data.value)));\n df_set_atten_lim(this.dfModel.handle, level);\n }\n break;\n case WorkletMessageTypes.SET_BYPASS:\n this.bypass = Boolean(data.value);\n break;\n }\n }\n getInputAvailable() {\n return (this.inputWritePos - this.inputReadPos + this.bufferSize) % this.bufferSize;\n }\n getOutputAvailable() {\n return (this.outputWritePos - this.outputReadPos + this.bufferSize) % this.bufferSize;\n }\n process(inputList, outputList) {\n const sourceLimit = Math.min(inputList.length, outputList.length);\n const input = inputList[0]?.[0];\n if (!input) {\n return true;\n }\n // Passthrough mode - copy input to all output channels\n if (!this.isInitialized || !this.dfModel || this.bypass || !this.tempFrame) {\n for (let inputNum = 0; inputNum < sourceLimit; inputNum++) {\n const output = outputList[inputNum];\n const channelCount = output.length;\n for (let channelNum = 0; channelNum < channelCount; channelNum++) {\n output[channelNum].set(input);\n }\n }\n return true;\n }\n // Write input to ring buffer\n for (let i = 0; i < input.length; i++) {\n this.inputBuffer[this.inputWritePos] = input[i];\n this.inputWritePos = (this.inputWritePos + 1) % this.bufferSize;\n }\n const frameLength = this.dfModel.frameLength;\n while (this.getInputAvailable() >= frameLength) {\n // Extract frame from ring buffer\n for (let i = 0; i < frameLength; i++) {\n this.tempFrame[i] = this.inputBuffer[this.inputReadPos];\n this.inputReadPos = (this.inputReadPos + 1) % this.bufferSize;\n }\n const processed = df_process_frame(this.dfModel.handle, this.tempFrame);\n // Write to output ring buffer\n for (let i = 0; i < processed.length; i++) {\n this.outputBuffer[this.outputWritePos] = processed[i];\n this.outputWritePos = (this.outputWritePos + 1) % this.bufferSize;\n }\n }\n const outputAvailable = this.getOutputAvailable();\n if (outputAvailable >= 128) {\n for (let inputNum = 0; inputNum < sourceLimit; inputNum++) {\n const output = outputList[inputNum];\n const channelCount = output.length;\n for (let channelNum = 0; channelNum < channelCount; channelNum++) {\n const outputChannel = output[channelNum];\n let readPos = this.outputReadPos;\n for (let i = 0; i < 128; i++) {\n outputChannel[i] = this.outputBuffer[readPos];\n readPos = (readPos + 1) % this.bufferSize;\n }\n }\n }\n this.outputReadPos = (this.outputReadPos + 128) % this.bufferSize;\n }\n return true;\n }\n }\n registerProcessor('deepfilter-audio-processor', DeepFilterAudioProcessor);\n\n})();\n"; - -class DeepFilterNet3Core { - constructor(config = {}) { - this.assets = null; - this.workletNode = null; - this.isInitialized = false; - this.bypassEnabled = false; - this.config = { - sampleRate: config.sampleRate ?? 48000, - noiseReductionLevel: config.noiseReductionLevel ?? 50, - assetConfig: config.assetConfig - }; - this.assetLoader = getAssetLoader(config.assetConfig); - } - async initialize() { - if (this.isInitialized) - return; - // Fetch and compile WASM on main thread - const assetUrls = this.assetLoader.getAssetUrls(); - const [wasmBytes, modelBytes] = await Promise.all([ - this.assetLoader.fetchAsset(assetUrls.wasm), - this.assetLoader.fetchAsset(assetUrls.model) - ]); - // Compile WASM module - const wasmModule = await WebAssembly.compile(wasmBytes); - this.assets = { wasmModule, modelBytes }; - this.isInitialized = true; - } - async createAudioWorkletNode(audioContext) { - this.ensureInitialized(); - if (!this.assets) { - throw new Error('Assets not loaded'); - } - await createWorkletModule(audioContext, workletCode); - this.workletNode = new AudioWorkletNode(audioContext, 'deepfilter-audio-processor', { - processorOptions: { - wasmModule: this.assets.wasmModule, - modelBytes: this.assets.modelBytes, - suppressionLevel: this.config.noiseReductionLevel - } - }); - return this.workletNode; - } - setSuppressionLevel(level) { - if (!this.workletNode || typeof level !== 'number' || isNaN(level)) - return; - const clampedLevel = Math.max(0, Math.min(100, Math.floor(level))); - this.workletNode.port.postMessage({ - type: WorkletMessageTypes.SET_SUPPRESSION_LEVEL, - value: clampedLevel - }); - } - destroy() { - if (!this.isInitialized) - return; - if (this.workletNode) { - this.workletNode.disconnect(); - this.workletNode = null; - } - this.assets = null; - this.isInitialized = false; - } - isReady() { - return this.isInitialized && this.workletNode !== null; - } - setNoiseSuppressionEnabled(enabled) { - if (!this.workletNode) - return; - this.bypassEnabled = !enabled; - this.workletNode.port.postMessage({ - type: WorkletMessageTypes.SET_BYPASS, - value: !enabled - }); - } - isNoiseSuppressionEnabled() { - return !this.bypassEnabled; - } - ensureInitialized() { - if (!this.isInitialized) { - throw new Error('Processor not initialized. Call initialize() first.'); - } - } -} - -class DeepFilterNoiseFilterProcessor { - constructor(options = {}) { - this.name = 'deepfilternet3-noise-filter'; - this.audioContext = null; - this.sourceNode = null; - this.workletNode = null; - this.destination = null; - this.enabled = true; - this.init = async (opts) => { - const track = opts.track ?? opts.mediaStreamTrack; - if (!track) { - throw new Error('DeepFilterNoiseFilterProcessor.init: missing MediaStreamTrack'); - } - this.originalTrack = track; - await this.ensureGraph(); - }; - this.restart = async (opts) => { - const track = opts.track ?? opts.mediaStreamTrack; - if (track) { - this.originalTrack = track; - } - await this.ensureGraph(); - }; - this.setEnabled = async (enable) => { - this.enabled = enable; - this.processor.setNoiseSuppressionEnabled(enable); - return this.enabled; - }; - this.suspend = async () => { - if (this.audioContext && this.audioContext.state === 'running') { - await this.audioContext.suspend(); - } - }; - this.resume = async () => { - if (this.audioContext && this.audioContext.state === 'suspended') { - await this.audioContext.resume(); - } - }; - this.destroy = async () => { - await this.teardownGraph(); - this.processor.destroy(); - }; - const cfg = { - sampleRate: options.sampleRate ?? 48000, - noiseReductionLevel: options.noiseReductionLevel ?? 80, - assetConfig: options.assetConfig - }; - this.enabled = options.enabled ?? true; - this.processor = new DeepFilterNet3Core(cfg); - } - static isSupported() { - return typeof AudioContext !== 'undefined' && typeof WebAssembly !== 'undefined'; - } - setSuppressionLevel(level) { - this.processor.setSuppressionLevel(level); - } - isEnabled() { - return this.enabled; - } - isNoiseSuppressionEnabled() { - return this.processor.isNoiseSuppressionEnabled(); - } - async ensureGraph() { - if (!this.originalTrack) { - throw new Error('No source track'); - } - this.audioContext ?? (this.audioContext = new AudioContext({ sampleRate: 48000 })); - if (this.audioContext.state !== 'running') { - try { - await this.audioContext.resume(); - } - catch { - // Ignore resume errors - } - } - await this.processor.initialize(); - if (!this.workletNode) { - const node = await this.processor.createAudioWorkletNode(this.audioContext); - this.workletNode = node; - } - if (!this.destination) { - this.destination = this.audioContext.createMediaStreamDestination(); - this.processedTrack = this.destination.stream.getAudioTracks()[0]; - } - if (this.sourceNode) { - this.sourceNode.disconnect(); - } - this.sourceNode = this.audioContext.createMediaStreamSource(new MediaStream([this.originalTrack])); - this.sourceNode.connect(this.workletNode).connect(this.destination); - await this.setEnabled(this.enabled); - } - async teardownGraph() { - try { - if (this.workletNode) { - this.workletNode.disconnect(); - this.workletNode = null; - } - if (this.sourceNode) { - this.sourceNode.disconnect(); - this.sourceNode = null; - } - if (this.destination) { - this.destination.disconnect(); - this.destination = null; - } - if (this.audioContext) { - void this.audioContext.close(); - this.audioContext = null; - } - } - catch { - // Ignore disconnect errors - } - } -} -function DeepFilterNoiseFilter(options) { - return new DeepFilterNoiseFilterProcessor(options); -} - -export { AssetLoader, DeepFilterNet3Core, DeepFilterNoiseFilter, DeepFilterNoiseFilterProcessor, getAssetLoader }; diff --git a/desktop/vendor/deepfilternet3/v2/models/DeepFilterNet3_onnx.tar.gz b/desktop/vendor/deepfilternet3/v2/models/DeepFilterNet3_onnx.tar.gz deleted file mode 100644 index 1c4f4ff..0000000 Binary files a/desktop/vendor/deepfilternet3/v2/models/DeepFilterNet3_onnx.tar.gz and /dev/null differ diff --git a/desktop/vendor/deepfilternet3/v2/pkg/df_bg.wasm b/desktop/vendor/deepfilternet3/v2/pkg/df_bg.wasm deleted file mode 100644 index 0d02360..0000000 Binary files a/desktop/vendor/deepfilternet3/v2/pkg/df_bg.wasm and /dev/null differ diff --git a/main.js b/main.js deleted file mode 100644 index 030c413..0000000 --- a/main.js +++ /dev/null @@ -1,313 +0,0 @@ -const { app, BrowserWindow, session, desktopCapturer, ipcMain, clipboard } = require('electron'); -const { autoUpdater } = require('electron-updater'); -const path = require('path'); -const packageJson = require('./package.json'); -const PERIODIC_UPDATE_CHECK_INTERVAL_MS = 1 * 60 * 1000; - -const updateState = { - status: 'idle', // idle | checking | available | downloading | downloaded | installing | not-available | error - info: null, - error: null, -}; - -function broadcastUpdateState() { - const wins = BrowserWindow.getAllWindows(); - for (const win of wins) { - if (!win.isDestroyed()) { - win.webContents.send('update-state', updateState); - } - } -} - -function isNewerVersionAvailable(info) { - const next = info && typeof info.version === 'string' ? info.version : ''; - return Boolean(next) && next !== app.getVersion(); -} - -let updateCheckInProgress = false; -let installInProgress = false; -let periodicUpdateTimer = null; - -function resolveBackendUrl() { - const configuredUrl = (process.env.CHATTZ_URL || process.env.APP_BASE_URL || '').trim(); - if (configuredUrl) { - return configuredUrl.replace(/\/$/, ''); - } - - const packagedFallback = typeof packageJson.homepage === 'string' - ? packageJson.homepage.trim() - : ''; - if (app.isPackaged && packagedFallback) { - return packagedFallback.replace(/\/$/, ''); - } - - return 'http://localhost:3000'; -} - -function webContentsOrigin(webContents) { - if (!webContents || typeof webContents.getURL !== 'function') { - return null; - } - return safeOrigin(webContents.getURL()); -} - -async function runUpdateCheck(reason = 'manual') { - if (installInProgress) { - console.log(`Update check skipped (${reason}): install already in progress`); - return; - } - if (updateCheckInProgress) { - console.log(`Update check skipped (${reason}): another check is already in progress`); - return; - } - updateCheckInProgress = true; - updateState.status = 'checking'; - updateState.error = null; - try { - const result = await autoUpdater.checkForUpdates(); - const info = result && result.updateInfo ? result.updateInfo : null; - if (isNewerVersionAvailable(info)) { - updateState.status = 'available'; - updateState.info = info; - updateState.error = null; - } else { - updateState.status = 'not-available'; - updateState.info = info; - updateState.error = null; - } - } catch (err) { - updateState.status = 'error'; - updateState.error = err && err.message ? err.message : String(err); - console.error(`Update check failed (${reason})`, err); - } finally { - updateCheckInProgress = false; - broadcastUpdateState(); - } -} - -function installDownloadedUpdate() { - if (installInProgress) { - console.log('Update install already in progress'); - return; - } - - installInProgress = true; - updateState.status = 'installing'; - updateState.error = null; - broadcastUpdateState(); - - const wins = BrowserWindow.getAllWindows(); - for (const win of wins) { - if (win.isDestroyed()) continue; - try { - win.removeAllListeners('close'); - win.destroy(); - } catch (err) { - console.warn('Failed to destroy window before update install', err); - } - } - - setImmediate(() => { - try { - autoUpdater.quitAndInstall(false, true); - } catch (err) { - installInProgress = false; - updateState.status = 'error'; - updateState.error = err && err.message ? err.message : String(err); - broadcastUpdateState(); - console.error('quitAndInstall failed', err); - } - }); - - setTimeout(() => { - if (installInProgress) { - console.warn('Update install is still waiting for app shutdown'); - } - }, 15000); -} - -function startPeriodicUpdateChecks() { - if (periodicUpdateTimer || !app.isPackaged) { - return; - } - - periodicUpdateTimer = setInterval(() => { - void runUpdateCheck('periodic'); - }, PERIODIC_UPDATE_CHECK_INTERVAL_MS); -} - -function createWindow() { - const sess = session.fromPartition('persist:chattz'); - const backendUrl = resolveBackendUrl(); - const backendOrigin = new URL(backendUrl).origin; - console.log(`Desktop backend URL: ${backendUrl}`); - - const win = new BrowserWindow({ - width: 1200, - height: 800, - title: "Chattz Desktop", - webPreferences: { - nodeIntegration: false, - contextIsolation: true, - session: sess, - preload: path.join(__dirname, 'desktop', 'preload.js') - } - }); - - win.setAutoHideMenuBar(true); - win.setMenuBarVisibility(true); - - sess.setPermissionCheckHandler((webContents, permission) => { - const origin = webContentsOrigin(webContents); - if (origin !== backendOrigin) return false; - return permission === 'media' || permission === 'clipboard-write'; - }); - - sess.setPermissionRequestHandler((webContents, permission, callback) => { - const origin = webContentsOrigin(webContents); - if (origin === backendOrigin && (permission === 'media' || permission === 'clipboard-write')) { - callback(true); - } else { - callback(false); - } - }); - - sess.setDisplayMediaRequestHandler((request, callback) => { - const origin = safeOrigin(request.frame?.url || win.webContents.getURL()); - if (origin !== backendOrigin) { - callback(null); - return; - } - desktopCapturer.getSources({ types: ['screen', 'window'] }).then((sources) => { - if (sources && sources.length > 0) { - const screenSource = sources.find(s => s.id.startsWith('screen')) || sources[0]; - callback({ video: screenSource, audio: 'loopback' }); - } else { - callback(null); - } - }).catch(err => { - console.error("Failed to get desktop sources for screen share", err); - callback(null); - }); - }); - - win.loadURL(backendUrl).catch((err) => { - console.error(`Failed to load desktop app: ${err}`); - }); - - // Ensure renderer receives latest updater state after any (re)load. - // Delay broadcast by 300ms to give the renderer time to register its - // onUpdateState IPC listener before we push state. - win.webContents.on('did-finish-load', () => { - setTimeout(() => { - if (!win.isDestroyed()) broadcastUpdateState(); - }, 300); - }); - - // Uncomment to debug - // win.webContents.openDevTools(); -} - -app.commandLine.appendSwitch('disable-webrtc-hw-encoding'); // Sometime helps resolve codec mismatch behavior -app.commandLine.appendSwitch('log-level', '3'); // Silences standard Chromium warning logs (like SRTP transport unprotect logs which are benign timing issues) - -app.whenReady().then(() => { - ipcMain.handle('clipboard-write', (event, text) => { - clipboard.writeText(text); - return true; - }); - - ipcMain.handle('get-update-state', () => ({ ...updateState })); - ipcMain.handle('check-for-updates-now', async () => { - await runUpdateCheck('renderer-direct'); - return { ...updateState }; - }); - - createWindow(); - - // Configure Auto-Updater - autoUpdater.autoDownload = false; - autoUpdater.logger = console; - - autoUpdater.on('update-available', (info) => { - updateState.status = 'available'; - updateState.info = info; - updateState.error = null; - broadcastUpdateState(); - const wins = BrowserWindow.getAllWindows(); - if (wins.length > 0) wins[0].webContents.send('update-available', info); - }); - - autoUpdater.on('update-not-available', (info) => { - updateState.status = 'not-available'; - updateState.info = info || null; - updateState.error = null; - broadcastUpdateState(); - }); - - autoUpdater.on('update-downloaded', (info) => { - updateState.status = 'downloaded'; - updateState.info = info; - updateState.error = null; - broadcastUpdateState(); - const wins = BrowserWindow.getAllWindows(); - if (wins.length > 0) wins[0].webContents.send('update-downloaded', info); - }); - - autoUpdater.on('error', (err) => { - updateState.status = 'error'; - updateState.error = err.message; - broadcastUpdateState(); - const wins = BrowserWindow.getAllWindows(); - if (wins.length > 0) wins[0].webContents.send('update-error', err.message); - }); - - ipcMain.on('check-for-updates', () => { - void runUpdateCheck('manual'); - }); - - ipcMain.on('download-update', () => { - if (installInProgress) return; - updateState.status = 'downloading'; - updateState.error = null; - broadcastUpdateState(); - autoUpdater.downloadUpdate(); - }); - - ipcMain.on('quit-and-install', () => { - installDownloadedUpdate(); - }); - - // Check once on startup - setTimeout(() => { - void runUpdateCheck('startup'); - }, 5000); - startPeriodicUpdateChecks(); - - app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } - }); -}); - -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } -}); - -app.on('before-quit', () => { - if (periodicUpdateTimer) { - clearInterval(periodicUpdateTimer); - periodicUpdateTimer = null; - } -}); - -function safeOrigin(value) { - try { - return new URL(value).origin; - } catch (_) { - return null; - } -} diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 686ca4b..0000000 --- a/package-lock.json +++ /dev/null @@ -1,5307 +0,0 @@ -{ - "name": "chattz-electron", - "version": "0.0.50", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "chattz-electron", - "version": "0.0.50", - "dependencies": { - "electron-updater": "^6.8.3" - }, - "devDependencies": { - "electron": "^34.5.8", - "electron-builder": "^25.1.8" - } - }, - "node_modules/@develar/schema-utils": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", - "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.0", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/@electron/asar": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", - "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^5.0.0", - "glob": "^7.1.6", - "minimatch": "^3.0.4" - }, - "bin": { - "asar": "bin/asar.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/@electron/asar/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@electron/asar/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@electron/asar/node_modules/minimatch": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.4.tgz", - "integrity": "sha512-twmL+S8+7yIsE9wsqgzU3E8/LumN3M3QELrBZ20OdmQ9jB2JvW5oZtBEmft84k/Gs5CG9mqtWc6Y9vW+JEzGxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@electron/get": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", - "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^11.8.5", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "global-agent": "^3.0.0" - } - }, - "node_modules/@electron/notarize": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", - "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "fs-extra": "^9.0.1", - "promise-retry": "^2.0.1" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@electron/notarize/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/notarize/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/notarize/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@electron/osx-sign": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz", - "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "compare-version": "^0.1.2", - "debug": "^4.3.4", - "fs-extra": "^10.0.0", - "isbinaryfile": "^4.0.8", - "minimist": "^1.2.6", - "plist": "^3.0.5" - }, - "bin": { - "electron-osx-flat": "bin/electron-osx-flat.js", - "electron-osx-sign": "bin/electron-osx-sign.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@electron/osx-sign/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/@electron/osx-sign/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/osx-sign/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@electron/rebuild": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.6.1.tgz", - "integrity": "sha512-f6596ZHpEq/YskUd8emYvOUne89ij8mQgjYFA5ru25QwbrRO+t1SImofdDv7kKOuWCmVOuU5tvfkbgGxIl3E/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "node-abi": "^3.45.0", - "node-api-version": "^0.2.0", - "node-gyp": "^9.0.0", - "ora": "^5.1.0", - "read-binary-file-arch": "^1.0.6", - "semver": "^7.3.5", - "tar": "^6.0.5", - "yargs": "^17.0.1" - }, - "bin": { - "electron-rebuild": "lib/cli.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/rebuild/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@electron/rebuild/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/rebuild/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/rebuild/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@electron/universal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", - "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron/asar": "^3.2.7", - "@malept/cross-spawn-promise": "^2.0.0", - "debug": "^4.3.1", - "dir-compare": "^4.2.0", - "fs-extra": "^11.1.1", - "minimatch": "^9.0.3", - "plist": "^3.1.0" - }, - "engines": { - "node": ">=16.4" - } - }, - "node_modules/@electron/universal/node_modules/fs-extra": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", - "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@electron/universal/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/universal/node_modules/minimatch": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.7.tgz", - "integrity": "sha512-MOwgjc8tfrpn5QQEvjijjmDVtMw2oL88ugTevzxQnzRLm6l3fVEF2gzU0kYeYYKD8C66+IdGX6peJ4MyUlUnPg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@electron/universal/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@malept/cross-spawn-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", - "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/@malept/flatpak-bundler": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", - "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "fs-extra": "^9.0.0", - "lodash": "^4.17.15", - "tmp-promise": "^3.0.2" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@malept/flatpak-bundler/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.19.33", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.33.tgz", - "integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/plist": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", - "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*", - "xmlbuilder": ">=11.0.1" - } - }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/verror": { - "version": "1.10.11", - "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", - "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", - "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/7zip-bin": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", - "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/app-builder-bin": { - "version": "5.0.0-alpha.10", - "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.10.tgz", - "integrity": "sha512-Ev4jj3D7Bo+O0GPD2NMvJl+PGiBAfS7pUGawntBNpCbxtpncfUixqFj9z9Jme7V7s3LBGqsWZZP54fxBX3JKJw==", - "dev": true, - "license": "MIT" - }, - "node_modules/app-builder-lib": { - "version": "25.1.8", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-25.1.8.tgz", - "integrity": "sha512-pCqe7dfsQFBABC1jeKZXQWhGcCPF3rPCXDdfqVKjIeWBcXzyC1iOWZdfFhGl+S9MyE/k//DFmC6FzuGAUudNDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@develar/schema-utils": "~2.6.5", - "@electron/notarize": "2.5.0", - "@electron/osx-sign": "1.3.1", - "@electron/rebuild": "3.6.1", - "@electron/universal": "2.0.1", - "@malept/flatpak-bundler": "^0.4.0", - "@types/fs-extra": "9.0.13", - "async-exit-hook": "^2.0.1", - "bluebird-lst": "^1.0.9", - "builder-util": "25.1.7", - "builder-util-runtime": "9.2.10", - "chromium-pickle-js": "^0.2.0", - "config-file-ts": "0.2.8-rc1", - "debug": "^4.3.4", - "dotenv": "^16.4.5", - "dotenv-expand": "^11.0.6", - "ejs": "^3.1.8", - "electron-publish": "25.1.7", - "form-data": "^4.0.0", - "fs-extra": "^10.1.0", - "hosted-git-info": "^4.1.0", - "is-ci": "^3.0.0", - "isbinaryfile": "^5.0.0", - "js-yaml": "^4.1.0", - "json5": "^2.2.3", - "lazy-val": "^1.0.5", - "minimatch": "^10.0.0", - "resedit": "^1.7.0", - "sanitize-filename": "^1.6.3", - "semver": "^7.3.8", - "tar": "^6.1.12", - "temp-file": "^3.4.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "dmg-builder": "25.1.8", - "electron-builder-squirrel-windows": "25.1.8" - } - }, - "node_modules/app-builder-lib/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/app-builder-lib/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/app-builder-lib/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/app-builder-lib/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/aproba": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "dev": true, - "license": "ISC" - }, - "node_modules/archiver": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", - "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "archiver-utils": "^2.1.0", - "async": "^3.2.4", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.1.2", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/archiver-utils/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/archiver-utils/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, - "node_modules/async-exit-hook": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", - "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true, - "license": "MIT" - }, - "node_modules/bluebird-lst": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", - "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "bluebird": "^3.5.5" - } - }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/brace-expansion": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz", - "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/builder-util": { - "version": "25.1.7", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-25.1.7.tgz", - "integrity": "sha512-7jPjzBwEGRbwNcep0gGNpLXG9P94VA3CPAZQCzxkFXiV2GMQKlziMbY//rXPI7WKfhsvGgFXjTcXdBEwgXw9ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/debug": "^4.1.6", - "7zip-bin": "~5.2.0", - "app-builder-bin": "5.0.0-alpha.10", - "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.2.10", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "debug": "^4.3.4", - "fs-extra": "^10.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "is-ci": "^3.0.0", - "js-yaml": "^4.1.0", - "source-map-support": "^0.5.19", - "stat-mode": "^1.0.0", - "temp-file": "^3.4.0" - } - }, - "node_modules/builder-util-runtime": { - "version": "9.2.10", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.10.tgz", - "integrity": "sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/builder-util/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/builder-util/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/builder-util/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/cacache/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.8.tgz", - "integrity": "sha512-7RN35vit8DeBclkofOVmBY0eDAZZQd1HzmukRdSyz95CRh8FT54eqnbj0krQr3mrHR6sfRyYkyhwBWjoV5uqlQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/chromium-pickle-js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", - "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/compare-version": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", - "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/compress-commons": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", - "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/config-file-ts": { - "version": "0.2.8-rc1", - "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz", - "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob": "^10.3.12", - "typescript": "^5.4.3" - } - }, - "node_modules/config-file-ts/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minimatch": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.7.tgz", - "integrity": "sha512-MOwgjc8tfrpn5QQEvjijjmDVtMw2oL88ugTevzxQnzRLm6l3fVEF2gzU0kYeYYKD8C66+IdGX6peJ4MyUlUnPg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "buffer": "^5.1.0" - } - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/crc32-stream": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", - "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/dir-compare": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", - "integrity": "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimatch": "^3.0.5", - "p-limit": "^3.1.0 " - } - }, - "node_modules/dir-compare/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/dir-compare/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/dir-compare/node_modules/minimatch": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.4.tgz", - "integrity": "sha512-twmL+S8+7yIsE9wsqgzU3E8/LumN3M3QELrBZ20OdmQ9jB2JvW5oZtBEmft84k/Gs5CG9mqtWc6Y9vW+JEzGxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/dmg-builder": { - "version": "25.1.8", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-25.1.8.tgz", - "integrity": "sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "app-builder-lib": "25.1.8", - "builder-util": "25.1.7", - "builder-util-runtime": "9.2.10", - "fs-extra": "^10.1.0", - "iconv-lite": "^0.6.2", - "js-yaml": "^4.1.0" - }, - "optionalDependencies": { - "dmg-license": "^1.0.11" - } - }, - "node_modules/dmg-builder/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dmg-builder/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/dmg-builder/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/dmg-license": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", - "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "@types/plist": "^3.0.1", - "@types/verror": "^1.10.3", - "ajv": "^6.10.0", - "crc": "^3.8.0", - "iconv-corefoundation": "^1.1.7", - "plist": "^3.0.4", - "smart-buffer": "^4.0.2", - "verror": "^1.10.0" - }, - "bin": { - "dmg-license": "bin/dmg-license.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dotenv-expand": { - "version": "11.0.7", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", - "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dotenv": "^16.4.5" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron": { - "version": "34.5.8", - "resolved": "https://registry.npmjs.org/electron/-/electron-34.5.8.tgz", - "integrity": "sha512-vxLD65mabTzYmEVa9KceMHM0+zO+vqgrhcyNVlmTd0IGV5J7XZ8v/qElm0o4YQ4wPeq7olZkUjZkBQQEdr23/g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@electron/get": "^2.0.0", - "@types/node": "^20.9.0", - "extract-zip": "^2.0.1" - }, - "bin": { - "electron": "cli.js" - }, - "engines": { - "node": ">= 12.20.55" - } - }, - "node_modules/electron-builder": { - "version": "25.1.8", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-25.1.8.tgz", - "integrity": "sha512-poRgAtUHHOnlzZnc9PK4nzG53xh74wj2Jy7jkTrqZ0MWPoHGh1M2+C//hGeYdA+4K8w4yiVCNYoLXF7ySj2Wig==", - "dev": true, - "license": "MIT", - "dependencies": { - "app-builder-lib": "25.1.8", - "builder-util": "25.1.7", - "builder-util-runtime": "9.2.10", - "chalk": "^4.1.2", - "dmg-builder": "25.1.8", - "fs-extra": "^10.1.0", - "is-ci": "^3.0.0", - "lazy-val": "^1.0.5", - "simple-update-notifier": "2.0.0", - "yargs": "^17.6.2" - }, - "bin": { - "electron-builder": "cli.js", - "install-app-deps": "install-app-deps.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/electron-builder-squirrel-windows": { - "version": "25.1.8", - "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-25.1.8.tgz", - "integrity": "sha512-2ntkJ+9+0GFP6nAISiMabKt6eqBB0kX1QqHNWFWAXgi0VULKGisM46luRFpIBiU3u/TDmhZMM8tzvo2Abn3ayg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "app-builder-lib": "25.1.8", - "archiver": "^5.3.1", - "builder-util": "25.1.7", - "fs-extra": "^10.1.0" - } - }, - "node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-builder-squirrel-windows/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-builder-squirrel-windows/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-builder/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-builder/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-builder/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-publish": { - "version": "25.1.7", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-25.1.7.tgz", - "integrity": "sha512-+jbTkR9m39eDBMP4gfbqglDd6UvBC7RLh5Y0MhFSsc6UkGHj9Vj9TWobxevHYMMqmoujL11ZLjfPpMX+Pt6YEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/fs-extra": "^9.0.11", - "builder-util": "25.1.7", - "builder-util-runtime": "9.2.10", - "chalk": "^4.1.2", - "fs-extra": "^10.1.0", - "lazy-val": "^1.0.5", - "mime": "^2.5.2" - } - }, - "node_modules/electron-publish/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-publish/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-publish/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-updater": { - "version": "6.8.3", - "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.8.3.tgz", - "integrity": "sha512-Z6sgw3jgbikWKXei1ENdqFOxBP0WlXg3TtKfz0rgw2vIZFJUyI4pD7ZN7jrkm7EoMK+tcm/qTnPUdqfZukBlBQ==", - "license": "MIT", - "dependencies": { - "builder-util-runtime": "9.5.1", - "fs-extra": "^10.1.0", - "js-yaml": "^4.1.0", - "lazy-val": "^1.0.5", - "lodash.escaperegexp": "^4.1.2", - "lodash.isequal": "^4.5.0", - "semver": "~7.7.3", - "tiny-typed-emitter": "^2.1.0" - } - }, - "node_modules/electron-updater/node_modules/builder-util-runtime": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", - "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/electron-updater/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-updater/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-updater/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-updater/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/exponential-backoff": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", - "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extsprintf": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", - "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "optional": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/filelist": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.5.tgz", - "integrity": "sha512-ct/ckWBV/9Dg3MlvCXsLcSUyoWwv9mCKqlhLNB2DAuXR/NZolSXlQqP5dyy6guWlPXBhodZyZ5lGPQcbQDxrEQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "minimatch": "^10.2.1" - }, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.4.tgz", - "integrity": "sha512-twmL+S8+7yIsE9wsqgzU3E8/LumN3M3QELrBZ20OdmQ9jB2JvW5oZtBEmft84k/Gs5CG9mqtWc6Y9vW+JEzGxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/global-agent/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/iconv-corefoundation": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", - "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "cli-truncate": "^2.1.0", - "node-addon-api": "^1.6.3" - }, - "engines": { - "node": "^8.11.2 || >=10" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true, - "license": "ISC" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/isbinaryfile": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz", - "integrity": "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jake": { - "version": "10.9.4", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", - "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "async": "^3.2.6", - "filelist": "^1.0.4", - "picocolors": "^1.1.1" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "license": "ISC", - "optional": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/lazy-val": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", - "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", - "license": "MIT" - }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/lazystream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", - "license": "MIT" - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz", - "integrity": "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-abi": { - "version": "3.87.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz", - "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-abi/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", - "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/node-api-version": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz", - "integrity": "sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - } - }, - "node_modules/node-api-version/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", - "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.13 || ^14.13 || >=16" - } - }, - "node_modules/node-gyp/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/pe-library": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz", - "integrity": "sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jet2jet" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/plist": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", - "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xmldom/xmldom": "^0.8.8", - "base64-js": "^1.5.1", - "xmlbuilder": "^15.1.1" - }, - "engines": { - "node": ">=10.4.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-binary-file-arch": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", - "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "bin": { - "read-binary-file-arch": "cli.js" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdir-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", - "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "minimatch": "^5.1.0" - } - }, - "node_modules/readdir-glob/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/readdir-glob/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/readdir-glob/node_modules/minimatch": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.8.tgz", - "integrity": "sha512-7RN35vit8DeBclkofOVmBY0eDAZZQd1HzmukRdSyz95CRh8FT54eqnbj0krQr3mrHR6sfRyYkyhwBWjoV5uqlQ==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resedit": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.2.tgz", - "integrity": "sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pe-library": "^0.4.1" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jet2jet" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" - }, - "node_modules/sanitize-filename": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", - "dev": true, - "license": "WTFPL OR ISC", - "dependencies": { - "truncate-utf8-bytes": "^1.0.0" - } - }, - "node_modules/sax": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=11.0.0" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/socks-proxy-agent/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true - }, - "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/stat-mode": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", - "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.1.0" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/temp-file": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", - "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-exit-hook": "^2.0.1", - "fs-extra": "^10.0.0" - } - }, - "node_modules/temp-file/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/temp-file/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/temp-file/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/tiny-typed-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", - "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", - "license": "MIT" - }, - "node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.14" - } - }, - "node_modules/tmp-promise": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", - "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "tmp": "^0.2.0" - } - }, - "node_modules/truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", - "dev": true, - "license": "WTFPL", - "dependencies": { - "utf8-byte-length": "^1.0.1" - } - }, - "node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/utf8-byte-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", - "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", - "dev": true, - "license": "(WTFPL OR MIT)" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/verror": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", - "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/xmlbuilder": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zip-stream": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", - "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "archiver-utils": "^3.0.4", - "compress-commons": "^4.1.2", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/zip-stream/node_modules/archiver-utils": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", - "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "glob": "^7.2.3", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index f5c75b8..0000000 --- a/package.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "chattz-electron", - "version": "0.0.50", - "description": "Electron frontend for Chattz", - "author": "Pavel Flegr ", - "homepage": "https://discord.flegr.me", - "repository": { - "type": "git", - "url": "https://git.flegr.me/pavel/discord.git" - }, - "main": "main.js", - "scripts": { - "build:html": "node scripts/generate-html.js", - "start": "npm run build:html && electron .", - "dev": "npm run build:html && electron .", - "dist": "npm run build:html && electron-builder --publish never", - "dist:linux": "npm run build:html && electron-builder --linux --publish never", - "dist:win": "npm run build:html && electron-builder --win --publish never" - }, - "build": { - "appId": "me.flegr.chattz", - "productName": "Chattz", - "linux": { - "target": [ - "AppImage", - "rpm" - ], - "category": "Chat", - "icon": "build/icon.png" - }, - "win": { - "target": [ - "nsis" - ] - }, - "publish": [ - { - "provider": "generic", - "url": "https://discord.flegr.me/static/installers", - "channel": "latest" - } - ], - "files": [ - "main.js", - "package.json", - "desktop/", - "static/", - "!dist" - ], - "directories": { - "output": "dist" - } - }, - "devDependencies": { - "electron": "^34.5.8", - "electron-builder": "^25.1.8" - }, - "dependencies": { - "electron-updater": "^6.8.3" - } -} diff --git a/scripts/generate-html.js b/scripts/generate-html.js deleted file mode 100644 index a773454..0000000 --- a/scripts/generate-html.js +++ /dev/null @@ -1,57 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -const root = path.resolve(__dirname, '..'); -const templatePath = path.join(root, 'shared-html', 'index.template.html'); -const template = fs.readFileSync(templatePath, 'utf8'); - -const updaterMarkup = ``; - -const variants = { - web: { - styles_href: '/static/styles.css', - lucide_src: '/static/vendor/lucide.min.js', - app_src: '/static/app.js?v=20260227-shared-core-1', - web_downloads: `
- Desktop downloads: - Windows - Linux (RPM) -
`, - desktop_updater: updaterMarkup, - outPath: path.join(root, 'static', 'index.html'), - }, - desktop: { - styles_href: '../static/styles.css', - lucide_src: '../static/vendor/lucide.min.js', - app_src: 'app.js?v=20260227-shared-core-1', - web_downloads: '', - desktop_updater: updaterMarkup, - outPath: path.join(root, 'desktop', 'index.html'), - }, -}; - -for (const variant of Object.values(variants)) { - let output = template; - for (const [key, value] of Object.entries(variant)) { - if (key === 'outPath') continue; - const token = `{{${key}}}`; - if (value === '') { - output = output.replace(new RegExp(`^[ \\t]*\\{\\{${key}\\}\\}[ \\t]*\\n?`, 'm'), ''); - continue; - } - output = output.replaceAll(token, value); - } - - if (/\{\{[a-z_]+\}\}/i.test(output)) { - throw new Error(`Unresolved template placeholders remain in ${variant.outPath}`); - } - - fs.writeFileSync( - variant.outPath, - `\n${output}`, - 'utf8' - ); -} diff --git a/shared-html/index.template.html b/shared-html/index.template.html deleted file mode 100644 index 3425611..0000000 --- a/shared-html/index.template.html +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - - Chattz - - - - - - -
-
-
C
-

Chattz

-

Sign in to open your servers.

- - {{web_downloads}} -

-
-
- - - - - - - - - - - - - - - - - - - diff --git a/src/auth.rs b/src/auth.rs index 535953e..66fd67a 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,25 +1,32 @@ -use anyhow::{Result, anyhow}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use anyhow::{Context, Result, anyhow}; use axum::{ Json, extract::{FromRef, FromRequestParts}, - http::{HeaderMap, StatusCode, request::Parts}, + http::{StatusCode, request::Parts}, response::{IntoResponse, Response}, }; -use chrono::{Duration, Utc}; -use serde::Serialize; -use sha2::{Digest, Sha256}; +use jsonwebtoken::{DecodingKey, EncodingKey, Header, Validation, decode, encode}; +use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{AppState, db}; -pub const OAUTH_STATE_COOKIE: &str = "chattz_oauth_state"; -pub const SESSION_COOKIE: &str = "chattz_session"; -const SESSION_TTL_DAYS: i64 = 30; +const SESSION_COOKIE: &str = "chattz_session"; +const OAUTH_STATE_COOKIE: &str = "chattz_oauth_state"; +const SESSION_TTL_SECS: u64 = 60 * 60 * 24 * 7; + +#[derive(Debug, Serialize, Deserialize, Clone)] +struct SessionClaims { + sub: String, + exp: usize, + iat: usize, +} #[derive(Debug, Clone)] pub struct AuthUser { pub id: Uuid, - pub session_id: String, } #[derive(Debug)] @@ -36,13 +43,6 @@ impl ApiError { } } - pub fn forbidden(msg: &str) -> Self { - Self { - status: StatusCode::FORBIDDEN, - message: msg.to_string(), - } - } - pub fn bad_request(msg: &str) -> Self { Self { status: StatusCode::BAD_REQUEST, @@ -56,13 +56,6 @@ impl ApiError { message: msg.to_string(), } } - - pub fn service_unavailable(msg: &str) -> Self { - Self { - status: StatusCode::SERVICE_UNAVAILABLE, - message: msg.to_string(), - } - } } #[derive(Serialize)] @@ -72,13 +65,7 @@ struct ErrorBody<'a> { impl IntoResponse for ApiError { fn into_response(self) -> Response { - ( - self.status, - Json(ErrorBody { - error: &self.message, - }), - ) - .into_response() + (self.status, Json(ErrorBody { error: &self.message })).into_response() } } @@ -90,25 +77,25 @@ impl From for ApiError { impl FromRequestParts for AuthUser where - AppState: FromRef, + AppState: axum::extract::FromRef, S: Send + Sync, { type Rejection = ApiError; async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { let app = AppState::from_ref(state); - let session_id = read_cookie_from_headers(&parts.headers, SESSION_COOKIE) - .ok_or_else(|| ApiError::unauthorized("missing session cookie"))?; + let token = read_cookie(parts, SESSION_COOKIE).ok_or_else(|| ApiError::unauthorized("missing session"))?; + let user_id = verify_session(&token, &app.settings.session_secret) + .map_err(|_| ApiError::unauthorized("invalid session"))?; - let user_id = db::touch_active_session(&app.db, &session_id) + let exists = db::user_exists(&app.db, user_id) .await - .map_err(|_| ApiError::unauthorized("invalid or expired session"))? - .ok_or_else(|| ApiError::unauthorized("invalid or expired session"))?; + .map_err(|_| ApiError::unauthorized("session user not found"))?; + if !exists { + return Err(ApiError::unauthorized("session user not found")); + } - Ok(Self { - id: user_id, - session_id, - }) + Ok(Self { id: user_id }) } } @@ -116,14 +103,6 @@ pub fn new_oauth_state() -> String { Uuid::new_v4().to_string() } -pub fn new_session_id() -> String { - Uuid::new_v4().simple().to_string() -} - -pub fn session_expiry() -> chrono::DateTime { - (Utc::now() + Duration::days(SESSION_TTL_DAYS)).fixed_offset() -} - pub fn make_oauth_state_cookie(value: &str, secure: bool) -> String { format!( "{name}={value}; Path=/; HttpOnly; SameSite=Lax; Max-Age=600{secure_flag}", @@ -133,32 +112,69 @@ pub fn make_oauth_state_cookie(value: &str, secure: bool) -> String { } pub fn clear_oauth_state_cookie(secure: bool) -> String { - clear_cookie(OAUTH_STATE_COOKIE, secure, "Lax") -} - -pub fn make_session_cookie(value: &str, secure: bool) -> String { format!( - "{name}={value}; Path=/; HttpOnly; SameSite=Strict; Max-Age={ttl}{secure_flag}", - name = SESSION_COOKIE, - ttl = Duration::days(SESSION_TTL_DAYS).num_seconds(), + "{name}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0{secure_flag}", + name = OAUTH_STATE_COOKIE, secure_flag = if secure { "; Secure" } else { "" } ) } -pub fn clear_session_cookie(secure: bool) -> String { - clear_cookie(SESSION_COOKIE, secure, "Strict") -} - -pub fn read_cookie_from_headers(headers: &HeaderMap, cookie_name: &str) -> Option { +pub fn read_oauth_state_from_headers(headers: &axum::http::HeaderMap) -> Option { let raw = headers.get(axum::http::header::COOKIE)?.to_str().ok()?; raw.split(';').find_map(|pair| { let mut kv = pair.trim().splitn(2, '='); let key = kv.next()?; let value = kv.next()?; - (key == cookie_name).then(|| value.to_string()) + (key == OAUTH_STATE_COOKIE).then(|| value.to_string()) }) } +pub fn new_session_cookie(user_id: Uuid, secret: &str, secure: bool) -> Result { + let now = now_ts(); + let claims = SessionClaims { + sub: user_id.to_string(), + iat: now as usize, + exp: (now + SESSION_TTL_SECS) as usize, + }; + + let token = encode( + &Header::default(), + &claims, + &EncodingKey::from_secret(secret.as_bytes()), + ) + .context("failed to encode session token")?; + + Ok(format!( + "{name}={token}; Path=/; HttpOnly; SameSite=Lax; Max-Age={ttl}{secure_flag}", + name = SESSION_COOKIE, + ttl = SESSION_TTL_SECS, + secure_flag = if secure { "; Secure" } else { "" } + )) +} + +pub fn clear_session_cookie(secure: bool) -> String { + format!( + "{name}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0{secure_flag}", + name = SESSION_COOKIE, + secure_flag = if secure { "; Secure" } else { "" } + ) +} + +fn verify_session(token: &str, secret: &str) -> Result { + let mut validation = Validation::default(); + validation.validate_exp = true; + + let data = decode::( + token, + &DecodingKey::from_secret(secret.as_bytes()), + &validation, + ) + .context("failed to decode session token")?; + + let user_id = Uuid::parse_str(&data.claims.sub).context("invalid sub in session token")?; + Ok(user_id) +} + pub fn validate_oauth_state(expected_cookie: Option, query_state: &str) -> Result<()> { let expected = expected_cookie.ok_or_else(|| anyhow!("missing oauth state cookie"))?; if expected != query_state { @@ -167,113 +183,19 @@ pub fn validate_oauth_state(expected_cookie: Option, query_state: &str) Ok(()) } -pub fn user_agent_hash(headers: &HeaderMap) -> Option { - header_hash(headers, axum::http::header::USER_AGENT.as_str()) +fn read_cookie(parts: &Parts, name: &str) -> Option { + let raw = parts.headers.get(axum::http::header::COOKIE)?.to_str().ok()?; + raw.split(';').find_map(|pair| { + let mut kv = pair.trim().splitn(2, '='); + let key = kv.next()?; + let value = kv.next()?; + (key == name).then(|| value.to_string()) + }) } -pub fn ip_hash(headers: &HeaderMap) -> Option { - headers - .get("x-forwarded-for") - .and_then(|v| v.to_str().ok()) - .and_then(|raw| raw.split(',').next().map(str::trim)) - .filter(|value| !value.is_empty()) - .map(hash_string) - .or_else(|| header_hash(headers, "x-real-ip")) -} - -pub fn origin_matches(headers: &HeaderMap, expected_origin: &str) -> bool { - headers - .get(axum::http::header::ORIGIN) - .and_then(|value| value.to_str().ok()) - .map(|origin| origin == expected_origin) - .unwrap_or(false) -} - -fn header_hash(headers: &HeaderMap, header_name: &str) -> Option { - headers - .get(header_name) - .and_then(|v| v.to_str().ok()) - .filter(|value| !value.trim().is_empty()) - .map(hash_string) -} - -fn hash_string(value: &str) -> String { - let mut hasher = Sha256::new(); - hasher.update(value.as_bytes()); - let digest = hasher.finalize(); - let mut out = String::with_capacity(digest.len() * 2); - for byte in digest { - out.push(nibble_to_hex(byte >> 4)); - out.push(nibble_to_hex(byte & 0x0f)); - } - out -} - -fn nibble_to_hex(value: u8) -> char { - match value { - 0..=9 => (b'0' + value) as char, - 10..=15 => (b'a' + (value - 10)) as char, - _ => unreachable!(), - } -} - -fn clear_cookie(name: &str, secure: bool, same_site: &str) -> String { - format!( - "{name}=; Path=/; HttpOnly; SameSite={same_site}; Max-Age=0{secure_flag}", - secure_flag = if secure { "; Secure" } else { "" } - ) -} - -#[cfg(test)] -mod tests { - use super::{ - SESSION_COOKIE, clear_session_cookie, hash_string, make_session_cookie, origin_matches, - read_cookie_from_headers, - }; - use axum::http::{HeaderMap, header}; - - #[test] - fn hash_string_is_stable() { - assert_eq!( - hash_string("example"), - "50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c" - ); - } - - #[test] - fn reads_named_cookie_from_header() { - let mut headers = HeaderMap::new(); - headers.insert( - header::COOKIE, - "other=value; chattz_session=session-123; another=ok" - .parse() - .unwrap(), - ); - - assert_eq!( - read_cookie_from_headers(&headers, SESSION_COOKIE), - Some("session-123".to_string()) - ); - } - - #[test] - fn origin_match_requires_exact_origin() { - let mut headers = HeaderMap::new(); - headers.insert(header::ORIGIN, "http://localhost:3000".parse().unwrap()); - - assert!(origin_matches(&headers, "http://localhost:3000")); - assert!(!origin_matches(&headers, "https://localhost:3000")); - } - - #[test] - fn session_cookie_has_strict_policy_and_clear_cookie_expires() { - let session_cookie = make_session_cookie("session-123", false); - let cleared_cookie = clear_session_cookie(false); - - assert!(session_cookie.contains("HttpOnly")); - assert!(session_cookie.contains("SameSite=Strict")); - assert!(session_cookie.contains("Max-Age=")); - assert!(cleared_cookie.contains("SameSite=Strict")); - assert!(cleared_cookie.contains("Max-Age=0")); - } +fn now_ts() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_else(|_| Duration::from_secs(0)) + .as_secs() } diff --git a/src/chat.rs b/src/chat.rs index 565f08b..10beca6 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1,30 +1,15 @@ -use std::collections::HashMap; - +use crate::AppState; use axum::extract::ws::{Message, WebSocket}; use futures_util::{SinkExt, StreamExt}; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use tokio::sync::{RwLock, mpsc}; use uuid::Uuid; -use crate::{AppState, db}; - -#[derive(Clone)] -pub struct ChatClient { - tx: mpsc::UnboundedSender, - is_idle: bool, -} - -#[derive(Serialize, Clone, Debug, PartialEq, Eq)] -pub struct OnlineUser { - pub user_id: Uuid, - pub online: bool, - pub idle: bool, -} - #[derive(Default)] pub struct ChatHub { - // user_id -> connection_id -> client - clients: RwLock>>, + // user_id -> sender + clients: RwLock>>, } #[derive(Serialize, Clone)] @@ -41,120 +26,68 @@ pub enum ServerEvent { UserPresence { user_id: Uuid, online: bool, - idle: bool, }, } #[derive(Deserialize)] #[serde(tag = "type", rename_all = "snake_case")] enum ClientEvent { + // Currently no interactive client events for the general chat WS Ping, - SetIdleStatus { is_idle: bool }, } impl ChatHub { - pub async fn add_client( - &self, - user_id: Uuid, - connection_id: Uuid, - tx: mpsc::UnboundedSender, - ) -> Option { + pub async fn add_client(&self, user_id: Uuid, tx: mpsc::UnboundedSender) { let mut clients = self.clients.write().await; - let previous = aggregate_presence(clients.get(&user_id), user_id); - - clients - .entry(user_id) - .or_default() - .insert(connection_id, ChatClient { tx, is_idle: false }); - - let current = aggregate_presence(clients.get(&user_id), user_id); - presence_delta(previous, current) + clients.insert(user_id, tx); } - pub async fn remove_client(&self, user_id: Uuid, connection_id: Uuid) -> Option { + pub async fn remove_client(&self, user_id: Uuid) { let mut clients = self.clients.write().await; - let previous = aggregate_presence(clients.get(&user_id), user_id); - - if let Some(connections) = clients.get_mut(&user_id) { - connections.remove(&connection_id); - if connections.is_empty() { - clients.remove(&user_id); - } - } - - let current = aggregate_presence(clients.get(&user_id), user_id); - presence_delta(previous, current) + clients.remove(&user_id); } - pub async fn get_online_users_for(&self, visible_user_ids: &[Uuid]) -> Vec { + pub async fn get_online_users(&self) -> Vec { let clients = self.clients.read().await; - visible_user_ids - .iter() - .filter_map(|user_id| aggregate_presence(clients.get(user_id), *user_id)) - .filter(|presence| presence.online) - .collect() + clients.keys().cloned().collect() } - pub async fn broadcast_to_many(&self, user_ids: Vec, event: ServerEvent) { + pub async fn broadcast_all(&self, event: ServerEvent) { let clients = self.clients.read().await; - for user_id in user_ids { - if let Some(connections) = clients.get(&user_id) { - for client in connections.values() { - let _ = client.tx.send(event.clone()); - } - } + for tx in clients.values() { + let _ = tx.send(event.clone()); } } pub async fn broadcast_to_user(&self, user_id: Uuid, event: ServerEvent) { let clients = self.clients.read().await; - if let Some(connections) = clients.get(&user_id) { - for client in connections.values() { - let _ = client.tx.send(event.clone()); - } + if let Some(tx) = clients.get(&user_id) { + let _ = tx.send(event); } } - pub async fn set_idle_status( - &self, - user_id: Uuid, - connection_id: Uuid, - is_idle: bool, - ) -> Option { - let mut clients = self.clients.write().await; - let previous = aggregate_presence(clients.get(&user_id), user_id); - - if let Some(connections) = clients.get_mut(&user_id) - && let Some(client) = connections.get_mut(&connection_id) - { - client.is_idle = is_idle; + pub async fn broadcast_to_many(&self, user_ids: Vec, event: ServerEvent) { + let clients = self.clients.read().await; + for user_id in user_ids { + if let Some(tx) = clients.get(&user_id) { + let _ = tx.send(event.clone()); + } } - - let current = aggregate_presence(clients.get(&user_id), user_id); - presence_delta(previous, current) } } pub async fn handle_socket(state: AppState, socket: WebSocket, user_id: Uuid) { let (mut ws_sender, mut ws_receiver) = socket.split(); let (tx, mut rx) = mpsc::unbounded_channel::(); - let connection_id = Uuid::new_v4(); - if let Some(presence) = state.chat.add_client(user_id, connection_id, tx).await { - if let Ok(visible_user_ids) = db::list_visible_user_ids(&state.db, user_id).await { - state - .chat - .broadcast_to_many( - visible_user_ids, - ServerEvent::UserPresence { - user_id: presence.user_id, - online: presence.online, - idle: presence.idle, - }, - ) - .await; - } - } + state.chat.add_client(user_id, tx).await; + state + .chat + .broadcast_all(ServerEvent::UserPresence { + user_id, + online: true, + }) + .await; let send_task = tokio::spawn(async move { while let Some(event) = rx.recv().await { @@ -168,187 +101,18 @@ pub async fn handle_socket(state: AppState, socket: WebSocket, user_id: Uuid) { }); while let Some(Ok(msg)) = ws_receiver.next().await { - match msg { - Message::Close(_) => break, - Message::Text(text) => { - if let Ok(ClientEvent::SetIdleStatus { is_idle }) = - serde_json::from_str::(&text) - && let Some(presence) = state - .chat - .set_idle_status(user_id, connection_id, is_idle) - .await - && let Ok(visible_user_ids) = - db::list_visible_user_ids(&state.db, user_id).await - { - state - .chat - .broadcast_to_many( - visible_user_ids, - ServerEvent::UserPresence { - user_id: presence.user_id, - online: presence.online, - idle: presence.idle, - }, - ) - .await; - } - } - _ => {} + if let Message::Close(_) = msg { + break; } } send_task.abort(); - if let Some(presence) = state.chat.remove_client(user_id, connection_id).await - && let Ok(visible_user_ids) = db::list_visible_user_ids(&state.db, user_id).await - { - state - .chat - .broadcast_to_many( - visible_user_ids, - ServerEvent::UserPresence { - user_id: presence.user_id, - online: presence.online, - idle: presence.idle, - }, - ) - .await; - } -} - -fn aggregate_presence( - connections: Option<&HashMap>, - user_id: Uuid, -) -> Option { - let connections = connections?; - if connections.is_empty() { - return None; - } - - let idle = connections.values().all(|client| client.is_idle); - Some(OnlineUser { - user_id, - online: true, - idle, - }) -} - -fn presence_delta(previous: Option, current: Option) -> Option { - match (previous, current) { - (None, None) => None, - (Some(prev), Some(curr)) if prev == curr => None, - (Some(prev), None) => Some(OnlineUser { - user_id: prev.user_id, - online: false, - idle: false, - }), - (_, Some(curr)) => Some(curr), - } -} - -#[cfg(test)] -mod tests { - use super::{ChatHub, OnlineUser, ServerEvent}; - use serde_json::json; - use tokio::sync::mpsc; - use uuid::Uuid; - - #[tokio::test] - async fn multiple_connections_keep_user_online_until_last_disconnect() { - let hub = ChatHub::default(); - let user_id = Uuid::new_v4(); - let first_connection = Uuid::new_v4(); - let second_connection = Uuid::new_v4(); - let (tx1, _rx1) = mpsc::unbounded_channel(); - let (tx2, _rx2) = mpsc::unbounded_channel(); - - let first_presence = hub.add_client(user_id, first_connection, tx1).await; - let second_presence = hub.add_client(user_id, second_connection, tx2).await; - let after_first_disconnect = hub.remove_client(user_id, first_connection).await; - let after_last_disconnect = hub.remove_client(user_id, second_connection).await; - - assert_eq!( - first_presence, - Some(OnlineUser { - user_id, - online: true, - idle: false, - }) - ); - assert_eq!(second_presence, None); - assert_eq!(after_first_disconnect, None); - assert_eq!( - after_last_disconnect, - Some(OnlineUser { - user_id, - online: false, - idle: false, - }) - ); - } - - #[tokio::test] - async fn idle_status_only_flips_when_all_connections_are_idle() { - let hub = ChatHub::default(); - let user_id = Uuid::new_v4(); - let first_connection = Uuid::new_v4(); - let second_connection = Uuid::new_v4(); - let (tx1, _rx1) = mpsc::unbounded_channel(); - let (tx2, _rx2) = mpsc::unbounded_channel(); - - hub.add_client(user_id, first_connection, tx1).await; - hub.add_client(user_id, second_connection, tx2).await; - - let first_idle = hub.set_idle_status(user_id, first_connection, true).await; - let second_idle = hub.set_idle_status(user_id, second_connection, true).await; - let active_again = hub.set_idle_status(user_id, first_connection, false).await; - - assert_eq!(first_idle, None); - assert_eq!( - second_idle, - Some(OnlineUser { - user_id, - online: true, - idle: true, - }) - ); - assert_eq!( - active_again, - Some(OnlineUser { - user_id, - online: true, - idle: false, - }) - ); - } - - #[tokio::test] - async fn broadcast_to_user_reaches_all_active_connections() { - let hub = ChatHub::default(); - let user_id = Uuid::new_v4(); - let first_connection = Uuid::new_v4(); - let second_connection = Uuid::new_v4(); - let (tx1, mut rx1) = mpsc::unbounded_channel(); - let (tx2, mut rx2) = mpsc::unbounded_channel(); - - hub.add_client(user_id, first_connection, tx1).await; - hub.add_client(user_id, second_connection, tx2).await; - - hub.broadcast_to_user( + state.chat.remove_client(user_id).await; + state + .chat + .broadcast_all(ServerEvent::UserPresence { user_id, - ServerEvent::DmCreated { - other_user_id: Uuid::new_v4(), - message: json!({ "body": "hello" }), - }, - ) + online: false, + }) .await; - - assert!(matches!( - rx1.try_recv(), - Ok(ServerEvent::DmCreated { message, .. }) if message["body"] == "hello" - )); - assert!(matches!( - rx2.try_recv(), - Ok(ServerEvent::DmCreated { message, .. }) if message["body"] == "hello" - )); - } } diff --git a/src/config.rs b/src/config.rs index fbe7ecb..0696d55 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,11 +1,8 @@ -use anyhow::{Context, Result, anyhow}; -use reqwest::Url; +use anyhow::{Context, Result}; #[derive(Clone, Debug)] pub struct Settings { pub port: u16, - pub app_base_url: String, - pub app_origin: String, pub database_url: String, pub oidc_client_id: String, pub oidc_client_secret: String, @@ -14,36 +11,21 @@ pub struct Settings { pub oidc_userinfo_url: String, pub oidc_redirect_url: String, pub oidc_scopes: String, - pub session_cookie_secure: bool, + pub session_secret: String, + pub cookie_secure: bool, pub stun_urls: Vec, pub turn_urls: Vec, pub turn_username: Option, pub turn_password: Option, - pub media: Option, -} - -#[derive(Clone, Debug)] -pub struct MediaSettings { - pub account_id: String, - pub access_key_id: String, - pub secret_access_key: String, - pub bucket: String, - pub public_base_url: String, } impl Settings { pub fn from_env() -> Result { - let app_base_url = required("APP_BASE_URL")?; - let app_url = Url::parse(&app_base_url).context("APP_BASE_URL must be a valid URL")?; - let app_origin = origin_from_url(&app_url)?; - Ok(Self { port: std::env::var("PORT") .unwrap_or_else(|_| "3000".into()) .parse() .context("PORT must be a valid u16")?, - app_base_url: trim_trailing_slash(&app_base_url), - app_origin, database_url: required("DATABASE_URL")?, oidc_client_id: required("OIDC_CLIENT_ID")?, oidc_client_secret: required("OIDC_CLIENT_SECRET")?, @@ -51,51 +33,20 @@ impl Settings { oidc_token_url: required("OIDC_TOKEN_URL")?, oidc_userinfo_url: required("OIDC_USERINFO_URL")?, oidc_redirect_url: required("OIDC_REDIRECT_URL")?, - oidc_scopes: std::env::var("OIDC_SCOPES") - .unwrap_or_else(|_| "openid profile email".to_string()), - session_cookie_secure: requires_secure_cookie(&app_url)?, + oidc_scopes: std::env::var("OIDC_SCOPES").unwrap_or_else(|_| "openid profile email".to_string()), + session_secret: required("SESSION_SECRET")?, + cookie_secure: std::env::var("COOKIE_SECURE") + .unwrap_or_else(|_| "false".into()) + .parse() + .context("COOKIE_SECURE must be true/false")?, stun_urls: parse_csv_env("STUN_URLS", "stun:stun.l.google.com:19302"), turn_urls: parse_csv_env("TURN_URLS", ""), turn_username: optional("TURN_USERNAME"), turn_password: optional("TURN_PASSWORD"), - media: MediaSettings::from_env()?, }) } } -impl MediaSettings { - fn from_env() -> Result> { - let account_id = optional("R2_ACCOUNT_ID"); - let access_key_id = optional("R2_ACCESS_KEY_ID"); - let secret_access_key = optional("R2_SECRET_ACCESS_KEY"); - let bucket = optional("R2_BUCKET"); - let public_base_url = optional("MEDIA_BASE_URL").or_else(|| optional("R2_PUBLIC_BASE_URL")); - - if account_id.is_none() - && access_key_id.is_none() - && secret_access_key.is_none() - && bucket.is_none() - && public_base_url.is_none() - { - return Ok(None); - } - - Ok(Some(Self { - account_id: account_id.context("missing env var R2_ACCOUNT_ID")?, - access_key_id: access_key_id.context("missing env var R2_ACCESS_KEY_ID")?, - secret_access_key: secret_access_key.context("missing env var R2_SECRET_ACCESS_KEY")?, - bucket: bucket.context("missing env var R2_BUCKET")?, - public_base_url: trim_trailing_slash( - &public_base_url.context("missing env var MEDIA_BASE_URL")?, - ), - })) - } - - pub fn endpoint_url(&self) -> String { - format!("https://{}.r2.cloudflarestorage.com", self.account_id) - } -} - fn required(name: &str) -> Result { std::env::var(name).with_context(|| format!("missing env var {name}")) } @@ -115,105 +66,3 @@ fn parse_csv_env(name: &str, default_value: &str) -> Vec { .map(ToString::to_string) .collect() } - -fn origin_from_url(url: &Url) -> Result { - let host = url - .host_str() - .ok_or_else(|| anyhow!("APP_BASE_URL must include a host"))?; - let mut origin = format!("{}://{}", url.scheme(), host); - if let Some(port) = url.port() { - origin.push(':'); - origin.push_str(&port.to_string()); - } - Ok(origin) -} - -fn requires_secure_cookie(url: &Url) -> Result { - match url.scheme() { - "https" => Ok(true), - "http" => { - let host = url - .host_str() - .ok_or_else(|| anyhow!("APP_BASE_URL must include a host"))?; - if matches!(host, "localhost" | "127.0.0.1" | "::1") { - Ok(false) - } else { - Err(anyhow!( - "APP_BASE_URL must use https outside localhost when session cookies are enabled" - )) - } - } - other => Err(anyhow!("APP_BASE_URL scheme {other} is not supported")), - } -} - -fn trim_trailing_slash(value: &str) -> String { - value.trim_end_matches('/').to_string() -} - -#[cfg(test)] -mod tests { - use super::{MediaSettings, origin_from_url, requires_secure_cookie, trim_trailing_slash}; - use reqwest::Url; - - #[test] - fn origin_from_url_preserves_explicit_port() { - let url = Url::parse("https://chat.example.com:8443/app").unwrap(); - let origin = origin_from_url(&url).unwrap(); - - assert_eq!(origin, "https://chat.example.com:8443"); - } - - #[test] - fn secure_cookie_is_required_for_https_origins() { - let url = Url::parse("https://chat.example.com").unwrap(); - - assert_eq!(requires_secure_cookie(&url).unwrap(), true); - } - - #[test] - fn localhost_http_is_allowed_without_secure_cookie() { - let url = Url::parse("http://localhost:3000").unwrap(); - - assert_eq!(requires_secure_cookie(&url).unwrap(), false); - } - - #[test] - fn non_localhost_http_is_rejected() { - let url = Url::parse("http://chat.example.com").unwrap(); - let err = requires_secure_cookie(&url).unwrap_err(); - - assert!( - err.to_string() - .contains("APP_BASE_URL must use https outside localhost") - ); - } - - #[test] - fn trim_trailing_slash_removes_only_suffix_slashes() { - assert_eq!( - trim_trailing_slash("https://chat.example.com///"), - "https://chat.example.com" - ); - assert_eq!( - trim_trailing_slash("https://chat.example.com/app"), - "https://chat.example.com/app" - ); - } - - #[test] - fn media_endpoint_url_uses_account_id() { - let media = MediaSettings { - account_id: "acct123".to_string(), - access_key_id: "key".to_string(), - secret_access_key: "secret".to_string(), - bucket: "bucket".to_string(), - public_base_url: "https://media.example.com".to_string(), - }; - - assert_eq!( - media.endpoint_url(), - "https://acct123.r2.cloudflarestorage.com" - ); - } -} diff --git a/src/db.rs b/src/db.rs index c86dd8c..cd6a234 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,22 +1,17 @@ -use std::collections::HashSet; - use anyhow::{Result, anyhow}; use chrono::{Duration, Utc}; use sea_orm::{ ActiveModelTrait, ActiveValue::Set, ColumnTrait, Condition, DatabaseConnection, DatabaseTransaction, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect, - Statement, TransactionTrait, sea_query::OnConflict, + TransactionTrait, sea_query::OnConflict, }; use uuid::Uuid; use crate::{ - entity::{ - attachments, channels, direct_messages, guild_members, guilds, invites, messages, sessions, - soundboard_sounds, users, - }, + entity::{channels, direct_messages, guild_members, guilds, invites, messages, users}, models::{ - Attachment, BasicUser, Channel, DmConversation, DmMessageWithAuthor, Guild, Invite, - MessageWithAuthor, SoundboardSound, User, + BasicUser, Channel, DmConversation, DmMessageWithAuthor, Guild, Invite, MessageWithAuthor, + User, }, }; @@ -28,88 +23,6 @@ pub async fn user_exists(db: &DatabaseConnection, user_id: Uuid) -> Result Ok(count > 0) } -pub async fn create_session( - db: &DatabaseConnection, - session_id: &str, - user_id: Uuid, - expires_at: chrono::DateTime, - user_agent_hash: Option, - ip_hash: Option, -) -> Result<()> { - sessions::Entity::insert(sessions::ActiveModel { - id: Set(session_id.to_string()), - user_id: Set(user_id), - expires_at: Set(expires_at), - created_at: Set(Utc::now().fixed_offset()), - last_seen_at: Set(Utc::now().fixed_offset()), - revoked_at: Set(None), - user_agent_hash: Set(user_agent_hash), - ip_hash: Set(ip_hash), - }) - .exec(db) - .await?; - - Ok(()) -} - -pub async fn touch_active_session( - db: &DatabaseConnection, - session_id: &str, -) -> Result> { - let session = sessions::Entity::find_by_id(session_id.to_string()) - .one(db) - .await?; - - let Some(session) = session else { - return Ok(None); - }; - - if session.revoked_at.is_some() || session.expires_at <= Utc::now().fixed_offset() { - return Ok(None); - } - - let user_id = session.user_id; - sessions::Entity::update_many() - .col_expr( - sessions::Column::LastSeenAt, - sea_orm::sea_query::Expr::value(Utc::now().fixed_offset()), - ) - .filter(sessions::Column::Id.eq(session_id.to_string())) - .exec(db) - .await?; - Ok(Some(user_id)) -} - -pub async fn revoke_session(db: &DatabaseConnection, session_id: &str) -> Result<()> { - if let Some(session) = sessions::Entity::find_by_id(session_id.to_string()) - .one(db) - .await? - { - sessions::Entity::update_many() - .col_expr( - sessions::Column::RevokedAt, - sea_orm::sea_query::Expr::value(Some(Utc::now().fixed_offset())), - ) - .filter(sessions::Column::Id.eq(session.id)) - .exec(db) - .await?; - } - - Ok(()) -} - -pub async fn cleanup_sessions(db: &DatabaseConnection) -> Result<()> { - sessions::Entity::delete_many() - .filter( - Condition::any() - .add(sessions::Column::ExpiresAt.lte(Utc::now().fixed_offset())) - .add(sessions::Column::RevokedAt.is_not_null()), - ) - .exec(db) - .await?; - Ok(()) -} - pub async fn upsert_user_from_oidc( db: &DatabaseConnection, oidc_sub: &str, @@ -190,58 +103,18 @@ pub async fn list_guilds_for_user(db: &DatabaseConnection, user_id: Uuid) -> Res .collect()) } -pub async fn list_visible_user_ids(db: &DatabaseConnection, user_id: Uuid) -> Result> { - let guild_ids: Vec = guild_members::Entity::find() - .filter(guild_members::Column::UserId.eq(user_id)) - .select_only() - .column(guild_members::Column::GuildId) - .into_tuple() - .all(db) - .await?; - - let mut visible = HashSet::from([user_id]); - - if !guild_ids.is_empty() { - let guild_users = guild_members::Entity::find() - .filter(guild_members::Column::GuildId.is_in(guild_ids)) - .all(db) - .await?; - visible.extend(guild_users.into_iter().map(|membership| membership.user_id)); - } - - let dm_rows = direct_messages::Entity::find() - .filter( - Condition::any() - .add(direct_messages::Column::SenderUserId.eq(user_id)) - .add(direct_messages::Column::RecipientUserId.eq(user_id)), - ) - .all(db) - .await?; - - for row in dm_rows { - if row.sender_user_id == user_id { - visible.insert(row.recipient_user_id); - } else { - visible.insert(row.sender_user_id); - } - } - - Ok(visible.into_iter().collect()) -} - pub async fn create_guild( db: &DatabaseConnection, owner_user_id: Uuid, name: &str, ) -> Result { - let txn = db.begin().await?; let guild = guilds::Entity::insert(guilds::ActiveModel { id: Set(Uuid::new_v4()), name: Set(name.to_string()), owner_user_id: Set(owner_user_id), ..Default::default() }) - .exec_with_returning(&txn) + .exec_with_returning(db) .await?; guild_members::Entity::insert(guild_members::ActiveModel { @@ -257,25 +130,12 @@ pub async fn create_guild( .do_nothing() .to_owned(), ) - .exec(&txn) + .exec(db) .await?; - txn.commit().await?; Ok(map_guild(guild)) } -pub async fn is_guild_owner( - db: &DatabaseConnection, - guild_id: Uuid, - user_id: Uuid, -) -> Result { - let guild = guilds::Entity::find_by_id(guild_id).one(db).await?; - match guild { - Some(g) => Ok(g.owner_user_id == user_id), - None => Ok(false), - } -} - pub async fn create_invite( db: &DatabaseConnection, guild_id: Uuid, @@ -317,12 +177,7 @@ pub async fn create_invite( pub async fn join_invite(db: &DatabaseConnection, code: &str, user_id: Uuid) -> Result { let txn = db.begin().await?; - let invite = invites::Entity::find() - .from_raw_sql(Statement::from_sql_and_values( - sea_orm::DatabaseBackend::Postgres, - r#"SELECT * FROM invites WHERE code = $1 FOR UPDATE"#, - [code.into()], - )) + let invite = invites::Entity::find_by_id(code.to_string()) .one(&txn) .await? .ok_or_else(|| anyhow!("invite not found"))?; @@ -475,63 +330,6 @@ pub async fn create_message( author_user_id: model.author_user_id, author_display_name: user.display_name, body: model.body, - attachments: Vec::new(), - created_at: model.created_at, - }) -} - -pub async fn create_message_with_attachment( - db: &DatabaseConnection, - channel_id: Uuid, - author_user_id: Uuid, - body: &str, - object_key: &str, - media_url: &str, - mime_type: &str, - size_bytes: i64, - original_filename: &str, -) -> Result { - let txn = db.begin().await?; - - let model = messages::Entity::insert(messages::ActiveModel { - id: Set(Uuid::new_v4()), - channel_id: Set(channel_id), - author_user_id: Set(author_user_id), - body: Set(body.to_string()), - ..Default::default() - }) - .exec_with_returning(&txn) - .await?; - - let attachment = attachments::Entity::insert(attachments::ActiveModel { - id: Set(Uuid::new_v4()), - channel_message_id: Set(Some(model.id)), - direct_message_id: Set(None), - uploader_user_id: Set(author_user_id), - object_key: Set(object_key.to_string()), - media_url: Set(media_url.to_string()), - mime_type: Set(mime_type.to_string()), - size_bytes: Set(size_bytes), - original_filename: Set(original_filename.to_string()), - ..Default::default() - }) - .exec_with_returning(&txn) - .await?; - - let user = users::Entity::find_by_id(author_user_id) - .one(&txn) - .await? - .ok_or_else(|| anyhow!("author not found"))?; - - txn.commit().await?; - - Ok(MessageWithAuthor { - id: model.id, - channel_id: model.channel_id, - author_user_id: model.author_user_id, - author_display_name: user.display_name, - body: model.body, - attachments: vec![map_attachment(attachment)], created_at: model.created_at, }) } @@ -549,10 +347,6 @@ pub async fn list_messages( .all(db) .await?; - let attachment_map = - list_attachments_for_channel_messages(db, rows.iter().map(|(msg, _)| msg.id).collect()) - .await?; - Ok(rows .into_iter() .map(|(msg, user)| { @@ -565,7 +359,6 @@ pub async fn list_messages( author_user_id: msg.author_user_id, author_display_name, body: msg.body, - attachments: attachment_map.get(&msg.id).cloned().unwrap_or_default(), created_at: msg.created_at, } }) @@ -599,63 +392,6 @@ pub async fn create_direct_message( recipient_user_id: model.recipient_user_id, author_display_name: user.display_name, body: model.body, - attachments: Vec::new(), - created_at: model.created_at, - }) -} - -pub async fn create_direct_message_with_attachment( - db: &DatabaseConnection, - sender_user_id: Uuid, - recipient_user_id: Uuid, - body: &str, - object_key: &str, - media_url: &str, - mime_type: &str, - size_bytes: i64, - original_filename: &str, -) -> Result { - let txn = db.begin().await?; - - let model = direct_messages::Entity::insert(direct_messages::ActiveModel { - id: Set(Uuid::new_v4()), - sender_user_id: Set(sender_user_id), - recipient_user_id: Set(recipient_user_id), - body: Set(body.to_string()), - ..Default::default() - }) - .exec_with_returning(&txn) - .await?; - - let attachment = attachments::Entity::insert(attachments::ActiveModel { - id: Set(Uuid::new_v4()), - channel_message_id: Set(None), - direct_message_id: Set(Some(model.id)), - uploader_user_id: Set(sender_user_id), - object_key: Set(object_key.to_string()), - media_url: Set(media_url.to_string()), - mime_type: Set(mime_type.to_string()), - size_bytes: Set(size_bytes), - original_filename: Set(original_filename.to_string()), - ..Default::default() - }) - .exec_with_returning(&txn) - .await?; - - let user = users::Entity::find_by_id(sender_user_id) - .one(&txn) - .await? - .ok_or_else(|| anyhow!("sender not found"))?; - - txn.commit().await?; - - Ok(DmMessageWithAuthor { - id: model.id, - author_user_id: model.sender_user_id, - recipient_user_id: model.recipient_user_id, - author_display_name: user.display_name, - body: model.body, - attachments: vec![map_attachment(attachment)], created_at: model.created_at, }) } @@ -698,9 +434,6 @@ pub async fn list_direct_messages( .map(|u| (u.id, u.display_name)) .collect(); - let attachment_map = - list_attachments_for_direct_messages(db, rows.iter().map(|msg| msg.id).collect()).await?; - Ok(rows .into_iter() .map(|msg| DmMessageWithAuthor { @@ -712,64 +445,11 @@ pub async fn list_direct_messages( .cloned() .unwrap_or_else(|| "Unknown User".to_string()), body: msg.body, - attachments: attachment_map.get(&msg.id).cloned().unwrap_or_default(), created_at: msg.created_at, }) .collect()) } -async fn list_attachments_for_channel_messages( - db: &DatabaseConnection, - message_ids: Vec, -) -> Result>> { - if message_ids.is_empty() { - return Ok(std::collections::HashMap::new()); - } - - let rows = attachments::Entity::find() - .filter(attachments::Column::ChannelMessageId.is_in(message_ids)) - .order_by_asc(attachments::Column::CreatedAt) - .all(db) - .await?; - - let mut grouped = std::collections::HashMap::>::new(); - for row in rows { - if let Some(message_id) = row.channel_message_id { - grouped - .entry(message_id) - .or_default() - .push(map_attachment(row)); - } - } - Ok(grouped) -} - -async fn list_attachments_for_direct_messages( - db: &DatabaseConnection, - message_ids: Vec, -) -> Result>> { - if message_ids.is_empty() { - return Ok(std::collections::HashMap::new()); - } - - let rows = attachments::Entity::find() - .filter(attachments::Column::DirectMessageId.is_in(message_ids)) - .order_by_asc(attachments::Column::CreatedAt) - .all(db) - .await?; - - let mut grouped = std::collections::HashMap::>::new(); - for row in rows { - if let Some(message_id) = row.direct_message_id { - grouped - .entry(message_id) - .or_default() - .push(map_attachment(row)); - } - } - Ok(grouped) -} - pub async fn list_dm_conversations( db: &DatabaseConnection, current_user_id: Uuid, @@ -843,16 +523,6 @@ fn map_guild(model: guilds::Model) -> Guild { } } -fn map_attachment(model: attachments::Model) -> Attachment { - Attachment { - id: model.id, - media_url: model.media_url, - mime_type: model.mime_type, - size_bytes: model.size_bytes, - original_filename: model.original_filename, - } -} - fn map_channel(model: channels::Model) -> Channel { Channel { id: model.id, @@ -905,385 +575,3 @@ async fn increment_invite_use_count( active.update(txn).await?; Ok(()) } - -pub async fn list_sounds(db: &DatabaseConnection, guild_id: Uuid) -> Result> { - let rows = soundboard_sounds::Entity::find() - .filter(soundboard_sounds::Column::GuildId.eq(guild_id)) - .order_by_asc(soundboard_sounds::Column::CreatedAt) - .all(db) - .await?; - - Ok(rows.into_iter().map(map_sound).collect()) -} - -pub async fn create_sound( - db: &DatabaseConnection, - guild_id: Uuid, - created_by_user_id: Uuid, - name: &str, - icon: &str, - object_key: &str, - media_url: &str, - mime_type: &str, - size_bytes: i64, -) -> Result { - let model = soundboard_sounds::Entity::insert(soundboard_sounds::ActiveModel { - id: Set(Uuid::new_v4()), - guild_id: Set(guild_id), - created_by_user_id: Set(created_by_user_id), - name: Set(name.to_string()), - icon: Set(icon.to_string()), - object_key: Set(Some(object_key.to_string())), - media_url: Set(media_url.to_string()), - mime_type: Set(Some(mime_type.to_string())), - size_bytes: Set(Some(size_bytes)), - // Keep the legacy column populated until every deployment has applied - // the nullable migration and old fallback paths are fully removed. - file_path: Set(Some(media_url.to_string())), - ..Default::default() - }) - .exec_with_returning(db) - .await?; - - Ok(map_sound(model)) -} - -pub async fn get_sound_by_id(db: &DatabaseConnection, id: Uuid) -> Result> { - let row = soundboard_sounds::Entity::find_by_id(id).one(db).await?; - Ok(row.map(map_sound)) -} - -pub async fn get_sound_object_key(db: &DatabaseConnection, id: Uuid) -> Result> { - let row = soundboard_sounds::Entity::find_by_id(id).one(db).await?; - Ok(row.and_then(|sound| sound.object_key)) -} - -pub async fn delete_sound(db: &DatabaseConnection, id: Uuid) -> Result<()> { - soundboard_sounds::Entity::delete_by_id(id).exec(db).await?; - Ok(()) -} - -fn map_sound(model: soundboard_sounds::Model) -> SoundboardSound { - SoundboardSound { - id: model.id, - guild_id: model.guild_id, - name: model.name, - icon: model.icon, - media_url: model.media_url, - mime_type: model.mime_type, - size_bytes: model.size_bytes, - created_by_user_id: model.created_by_user_id, - created_at: model.created_at, - } -} - -#[cfg(test)] -mod tests { - use super::{create_guild, create_sound, join_invite, list_visible_user_ids, validate_invite}; - use crate::entity::{direct_messages, guild_members, guilds, invites, soundboard_sounds}; - use chrono::{Duration, Utc}; - use sea_orm::{DatabaseBackend, MockDatabase, MockExecResult, Value}; - use std::collections::{BTreeMap, BTreeSet}; - use uuid::Uuid; - - #[tokio::test] - async fn visible_users_include_self_shared_guilds_and_dm_partners() { - let current_user_id = Uuid::new_v4(); - let guild_a = Uuid::new_v4(); - let guild_b = Uuid::new_v4(); - let guild_peer = Uuid::new_v4(); - let shared_dm_peer = Uuid::new_v4(); - - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![ - BTreeMap::from([("guild_id".to_string(), Value::from(guild_a))]), - BTreeMap::from([("guild_id".to_string(), Value::from(guild_b))]), - ]]) - .append_query_results([vec![ - guild_members::Model { - guild_id: guild_a, - user_id: current_user_id, - created_at: Utc::now().fixed_offset(), - }, - guild_members::Model { - guild_id: guild_b, - user_id: current_user_id, - created_at: Utc::now().fixed_offset(), - }, - guild_members::Model { - guild_id: guild_a, - user_id: guild_peer, - created_at: Utc::now().fixed_offset(), - }, - ]]) - .append_query_results([vec![ - direct_messages::Model { - id: Uuid::new_v4(), - sender_user_id: current_user_id, - recipient_user_id: shared_dm_peer, - body: "hello".to_string(), - created_at: Utc::now().fixed_offset(), - }, - direct_messages::Model { - id: Uuid::new_v4(), - sender_user_id: shared_dm_peer, - recipient_user_id: current_user_id, - body: "hi".to_string(), - created_at: Utc::now().fixed_offset(), - }, - ]]) - .into_connection(); - - let visible = list_visible_user_ids(&db, current_user_id).await.unwrap(); - let visible: BTreeSet<_> = visible.into_iter().collect(); - - assert_eq!( - visible, - BTreeSet::from([current_user_id, guild_peer, shared_dm_peer]) - ); - } - - #[tokio::test] - async fn visible_users_returns_self_when_no_relationships_exist() { - let current_user_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([Vec::>::new()]) - .append_query_results([Vec::::new()]) - .into_connection(); - - let visible = list_visible_user_ids(&db, current_user_id).await.unwrap(); - - assert_eq!(visible, vec![current_user_id]); - } - - #[test] - fn validate_invite_rejects_expired_invites() { - let invite = invites::Model { - code: "expired".to_string(), - guild_id: Uuid::new_v4(), - created_by_user_id: Uuid::new_v4(), - created_at: Utc::now().fixed_offset(), - expires_at: Some((Utc::now() - Duration::minutes(1)).fixed_offset()), - max_uses: Some(5), - use_count: 0, - }; - - let err = validate_invite(&invite).unwrap_err(); - assert!(err.to_string().contains("invite expired")); - } - - #[test] - fn validate_invite_rejects_exhausted_invites() { - let invite = invites::Model { - code: "used".to_string(), - guild_id: Uuid::new_v4(), - created_by_user_id: Uuid::new_v4(), - created_at: Utc::now().fixed_offset(), - expires_at: Some((Utc::now() + Duration::minutes(5)).fixed_offset()), - max_uses: Some(1), - use_count: 1, - }; - - let err = validate_invite(&invite).unwrap_err(); - assert!(err.to_string().contains("invite exhausted")); - } - - #[test] - fn validate_invite_accepts_active_invites() { - let invite = invites::Model { - code: "active".to_string(), - guild_id: Uuid::new_v4(), - created_by_user_id: Uuid::new_v4(), - created_at: Utc::now().fixed_offset(), - expires_at: Some((Utc::now() + Duration::minutes(5)).fixed_offset()), - max_uses: Some(3), - use_count: 1, - }; - - validate_invite(&invite).unwrap(); - } - - #[tokio::test] - async fn create_guild_runs_guild_and_membership_in_one_transaction() { - let owner_user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let created_at = Utc::now().fixed_offset(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![guilds::Model { - id: guild_id, - name: "Guild".to_string(), - owner_user_id, - created_at, - }]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .into_connection(); - - let guild = create_guild(&db, owner_user_id, "Guild").await.unwrap(); - let transaction_log = format!("{:?}", db.into_transaction_log()); - - assert_eq!(guild.id, guild_id); - assert!(transaction_log.contains("BEGIN"), "{transaction_log}"); - assert!(transaction_log.contains("guilds"), "{transaction_log}"); - assert!( - transaction_log.contains("guild_members"), - "{transaction_log}" - ); - assert!(transaction_log.contains("COMMIT"), "{transaction_log}"); - - let guild_insert = transaction_log.find("guilds"); - let membership_insert = transaction_log.find("guild_members"); - assert!(guild_insert.is_some() && membership_insert.is_some()); - assert!(guild_insert.unwrap() < membership_insert.unwrap()); - } - - #[tokio::test] - async fn join_invite_locks_invite_and_updates_use_count_in_one_transaction() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let created_by_user_id = Uuid::new_v4(); - let created_at = Utc::now().fixed_offset(); - let invite = invites::Model { - code: "invite123".to_string(), - guild_id, - created_by_user_id, - created_at, - expires_at: Some((Utc::now() + Duration::minutes(5)).fixed_offset()), - max_uses: Some(5), - use_count: 0, - }; - let updated_invite = invites::Model { - use_count: 1, - ..invite.clone() - }; - let guild = guilds::Model { - id: guild_id, - name: "Guild".to_string(), - owner_user_id: created_by_user_id, - created_at, - }; - - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![invite]]) - .append_query_results([Vec::::new()]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![updated_invite]]) - .append_query_results([vec![guild]]) - .into_connection(); - - let joined_guild = join_invite(&db, "invite123", user_id).await.unwrap(); - let transaction_log = format!("{:?}", db.into_transaction_log()); - - assert_eq!(joined_guild.id, guild_id); - assert!(transaction_log.contains("BEGIN"), "{transaction_log}"); - assert!(transaction_log.contains("FOR UPDATE"), "{transaction_log}"); - assert!( - transaction_log.contains("guild_members"), - "{transaction_log}" - ); - assert!(transaction_log.contains("UPDATE"), "{transaction_log}"); - assert!(transaction_log.contains("invites"), "{transaction_log}"); - assert!(transaction_log.contains("COMMIT"), "{transaction_log}"); - } - - #[tokio::test] - async fn join_invite_does_not_increment_use_count_for_existing_member() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let created_by_user_id = Uuid::new_v4(); - let created_at = Utc::now().fixed_offset(); - let invite = invites::Model { - code: "invite123".to_string(), - guild_id, - created_by_user_id, - created_at, - expires_at: Some((Utc::now() + Duration::minutes(5)).fixed_offset()), - max_uses: Some(5), - use_count: 3, - }; - let existing_member = guild_members::Model { - guild_id, - user_id, - created_at, - }; - let guild = guilds::Model { - id: guild_id, - name: "Guild".to_string(), - owner_user_id: created_by_user_id, - created_at, - }; - - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![invite]]) - .append_query_results([vec![existing_member]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![guild]]) - .into_connection(); - - let joined_guild = join_invite(&db, "invite123", user_id).await.unwrap(); - let transaction_log = format!("{:?}", db.into_transaction_log()); - - assert_eq!(joined_guild.id, guild_id); - assert!(transaction_log.contains("FOR UPDATE"), "{transaction_log}"); - assert!( - transaction_log.contains("guild_members"), - "{transaction_log}" - ); - assert!(transaction_log.contains("COMMIT"), "{transaction_log}"); - assert!( - !transaction_log.contains("UPDATE \"invites\""), - "{transaction_log}" - ); - } - - #[tokio::test] - async fn create_sound_keeps_legacy_file_path_populated() { - let guild_id = Uuid::new_v4(); - let sound_id = Uuid::new_v4(); - let created_by_user_id = Uuid::new_v4(); - let created_at = Utc::now().fixed_offset(); - let media_url = "https://media.example.com/soundboard/test.mp3"; - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![soundboard_sounds::Model { - id: sound_id, - guild_id, - name: "Airhorn".to_string(), - icon: "AH".to_string(), - object_key: Some("soundboard/test.mp3".to_string()), - media_url: media_url.to_string(), - mime_type: Some("audio/mpeg".to_string()), - size_bytes: Some(1234), - file_path: Some(media_url.to_string()), - created_by_user_id, - created_at, - }]]) - .into_connection(); - - let sound = create_sound( - &db, - guild_id, - created_by_user_id, - "Airhorn", - "AH", - "soundboard/test.mp3", - media_url, - "audio/mpeg", - 1234, - ) - .await - .unwrap(); - let transaction_log = format!("{:?}", db.into_transaction_log()); - - assert_eq!(sound.id, sound_id); - assert!(transaction_log.contains("file_path"), "{transaction_log}"); - assert!(transaction_log.contains(media_url), "{transaction_log}"); - } -} diff --git a/src/entity/attachments.rs b/src/entity/attachments.rs deleted file mode 100644 index f5581d1..0000000 --- a/src/entity/attachments.rs +++ /dev/null @@ -1,66 +0,0 @@ -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] -#[sea_orm(table_name = "attachments")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub id: Uuid, - pub channel_message_id: Option, - pub direct_message_id: Option, - pub uploader_user_id: Uuid, - pub object_key: String, - pub media_url: String, - pub mime_type: String, - pub size_bytes: i64, - pub original_filename: String, - pub created_at: DateTimeWithTimeZone, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::messages::Entity", - from = "Column::ChannelMessageId", - to = "super::messages::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - Messages, - #[sea_orm( - belongs_to = "super::direct_messages::Entity", - from = "Column::DirectMessageId", - to = "super::direct_messages::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - DirectMessages, - #[sea_orm( - belongs_to = "super::users::Entity", - from = "Column::UploaderUserId", - to = "super::users::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - Users, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Messages.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::DirectMessages.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Users.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entity/mod.rs b/src/entity/mod.rs index 0dcd3c5..4c990ec 100644 --- a/src/entity/mod.rs +++ b/src/entity/mod.rs @@ -1,10 +1,7 @@ -pub mod attachments; pub mod channels; pub mod direct_messages; pub mod guild_members; pub mod guilds; pub mod invites; pub mod messages; -pub mod sessions; -pub mod soundboard_sounds; pub mod users; diff --git a/src/entity/sessions.rs b/src/entity/sessions.rs deleted file mode 100644 index 7d66a24..0000000 --- a/src/entity/sessions.rs +++ /dev/null @@ -1,35 +0,0 @@ -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] -#[sea_orm(table_name = "sessions")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub id: String, - pub user_id: Uuid, - pub expires_at: DateTimeWithTimeZone, - pub created_at: DateTimeWithTimeZone, - pub last_seen_at: DateTimeWithTimeZone, - pub revoked_at: Option, - pub user_agent_hash: Option, - pub ip_hash: Option, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::users::Entity", - from = "Column::UserId", - to = "super::users::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - Users, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Users.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/src/entity/soundboard_sounds.rs b/src/entity/soundboard_sounds.rs deleted file mode 100644 index bd96feb..0000000 --- a/src/entity/soundboard_sounds.rs +++ /dev/null @@ -1,53 +0,0 @@ -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] -#[sea_orm(table_name = "soundboard_sounds")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub id: Uuid, - pub guild_id: Uuid, - pub name: String, - pub icon: String, - pub object_key: Option, - pub media_url: String, - pub mime_type: Option, - pub size_bytes: Option, - pub file_path: Option, - pub created_by_user_id: Uuid, - pub created_at: DateTimeWithTimeZone, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::guilds::Entity", - from = "Column::GuildId", - to = "super::guilds::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - Guilds, - #[sea_orm( - belongs_to = "super::users::Entity", - from = "Column::CreatedByUserId", - to = "super::users::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - Users, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Guilds.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Users.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/src/handlers.rs b/src/handlers.rs index f9675d9..ffa363b 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -1,21 +1,17 @@ use axum::{ Json, Router, - body::Bytes, - extract::{DefaultBodyLimit, Path, Query, State, WebSocketUpgrade}, + extract::{Path, Query, State, WebSocketUpgrade}, http::{HeaderMap, StatusCode, header}, response::{Html, IntoResponse, Redirect}, routing::{get, post}, }; -use chrono::Datelike; use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ AppState, auth::{self, ApiError, AuthUser}, - chat, db, - models::{DmMessageWithAuthor, Guild, MessageWithAuthor, SoundboardSound}, - voice, + chat, db, voice, }; pub fn routes() -> Router { @@ -30,11 +26,6 @@ pub fn routes() -> Router { "/dms/{other_user_id}/messages", get(list_dm_messages).post(send_dm_message), ) - .route( - "/dms/{other_user_id}/attachments", - post(upload_dm_attachment), - ) - .layer(DefaultBodyLimit::max(MAX_MEDIA_UPLOAD_BYTES)) .route("/presence", get(presence_list)) .route("/rtc-config", get(rtc_config)) .route("/guilds", get(list_guilds).post(create_guild)) @@ -46,25 +37,11 @@ pub fn routes() -> Router { ) .route("/guilds/{guild_id}/invites", post(create_invite)) .route("/invites/{code}/join", post(join_invite)) - .route( - "/guilds/{guild_id}/sounds", - get(list_sounds).post(upload_sound), - ) - .layer(DefaultBodyLimit::max(MAX_MEDIA_UPLOAD_BYTES)) - .route( - "/guilds/{guild_id}/sounds/{sound_id}", - post(delete_sound_post).delete(delete_sound), - ) .route("/channels", post(create_channel)) .route( "/channels/{channel_id}/messages", get(list_messages).post(send_message), ) - .route( - "/channels/{channel_id}/attachments", - post(upload_channel_attachment), - ) - .layer(DefaultBodyLimit::max(MAX_MEDIA_UPLOAD_BYTES)) .route("/channels/{channel_id}/voice/ws", get(voice_ws)) .route("/ws", get(chat_ws)) } @@ -92,7 +69,7 @@ async fn auth_login(State(state): State) -> Result, headers: HeaderMap, ) -> Result { - auth::validate_oauth_state( - auth::read_cookie_from_headers(&headers, auth::OAUTH_STATE_COOKIE), - &query.state, - ) - .map_err(|e| ApiError::bad_request(&e.to_string()))?; + auth::validate_oauth_state(auth::read_oauth_state_from_headers(&headers), &query.state) + .map_err(|e| ApiError::bad_request(&e.to_string()))?; let token_res = state .http @@ -228,51 +202,40 @@ async fn auth_callback( .await .map_err(|e| ApiError::internal(&format!("failed to persist user: {e}")))?; - let session_id = auth::new_session_id(); - db::create_session( - &state.db, - &session_id, + let session_cookie = auth::new_session_cookie( user.id, - auth::session_expiry(), - auth::user_agent_hash(&headers), - auth::ip_hash(&headers), + &state.settings.session_secret, + state.settings.cookie_secure, ) - .await - .map_err(|e| ApiError::internal(&format!("failed to create session: {e}")))?; + .map_err(|e| ApiError::internal(&e.to_string()))?; let mut headers = HeaderMap::new(); headers.append( header::SET_COOKIE, - auth::clear_oauth_state_cookie(state.settings.session_cookie_secure) + session_cookie .parse() - .map_err(|_| ApiError::internal("failed to clear oauth state cookie"))?, + .map_err(|_| ApiError::internal("failed to set session cookie"))?, ); headers.append( header::SET_COOKIE, - auth::make_session_cookie(&session_id, state.settings.session_cookie_secure) + auth::clear_oauth_state_cookie(state.settings.cookie_secure) .parse() - .map_err(|_| ApiError::internal("failed to set session cookie"))?, + .map_err(|_| ApiError::internal("failed to clear oauth state cookie"))?, ); Ok((headers, Redirect::to("/"))) } -async fn auth_logout( - State(state): State, - user: AuthUser, -) -> Result { - db::revoke_session(&state.db, &user.session_id) - .await - .map_err(|e| ApiError::internal(&format!("failed to revoke session: {e}")))?; - +async fn auth_logout(State(state): State) -> Result { let mut headers = HeaderMap::new(); - headers.insert( + headers.append( header::SET_COOKIE, - auth::clear_session_cookie(state.settings.session_cookie_secure) + auth::clear_session_cookie(state.settings.cookie_secure) .parse() .map_err(|_| ApiError::internal("failed to clear session cookie"))?, ); - Ok((headers, StatusCode::NO_CONTENT)) + + Ok((StatusCode::NO_CONTENT, headers)) } #[derive(Serialize)] @@ -333,12 +296,9 @@ async fn me(State(state): State, user: AuthUser) -> Result, - user: AuthUser, + _user: AuthUser, ) -> Result { - let visible_user_ids = db::list_visible_user_ids(&state.db, user.id) - .await - .map_err(|e| ApiError::internal(&format!("failed to load visible users: {e}")))?; - let users = state.chat.get_online_users_for(&visible_user_ids).await; + let users = state.chat.get_online_users().await; Ok(Json(users)) } @@ -439,8 +399,11 @@ async fn join_invite( State(state): State, user: AuthUser, Path(code): Path, -) -> Result, ApiError> { - let guild = db::join_invite(&state.db, &code, user.id).await?; +) -> Result { + let guild = db::join_invite(&state.db, &code.to_uppercase(), user.id) + .await + .map_err(|e| ApiError::bad_request(&format!("failed to join invite: {e}")))?; + Ok(Json(guild)) } @@ -679,101 +642,11 @@ async fn send_dm_message( Ok((StatusCode::CREATED, Json(SendMessageResponse { ok: true }))) } -async fn upload_channel_attachment( - State(state): State, - user: AuthUser, - Path(channel_id): Path, - headers: HeaderMap, - body: Bytes, -) -> Result { - ensure_channel_member(&state, channel_id, user.id).await?; - let uploaded = upload_media_from_request( - &state, - &headers, - body, - channel_object_key_prefix(channel_id), - ) - .await?; - - let message = db::create_message_with_attachment( - &state.db, - channel_id, - user.id, - "", - &uploaded.object_key, - &uploaded.media_url, - &uploaded.mime_type, - uploaded.size_bytes, - &uploaded.original_filename, - ) - .await - .map_err(|e| ApiError::internal(&format!("failed to create message attachment: {e}")))?; - - let guild_id = db::guild_id_for_channel(&state.db, channel_id) - .await - .map_err(|e| ApiError::internal(&format!("channel lookup failed: {e}")))? - .ok_or_else(|| ApiError::internal("channel not found after attachment upload"))?; - - let members = db::list_guild_member_ids(&state.db, guild_id) - .await - .map_err(|e| ApiError::internal(&format!("failed to list guild members: {e}")))?; - - broadcast_channel_message(&state, members, channel_id, &message).await; - Ok((StatusCode::CREATED, Json(message))) -} - -async fn upload_dm_attachment( - State(state): State, - user: AuthUser, - Path(other_user_id): Path, - headers: HeaderMap, - body: Bytes, -) -> Result { - if other_user_id == user.id { - return Err(ApiError::bad_request("cannot send dm to yourself")); - } - - let other_user_exists = db::user_exists(&state.db, other_user_id) - .await - .map_err(|e| ApiError::internal(&format!("user check failed: {e}")))?; - if !other_user_exists { - return Err(ApiError { - status: StatusCode::NOT_FOUND, - message: "user not found".to_string(), - }); - } - - let uploaded = upload_media_from_request( - &state, - &headers, - body, - dm_object_key_prefix(user.id, other_user_id), - ) - .await?; - - let message = db::create_direct_message_with_attachment( - &state.db, - user.id, - other_user_id, - "", - &uploaded.object_key, - &uploaded.media_url, - &uploaded.mime_type, - uploaded.size_bytes, - &uploaded.original_filename, - ) - .await - .map_err(|e| ApiError::internal(&format!("failed to create dm attachment: {e}")))?; - - broadcast_dm_message(&state, user.id, other_user_id, &message).await; - Ok((StatusCode::CREATED, Json(message))) -} - async fn voice_ws( + ws: WebSocketUpgrade, State(state): State, user: AuthUser, Path(channel_id): Path, - ws: WebSocketUpgrade, ) -> Result { ensure_channel_member(&state, channel_id, user.id).await?; @@ -795,470 +668,13 @@ async fn voice_ws( } async fn chat_ws( + ws: WebSocketUpgrade, State(state): State, user: AuthUser, - ws: WebSocketUpgrade, ) -> Result { Ok(ws.on_upgrade(move |socket| chat::handle_socket(state, socket, user.id))) } -async fn list_sounds( - State(state): State, - user: AuthUser, - Path(guild_id): Path, -) -> Result>, ApiError> { - ensure_guild_member(&state, guild_id, user.id).await?; - let sounds = db::list_sounds(&state.db, guild_id).await?; - Ok(Json(sounds)) -} - -async fn upload_sound( - State(state): State, - user: AuthUser, - Path(guild_id): Path, - mut multipart: axum::extract::Multipart, -) -> Result, ApiError> { - ensure_guild_member(&state, guild_id, user.id).await?; - - let mut name = None; - let mut icon = None; - let mut file_data = None; - let mut file_name = None; - - while let Some(field) = multipart - .next_field() - .await - .map_err(|e| ApiError::bad_request(&e.to_string()))? - { - let field_name = field.name().unwrap_or_default().to_string(); - if field_name == "name" { - name = Some( - field - .text() - .await - .map_err(|e| ApiError::bad_request(&e.to_string()))?, - ); - } else if field_name == "icon" { - icon = Some( - field - .text() - .await - .map_err(|e| ApiError::bad_request(&e.to_string()))?, - ); - } else if field_name == "file" { - file_name = Some(field.file_name().unwrap_or("sound.mp3").to_string()); - file_data = Some( - field - .bytes() - .await - .map_err(|e| ApiError::bad_request(&e.to_string()))?, - ); - } - } - - let (name, icon, file_data, file_name) = match (name, icon, file_data, file_name) { - (Some(n), Some(i), Some(d), Some(f)) => (n, i, d, f), - _ => return Err(ApiError::bad_request("missing fields")), - }; - - let validated = validate_sound_upload(&file_name, &file_data) - .map_err(|e| ApiError::bad_request(&e.to_string()))?; - - let storage = state - .media - .as_ref() - .ok_or_else(|| ApiError::service_unavailable("media storage is not configured"))?; - - let object_key = format!( - "soundboard/{guild_id}/{}-{}", - Uuid::new_v4(), - sanitize_file_name(&file_name) - ); - let media_url = storage - .upload_object( - &object_key, - file_data.to_vec(), - &validated.mime_type, - &file_name, - false, - ) - .await - .map_err(|e| ApiError::internal(&e.to_string()))?; - - let sound = db::create_sound( - &state.db, - guild_id, - user.id, - name.trim(), - icon.trim(), - &object_key, - &media_url, - &validated.mime_type, - validated.size_bytes, - ) - .await?; - Ok(Json(sound)) -} - -const MAX_MEDIA_UPLOAD_BYTES: usize = 50 * 1024 * 1024; - -struct UploadedMedia { - object_key: String, - media_url: String, - mime_type: String, - size_bytes: i64, - original_filename: String, -} - -#[derive(Debug)] -struct ValidatedUpload { - mime_type: String, - inline: bool, - size_bytes: i64, -} - -async fn upload_media_from_request( - state: &AppState, - headers: &HeaderMap, - body: Bytes, - object_key_prefix: String, -) -> Result { - let storage = state - .media - .as_ref() - .ok_or_else(|| ApiError::service_unavailable("media storage is not configured"))?; - - let original_filename = headers - .get("x-file-name") - .and_then(|v| v.to_str().ok()) - .map(str::trim) - .filter(|v| !v.is_empty()) - .map(ToString::to_string) - .ok_or_else(|| ApiError::bad_request("missing x-file-name header"))?; - - let raw_mime_type = headers - .get(header::CONTENT_TYPE) - .and_then(|v| v.to_str().ok()) - .map(str::trim) - .filter(|v| !v.is_empty()) - .unwrap_or("application/octet-stream") - .to_string(); - - if body.is_empty() { - return Err(ApiError::bad_request("missing file upload")); - } - if body.len() > MAX_MEDIA_UPLOAD_BYTES { - return Err(ApiError::bad_request("file exceeds 50MB upload limit")); - } - - let validated = validate_general_upload(&original_filename, &body, &raw_mime_type) - .map_err(|e| ApiError::bad_request(&e.to_string()))?; - let safe_name = sanitize_file_name(&original_filename); - let object_key = format!("{}/{}-{}", object_key_prefix, Uuid::new_v4(), safe_name); - let size_bytes = body.len() as i64; - let media_url = storage - .upload_object( - &object_key, - body.to_vec(), - &validated.mime_type, - &original_filename, - validated.inline, - ) - .await - .map_err(|e| ApiError::internal(&e.to_string()))?; - - Ok(UploadedMedia { - object_key, - media_url, - mime_type: validated.mime_type, - size_bytes, - original_filename, - }) -} - -async fn broadcast_channel_message( - state: &AppState, - members: Vec, - channel_id: Uuid, - message: &MessageWithAuthor, -) { - state - .chat - .broadcast_to_many( - members, - chat::ServerEvent::MessageCreated { - channel_id, - message: serde_json::to_value(message).unwrap_or_default(), - }, - ) - .await; -} - -async fn broadcast_dm_message( - state: &AppState, - current_user_id: Uuid, - other_user_id: Uuid, - message: &DmMessageWithAuthor, -) { - state - .chat - .broadcast_to_user( - current_user_id, - chat::ServerEvent::DmCreated { - other_user_id, - message: serde_json::to_value(message).unwrap_or_default(), - }, - ) - .await; - state - .chat - .broadcast_to_user( - other_user_id, - chat::ServerEvent::DmCreated { - other_user_id: current_user_id, - message: serde_json::to_value(message).unwrap_or_default(), - }, - ) - .await; -} - -fn sanitize_file_name(file_name: &str) -> String { - let sanitized: String = file_name - .chars() - .map(|ch| { - if ch.is_ascii_alphanumeric() || matches!(ch, '.' | '-' | '_') { - ch - } else { - '_' - } - }) - .collect(); - - let trimmed = sanitized.trim_matches(|ch| ch == '_' || ch == '.').trim(); - if trimmed.is_empty() { - "upload.bin".to_string() - } else { - trimmed.to_string() - } -} - -fn validate_general_upload( - file_name: &str, - bytes: &[u8], - claimed_mime: &str, -) -> anyhow::Result { - let extension = lower_file_extension(file_name) - .ok_or_else(|| anyhow::anyhow!("file extension is required"))?; - let normalized_mime = sniff_upload_type(bytes, &extension, claimed_mime) - .ok_or_else(|| anyhow::anyhow!("unsupported upload type"))?; - let inline = is_inline_media_type(&normalized_mime); - - Ok(ValidatedUpload { - mime_type: normalized_mime, - inline, - size_bytes: bytes.len() as i64, - }) -} - -fn validate_sound_upload(file_name: &str, bytes: &[u8]) -> anyhow::Result { - let extension = lower_file_extension(file_name) - .ok_or_else(|| anyhow::anyhow!("sound file extension is required"))?; - let Some(mime_type) = sniff_audio_type(bytes, &extension) else { - return Err(anyhow::anyhow!( - "only mp3, ogg, and wav sounds are supported" - )); - }; - - Ok(ValidatedUpload { - mime_type, - inline: false, - size_bytes: bytes.len() as i64, - }) -} - -fn lower_file_extension(file_name: &str) -> Option { - std::path::Path::new(file_name) - .extension() - .and_then(|ext| ext.to_str()) - .map(|ext| ext.to_ascii_lowercase()) -} - -fn sniff_upload_type(bytes: &[u8], extension: &str, claimed_mime: &str) -> Option { - sniff_audio_type(bytes, extension) - .or_else(|| sniff_image_type(bytes, extension)) - .or_else(|| sniff_video_type(bytes, extension)) - .or_else(|| sniff_document_type(extension, claimed_mime)) -} - -fn sniff_audio_type(bytes: &[u8], extension: &str) -> Option { - match extension { - "mp3" if bytes.starts_with(b"ID3") || bytes.first().copied() == Some(0xff) => { - Some("audio/mpeg".to_string()) - } - "ogg" if bytes.starts_with(b"OggS") => Some("audio/ogg".to_string()), - "wav" if bytes.starts_with(b"RIFF") && bytes.get(8..12) == Some(b"WAVE") => { - Some("audio/wav".to_string()) - } - _ => None, - } -} - -fn sniff_image_type(bytes: &[u8], extension: &str) -> Option { - match extension { - "png" if bytes.starts_with(b"\x89PNG\r\n\x1a\n") => Some("image/png".to_string()), - "jpg" | "jpeg" if bytes.starts_with(&[0xff, 0xd8, 0xff]) => Some("image/jpeg".to_string()), - "gif" if bytes.starts_with(b"GIF87a") || bytes.starts_with(b"GIF89a") => { - Some("image/gif".to_string()) - } - "webp" if bytes.starts_with(b"RIFF") && bytes.get(8..12) == Some(b"WEBP") => { - Some("image/webp".to_string()) - } - _ => None, - } -} - -fn sniff_video_type(bytes: &[u8], extension: &str) -> Option { - match extension { - "mp4" - if bytes - .windows(8) - .any(|window| window == b"ftypisom" || window == b"ftypmp42") => - { - Some("video/mp4".to_string()) - } - "webm" if bytes.starts_with(&[0x1a, 0x45, 0xdf, 0xa3]) => Some("video/webm".to_string()), - _ => None, - } -} - -fn sniff_document_type(extension: &str, claimed_mime: &str) -> Option { - match extension { - "pdf" => Some("application/pdf".to_string()), - "txt" => Some("text/plain".to_string()), - "json" => Some("application/json".to_string()), - "csv" => Some("text/csv".to_string()), - "md" => Some("text/markdown".to_string()), - "zip" => Some("application/zip".to_string()), - "gz" => Some("application/gzip".to_string()), - _ if matches!( - claimed_mime, - "application/pdf" - | "text/plain" - | "application/json" - | "text/csv" - | "text/markdown" - | "application/zip" - | "application/gzip" - ) => - { - Some(claimed_mime.to_string()) - } - _ => None, - } -} - -fn is_inline_media_type(mime_type: &str) -> bool { - matches!( - mime_type, - "image/png" - | "image/jpeg" - | "image/gif" - | "image/webp" - | "video/mp4" - | "video/webm" - | "audio/mpeg" - | "audio/ogg" - | "audio/wav" - | "application/pdf" - | "text/plain" - | "application/json" - | "text/csv" - | "text/markdown" - ) -} - -fn channel_object_key_prefix(channel_id: Uuid) -> String { - let now = chrono::Utc::now(); - format!( - "channels/{}/{:04}/{:02}", - channel_id, - now.year(), - now.month() - ) -} - -fn dm_object_key_prefix(user_a: Uuid, user_b: Uuid) -> String { - let now = chrono::Utc::now(); - let (left, right) = if user_a <= user_b { - (user_a, user_b) - } else { - (user_b, user_a) - }; - format!( - "dms/{}-{}/{:04}/{:02}", - left, - right, - now.year(), - now.month() - ) -} - -async fn delete_sound_post( - state: State, - user: AuthUser, - path: Path<(Uuid, Uuid)>, -) -> Result { - delete_sound(state, user, path).await -} - -async fn delete_sound( - State(state): State, - user: AuthUser, - Path((guild_id, sound_id)): Path<(Uuid, Uuid)>, -) -> Result { - ensure_guild_member(&state, guild_id, user.id).await?; - - let sound = db::get_sound_by_id(&state.db, sound_id) - .await - .map_err(|e| ApiError::internal(&e.to_string()))? - .ok_or_else(|| ApiError { - status: StatusCode::NOT_FOUND, - message: "sound not found".to_string(), - })?; - - if sound.guild_id != guild_id { - return Err(ApiError::bad_request("sound does not belong to this guild")); - } - - let is_owner = db::is_guild_owner(&state.db, guild_id, user.id) - .await - .map_err(|e| ApiError::internal(&e.to_string()))?; - - if sound.created_by_user_id != user.id && !is_owner { - return Err(ApiError { - status: StatusCode::FORBIDDEN, - message: "you do not have permission to delete this sound".to_string(), - }); - } - - let object_key = db::get_sound_object_key(&state.db, sound_id) - .await - .map_err(|e| ApiError::internal(&format!("failed to load sound storage key: {e}")))?; - - if let (Some(storage), Some(object_key)) = (state.media.as_ref(), object_key.as_deref()) { - storage - .delete_object(object_key) - .await - .map_err(|e| ApiError::internal(&format!("failed to delete sound media: {e}")))?; - } - - db::delete_sound(&state.db, sound_id) - .await - .map_err(|e| ApiError::internal(&format!("failed to delete sound record: {e}")))?; - - Ok(StatusCode::NO_CONTENT) -} - async fn ensure_guild_member( state: &AppState, guild_id: Uuid, @@ -1293,100 +709,3 @@ async fn ensure_channel_member( ensure_guild_member(state, guild_id, user_id).await } - -#[cfg(test)] -mod tests { - use super::{ - sanitize_file_name, upload_media_from_request, validate_general_upload, - validate_sound_upload, - }; - use crate::{AppState, chat::ChatHub, config::Settings, voice::VoiceHub}; - use axum::{ - body::Bytes, - http::{HeaderMap, StatusCode, header}, - }; - use sea_orm::{DatabaseBackend, MockDatabase}; - use std::sync::Arc; - - fn test_state() -> AppState { - AppState { - db: Arc::new(MockDatabase::new(DatabaseBackend::Postgres).into_connection()), - settings: Arc::new(Settings { - port: 3000, - app_base_url: "http://localhost:3000".to_string(), - app_origin: "http://localhost:3000".to_string(), - database_url: "postgres://localhost/test".to_string(), - oidc_client_id: "client".to_string(), - oidc_client_secret: "secret".to_string(), - oidc_authorize_url: "http://localhost:3000/oidc/authorize".to_string(), - oidc_token_url: "http://localhost:3000/oidc/token".to_string(), - oidc_userinfo_url: "http://localhost:3000/oidc/userinfo".to_string(), - oidc_redirect_url: "http://localhost:3000/auth/callback".to_string(), - oidc_scopes: "openid profile email".to_string(), - session_cookie_secure: false, - stun_urls: vec!["stun:stun.l.google.com:19302".to_string()], - turn_urls: Vec::new(), - turn_username: None, - turn_password: None, - media: None, - }), - http: reqwest::Client::new(), - voice: Arc::new(VoiceHub::default()), - chat: Arc::new(ChatHub::default()), - media: None, - } - } - - #[test] - fn sanitize_file_name_replaces_unsafe_chars() { - assert_eq!( - sanitize_file_name("../../hello world?.mp3"), - "hello_world_.mp3" - ); - } - - #[test] - fn validates_png_uploads() { - let png = b"\x89PNG\r\n\x1a\nrest"; - let upload = validate_general_upload("image.png", png, "image/png").unwrap(); - assert_eq!(upload.mime_type, "image/png"); - assert!(upload.inline); - } - - #[test] - fn rejects_unknown_uploads() { - let err = validate_general_upload("payload.exe", b"MZ...", "application/octet-stream") - .unwrap_err(); - assert!(err.to_string().contains("unsupported upload type")); - } - - #[test] - fn validates_sound_uploads() { - let wav = b"RIFFdataWAVE"; - let upload = validate_sound_upload("sound.wav", wav).unwrap(); - assert_eq!(upload.mime_type, "audio/wav"); - } - - #[tokio::test] - async fn upload_helper_requires_configured_media_storage() { - let state = test_state(); - let mut headers = HeaderMap::new(); - headers.insert("x-file-name", "photo.png".parse().unwrap()); - headers.insert(header::CONTENT_TYPE, "image/png".parse().unwrap()); - - let err = match upload_media_from_request( - &state, - &headers, - Bytes::from_static(b"\x89PNG\r\n\x1a\nrest"), - "channels/test".to_string(), - ) - .await - { - Ok(_) => panic!("expected upload helper to reject missing media storage"), - Err(err) => err, - }; - - assert_eq!(err.status, StatusCode::SERVICE_UNAVAILABLE); - assert_eq!(err.message, "media storage is not configured"); - } -} diff --git a/src/main.rs b/src/main.rs index a6e3c34..53ea6f2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,6 @@ mod config; mod db; mod entity; mod handlers; -mod media; mod migration; mod models; mod voice; @@ -12,32 +11,21 @@ mod voice; use std::{net::SocketAddr, sync::Arc}; use anyhow::Context; -use axum::{ - Router, - extract::{Request, State}, - http::{HeaderValue, Method, header}, - middleware::{Next, from_fn_with_state}, - response::Response, - routing::get, -}; +use axum::{Router, routing::get}; use sea_orm::Database; use sea_orm_migration::MigratorTrait; use tower_http::{services::ServeDir, trace::TraceLayer}; use tracing::info; -use crate::{ - auth::ApiError, config::Settings, handlers::routes, media::MediaStorage, migration::Migrator, - voice::VoiceHub, -}; +use crate::{config::Settings, handlers::routes, migration::Migrator, voice::VoiceHub}; #[derive(Clone)] pub struct AppState { - pub db: Arc, + pub db: sea_orm::DatabaseConnection, pub settings: Arc, pub http: reqwest::Client, pub voice: Arc, pub chat: Arc, - pub media: Option>, } #[tokio::main] @@ -54,25 +42,22 @@ async fn main() -> anyhow::Result<()> { Migrator::up(&db, None) .await .with_context(|| "failed to run migrations")?; - db::cleanup_sessions(&db) - .await - .with_context(|| "failed to clean expired sessions")?; - - let media = match settings.media.as_ref() { - Some(media_settings) => Some(Arc::new(MediaStorage::new(media_settings).await?)), - None => None, - }; let state = AppState { - db: Arc::new(db), + db, settings, http: reqwest::Client::new(), voice: Arc::new(VoiceHub::default()), chat: Arc::new(chat::ChatHub::default()), - media, }; let port = state.settings.port; - let app = build_app(state); + + let app = Router::new() + .route("/health", get(handlers::health)) + .nest_service("/static", ServeDir::new("static")) + .merge(routes()) + .with_state(state) + .layer(TraceLayer::new_for_http()); let addr = SocketAddr::from(([0, 0, 0, 0], port)); info!(%addr, "server started"); @@ -88,1092 +73,3 @@ fn init_tracing() { tracing_subscriber::fmt().with_env_filter(filter).init(); } - -fn build_app(state: AppState) -> Router { - let settings = Arc::clone(&state.settings); - Router::new() - .route("/health", get(handlers::health)) - .nest_service("/static", ServeDir::new("static")) - .merge(routes()) - .with_state(state) - .layer(from_fn_with_state( - Arc::clone(&settings), - add_security_headers, - )) - .layer(from_fn_with_state( - Arc::clone(&settings), - require_same_origin, - )) - .layer(TraceLayer::new_for_http()) -} - -async fn require_same_origin( - State(settings): State>, - request: Request, - next: Next, -) -> Result { - let requires_origin = matches!(*request.method(), Method::POST | Method::DELETE) - || is_websocket_upgrade(&request); - - if requires_origin && !auth::origin_matches(request.headers(), &settings.app_origin) { - return Err(ApiError::forbidden("cross-origin request rejected")); - } - - Ok(next.run(request).await) -} - -async fn add_security_headers( - State(settings): State>, - request: Request, - next: Next, -) -> Response { - let mut response = next.run(request).await; - let csp = build_csp(&settings); - - if let Ok(value) = HeaderValue::from_str(&csp) { - response - .headers_mut() - .insert("content-security-policy", value); - } - response.headers_mut().insert( - header::X_CONTENT_TYPE_OPTIONS, - HeaderValue::from_static("nosniff"), - ); - response - .headers_mut() - .insert(header::X_FRAME_OPTIONS, HeaderValue::from_static("DENY")); - response.headers_mut().insert( - header::REFERRER_POLICY, - HeaderValue::from_static("same-origin"), - ); - response -} - -fn is_websocket_upgrade(request: &Request) -> bool { - request - .headers() - .get(header::UPGRADE) - .and_then(|value| value.to_str().ok()) - .map(|value| value.eq_ignore_ascii_case("websocket")) - .unwrap_or(false) -} - -fn build_csp(settings: &Settings) -> String { - let media_origin = settings - .media - .as_ref() - .map(|media| media.public_base_url.as_str()) - .unwrap_or("'self'"); - - format!( - "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https: {media_origin}; media-src 'self' https: {media_origin}; connect-src 'self' ws: wss: https://api.klipy.com; font-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" - ) -} - -#[cfg(test)] -mod tests { - use super::{AppState, build_app, build_csp}; - use crate::{ - auth, chat, - config::{MediaSettings, Settings}, - entity::{guilds, sessions, soundboard_sounds, users}, - voice::VoiceHub, - }; - use axum::{ - body::Body, - http::{Method, Request, StatusCode, header}, - }; - use chrono::Utc; - use sea_orm::MockExecResult; - use sea_orm::{DatabaseBackend, MockDatabase, Value}; - use std::{collections::BTreeMap, sync::Arc}; - use tower::ServiceExt; - use uuid::Uuid; - - fn test_settings() -> Arc { - Arc::new(Settings { - port: 3000, - app_base_url: "http://localhost:3000".to_string(), - app_origin: "http://localhost:3000".to_string(), - database_url: "postgres://localhost/test".to_string(), - oidc_client_id: "client".to_string(), - oidc_client_secret: "secret".to_string(), - oidc_authorize_url: "http://localhost:3000/oidc/authorize".to_string(), - oidc_token_url: "http://localhost:3000/oidc/token".to_string(), - oidc_userinfo_url: "http://localhost:3000/oidc/userinfo".to_string(), - oidc_redirect_url: "http://localhost:3000/auth/callback".to_string(), - oidc_scopes: "openid profile email".to_string(), - session_cookie_secure: false, - stun_urls: vec!["stun:stun.l.google.com:19302".to_string()], - turn_urls: Vec::new(), - turn_username: None, - turn_password: None, - media: None, - }) - } - - fn build_state(db: sea_orm::DatabaseConnection) -> AppState { - AppState { - db: Arc::new(db), - settings: test_settings(), - http: reqwest::Client::new(), - voice: Arc::new(VoiceHub::default()), - chat: Arc::new(chat::ChatHub::default()), - media: None, - } - } - - fn build_state_with_settings( - db: sea_orm::DatabaseConnection, - settings: Arc, - ) -> AppState { - AppState { - db: Arc::new(db), - settings, - http: reqwest::Client::new(), - voice: Arc::new(VoiceHub::default()), - chat: Arc::new(chat::ChatHub::default()), - media: None, - } - } - - fn websocket_request(uri: &str) -> axum::http::request::Builder { - Request::builder() - .uri(uri) - .header(header::CONNECTION, "upgrade") - .header(header::UPGRADE, "websocket") - .header("sec-websocket-version", "13") - .header("sec-websocket-key", "dGhlIHNhbXBsZSBub25jZQ==") - } - - fn mock_session(session_id: &str, user_id: Uuid) -> sessions::Model { - let now = Utc::now().fixed_offset(); - sessions::Model { - id: session_id.to_string(), - user_id, - expires_at: (Utc::now() + chrono::Duration::days(1)).fixed_offset(), - created_at: now, - last_seen_at: now, - revoked_at: None, - user_agent_hash: None, - ip_hash: None, - } - } - - fn count_row(value: i64) -> BTreeMap { - BTreeMap::from([("num_items".to_string(), Value::from(value))]) - } - - fn guild_id_row(guild_id: Uuid) -> BTreeMap { - BTreeMap::from([("guild_id".to_string(), Value::from(guild_id))]) - } - - #[tokio::test] - async fn me_requires_valid_session_cookie() { - let user_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![sessions::Model { - id: "session-1".to_string(), - user_id, - expires_at: (Utc::now() + chrono::Duration::days(1)).fixed_offset(), - created_at: Utc::now().fixed_offset(), - last_seen_at: Utc::now().fixed_offset(), - revoked_at: None, - user_agent_hash: None, - ip_hash: None, - }]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![users::Model { - id: user_id, - oidc_sub: "oidc-sub".to_string(), - email: Some("user@example.com".to_string()), - display_name: "User".to_string(), - avatar_url: None, - created_at: Utc::now().fixed_offset(), - updated_at: Utc::now().fixed_offset(), - }]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .uri("/me") - .header( - header::COOKIE, - format!("{}=session-1", auth::SESSION_COOKIE), - ) - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::OK); - } - - #[tokio::test] - async fn health_response_includes_security_headers() { - let db = MockDatabase::new(DatabaseBackend::Postgres).into_connection(); - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .uri("/health") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.headers().get("x-content-type-options").unwrap(), - "nosniff" - ); - assert_eq!(response.headers().get("x-frame-options").unwrap(), "DENY"); - assert_eq!( - response.headers().get("referrer-policy").unwrap(), - "same-origin" - ); - assert!(response.headers().contains_key("content-security-policy")); - } - - #[tokio::test] - async fn logout_revokes_session_and_clears_cookie() { - let user_id = Uuid::new_v4(); - let now = Utc::now().fixed_offset(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![sessions::Model { - id: "session-2".to_string(), - user_id, - expires_at: (Utc::now() + chrono::Duration::days(1)).fixed_offset(), - created_at: now, - last_seen_at: now, - revoked_at: None, - user_agent_hash: None, - ip_hash: None, - }]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![sessions::Model { - id: "session-2".to_string(), - user_id, - expires_at: (Utc::now() + chrono::Duration::days(1)).fixed_offset(), - created_at: now, - last_seen_at: now, - revoked_at: None, - user_agent_hash: None, - ip_hash: None, - }]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri("/auth/logout") - .header( - header::COOKIE, - format!("{}=session-2", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::NO_CONTENT); - let cookie = response.headers().get(header::SET_COOKIE).unwrap(); - assert!(cookie.to_str().unwrap().contains("Max-Age=0")); - } - - #[tokio::test] - async fn rejects_cross_origin_post_before_handler_runs() { - let db = MockDatabase::new(DatabaseBackend::Postgres).into_connection(); - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri("/auth/logout") - .header(header::ORIGIN, "https://evil.example") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::FORBIDDEN); - } - - #[tokio::test] - async fn websocket_requires_valid_same_origin() { - let db = MockDatabase::new(DatabaseBackend::Postgres).into_connection(); - let app = build_app(build_state(db)); - let response = app - .oneshot( - websocket_request("/ws") - .header(header::ORIGIN, "https://evil.example") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::FORBIDDEN); - } - - #[tokio::test] - async fn websocket_requires_session_cookie() { - let db = MockDatabase::new(DatabaseBackend::Postgres).into_connection(); - let app = build_app(build_state(db)); - let response = app - .oneshot( - websocket_request("/ws") - .header(header::ORIGIN, "http://localhost:3000") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::UNAUTHORIZED); - } - - #[tokio::test] - async fn voice_websocket_requires_same_origin() { - let channel_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres).into_connection(); - let app = build_app(build_state(db)); - let response = app - .oneshot( - websocket_request(&format!("/channels/{channel_id}/voice/ws")) - .header(header::ORIGIN, "https://evil.example") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::FORBIDDEN); - } - - #[tokio::test] - async fn voice_websocket_requires_session_cookie() { - let channel_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres).into_connection(); - let app = build_app(build_state(db)); - let response = app - .oneshot( - websocket_request(&format!("/channels/{channel_id}/voice/ws")) - .header(header::ORIGIN, "http://localhost:3000") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::UNAUTHORIZED); - } - - #[tokio::test] - async fn delete_sound_requires_guild_membership() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let sound_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-sound-1", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![count_row(0)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::DELETE) - .uri(format!("/guilds/{guild_id}/sounds/{sound_id}")) - .header( - header::COOKIE, - format!("{}=session-sound-1", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::FORBIDDEN); - } - - #[tokio::test] - async fn delete_sound_forbids_non_owner_non_creator() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let sound_id = Uuid::new_v4(); - let created_at = Utc::now().fixed_offset(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-sound-2", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![count_row(1)]]) - .append_query_results([vec![soundboard_sounds::Model { - id: sound_id, - guild_id, - name: "Test".to_string(), - icon: "x".to_string(), - object_key: Some("soundboard/test.mp3".to_string()), - media_url: "https://media.example.com/test.mp3".to_string(), - mime_type: Some("audio/mpeg".to_string()), - size_bytes: Some(123), - file_path: None, - created_by_user_id: Uuid::new_v4(), - created_at, - }]]) - .append_query_results([vec![guilds::Model { - id: guild_id, - name: "Guild".to_string(), - owner_user_id: Uuid::new_v4(), - created_at, - }]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::DELETE) - .uri(format!("/guilds/{guild_id}/sounds/{sound_id}")) - .header( - header::COOKIE, - format!("{}=session-sound-2", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::FORBIDDEN); - } - - #[tokio::test] - async fn delete_sound_returns_not_found_for_missing_sound() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let sound_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-sound-3", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![count_row(1)]]) - .append_query_results([Vec::::new()]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::DELETE) - .uri(format!("/guilds/{guild_id}/sounds/{sound_id}")) - .header( - header::COOKIE, - format!("{}=session-sound-3", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::NOT_FOUND); - } - - #[tokio::test] - async fn delete_sound_rejects_wrong_guild_sound() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let other_guild_id = Uuid::new_v4(); - let sound_id = Uuid::new_v4(); - let created_at = Utc::now().fixed_offset(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-sound-4", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![count_row(1)]]) - .append_query_results([vec![soundboard_sounds::Model { - id: sound_id, - guild_id: other_guild_id, - name: "Test".to_string(), - icon: "x".to_string(), - object_key: Some("soundboard/test.mp3".to_string()), - media_url: "https://media.example.com/test.mp3".to_string(), - mime_type: Some("audio/mpeg".to_string()), - size_bytes: Some(123), - file_path: None, - created_by_user_id: user_id, - created_at, - }]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::DELETE) - .uri(format!("/guilds/{guild_id}/sounds/{sound_id}")) - .header( - header::COOKIE, - format!("{}=session-sound-4", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - } - - #[tokio::test] - async fn channel_attachment_requires_guild_membership() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let channel_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-channel-1", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![guild_id_row(guild_id)]]) - .append_query_results([vec![count_row(0)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri(format!("/channels/{channel_id}/attachments")) - .header( - header::COOKIE, - format!("{}=session-channel-1", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .header("x-file-name", "photo.png") - .header(header::CONTENT_TYPE, "image/png") - .body(Body::from(Vec::from(&b"\x89PNG\r\n\x1a\nrest"[..]))) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::FORBIDDEN); - } - - #[tokio::test] - async fn channel_attachment_requires_media_storage_when_member() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let channel_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-channel-2", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![guild_id_row(guild_id)]]) - .append_query_results([vec![count_row(1)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri(format!("/channels/{channel_id}/attachments")) - .header( - header::COOKIE, - format!("{}=session-channel-2", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .header("x-file-name", "photo.png") - .header(header::CONTENT_TYPE, "image/png") - .body(Body::from(Vec::from(&b"\x89PNG\r\n\x1a\nrest"[..]))) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::SERVICE_UNAVAILABLE); - } - - #[tokio::test] - async fn dm_attachment_rejects_sending_to_self() { - let user_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-dm-1", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri(format!("/dms/{user_id}/attachments")) - .header( - header::COOKIE, - format!("{}=session-dm-1", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .header("x-file-name", "photo.png") - .header(header::CONTENT_TYPE, "image/png") - .body(Body::from(Vec::from(&b"\x89PNG\r\n\x1a\nrest"[..]))) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - } - - #[tokio::test] - async fn dm_attachment_returns_not_found_for_missing_recipient() { - let user_id = Uuid::new_v4(); - let other_user_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-dm-2", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![count_row(0)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri(format!("/dms/{other_user_id}/attachments")) - .header( - header::COOKIE, - format!("{}=session-dm-2", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .header("x-file-name", "photo.png") - .header(header::CONTENT_TYPE, "image/png") - .body(Body::from(Vec::from(&b"\x89PNG\r\n\x1a\nrest"[..]))) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::NOT_FOUND); - } - - #[tokio::test] - async fn dm_attachment_requires_media_storage_for_existing_user() { - let user_id = Uuid::new_v4(); - let other_user_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-dm-3", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![count_row(1)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri(format!("/dms/{other_user_id}/attachments")) - .header( - header::COOKIE, - format!("{}=session-dm-3", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .header("x-file-name", "photo.png") - .header(header::CONTENT_TYPE, "image/png") - .body(Body::from(Vec::from(&b"\x89PNG\r\n\x1a\nrest"[..]))) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::SERVICE_UNAVAILABLE); - } - - #[tokio::test] - async fn join_invite_route_returns_guild_for_valid_invite() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let created_by_user_id = Uuid::new_v4(); - let created_at = Utc::now().fixed_offset(); - let invite = crate::entity::invites::Model { - code: "invite-route".to_string(), - guild_id, - created_by_user_id, - created_at, - expires_at: Some((Utc::now() + chrono::Duration::minutes(5)).fixed_offset()), - max_uses: Some(5), - use_count: 0, - }; - let updated_invite = crate::entity::invites::Model { - use_count: 1, - ..invite.clone() - }; - let guild = guilds::Model { - id: guild_id, - name: "Guild".to_string(), - owner_user_id: created_by_user_id, - created_at, - }; - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-invite-1", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![invite]]) - .append_query_results([Vec::::new()]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![updated_invite]]) - .append_query_results([vec![guild]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri("/invites/invite-route/join") - .header( - header::COOKIE, - format!("{}=session-invite-1", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::OK); - } - - #[tokio::test] - async fn list_guild_channels_requires_membership() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-guild-channels", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![count_row(0)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .uri(format!("/guilds/{guild_id}/channels")) - .header( - header::COOKIE, - format!("{}=session-guild-channels", auth::SESSION_COOKIE), - ) - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::FORBIDDEN); - } - - #[tokio::test] - async fn list_guild_members_requires_membership() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-guild-members", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![count_row(0)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .uri(format!("/guilds/{guild_id}/members")) - .header( - header::COOKIE, - format!("{}=session-guild-members", auth::SESSION_COOKIE), - ) - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::FORBIDDEN); - } - - #[tokio::test] - async fn channel_message_requires_membership() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let channel_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-channel-message-1", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![guild_id_row(guild_id)]]) - .append_query_results([vec![count_row(0)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri(format!("/channels/{channel_id}/messages")) - .header( - header::COOKIE, - format!("{}=session-channel-message-1", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .header(header::CONTENT_TYPE, "application/json") - .body(Body::from(r#"{"body":"hello"}"#)) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::FORBIDDEN); - } - - #[tokio::test] - async fn channel_message_rejects_empty_body_for_members() { - let user_id = Uuid::new_v4(); - let guild_id = Uuid::new_v4(); - let channel_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-channel-message-2", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![guild_id_row(guild_id)]]) - .append_query_results([vec![count_row(1)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri(format!("/channels/{channel_id}/messages")) - .header( - header::COOKIE, - format!("{}=session-channel-message-2", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .header(header::CONTENT_TYPE, "application/json") - .body(Body::from(r#"{"body":" "}"#)) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - } - - #[tokio::test] - async fn dm_messages_reject_self_conversation() { - let user_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-dm-messages-1", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .uri(format!("/dms/{user_id}/messages")) - .header( - header::COOKIE, - format!("{}=session-dm-messages-1", auth::SESSION_COOKIE), - ) - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - } - - #[tokio::test] - async fn dm_messages_return_not_found_for_missing_user() { - let user_id = Uuid::new_v4(); - let other_user_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-dm-messages-2", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![count_row(0)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .uri(format!("/dms/{other_user_id}/messages")) - .header( - header::COOKIE, - format!("{}=session-dm-messages-2", auth::SESSION_COOKIE), - ) - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::NOT_FOUND); - } - - #[tokio::test] - async fn send_dm_message_rejects_empty_body() { - let user_id = Uuid::new_v4(); - let other_user_id = Uuid::new_v4(); - let db = MockDatabase::new(DatabaseBackend::Postgres) - .append_query_results([vec![mock_session("session-dm-send-1", user_id)]]) - .append_exec_results([MockExecResult { - last_insert_id: 0, - rows_affected: 1, - }]) - .append_query_results([vec![count_row(1)]]) - .into_connection(); - - let app = build_app(build_state(db)); - let response = app - .oneshot( - Request::builder() - .method(Method::POST) - .uri(format!("/dms/{other_user_id}/messages")) - .header( - header::COOKIE, - format!("{}=session-dm-send-1", auth::SESSION_COOKIE), - ) - .header(header::ORIGIN, "http://localhost:3000") - .header(header::CONTENT_TYPE, "application/json") - .body(Body::from(r#"{"body":" "}"#)) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - } - - #[test] - fn csp_includes_media_origin_when_configured() { - let settings = Arc::new(Settings { - media: Some(MediaSettings { - account_id: "acct".to_string(), - access_key_id: "key".to_string(), - secret_access_key: "secret".to_string(), - bucket: "bucket".to_string(), - public_base_url: "https://media.example.com".to_string(), - }), - ..(*test_settings()).clone() - }); - let csp = build_csp(&settings); - - assert!(csp.contains("https://media.example.com")); - assert!(csp.contains("object-src 'none'")); - } - - #[tokio::test] - async fn health_route_uses_media_origin_in_csp_when_configured() { - let settings = Arc::new(Settings { - media: Some(MediaSettings { - account_id: "acct".to_string(), - access_key_id: "key".to_string(), - secret_access_key: "secret".to_string(), - bucket: "bucket".to_string(), - public_base_url: "https://media.example.com".to_string(), - }), - ..(*test_settings()).clone() - }); - let db = MockDatabase::new(DatabaseBackend::Postgres).into_connection(); - let app = build_app(build_state_with_settings(db, settings)); - let response = app - .oneshot( - Request::builder() - .uri("/health") - .body(Body::empty()) - .unwrap(), - ) - .await - .unwrap(); - let csp = response - .headers() - .get("content-security-policy") - .unwrap() - .to_str() - .unwrap(); - - assert!(csp.contains("https://media.example.com")); - } -} diff --git a/src/media.rs b/src/media.rs deleted file mode 100644 index d3f3255..0000000 --- a/src/media.rs +++ /dev/null @@ -1,87 +0,0 @@ -use anyhow::{Result, anyhow}; -use aws_config::BehaviorVersion; -use aws_sdk_s3::{ - Client, - config::{Credentials, Region}, - primitives::ByteStream, -}; - -use crate::config::MediaSettings; - -#[derive(Clone)] -pub struct MediaStorage { - client: Client, - bucket: String, - public_base_url: String, -} - -impl MediaStorage { - pub async fn new(settings: &MediaSettings) -> Result { - let shared_config = aws_config::defaults(BehaviorVersion::latest()) - .region(Region::new("auto")) - .credentials_provider(Credentials::new( - settings.access_key_id.clone(), - settings.secret_access_key.clone(), - None, - None, - "chattz-r2", - )) - .load() - .await; - - let config = aws_sdk_s3::config::Builder::from(&shared_config) - .endpoint_url(settings.endpoint_url()) - .force_path_style(true) - .build(); - - Ok(Self { - client: Client::from_conf(config), - bucket: settings.bucket.clone(), - public_base_url: settings.public_base_url.trim_end_matches('/').to_string(), - }) - } - - pub async fn upload_object( - &self, - object_key: &str, - bytes: Vec, - content_type: &str, - original_filename: &str, - inline: bool, - ) -> Result { - self.client - .put_object() - .bucket(&self.bucket) - .key(object_key) - .body(ByteStream::from(bytes)) - .content_type(content_type) - .content_disposition(format!( - "{}; filename=\"{}\"", - if inline { "inline" } else { "attachment" }, - sanitize_header_value(original_filename) - )) - .send() - .await - .map_err(|e| anyhow!("failed to upload object to R2: {e}"))?; - - Ok(format!("{}/{}", self.public_base_url, object_key)) - } - - pub async fn delete_object(&self, object_key: &str) -> Result<()> { - self.client - .delete_object() - .bucket(&self.bucket) - .key(object_key) - .send() - .await - .map_err(|e| anyhow!("failed to delete object from R2: {e}"))?; - Ok(()) - } -} - -fn sanitize_header_value(value: &str) -> String { - value - .chars() - .filter(|c| *c != '\\' && *c != '"' && !c.is_control()) - .collect() -} diff --git a/src/migration/m20260213_000001_init.rs b/src/migration/m20260213_000001_init.rs index 3c1d1ff..9c671d4 100644 --- a/src/migration/m20260213_000001_init.rs +++ b/src/migration/m20260213_000001_init.rs @@ -11,13 +11,13 @@ impl MigrationTrait for Migration { Table::create() .table(Users::Table) .if_not_exists() - .col(ColumnDef::new(Users::Id).uuid().not_null().primary_key()) .col( - ColumnDef::new(Users::OidcSub) - .string() + ColumnDef::new(Users::Id) + .uuid() .not_null() - .unique_key(), + .primary_key(), ) + .col(ColumnDef::new(Users::OidcSub).string().not_null().unique_key()) .col(ColumnDef::new(Users::Email).string()) .col(ColumnDef::new(Users::DisplayName).string().not_null()) .col(ColumnDef::new(Users::AvatarUrl).string()) @@ -42,7 +42,12 @@ impl MigrationTrait for Migration { Table::create() .table(Guilds::Table) .if_not_exists() - .col(ColumnDef::new(Guilds::Id).uuid().not_null().primary_key()) + .col( + ColumnDef::new(Guilds::Id) + .uuid() + .not_null() + .primary_key(), + ) .col(ColumnDef::new(Guilds::Name).string().not_null()) .col(ColumnDef::new(Guilds::OwnerUserId).uuid().not_null()) .col( @@ -103,7 +108,12 @@ impl MigrationTrait for Migration { Table::create() .table(Channels::Table) .if_not_exists() - .col(ColumnDef::new(Channels::Id).uuid().not_null().primary_key()) + .col( + ColumnDef::new(Channels::Id) + .uuid() + .not_null() + .primary_key(), + ) .col(ColumnDef::new(Channels::GuildId).uuid().not_null()) .col(ColumnDef::new(Channels::Name).string().not_null()) .col( @@ -128,7 +138,12 @@ impl MigrationTrait for Migration { Table::create() .table(Messages::Table) .if_not_exists() - .col(ColumnDef::new(Messages::Id).uuid().not_null().primary_key()) + .col( + ColumnDef::new(Messages::Id) + .uuid() + .not_null() + .primary_key(), + ) .col(ColumnDef::new(Messages::ChannelId).uuid().not_null()) .col(ColumnDef::new(Messages::AuthorUserId).uuid().not_null()) .col(ColumnDef::new(Messages::Body).text().not_null()) diff --git a/src/migration/m20260213_000002_invites.rs b/src/migration/m20260213_000002_invites.rs index 3dbcd5d..e99c28d 100644 --- a/src/migration/m20260213_000002_invites.rs +++ b/src/migration/m20260213_000002_invites.rs @@ -11,12 +11,7 @@ impl MigrationTrait for Migration { Table::create() .table(Invites::Table) .if_not_exists() - .col( - ColumnDef::new(Invites::Code) - .string() - .not_null() - .primary_key(), - ) + .col(ColumnDef::new(Invites::Code).string().not_null().primary_key()) .col(ColumnDef::new(Invites::GuildId).uuid().not_null()) .col(ColumnDef::new(Invites::CreatedByUserId).uuid().not_null()) .col( diff --git a/src/migration/m20260213_000004_direct_messages.rs b/src/migration/m20260213_000004_direct_messages.rs index 63ba7e2..4b723ab 100644 --- a/src/migration/m20260213_000004_direct_messages.rs +++ b/src/migration/m20260213_000004_direct_messages.rs @@ -17,16 +17,8 @@ impl MigrationTrait for Migration { .not_null() .primary_key(), ) - .col( - ColumnDef::new(DirectMessages::SenderUserId) - .uuid() - .not_null(), - ) - .col( - ColumnDef::new(DirectMessages::RecipientUserId) - .uuid() - .not_null(), - ) + .col(ColumnDef::new(DirectMessages::SenderUserId).uuid().not_null()) + .col(ColumnDef::new(DirectMessages::RecipientUserId).uuid().not_null()) .col(ColumnDef::new(DirectMessages::Body).text().not_null()) .col( ColumnDef::new(DirectMessages::CreatedAt) diff --git a/src/migration/m20260224_000005_soundboard.rs b/src/migration/m20260224_000005_soundboard.rs deleted file mode 100644 index eef7e4e..0000000 --- a/src/migration/m20260224_000005_soundboard.rs +++ /dev/null @@ -1,86 +0,0 @@ -use sea_orm_migration::prelude::*; - -#[derive(DeriveMigrationName)] -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(SoundboardSounds::Table) - .if_not_exists() - .col( - ColumnDef::new(SoundboardSounds::Id) - .uuid() - .not_null() - .primary_key(), - ) - .col(ColumnDef::new(SoundboardSounds::GuildId).uuid().not_null()) - .col(ColumnDef::new(SoundboardSounds::Name).string().not_null()) - .col(ColumnDef::new(SoundboardSounds::Icon).string().not_null()) - .col( - ColumnDef::new(SoundboardSounds::FilePath) - .string() - .not_null(), - ) - .col( - ColumnDef::new(SoundboardSounds::CreatedByUserId) - .uuid() - .not_null(), - ) - .col( - ColumnDef::new(SoundboardSounds::CreatedAt) - .timestamp_with_time_zone() - .not_null() - .default(Expr::current_timestamp()), - ) - .foreign_key( - ForeignKey::create() - .name("fk_soundboard_sounds_guild") - .from(SoundboardSounds::Table, SoundboardSounds::GuildId) - .to(Guilds::Table, Guilds::Id) - .on_delete(ForeignKeyAction::Cascade), - ) - .foreign_key( - ForeignKey::create() - .name("fk_soundboard_sounds_user") - .from(SoundboardSounds::Table, SoundboardSounds::CreatedByUserId) - .to(Users::Table, Users::Id), - ) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(SoundboardSounds::Table).to_owned()) - .await - } -} - -#[derive(DeriveIden)] -enum SoundboardSounds { - Table, - Id, - GuildId, - Name, - Icon, - FilePath, - CreatedByUserId, - CreatedAt, -} - -#[derive(DeriveIden)] -enum Users { - Table, - Id, -} - -#[derive(DeriveIden)] -enum Guilds { - Table, - Id, -} diff --git a/src/migration/m20260227_000006_attachments.rs b/src/migration/m20260227_000006_attachments.rs deleted file mode 100644 index 96f6da6..0000000 --- a/src/migration/m20260227_000006_attachments.rs +++ /dev/null @@ -1,122 +0,0 @@ -use sea_orm_migration::prelude::*; - -#[derive(DeriveMigrationName)] -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(Attachments::Table) - .if_not_exists() - .col( - ColumnDef::new(Attachments::Id) - .uuid() - .not_null() - .primary_key(), - ) - .col(ColumnDef::new(Attachments::ChannelMessageId).uuid().null()) - .col(ColumnDef::new(Attachments::DirectMessageId).uuid().null()) - .col(ColumnDef::new(Attachments::UploaderUserId).uuid().not_null()) - .col(ColumnDef::new(Attachments::ObjectKey).string().not_null()) - .col(ColumnDef::new(Attachments::MediaUrl).string().not_null()) - .col(ColumnDef::new(Attachments::MimeType).string().not_null()) - .col(ColumnDef::new(Attachments::SizeBytes).big_integer().not_null()) - .col(ColumnDef::new(Attachments::OriginalFilename).string().not_null()) - .col( - ColumnDef::new(Attachments::CreatedAt) - .timestamp_with_time_zone() - .not_null() - .default(Expr::current_timestamp()), - ) - .foreign_key( - ForeignKey::create() - .name("fk_attachments_channel_message") - .from(Attachments::Table, Attachments::ChannelMessageId) - .to(Messages::Table, Messages::Id) - .on_delete(ForeignKeyAction::Cascade), - ) - .foreign_key( - ForeignKey::create() - .name("fk_attachments_direct_message") - .from(Attachments::Table, Attachments::DirectMessageId) - .to(DirectMessages::Table, DirectMessages::Id) - .on_delete(ForeignKeyAction::Cascade), - ) - .foreign_key( - ForeignKey::create() - .name("fk_attachments_uploader") - .from(Attachments::Table, Attachments::UploaderUserId) - .to(Users::Table, Users::Id), - ) - .check( - Expr::cust( - "(channel_message_id IS NOT NULL AND direct_message_id IS NULL) OR (channel_message_id IS NULL AND direct_message_id IS NOT NULL)", - ), - ) - .to_owned(), - ) - .await?; - - manager - .create_index( - Index::create() - .name("idx_attachments_channel_message") - .table(Attachments::Table) - .col(Attachments::ChannelMessageId) - .to_owned(), - ) - .await?; - - manager - .create_index( - Index::create() - .name("idx_attachments_direct_message") - .table(Attachments::Table) - .col(Attachments::DirectMessageId) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(Attachments::Table).to_owned()) - .await - } -} - -#[derive(DeriveIden)] -enum Attachments { - Table, - Id, - ChannelMessageId, - DirectMessageId, - UploaderUserId, - ObjectKey, - MediaUrl, - MimeType, - SizeBytes, - OriginalFilename, - CreatedAt, -} - -#[derive(DeriveIden)] -enum Messages { - Table, - Id, -} - -#[derive(DeriveIden)] -enum DirectMessages { - Table, - Id, -} - -#[derive(DeriveIden)] -enum Users { - Table, - Id, -} diff --git a/src/migration/m20260227_000007_sessions.rs b/src/migration/m20260227_000007_sessions.rs deleted file mode 100644 index 739f690..0000000 --- a/src/migration/m20260227_000007_sessions.rs +++ /dev/null @@ -1,107 +0,0 @@ -use sea_orm_migration::prelude::*; - -#[derive(DeriveMigrationName)] -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(Sessions::Table) - .if_not_exists() - .col( - ColumnDef::new(Sessions::Id) - .string() - .not_null() - .primary_key(), - ) - .col(ColumnDef::new(Sessions::UserId).uuid().not_null()) - .col( - ColumnDef::new(Sessions::ExpiresAt) - .timestamp_with_time_zone() - .not_null(), - ) - .col( - ColumnDef::new(Sessions::CreatedAt) - .timestamp_with_time_zone() - .not_null() - .default(Expr::current_timestamp()), - ) - .col( - ColumnDef::new(Sessions::LastSeenAt) - .timestamp_with_time_zone() - .not_null() - .default(Expr::current_timestamp()), - ) - .col(ColumnDef::new(Sessions::RevokedAt).timestamp_with_time_zone()) - .col(ColumnDef::new(Sessions::UserAgentHash).string()) - .col(ColumnDef::new(Sessions::IpHash).string()) - .foreign_key( - ForeignKey::create() - .name("fk_sessions_user") - .from(Sessions::Table, Sessions::UserId) - .to(Users::Table, Users::Id) - .on_delete(ForeignKeyAction::Cascade), - ) - .to_owned(), - ) - .await?; - - manager - .create_index( - Index::create() - .name("idx_sessions_user_id") - .table(Sessions::Table) - .col(Sessions::UserId) - .to_owned(), - ) - .await?; - - manager - .create_index( - Index::create() - .name("idx_sessions_expires_at") - .table(Sessions::Table) - .col(Sessions::ExpiresAt) - .to_owned(), - ) - .await?; - - manager - .create_index( - Index::create() - .name("idx_sessions_revoked_at") - .table(Sessions::Table) - .col(Sessions::RevokedAt) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(Sessions::Table).to_owned()) - .await - } -} - -#[derive(DeriveIden)] -enum Sessions { - Table, - Id, - UserId, - ExpiresAt, - CreatedAt, - LastSeenAt, - RevokedAt, - UserAgentHash, - IpHash, -} - -#[derive(DeriveIden)] -enum Users { - Table, - Id, -} diff --git a/src/migration/m20260227_000008_soundboard_media.rs b/src/migration/m20260227_000008_soundboard_media.rs deleted file mode 100644 index 01942fe..0000000 --- a/src/migration/m20260227_000008_soundboard_media.rs +++ /dev/null @@ -1,72 +0,0 @@ -use sea_orm_migration::prelude::*; - -#[derive(DeriveMigrationName)] -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .alter_table( - Table::alter() - .table(SoundboardSounds::Table) - .add_column(ColumnDef::new(SoundboardSounds::ObjectKey).string().null()) - .add_column(ColumnDef::new(SoundboardSounds::MediaUrl).string().null()) - .add_column(ColumnDef::new(SoundboardSounds::MimeType).string().null()) - .add_column( - ColumnDef::new(SoundboardSounds::SizeBytes) - .big_integer() - .null(), - ) - .to_owned(), - ) - .await?; - - manager - .get_connection() - .execute_unprepared( - r#" - UPDATE soundboard_sounds - SET media_url = file_path - WHERE media_url IS NULL - "#, - ) - .await?; - - manager - .alter_table( - Table::alter() - .table(SoundboardSounds::Table) - .modify_column( - ColumnDef::new(SoundboardSounds::MediaUrl) - .string() - .not_null(), - ) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .alter_table( - Table::alter() - .table(SoundboardSounds::Table) - .drop_column(SoundboardSounds::ObjectKey) - .drop_column(SoundboardSounds::MediaUrl) - .drop_column(SoundboardSounds::MimeType) - .drop_column(SoundboardSounds::SizeBytes) - .to_owned(), - ) - .await - } -} - -#[derive(DeriveIden)] -enum SoundboardSounds { - Table, - ObjectKey, - MediaUrl, - MimeType, - SizeBytes, -} diff --git a/src/migration/m20260227_000009_soundboard_file_path_nullable.rs b/src/migration/m20260227_000009_soundboard_file_path_nullable.rs deleted file mode 100644 index 116710c..0000000 --- a/src/migration/m20260227_000009_soundboard_file_path_nullable.rs +++ /dev/null @@ -1,50 +0,0 @@ -use sea_orm_migration::prelude::*; - -#[derive(DeriveMigrationName)] -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .alter_table( - Table::alter() - .table(SoundboardSounds::Table) - .modify_column(ColumnDef::new(SoundboardSounds::FilePath).string().null()) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .get_connection() - .execute_unprepared( - r#" - UPDATE soundboard_sounds - SET file_path = media_url - WHERE file_path IS NULL - "#, - ) - .await?; - - manager - .alter_table( - Table::alter() - .table(SoundboardSounds::Table) - .modify_column( - ColumnDef::new(SoundboardSounds::FilePath) - .string() - .not_null(), - ) - .to_owned(), - ) - .await - } -} - -#[derive(DeriveIden)] -enum SoundboardSounds { - Table, - FilePath, -} diff --git a/src/migration/mod.rs b/src/migration/mod.rs index ab46deb..b05f91c 100644 --- a/src/migration/mod.rs +++ b/src/migration/mod.rs @@ -4,11 +4,6 @@ mod m20260213_000001_init; mod m20260213_000002_invites; mod m20260213_000003_channel_kind; mod m20260213_000004_direct_messages; -mod m20260224_000005_soundboard; -mod m20260227_000006_attachments; -mod m20260227_000007_sessions; -mod m20260227_000008_soundboard_media; -mod m20260227_000009_soundboard_file_path_nullable; pub struct Migrator; @@ -20,11 +15,6 @@ impl MigratorTrait for Migrator { Box::new(m20260213_000002_invites::Migration), Box::new(m20260213_000003_channel_kind::Migration), Box::new(m20260213_000004_direct_messages::Migration), - Box::new(m20260224_000005_soundboard::Migration), - Box::new(m20260227_000006_attachments::Migration), - Box::new(m20260227_000007_sessions::Migration), - Box::new(m20260227_000008_soundboard_media::Migration), - Box::new(m20260227_000009_soundboard_file_path_nullable::Migration), ] } } diff --git a/src/models.rs b/src/models.rs index b54e303..3384ec4 100644 --- a/src/models.rs +++ b/src/models.rs @@ -31,12 +31,12 @@ pub struct Channel { } #[derive(Debug, Clone, Serialize)] -pub struct Attachment { +pub struct Message { pub id: Uuid, - pub media_url: String, - pub mime_type: String, - pub size_bytes: i64, - pub original_filename: String, + pub channel_id: Uuid, + pub author_user_id: Uuid, + pub body: String, + pub created_at: DateTimeWithTimeZone, } #[derive(Debug, Clone, Serialize)] @@ -46,14 +46,13 @@ pub struct BasicUser { pub avatar_url: Option, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, sea_orm::FromQueryResult)] pub struct MessageWithAuthor { pub id: Uuid, pub channel_id: Uuid, pub author_user_id: Uuid, pub author_display_name: String, pub body: String, - pub attachments: Vec, pub created_at: DateTimeWithTimeZone, } @@ -72,7 +71,6 @@ pub struct DmMessageWithAuthor { pub recipient_user_id: Uuid, pub author_display_name: String, pub body: String, - pub attachments: Vec, pub created_at: DateTimeWithTimeZone, } @@ -86,16 +84,3 @@ pub struct Invite { pub max_uses: Option, pub use_count: i32, } - -#[derive(Debug, Clone, Serialize)] -pub struct SoundboardSound { - pub id: Uuid, - pub guild_id: Uuid, - pub name: String, - pub icon: String, - pub media_url: String, - pub mime_type: Option, - pub size_bytes: Option, - pub created_by_user_id: Uuid, - pub created_at: DateTimeWithTimeZone, -} diff --git a/src/voice.rs b/src/voice.rs index 5dc3ec8..98d9fb9 100644 --- a/src/voice.rs +++ b/src/voice.rs @@ -10,16 +10,12 @@ use crate::{AppState, db}; #[derive(Default)] pub struct VoiceHub { - rooms: RwLock>>>, + rooms: RwLock>>, } #[derive(Clone)] struct ClientHandle { display_name: String, - is_sharing_video: bool, - is_sharing_screen: bool, - is_speaking: bool, - is_muted: bool, tx: mpsc::UnboundedSender, } @@ -27,53 +23,20 @@ struct ClientHandle { pub struct VoiceParticipant { pub user_id: Uuid, pub display_name: String, - pub is_sharing_video: bool, - pub is_sharing_screen: bool, - pub is_speaking: bool, - pub is_muted: bool, } #[derive(Serialize, Clone)] #[serde(tag = "type", rename_all = "snake_case")] enum ServerEvent { - Peers { - peers: Vec, - }, - PeerJoined { - user_id: Uuid, - display_name: String, - }, - PeerLeft { - user_id: Uuid, - }, - VideoStatusChanged { - user_id: Uuid, - is_sharing_video: bool, - }, - ScreenStatusChanged { - user_id: Uuid, - is_sharing_screen: bool, - }, - SpeakingStatusChanged { - user_id: Uuid, - is_speaking: bool, - }, - MuteStatusChanged { - user_id: Uuid, - is_muted: bool, - }, + Peers { peers: Vec }, + PeerJoined { user_id: Uuid, display_name: String }, + PeerLeft { user_id: Uuid }, Signal { from_user_id: Uuid, kind: String, data: serde_json::Value, }, - Error { - message: String, - }, - PlaySound { - user_id: Uuid, - media_url: String, - }, + Error { message: String }, } #[derive(Deserialize)] @@ -84,31 +47,6 @@ enum ClientEvent { kind: String, data: serde_json::Value, }, - SetVideoStatus { - is_sharing_video: bool, - }, - SetScreenStatus { - is_sharing_screen: bool, - }, - SetSpeakingStatus { - is_speaking: bool, - }, - SetMuteStatus { - is_muted: bool, - }, - PlaySound { - sound_id: Uuid, - }, -} - -#[derive(Default)] -struct VoiceStateChange { - joined: Option, - left_user_id: Option, - video_changed: Option<(Uuid, bool)>, - screen_changed: Option<(Uuid, bool)>, - speaking_changed: Option<(Uuid, bool)>, - mute_changed: Option<(Uuid, bool)>, } impl VoiceHub { @@ -119,7 +57,10 @@ impl VoiceHub { }; room.iter() - .filter_map(|(user_id, connections)| aggregate_participant(Some(connections), *user_id)) + .map(|(user_id, handle)| VoiceParticipant { + user_id: *user_id, + display_name: handle.display_name.clone(), + }) .collect() } @@ -127,58 +68,58 @@ impl VoiceHub { &self, room_id: Uuid, user_id: Uuid, - connection_id: Uuid, display_name: String, tx: mpsc::UnboundedSender, - ) -> (Vec, VoiceStateChange) { + ) -> Vec { let mut rooms = self.rooms.write().await; let room = rooms.entry(room_id).or_default(); let peers = room .iter() - .filter_map(|(peer_id, connections)| aggregate_participant(Some(connections), *peer_id)) + .map(|(peer_id, peer)| VoiceParticipant { + user_id: *peer_id, + display_name: peer.display_name.clone(), + }) .collect::>(); - let previous = aggregate_participant(room.get(&user_id), user_id); - room.entry(user_id).or_default().insert( - connection_id, + room.insert( + user_id, ClientHandle { - display_name, - is_sharing_video: false, - is_sharing_screen: false, - is_speaking: false, - is_muted: false, + display_name: display_name.clone(), tx, }, ); - let current = aggregate_participant(room.get(&user_id), user_id); - (peers, diff_voice_state(previous, current)) - } - - async fn leave(&self, room_id: Uuid, user_id: Uuid, connection_id: Uuid) -> VoiceStateChange { - let mut rooms = self.rooms.write().await; - let Some(room) = rooms.get_mut(&room_id) else { - return VoiceStateChange::default(); - }; - - let previous = aggregate_participant(room.get(&user_id), user_id); - if let Some(connections) = room.get_mut(&user_id) { - connections.remove(&connection_id); - if connections.is_empty() { - room.remove(&user_id); + for (peer_id, peer) in room.iter() { + if *peer_id != user_id { + let _ = peer.tx.send(ServerEvent::PeerJoined { + user_id, + display_name: display_name.clone(), + }); } } - let current = aggregate_participant(room.get(&user_id), user_id); + + peers + } + + async fn leave(&self, room_id: Uuid, user_id: Uuid) { + let mut rooms = self.rooms.write().await; + let Some(room) = rooms.get_mut(&room_id) else { + return; + }; + + room.remove(&user_id); + + for peer in room.values() { + let _ = peer.tx.send(ServerEvent::PeerLeft { user_id }); + } if room.is_empty() { rooms.remove(&room_id); } - - diff_voice_state(previous, current) } - pub async fn relay_signal( + async fn relay_signal( &self, room_id: Uuid, from_user_id: Uuid, @@ -191,10 +132,7 @@ impl VoiceHub { return; }; - if let Some(target) = room - .get(&to_user_id) - .and_then(|connections| connections.values().next()) - { + if let Some(target) = room.get(&to_user_id) { let _ = target.tx.send(ServerEvent::Signal { from_user_id, kind, @@ -202,214 +140,21 @@ impl VoiceHub { }); } } - - async fn set_video_status( - &self, - room_id: Uuid, - user_id: Uuid, - connection_id: Uuid, - is_sharing_video: bool, - ) -> VoiceStateChange { - let mut rooms = self.rooms.write().await; - let Some(room) = rooms.get_mut(&room_id) else { - return VoiceStateChange::default(); - }; - - let previous = aggregate_participant(room.get(&user_id), user_id); - if let Some(handle) = room - .get_mut(&user_id) - .and_then(|connections| connections.get_mut(&connection_id)) - { - handle.is_sharing_video = is_sharing_video; - } - let current = aggregate_participant(room.get(&user_id), user_id); - diff_voice_state(previous, current) - } - - async fn set_screen_status( - &self, - room_id: Uuid, - user_id: Uuid, - connection_id: Uuid, - is_sharing_screen: bool, - ) -> VoiceStateChange { - let mut rooms = self.rooms.write().await; - let Some(room) = rooms.get_mut(&room_id) else { - return VoiceStateChange::default(); - }; - - let previous = aggregate_participant(room.get(&user_id), user_id); - if let Some(handle) = room - .get_mut(&user_id) - .and_then(|connections| connections.get_mut(&connection_id)) - { - handle.is_sharing_screen = is_sharing_screen; - } - let current = aggregate_participant(room.get(&user_id), user_id); - diff_voice_state(previous, current) - } - - async fn set_speaking_status( - &self, - room_id: Uuid, - user_id: Uuid, - connection_id: Uuid, - is_speaking: bool, - ) -> VoiceStateChange { - let mut rooms = self.rooms.write().await; - let Some(room) = rooms.get_mut(&room_id) else { - return VoiceStateChange::default(); - }; - - let previous = aggregate_participant(room.get(&user_id), user_id); - if let Some(handle) = room - .get_mut(&user_id) - .and_then(|connections| connections.get_mut(&connection_id)) - { - handle.is_speaking = is_speaking; - } - let current = aggregate_participant(room.get(&user_id), user_id); - diff_voice_state(previous, current) - } - - async fn set_mute_status( - &self, - room_id: Uuid, - user_id: Uuid, - connection_id: Uuid, - is_muted: bool, - ) -> VoiceStateChange { - let mut rooms = self.rooms.write().await; - let Some(room) = rooms.get_mut(&room_id) else { - return VoiceStateChange::default(); - }; - - let previous = aggregate_participant(room.get(&user_id), user_id); - if let Some(handle) = room - .get_mut(&user_id) - .and_then(|connections| connections.get_mut(&connection_id)) - { - handle.is_muted = is_muted; - } - let current = aggregate_participant(room.get(&user_id), user_id); - diff_voice_state(previous, current) - } - - pub async fn play_sound(&self, room_id: Uuid, user_id: Uuid, media_url: String) { - let rooms = self.rooms.read().await; - let Some(room) = rooms.get(&room_id) else { - return; - }; - - for (peer_id, connections) in room.iter() { - if *peer_id == user_id { - continue; - } - for peer in connections.values() { - let _ = peer.tx.send(ServerEvent::PlaySound { - user_id, - media_url: media_url.clone(), - }); - } - } - } - - async fn emit_change(&self, room_id: Uuid, user_id: Uuid, change: VoiceStateChange) { - if is_voice_state_change_empty(&change) { - return; - } - - let rooms = self.rooms.read().await; - let Some(room) = rooms.get(&room_id) else { - return; - }; - - if let Some(participant) = change.joined { - broadcast_voice_event( - room, - user_id, - ServerEvent::PeerJoined { - user_id: participant.user_id, - display_name: participant.display_name, - }, - ); - } - if let Some(left_user_id) = change.left_user_id { - broadcast_voice_event( - room, - user_id, - ServerEvent::PeerLeft { - user_id: left_user_id, - }, - ); - } - if let Some((changed_user_id, is_sharing_video)) = change.video_changed { - broadcast_voice_event( - room, - user_id, - ServerEvent::VideoStatusChanged { - user_id: changed_user_id, - is_sharing_video, - }, - ); - } - if let Some((changed_user_id, is_sharing_screen)) = change.screen_changed { - broadcast_voice_event( - room, - user_id, - ServerEvent::ScreenStatusChanged { - user_id: changed_user_id, - is_sharing_screen, - }, - ); - } - if let Some((changed_user_id, is_speaking)) = change.speaking_changed { - broadcast_voice_event( - room, - user_id, - ServerEvent::SpeakingStatusChanged { - user_id: changed_user_id, - is_speaking, - }, - ); - } - if let Some((changed_user_id, is_muted)) = change.mute_changed { - broadcast_voice_event( - room, - user_id, - ServerEvent::MuteStatusChanged { - user_id: changed_user_id, - is_muted, - }, - ); - } - } } pub async fn handle_socket(state: AppState, socket: WebSocket, room_id: Uuid, user_id: Uuid) { let Some(user) = db::get_user_by_id(&state.db, user_id).await.ok().flatten() else { return; }; - let Ok(Some(guild_id)) = db::guild_id_for_channel(&state.db, room_id).await else { - return; - }; let (mut ws_sender, mut ws_receiver) = socket.split(); let (tx, mut rx) = mpsc::unbounded_channel::(); - let connection_id = Uuid::new_v4(); - let (peers, change) = state + let peers = state .voice - .join( - room_id, - user_id, - connection_id, - user.display_name.clone(), - tx.clone(), - ) + .join(room_id, user_id, user.display_name.clone(), tx.clone()) .await; let _ = tx.send(ServerEvent::Peers { peers }); - state.voice.emit_change(room_id, user_id, change).await; let send_task = tokio::spawn(async move { while let Some(event) = rx.recv().await { @@ -437,44 +182,6 @@ pub async fn handle_socket(state: AppState, socket: WebSocket, room_id: Uuid, us .relay_signal(room_id, user_id, to_user_id, kind, data) .await; } - Ok(ClientEvent::SetVideoStatus { is_sharing_video }) => { - let change = state - .voice - .set_video_status(room_id, user_id, connection_id, is_sharing_video) - .await; - state.voice.emit_change(room_id, user_id, change).await; - } - Ok(ClientEvent::SetScreenStatus { is_sharing_screen }) => { - let change = state - .voice - .set_screen_status(room_id, user_id, connection_id, is_sharing_screen) - .await; - state.voice.emit_change(room_id, user_id, change).await; - } - Ok(ClientEvent::SetSpeakingStatus { is_speaking }) => { - let change = state - .voice - .set_speaking_status(room_id, user_id, connection_id, is_speaking) - .await; - state.voice.emit_change(room_id, user_id, change).await; - } - Ok(ClientEvent::SetMuteStatus { is_muted }) => { - let change = state - .voice - .set_mute_status(room_id, user_id, connection_id, is_muted) - .await; - state.voice.emit_change(room_id, user_id, change).await; - } - Ok(ClientEvent::PlaySound { sound_id }) => { - if let Ok(Some(sound)) = db::get_sound_by_id(&state.db, sound_id).await - && sound.guild_id == guild_id - { - state - .voice - .play_sound(room_id, user_id, sound.media_url) - .await; - } - } Err(err) => { let _ = tx.send(ServerEvent::Error { message: format!("invalid voice message: {err}"), @@ -488,183 +195,5 @@ pub async fn handle_socket(state: AppState, socket: WebSocket, room_id: Uuid, us } send_task.abort(); - let change = state.voice.leave(room_id, user_id, connection_id).await; - state.voice.emit_change(room_id, user_id, change).await; -} - -fn aggregate_participant( - connections: Option<&HashMap>, - user_id: Uuid, -) -> Option { - let connections = connections?; - if connections.is_empty() { - return None; - } - - let mut handles = connections.values(); - let first = handles.next()?; - Some(VoiceParticipant { - user_id, - display_name: first.display_name.clone(), - is_sharing_video: connections.values().any(|handle| handle.is_sharing_video), - is_sharing_screen: connections.values().any(|handle| handle.is_sharing_screen), - is_speaking: connections.values().any(|handle| handle.is_speaking), - is_muted: connections.values().all(|handle| handle.is_muted), - }) -} - -fn diff_voice_state( - previous: Option, - current: Option, -) -> VoiceStateChange { - match (previous, current) { - (None, None) => VoiceStateChange::default(), - (None, Some(current)) => VoiceStateChange { - joined: Some(current), - ..Default::default() - }, - (Some(previous), None) => VoiceStateChange { - left_user_id: Some(previous.user_id), - ..Default::default() - }, - (Some(previous), Some(current)) => VoiceStateChange { - video_changed: (previous.is_sharing_video != current.is_sharing_video) - .then_some((current.user_id, current.is_sharing_video)), - screen_changed: (previous.is_sharing_screen != current.is_sharing_screen) - .then_some((current.user_id, current.is_sharing_screen)), - speaking_changed: (previous.is_speaking != current.is_speaking) - .then_some((current.user_id, current.is_speaking)), - mute_changed: (previous.is_muted != current.is_muted) - .then_some((current.user_id, current.is_muted)), - ..Default::default() - }, - } -} - -fn broadcast_voice_event( - room: &HashMap>, - source_user_id: Uuid, - event: ServerEvent, -) { - for (peer_id, connections) in room { - if *peer_id == source_user_id { - continue; - } - for peer in connections.values() { - let _ = peer.tx.send(event.clone()); - } - } -} - -fn is_voice_state_change_empty(change: &VoiceStateChange) -> bool { - change.joined.is_none() - && change.left_user_id.is_none() - && change.video_changed.is_none() - && change.screen_changed.is_none() - && change.speaking_changed.is_none() - && change.mute_changed.is_none() -} - -#[cfg(test)] -mod tests { - use super::{VoiceHub, aggregate_participant}; - use std::collections::HashMap; - use tokio::sync::mpsc; - use uuid::Uuid; - - #[tokio::test] - async fn multiple_connections_keep_voice_participant_until_last_leave() { - let hub = VoiceHub::default(); - let room_id = Uuid::new_v4(); - let user_id = Uuid::new_v4(); - let first_connection = Uuid::new_v4(); - let second_connection = Uuid::new_v4(); - let (tx1, _rx1) = mpsc::unbounded_channel(); - let (tx2, _rx2) = mpsc::unbounded_channel(); - - let (_peers, first_join) = hub - .join(room_id, user_id, first_connection, "User".to_string(), tx1) - .await; - let (_peers, second_join) = hub - .join(room_id, user_id, second_connection, "User".to_string(), tx2) - .await; - let first_leave = hub.leave(room_id, user_id, first_connection).await; - let second_leave = hub.leave(room_id, user_id, second_connection).await; - - assert!(first_join.joined.is_some()); - assert!(second_join.joined.is_none()); - assert!(first_leave.left_user_id.is_none()); - assert_eq!(second_leave.left_user_id, Some(user_id)); - } - - #[tokio::test] - async fn voice_mute_state_only_flips_when_all_connections_are_muted() { - let hub = VoiceHub::default(); - let room_id = Uuid::new_v4(); - let user_id = Uuid::new_v4(); - let first_connection = Uuid::new_v4(); - let second_connection = Uuid::new_v4(); - let (tx1, _rx1) = mpsc::unbounded_channel(); - let (tx2, _rx2) = mpsc::unbounded_channel(); - - let _ = hub - .join(room_id, user_id, first_connection, "User".to_string(), tx1) - .await; - let _ = hub - .join(room_id, user_id, second_connection, "User".to_string(), tx2) - .await; - - let first_mute = hub - .set_mute_status(room_id, user_id, first_connection, true) - .await; - let second_mute = hub - .set_mute_status(room_id, user_id, second_connection, true) - .await; - let unmute = hub - .set_mute_status(room_id, user_id, first_connection, false) - .await; - - assert!(first_mute.mute_changed.is_none()); - assert_eq!(second_mute.mute_changed, Some((user_id, true))); - assert_eq!(unmute.mute_changed, Some((user_id, false))); - } - - #[test] - fn aggregate_participant_combines_connection_state() { - let user_id = Uuid::new_v4(); - let first_connection = Uuid::new_v4(); - let second_connection = Uuid::new_v4(); - let mut connections = HashMap::new(); - let (tx1, _rx1) = mpsc::unbounded_channel(); - let (tx2, _rx2) = mpsc::unbounded_channel(); - - connections.insert( - first_connection, - super::ClientHandle { - display_name: "User".to_string(), - is_sharing_video: true, - is_sharing_screen: false, - is_speaking: false, - is_muted: true, - tx: tx1, - }, - ); - connections.insert( - second_connection, - super::ClientHandle { - display_name: "User".to_string(), - is_sharing_video: false, - is_sharing_screen: true, - is_speaking: true, - is_muted: false, - tx: tx2, - }, - ); - - let participant = aggregate_participant(Some(&connections), user_id).unwrap(); - assert!(participant.is_sharing_video); - assert!(participant.is_sharing_screen); - assert!(participant.is_speaking); - assert!(!participant.is_muted); - } + state.voice.leave(room_id, user_id).await; } diff --git a/static/app.js b/static/app.js index 2794dc8..9cb45e0 100644 --- a/static/app.js +++ b/static/app.js @@ -1 +1,978 @@ -import "./shared/app-core.js"; +const state = { + me: null, + guilds: [], + channels: [], + dmConversations: [], + members: [], + voicePresence: new Map(), + selectedGuildId: null, + selectedTextChannelId: null, + selectedDmUserId: null, + selectedDmDisplayName: null, + selectedVoiceChannelId: null, + voice: { + ws: null, + joinedChannelId: null, + localStream: null, + rawStream: null, + audioContext: null, + peerConnections: new Map(), + muted: false, + iceServers: [{ urls: "stun:stun.l.google.com:19302" }], + }, + voicePresencePollId: null, + chatWs: null, + lastMessageId: null, + onlineUsers: new Set(), +}; + +const el = { + authScreen: document.getElementById("auth-screen"), + loginBtn: document.getElementById("login-btn"), + main: document.getElementById("main"), + status: document.getElementById("status"), + + // Guilds + guildList: document.getElementById("guild-list"), + addGuildBtn: document.getElementById("add-guild-btn"), + guildTitle: document.getElementById("guild-title"), + createInviteBtn: document.getElementById("create-invite-btn"), + + // Channels + channelList: document.getElementById("channel-list"), + voiceChannelList: document.getElementById("voice-channel-list"), + addTextBtn: document.getElementById("add-text-btn"), + addVoiceBtn: document.getElementById("add-voice-btn"), + dmList: document.getElementById("dm-list"), + channelTitle: document.getElementById("channel-title"), + + // Messages + messageList: document.getElementById("message-list"), + messageForm: document.getElementById("message-form"), + messageBody: document.getElementById("message-body"), + + // User Panel + userName: document.getElementById("user-name"), + userAvatar: document.getElementById("user-avatar"), + logoutBtn: document.getElementById("logout-btn"), + + // Voice Connection + voiceConnection: document.getElementById("voice-connection"), + vcChannelName: document.getElementById("vc-channel-name"), + voiceMuteBtn: document.getElementById("voice-mute-btn"), + voiceLeaveBtn: document.getElementById("voice-leave-btn"), + + // Members + memberList: document.getElementById("member-list"), + + // Modals + modalContainer: document.getElementById("modal-container"), + guildForm: document.getElementById("guild-form"), + guildName: document.getElementById("guild-name"), + modalCancel: document.getElementById("modal-cancel"), + + channelModal: document.getElementById("channel-modal"), + channelForm: document.getElementById("channel-form"), + channelName: document.getElementById("channel-name"), + channelModalCancel: document.getElementById("channel-modal-cancel"), + + // Mobile + mobileMenuBtn: document.getElementById("mobile-menu-btn"), + mobileMembersBtn: document.getElementById("mobile-members-btn"), + overlay: document.getElementById("overlay"), + utilitySidebar: document.getElementById("utility-sidebar"), +}; + +// --- API Helpers --- + +async function api(path, options = {}) { + const res = await fetch(path, { + ...options, + headers: { + "content-type": "application/json", + ...(options.headers || {}), + }, + credentials: "same-origin", + }); + + if (!res.ok) { + let detail = "request failed"; + try { + const body = await res.json(); + detail = body.error || detail; + } catch { } + throw new Error(`${res.status}: ${detail}`); + } + + if (res.status === 204) return null; + return res.json(); +} + +// --- Utils --- + +function shortName(name) { + if (!name || typeof name !== 'string') return "?"; + const trimmed = name.trim(); + if (!trimmed) return "?"; + const words = trimmed.split(/\s+/).filter(w => w.length > 0).slice(0, 2); + if (words.length === 0) return "?"; + if (words.length === 1) return words[0].substring(0, 2).toUpperCase(); + return words.map((w) => w[0]?.toUpperCase() || "").join(""); +} + +function escapeHtml(s) { + if (s === null || s === undefined) return ""; + return String(s) + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); +} + +function formatDate(isoString) { + const d = new Date(isoString); + const now = new Date(); + const isToday = d.toDateString() === now.toDateString(); + + if (isToday) { + return `Today at ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`; + } + return d.toLocaleDateString(); +} + +let audioCtx = null; + +// Global interaction listener to unlock AudioContext (autoplay policy) +window.addEventListener('click', () => { + if (audioCtx && audioCtx.state === 'suspended') { + audioCtx.resume(); + } +}, { once: true }); + +function playSound(type) { + try { + if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)(); + if (audioCtx.state === 'suspended') audioCtx.resume(); + + const sounds = { + message: { freq: 880, type: 'sine', duration: 0.1, volume: 0.1 }, + dm: { freq: [660, 880], type: 'sine', duration: 0.15, volume: 0.1 }, + join: { freq: [440, 880], type: 'sine', duration: 0.2, volume: 0.1 }, + leave: { freq: [880, 440], type: 'sine', duration: 0.2, volume: 0.1 }, + 'peer-join': { freq: [660, 990], type: 'sine', duration: 0.15, volume: 0.05 }, + 'peer-leave': { freq: [990, 660], type: 'sine', duration: 0.15, volume: 0.05 }, + }; + + const s = sounds[type]; + if (!s) return; + + const osc = audioCtx.createOscillator(); + const gain = audioCtx.createGain(); + + osc.type = s.type; + if (Array.isArray(s.freq)) { + osc.frequency.setValueAtTime(s.freq[0], audioCtx.currentTime); + osc.frequency.exponentialRampToValueAtTime(s.freq[1], audioCtx.currentTime + s.duration); + } else { + osc.frequency.setValueAtTime(s.freq, audioCtx.currentTime); + } + + gain.gain.setValueAtTime(s.volume, audioCtx.currentTime); + gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + s.duration); + + osc.connect(gain); + gain.connect(audioCtx.destination); + + osc.start(); + osc.stop(audioCtx.currentTime + s.duration); + } catch (err) { + console.warn("playSound failed", err); + } +} +const LAST_GUILD_STORAGE_KEY = "chattz:lastGuildId"; + +// --- Renderers --- + +function renderGuilds() { + el.guildList.innerHTML = ""; + + for (const guild of state.guilds) { + const btn = document.createElement("button"); + btn.className = `guild-pill ${state.selectedGuildId === guild.id ? "active" : ""}`; + btn.title = guild.name; + btn.textContent = shortName(guild.name); + btn.onclick = async () => { + state.selectedGuildId = guild.id; + state.selectedTextChannelId = null; + state.selectedVoiceChannelId = null; + state.selectedDmUserId = null; + state.selectedDmDisplayName = null; + localStorage.setItem(LAST_GUILD_STORAGE_KEY, guild.id); + renderGuilds(); + renderDMs(); + await loadChannels(); + await loadGuildMembers(); + await refreshVoicePresence(); + startVoicePresencePolling(); + renderMessages([]); + updateHeaderLabels(); + }; + el.guildList.appendChild(btn); + } +} + +function renderChannels() { + el.channelList.innerHTML = ""; + el.voiceChannelList.innerHTML = ""; + + for (const channel of state.channels) { + const row = document.createElement("button"); + row.className = `channel-row ${(channel.kind === 'text' && state.selectedTextChannelId === channel.id) || + (channel.kind === 'voice' && state.selectedVoiceChannelId === channel.id) ? "active" : "" + }`; + + const iconName = channel.kind === 'text' ? 'hash' : 'volume-2'; + row.innerHTML = ` ${escapeHtml(channel.name)}`; + + row.onclick = async () => { + if (channel.kind === 'text') { + state.selectedDmUserId = null; + state.selectedDmDisplayName = null; + state.selectedTextChannelId = channel.id; + renderChannels(); + renderDMs(); + updateHeaderLabels(); + const messages = await api(`/channels/${channel.id}/messages?limit=100`); + renderMessages(messages); + } else { + state.selectedDmUserId = null; + state.selectedDmDisplayName = null; + state.selectedVoiceChannelId = channel.id; + renderChannels(); + renderDMs(); + joinVoice(); + } + if (window.innerWidth <= 768) closeMobileMenus(); + }; + + if (channel.kind === 'text') { + el.channelList.appendChild(row); + } else { + el.voiceChannelList.appendChild(row); + + const participants = state.voicePresence.get(channel.id) || []; + if (participants.length > 0) { + const pList = document.createElement("div"); + pList.className = "voice-row-members channel-list"; + pList.style.paddingLeft = "24px"; + for (const p of participants) { + const pRow = document.createElement("div"); + pRow.className = "channel-row"; + pRow.style.padding = "2px 8px"; + pRow.innerHTML = `
${shortName(p.display_name)}
${escapeHtml(p.display_name)}`; + pList.appendChild(pRow); + } + el.voiceChannelList.appendChild(pList); + } + } + } + lucide.createIcons(); +} + +function renderDMs() { + el.dmList.innerHTML = ""; + for (const dm of state.dmConversations) { + const isOnline = state.onlineUsers.has(dm.user_id); + const row = document.createElement("button"); + row.className = `channel-row ${state.selectedDmUserId === dm.user_id ? "active" : ""}`; + row.innerHTML = ` +
+ +
+
+ ${escapeHtml(dm.display_name)} + `; + row.onclick = async () => { + state.selectedDmUserId = dm.user_id; + state.selectedDmDisplayName = dm.display_name; + state.selectedTextChannelId = null; + state.selectedVoiceChannelId = null; + renderChannels(); + renderDMs(); + updateHeaderLabels(); + const messages = await api(`/dms/${dm.user_id}/messages?limit=100`); + renderMessages(messages); + }; + el.dmList.appendChild(row); + } + + lucide.createIcons(); +} + +function renderMessages(messages) { + el.messageList.innerHTML = ""; + let lastAuthorId = null; + let lastTime = null; + + for (const m of messages.slice().reverse()) { + const row = document.createElement("div"); + const mDate = new Date(m.created_at); + const isGrouped = lastAuthorId === m.author_user_id && + lastTime && (mDate - lastTime < 300000); // 5 minutes + + row.className = `msg ${isGrouped ? "msg-grouped" : ""}`; + + const displayName = m.author_display_name || "Unknown User"; + + if (isGrouped) { + row.innerHTML = `
${escapeHtml(m.body)}
`; + } else { + row.innerHTML = ` +
${shortName(displayName)}
+
+
+ ${escapeHtml(displayName)} + ${formatDate(m.created_at)} +
+
${escapeHtml(m.body)}
+
+ `; + } + el.messageList.appendChild(row); + lastAuthorId = m.author_user_id; + lastTime = mDate; + } + + if (messages.length > 0) { + state.lastMessageId = messages[0].id; + } + + el.messageList.scrollTop = el.messageList.scrollHeight; +} + +function renderMembers() { + el.memberList.innerHTML = ""; + for (const m of state.members) { + const isOnline = state.onlineUsers.has(m.id); + const row = document.createElement("div"); + row.className = "member-row"; + row.innerHTML = ` +
+ ${shortName(m.display_name)} +
+
+
${escapeHtml(m.display_name)}
+ `; + row.style.cursor = "pointer"; + row.onclick = async () => { + if (state.me && m.id === state.me.id) return; + state.selectedDmUserId = m.id; + state.selectedDmDisplayName = m.display_name; + state.selectedTextChannelId = null; + state.selectedVoiceChannelId = null; + renderChannels(); + renderDMs(); + updateHeaderLabels(); + const messages = await api(`/dms/${m.id}/messages?limit=100`); + renderMessages(messages); + }; + el.memberList.appendChild(row); + } +} + +function updateHeaderLabels() { + const guild = state.guilds.find((g) => g.id === state.selectedGuildId); + el.guildTitle.textContent = guild ? guild.name : "No server selected"; + + if (state.selectedDmUserId) { + const dmFromConversations = state.dmConversations.find((u) => u.user_id === state.selectedDmUserId); + const dmFromMembers = state.members.find((m) => m.id === state.selectedDmUserId); + const displayName = dmFromConversations?.display_name || dmFromMembers?.display_name || state.selectedDmDisplayName; + const dmName = displayName ? `@${displayName}` : "Direct Message"; + el.channelTitle.textContent = dmName; + el.messageBody.placeholder = displayName + ? `Message @${displayName}` + : "Message"; + return; + } + + const channel = state.channels.find((c) => c.id === state.selectedTextChannelId); + el.channelTitle.textContent = channel ? channel.name : "Select a channel"; + el.messageBody.placeholder = channel ? `Message #${channel.name}` : "Select a channel"; +} + +async function createInviteLink() { + if (!state.selectedGuildId) { + alert("Select a server first."); + return; + } + try { + const invite = await api(`/guilds/${state.selectedGuildId}/invites`, { + method: "POST", + body: JSON.stringify({ max_uses: 50, expires_in_hours: 24 }), + }); + const link = `${location.origin}/?invite=${encodeURIComponent(invite.code)}`; + try { + await navigator.clipboard.writeText(link); + alert(`Invite link copied:\n${link}`); + } catch { + prompt("Copy invite link:", link); + } + } catch (err) { + alert(err.message); + } +} + +// --- Logic --- + +async function loadGuilds() { + state.guilds = await api("/guilds"); + renderGuilds(); +} + +async function loadDMConversations() { + state.dmConversations = await api("/dms"); + renderDMs(); +} + +async function loadGuildMembers() { + if (!state.selectedGuildId) { + state.members = []; + renderMembers(); + return; + } + state.members = await api(`/guilds/${state.selectedGuildId}/members`); + renderMembers(); +} + +async function loadChannels() { + if (!state.selectedGuildId) { + state.channels = []; + renderChannels(); + return; + } + + state.channels = await api(`/guilds/${state.selectedGuildId}/channels`); + renderChannels(); +} + +async function refreshVoicePresence() { + if (!state.selectedGuildId) { + state.voicePresence.clear(); + renderChannels(); + return; + } + + try { + const res = await api(`/guilds/${state.selectedGuildId}/voice-presence`); + state.voicePresence.clear(); + for (const entry of res.channels || []) { + state.voicePresence.set(entry.channel_id, entry.participants || []); + } + renderChannels(); + } catch (err) { + console.warn("voice presence failed", err); + } +} + +function startVoicePresencePolling() { + if (state.voicePresencePollId) clearInterval(state.voicePresencePollId); + state.voicePresencePollId = setInterval(() => { + refreshVoicePresence().catch(() => { }); + }, 3000); +} + +function initChatWs() { + if (state.chatWs) state.chatWs.close(); + const protocol = location.protocol === "https:" ? "wss:" : "ws:"; + const wsUrl = `${protocol}//${location.host}/ws`; + const ws = new WebSocket(wsUrl); + state.chatWs = ws; + + ws.onmessage = (event) => { + const msg = JSON.parse(event.data); + const authorId = msg.message?.author_user_id; + const isFromMe = authorId && state.me && authorId === state.me.id; + + if (msg.type === "message_created") { + if (!isFromMe) playSound('message'); + if (state.selectedTextChannelId === msg.channel_id) { + api(`/channels/${state.selectedTextChannelId}/messages?limit=100`).then(renderMessages); + } + } else if (msg.type === "dm_created") { + if (!isFromMe) playSound('dm'); + if (state.selectedDmUserId === msg.other_user_id) { + api(`/dms/${state.selectedDmUserId}/messages?limit=100`).then(renderMessages); + playSound('dm'); + loadDMConversations().then(renderDMs); + } else { + loadDMConversations().then(renderDMs); + } + } else if (msg.type === "user_presence") { + if (msg.online) { + state.onlineUsers.add(msg.user_id); + } else { + state.onlineUsers.delete(msg.user_id); + } + renderMembers(); + renderDMs(); + } + }; + + ws.onclose = () => { + console.log("Chat WS closed, reconnecting..."); + setTimeout(initChatWs, 3000); + }; +} + +// --- Voice --- + +function getVoiceWsUrl(channelId) { + const proto = location.protocol === "https:" ? "wss" : "ws"; + return `${proto}://${location.host}/channels/${channelId}/voice/ws`; +} + +function shouldInitiateOffer(peerId) { + if (!state.me || !state.me.id) return false; + return state.me.id > peerId; +} + +function stopAndClearAudioPipeline() { + if (state.voice.localStream) { + for (const track of state.voice.localStream.getTracks()) track.stop(); + } + if (state.voice.rawStream && state.voice.rawStream !== state.voice.localStream) { + for (const track of state.voice.rawStream.getTracks()) track.stop(); + } + if (state.voice.audioContext) { + state.voice.audioContext.close().catch(() => { }); + } + state.voice.localStream = null; + state.voice.rawStream = null; + state.voice.audioContext = null; +} + +async function buildAudioPipeline(rawStream) { + const audioContext = new AudioContext(); + const source = audioContext.createMediaStreamSource(rawStream); + const destination = audioContext.createMediaStreamDestination(); + state.voice.audioContext = audioContext; + + let head = source; + + head.connect(destination); + + return destination.stream; +} + +async function createLocalVoiceStream() { + const constraints = { + audio: { + channelCount: 1, + sampleRate: 48000, + echoCancellation: true, + noiseSuppression: true, + autoGainControl: false, + }, + video: false, + }; + const rawStream = await navigator.mediaDevices.getUserMedia(constraints); + const localStream = await buildAudioPipeline(rawStream); + state.voice.rawStream = rawStream; + state.voice.localStream = localStream; + if (state.voice.muted) { + state.voice.localStream.getAudioTracks().forEach((t) => { + t.enabled = false; + }); + } +} + +function ensurePeerConnection(peerId) { + if (state.voice.peerConnections.has(peerId)) { + return state.voice.peerConnections.get(peerId); + } + + const pc = new RTCPeerConnection({ iceServers: state.voice.iceServers }); + + if (state.voice.localStream) { + for (const track of state.voice.localStream.getTracks()) { + pc.addTrack(track, state.voice.localStream); + } + } + + pc.onicecandidate = (event) => { + if (!event.candidate || !state.voice.ws) return; + state.voice.ws.send(JSON.stringify({ + type: "signal", + to_user_id: peerId, + kind: "ice", + data: event.candidate, + })); + }; + + pc.ontrack = (event) => { + let audio = document.getElementById(`audio-${peerId}`); + if (!audio) { + audio = document.createElement("audio"); + audio.id = `audio-${peerId}`; + audio.autoplay = true; + audio.playsInline = true; + document.body.appendChild(audio); + } + audio.srcObject = event.streams[0]; + }; + + state.voice.peerConnections.set(peerId, pc); + return pc; +} + +async function sendOffer(peerId) { + const pc = ensurePeerConnection(peerId); + const offer = await pc.createOffer(); + await pc.setLocalDescription(offer); + state.voice.ws.send(JSON.stringify({ + type: "signal", + to_user_id: peerId, + kind: "offer", + data: offer, + })); +} + +async function handleSignal(fromPeerId, kind, data) { + const pc = ensurePeerConnection(fromPeerId); + + if (kind === "offer") { + await pc.setRemoteDescription(new RTCSessionDescription(data)); + const answer = await pc.createAnswer(); + await pc.setLocalDescription(answer); + state.voice.ws.send(JSON.stringify({ + type: "signal", + to_user_id: fromPeerId, + kind: "answer", + data: answer, + })); + } else if (kind === "answer") { + await pc.setRemoteDescription(new RTCSessionDescription(data)); + } else if (kind === "ice") { + try { + await pc.addIceCandidate(data ? new RTCIceCandidate(data) : null); + } catch (err) { + console.warn("failed to add ice candidate", err); + } + } +} + +async function joinVoice() { + if (!state.selectedVoiceChannelId) return; + if (state.voice.joinedChannelId === state.selectedVoiceChannelId) return; + + await leaveVoice(); + + try { + await createLocalVoiceStream(); + } catch (err) { + console.error("microphone denied", err); + return; + } + + const ws = new WebSocket(getVoiceWsUrl(state.selectedVoiceChannelId)); + state.voice.ws = ws; + state.voice.joinedChannelId = state.selectedVoiceChannelId; + + ws.onopen = () => { + const channel = state.channels.find(c => c.id === state.selectedVoiceChannelId); + el.vcChannelName.textContent = channel ? channel.name : "Voice"; + el.voiceConnection.classList.remove("hidden"); + playSound('join'); + refreshVoicePresence().catch(() => { }); + }; + + ws.onmessage = async (event) => { + const msg = JSON.parse(event.data); + if (msg.type === "peers") { + for (const peer of msg.peers) { + if (shouldInitiateOffer(peer.user_id)) await sendOffer(peer.user_id); + } + } else if (msg.type === "peer_joined") { + playSound('peer-join'); + if (shouldInitiateOffer(msg.user_id)) await sendOffer(msg.user_id); + } else if (msg.type === "peer_left") { + playSound('peer-leave'); + const pc = state.voice.peerConnections.get(msg.user_id); + if (pc) { + pc.close(); + state.voice.peerConnections.delete(msg.user_id); + } + document.getElementById(`audio-${msg.user_id}`)?.remove(); + } else if (msg.type === "signal") { + await handleSignal(msg.from_user_id, msg.kind, msg.data); + } + refreshVoicePresence().catch(() => { }); + }; + + ws.onclose = () => { + el.voiceConnection.classList.add("hidden"); + for (const pc of state.voice.peerConnections.values()) pc.close(); + state.voice.peerConnections.clear(); + stopAndClearAudioPipeline(); + state.voice.joinedChannelId = null; + state.voice.ws = null; + playSound('leave'); + refreshVoicePresence().catch(() => { }); + }; +} + +async function leaveVoice() { + if (state.voice.ws) state.voice.ws.close(); +} + +function toggleMute() { + if (!state.voice.localStream) return; + state.voice.muted = !state.voice.muted; + state.voice.localStream.getAudioTracks().forEach((t) => { + t.enabled = !state.voice.muted; + }); + el.voiceMuteBtn.innerHTML = state.voice.muted ? '' : ''; + el.voiceMuteBtn.style.color = state.voice.muted ? 'var(--danger)' : 'var(--text-muted)'; + lucide.createIcons(); +} + +// --- Mobile Logic --- + +function toggleMobileMenu() { + const isOpen = el.main.classList.contains("menu-open"); + if (isOpen) { + el.main.classList.remove("menu-open"); + el.overlay.classList.add("hidden"); + } else { + el.main.classList.add("menu-open"); + el.utilitySidebar.classList.remove("active"); // close members if open + el.overlay.classList.remove("hidden"); + } +} + +function toggleMobileMembers() { + const isOpen = el.utilitySidebar.classList.contains("active"); + if (isOpen) { + el.utilitySidebar.classList.remove("active"); + el.overlay.classList.add("hidden"); + } else { + el.utilitySidebar.classList.add("active"); + el.main.classList.remove("menu-open"); // close menu if open + el.overlay.classList.remove("hidden"); + } +} + +function closeMobileMenus() { + el.main.classList.remove("menu-open"); + el.utilitySidebar.classList.remove("active"); + el.overlay.classList.add("hidden"); +} + +// --- Initialization --- + +async function init() { + lucide.createIcons(); + + el.loginBtn.onclick = () => { location.href = "/auth/login"; }; + + el.logoutBtn.onclick = async () => { + await leaveVoice(); + await api("/auth/logout", { method: "POST" }); + location.reload(); + }; + + el.addGuildBtn.onclick = () => { el.modalContainer.classList.remove("hidden"); }; + el.createInviteBtn.onclick = createInviteLink; + el.modalCancel.onclick = () => { el.modalContainer.classList.add("hidden"); }; + + el.addTextBtn.onclick = () => { + if (!state.selectedGuildId) { + alert("Create or select a server first."); + return; + } + document.querySelector('input[name="channel-kind"][value="text"]').checked = true; + el.channelModal.classList.remove("hidden"); + }; + el.addVoiceBtn.onclick = () => { + if (!state.selectedGuildId) { + alert("Create or select a server first."); + return; + } + document.querySelector('input[name="channel-kind"][value="voice"]').checked = true; + el.channelModal.classList.remove("hidden"); + }; + el.channelModalCancel.onclick = () => { el.channelModal.classList.add("hidden"); }; + + // Mobile Listeners + if (el.mobileMenuBtn) el.mobileMenuBtn.onclick = toggleMobileMenu; + if (el.mobileMembersBtn) el.mobileMembersBtn.onclick = toggleMobileMembers; + if (el.overlay) el.overlay.onclick = closeMobileMenus; + + el.guildForm.onsubmit = async (e) => { + e.preventDefault(); + try { + const guild = await api("/guilds", { + method: "POST", + body: JSON.stringify({ name: el.guildName.value }), + }); + el.guildName.value = ""; + el.modalContainer.classList.add("hidden"); + state.guilds.push(guild); + state.selectedGuildId = guild.id; + state.selectedTextChannelId = null; + state.selectedVoiceChannelId = null; + state.selectedDmUserId = null; + state.selectedDmDisplayName = null; + localStorage.setItem(LAST_GUILD_STORAGE_KEY, guild.id); + renderGuilds(); + await loadChannels(); + await loadGuildMembers(); + await refreshVoicePresence(); + renderMessages([]); + updateHeaderLabels(); + } catch (err) { alert(err.message); } + }; + + el.channelForm.onsubmit = async (e) => { + e.preventDefault(); + if (!state.selectedGuildId) { + alert("Select a server first."); + return; + } + const kindInput = document.querySelector('input[name="channel-kind"]:checked'); + const kind = kindInput ? kindInput.value : "text"; + const channelName = el.channelName.value.trim(); + if (!channelName) { + alert("Channel name is required."); + return; + } + try { + const created = await api("/channels", { + method: "POST", + body: JSON.stringify({ + guild_id: state.selectedGuildId, + name: channelName, + kind: kind, + }), + }); + el.channelName.value = ""; + el.channelModal.classList.add("hidden"); + await loadChannels(); + if (created.kind === "text") { + state.selectedTextChannelId = created.id; + state.selectedVoiceChannelId = null; + state.selectedDmUserId = null; + state.selectedDmDisplayName = null; + renderChannels(); + renderDMs(); + updateHeaderLabels(); + const messages = await api(`/channels/${created.id}/messages?limit=100`); + renderMessages(messages); + } else { + state.selectedVoiceChannelId = created.id; + state.selectedTextChannelId = null; + state.selectedDmUserId = null; + state.selectedDmDisplayName = null; + renderChannels(); + renderDMs(); + updateHeaderLabels(); + } + } catch (err) { alert(err.message); } + }; + + el.messageForm.onsubmit = async (e) => { + e.preventDefault(); + const body = el.messageBody.value.trim(); + if (!body) return; + + try { + if (state.selectedTextChannelId) { + await api(`/channels/${state.selectedTextChannelId}/messages`, { + method: "POST", + body: JSON.stringify({ body }), + }); + } else if (state.selectedDmUserId) { + await api(`/dms/${state.selectedDmUserId}/messages`, { + method: "POST", + body: JSON.stringify({ body }), + }); + } else { + return; + } + el.messageBody.value = ""; + const messages = state.selectedTextChannelId + ? await api(`/channels/${state.selectedTextChannelId}/messages?limit=100`) + : await api(`/dms/${state.selectedDmUserId}/messages?limit=100`); + renderMessages(messages); + await loadDMConversations(); + renderDMs(); + } catch (err) { alert(err.message); } + }; + + el.voiceMuteBtn.onclick = toggleMute; + el.voiceLeaveBtn.onclick = leaveVoice; + + try { + state.me = await api("/me"); + if (state.me && state.me.display_name) { + el.userName.textContent = state.me.display_name; + el.userAvatar.textContent = shortName(state.me.display_name); + } + el.authScreen.classList.add("hidden"); + el.main.classList.remove("hidden"); + + const params = new URLSearchParams(location.search); + const inviteCode = params.get("invite"); + if (inviteCode) { + try { + const joinedGuild = await api(`/invites/${encodeURIComponent(inviteCode)}/join`, { + method: "POST", + }); + localStorage.setItem(LAST_GUILD_STORAGE_KEY, joinedGuild.id); + } catch (err) { + alert(`Failed to join invite: ${err.message}`); + } finally { + params.delete("invite"); + const nextQuery = params.toString(); + const nextUrl = `${location.pathname}${nextQuery ? `?${nextQuery}` : ""}`; + history.replaceState(null, "", nextUrl); + } + } + + await loadGuilds(); + await loadDMConversations(); + + try { + const online = await api("/presence"); + state.onlineUsers = new Set(online); + } catch (err) { console.warn("presence sync failed", err); } + + if (state.guilds.length > 0) { + const lastGuildId = localStorage.getItem(LAST_GUILD_STORAGE_KEY); + const guild = state.guilds.find((g) => g.id === lastGuildId) || state.guilds[0]; + state.selectedGuildId = guild.id; + localStorage.setItem(LAST_GUILD_STORAGE_KEY, guild.id); + renderGuilds(); + await loadChannels(); + await loadGuildMembers(); + await refreshVoicePresence(); + updateHeaderLabels(); + } else { + state.members = []; + renderMembers(); + updateHeaderLabels(); + } + + initChatWs(); + startVoicePresencePolling(); + lucide.createIcons(); + } catch (err) { + console.error("init failed", err); + el.authScreen.classList.remove("hidden"); + el.main.classList.add("hidden"); + } +} + +init(); diff --git a/static/index.html b/static/index.html index 550c656..7a2a85f 100644 --- a/static/index.html +++ b/static/index.html @@ -1,4 +1,3 @@ - @@ -8,7 +7,7 @@ Chattz - + @@ -18,11 +17,6 @@

Chattz

Sign in to open your servers.

-
- Desktop downloads: - Windows - Linux (RPM) -

@@ -43,7 +37,6 @@ -
- - -
@@ -172,24 +144,6 @@ - - - - - - + - + \ No newline at end of file diff --git a/static/shared/app-core.js b/static/shared/app-core.js deleted file mode 100644 index 8531b48..0000000 --- a/static/shared/app-core.js +++ /dev/null @@ -1,2405 +0,0 @@ -const state = { - sessionActive: false, - me: null, - guilds: [], - channels: [], - dmConversations: [], - members: [], - voicePresence: new Map(), - selectedGuildId: null, - selectedTextChannelId: null, - selectedDmUserId: null, - selectedDmDisplayName: null, - selectedVoiceChannelId: null, - voice: { - ws: null, - joinedChannelId: null, - localStream: null, - rawStream: null, - videoStream: null, - screenStream: null, - peerConnections: new Map(), - videoSenders: new Map(), - screenSenders: new Map(), - muted: false, - sharingVideo: false, - sharingScreen: false, - deepFilterProcessor: null, - deepFilterModule: null, - viewMode: 'chat', // 'chat' or 'video' - iceServers: [{ urls: "stun:stun.l.google.com:19302" }], - peerGainNodes: new Map(), // userId -> GainNode - peerAudioNodes: new Map(), // userId -> { sourceNode, compressorNode, gainNode } - visibleVolumeSliders: new Set(), // userIds whose sliders are visible - }, - voicePresencePollId: null, - chatWs: null, - lastMessageId: null, - onlineUsers: new Set(), - idleUsers: new Set(), - userVolumes: new Map(), // userId -> volume (0.0 to 2.0) -}; - -// --- Storage --- -const LAST_GUILD_STORAGE_KEY = "chattz:lastGuildId"; - -function storageGet(key) { - return localStorage.getItem(key); -} - -function storageSet(key, value) { - localStorage.setItem(key, value); -} - -function storageRemove(key) { - localStorage.removeItem(key); -} - -function getWsUrl(path) { - const proto = location.protocol === "https:" ? "wss" : "ws"; - return `${proto}://${location.host}${path}`; -} - - - - - - -const el = { - authScreen: document.getElementById("auth-screen"), - loginBtn: document.getElementById("login-btn"), - main: document.getElementById("main"), - status: document.getElementById("status"), - - // Guilds - guildList: document.getElementById("guild-list"), - addGuildBtn: document.getElementById("add-guild-btn"), - guildTitle: document.getElementById("guild-title"), - createInviteBtn: document.getElementById("create-invite-btn"), - inviteCopiedBadge: document.getElementById("invite-copied-badge"), - - // Channels - channelList: document.getElementById("channel-list"), - voiceChannelList: document.getElementById("voice-channel-list"), - addTextBtn: document.getElementById("add-text-btn"), - addVoiceBtn: document.getElementById("add-voice-btn"), - dmList: document.getElementById("dm-list"), - channelTitle: document.getElementById("channel-title"), - - // Messages - messageList: document.getElementById("message-list"), - messageForm: document.getElementById("message-form"), - messageBody: document.getElementById("message-body"), - mediaUploadBtn: document.getElementById("media-upload-btn"), - mediaFileInput: document.getElementById("media-file-input"), - - // User Panel - userName: document.getElementById("user-name"), - userAvatar: document.getElementById("user-avatar"), - logoutBtn: document.getElementById("logout-btn"), - updateNotifier: document.getElementById("update-notifier"), - updateDownloadBtn: document.getElementById("update-download-btn"), - updateInstallBtn: document.getElementById("update-install-btn"), - - // Voice Connection - voiceConnection: document.getElementById("voice-connection"), - vcChannelName: document.getElementById("vc-channel-name"), - voiceVideoBtn: document.getElementById("voice-video-btn"), - voiceScreenBtn: document.getElementById("voice-screen-btn"), - voiceMuteBtn: document.getElementById("voice-mute-btn"), - voiceLeaveBtn: document.getElementById("voice-leave-btn"), - videoGrid: document.getElementById("video-grid"), - messageForm: document.getElementById("message-form"), - messageInputWrapper: document.querySelector(".chat-input-wrapper"), - - // Members - memberList: document.getElementById("member-list"), - - // Modals - modalContainer: document.getElementById("modal-container"), - guildForm: document.getElementById("guild-form"), - guildName: document.getElementById("guild-name"), - modalCancel: document.getElementById("modal-cancel"), - - channelModal: document.getElementById("channel-modal"), - channelForm: document.getElementById("channel-form"), - channelName: document.getElementById("channel-name"), - channelModalCancel: document.getElementById("channel-modal-cancel"), - - // Sound Board - soundboard: document.getElementById('soundboard'), - soundboardGrid: document.getElementById('soundboard-grid'), - addSoundBtn: document.getElementById('add-sound-btn'), - soundModal: document.getElementById('sound-modal'), - soundForm: document.getElementById('sound-form'), - soundName: document.getElementById('sound-name'), - soundIcon: document.getElementById('sound-icon'), - soundFile: document.getElementById('sound-file'), - soundModalCancel: document.getElementById('sound-modal-cancel'), - soundSubmitBtn: document.getElementById('sound-submit-btn'), - uploadLimitModal: document.getElementById('upload-limit-modal'), - uploadLimitMessage: document.getElementById('upload-limit-message'), - uploadLimitOk: document.getElementById('upload-limit-ok'), - - // Mobile - mobileMenuBtn: document.getElementById("mobile-menu-btn"), - mobileMembersBtn: document.getElementById("mobile-members-btn"), - overlay: document.getElementById("overlay"), - utilitySidebar: document.getElementById("utility-sidebar"), - - // GIF Picker - gifBtn: document.getElementById("gif-btn"), - gifPicker: document.getElementById("gif-picker"), - gifPickerClose: document.getElementById("gif-picker-close"), - gifSearchInput: document.getElementById("gif-search-input"), - gifResults: document.getElementById("gif-results"), -}; - -function stopVoicePresencePolling() { - if (!state.voicePresencePollId) return; - clearInterval(state.voicePresencePollId); - state.voicePresencePollId = null; -} - -function closeChatWs() { - if (!state.chatWs) return; - const ws = state.chatWs; - state.chatWs = null; - ws.onclose = null; - ws.onmessage = null; - ws.onerror = null; - try { - ws.close(); - } catch { } -} - -async function showLoggedOutState(message = "Session expired, please log in again") { - state.sessionActive = false; - stopVoicePresencePolling(); - closeChatWs(); - await leaveVoice(); - - state.me = null; - state.guilds = []; - state.channels = []; - state.dmConversations = []; - state.members = []; - state.voicePresence.clear(); - state.selectedGuildId = null; - state.selectedTextChannelId = null; - state.selectedDmUserId = null; - state.selectedDmDisplayName = null; - state.selectedVoiceChannelId = null; - state.lastMessageId = null; - state.onlineUsers.clear(); - state.idleUsers.clear(); - state.userVolumes.clear(); - state.voice.viewMode = 'chat'; - - el.userName.textContent = "Username"; - el.userAvatar.textContent = "U"; - el.status.textContent = message; - el.soundboard.classList.add("hidden"); - el.voiceConnection.classList.add("hidden"); - renderGuilds(); - renderChannels(); - renderDMs(); - renderMembers(); - renderMessages([]); - updateHeaderLabels(); - el.main.classList.add("hidden"); - el.authScreen.classList.remove("hidden"); -} - -// --- API Helpers --- - -async function api(path, options = {}) { - const headers = { - ...(options.headers || {}), - }; - if (!headers["content-type"] && options.body && !(options.body instanceof FormData)) { - headers["content-type"] = "application/json"; - } - - const res = await fetch(path, { - ...options, - headers, - credentials: "same-origin", - }); - - if (res.status === 401) { - await showLoggedOutState("Session expired, please log in again"); - const err = new Error("Session expired, please log in again"); - err.isAuthError = true; - throw err; - } - - if (!res.ok) { - let detail = "request failed"; - try { - const body = await res.json(); - detail = body.error || detail; - } catch { } - throw new Error(`${res.status}: ${detail}`); - } - - if (res.status === 204) return null; - return res.json(); -} - -// --- Utils --- - -function shortName(name) { - if (!name || typeof name !== 'string') return "?"; - const trimmed = name.trim(); - if (!trimmed) return "?"; - const words = trimmed.split(/\s+/).filter(w => w.length > 0).slice(0, 2); - if (words.length === 0) return "?"; - if (words.length === 1) return words[0].substring(0, 2).toUpperCase(); - return words.map((w) => w[0]?.toUpperCase() || "").join(""); -} - -function escapeHtml(s) { - if (s === null || s === undefined) return ""; - return String(s) - .replaceAll("&", "&") - .replaceAll("<", "<") - .replaceAll(">", ">") - .replaceAll('"', """) - .replaceAll("'", "'"); -} - -const GIF_URL_REGEX = /(https?:\/\/[^\s]+(?:\.gif|\/giphy\.gif)[^\s]*)/gi; - -function normalizeMediaUrl(raw) { - try { - const url = new URL(raw, location.origin); - if (url.protocol !== "http:" && url.protocol !== "https:") { - return null; - } - return url.href; - } catch { - return null; - } -} - -function formatBytes(size) { - if (!Number.isFinite(size) || size < 1024) return `${size || 0} B`; - const units = ["KB", "MB", "GB"]; - let value = size; - let unitIndex = -1; - while (value >= 1024 && unitIndex < units.length - 1) { - value /= 1024; - unitIndex += 1; - } - return `${value.toFixed(value >= 10 || unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`; -} - -const MAX_MEDIA_UPLOAD_BYTES = 50 * 1024 * 1024; - -function buildMessageBody(body) { - const fragment = document.createDocumentFragment(); - const text = String(body || ""); - let cursor = 0; - - for (const match of text.matchAll(new RegExp(GIF_URL_REGEX))) { - const [rawUrl] = match; - const start = match.index ?? 0; - if (start > cursor) { - fragment.appendChild(document.createTextNode(text.slice(cursor, start))); - } - - const safeUrl = normalizeMediaUrl(rawUrl); - if (safeUrl) { - const gifWrap = document.createElement("div"); - gifWrap.className = "msg-gif"; - - const image = document.createElement("img"); - image.loading = "lazy"; - image.src = safeUrl; - gifWrap.appendChild(image); - fragment.appendChild(gifWrap); - } else { - fragment.appendChild(document.createTextNode(rawUrl)); - } - - cursor = start + rawUrl.length; - } - - if (cursor < text.length) { - fragment.appendChild(document.createTextNode(text.slice(cursor))); - } - - return fragment; -} - -function buildAttachments(attachments = []) { - const fragment = document.createDocumentFragment(); - - for (const attachment of attachments) { - const safeUrl = normalizeMediaUrl(attachment.media_url); - if (!safeUrl) continue; - - const mime = attachment.mime_type || "application/octet-stream"; - const fileName = attachment.original_filename || "file"; - const size = formatBytes(attachment.size_bytes); - - if (mime.startsWith("image/")) { - const link = document.createElement("a"); - link.className = "msg-attachment msg-attachment-image"; - link.href = safeUrl; - link.target = "_blank"; - link.rel = "noopener noreferrer"; - - const image = document.createElement("img"); - image.src = safeUrl; - image.alt = fileName; - image.loading = "lazy"; - link.appendChild(image); - fragment.appendChild(link); - continue; - } - - if (mime.startsWith("video/")) { - const wrapper = document.createElement("div"); - wrapper.className = "msg-attachment msg-attachment-video"; - - const video = document.createElement("video"); - video.controls = true; - video.preload = "metadata"; - video.src = safeUrl; - wrapper.appendChild(video); - fragment.appendChild(wrapper); - continue; - } - - if (mime.startsWith("audio/")) { - const wrapper = document.createElement("div"); - wrapper.className = "msg-attachment msg-attachment-audio"; - - const audio = document.createElement("audio"); - audio.controls = true; - audio.preload = "metadata"; - audio.src = safeUrl; - wrapper.appendChild(audio); - - const link = document.createElement("a"); - link.href = safeUrl; - link.target = "_blank"; - link.rel = "noopener noreferrer"; - link.textContent = fileName; - wrapper.appendChild(link); - - fragment.appendChild(wrapper); - continue; - } - - const link = document.createElement("a"); - link.className = "msg-attachment msg-attachment-file"; - link.href = safeUrl; - link.target = "_blank"; - link.rel = "noopener noreferrer"; - - const icon = document.createElement("i"); - icon.setAttribute("data-lucide", "file"); - link.appendChild(icon); - - const name = document.createElement("span"); - name.textContent = fileName; - link.appendChild(name); - - const meta = document.createElement("small"); - meta.textContent = size; - link.appendChild(meta); - - fragment.appendChild(link); - } - - return fragment; -} - -function showMediaUploadLimitError(file) { - const selectedSize = formatBytes(file?.size || 0); - if (el.uploadLimitModal && el.uploadLimitMessage) { - el.uploadLimitMessage.textContent = `Uploads are limited to 50 MB per file. Selected file size: ${selectedSize}.`; - el.uploadLimitModal.classList.remove("hidden"); - return; - } - alert(`Uploads are limited to 50 MB per file.\nSelected file size: ${selectedSize}.`); -} - -function formatDate(isoString) { - const d = new Date(isoString); - const now = new Date(); - const isToday = d.toDateString() === now.toDateString(); - - if (isToday) { - return `Today at ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`; - } - return d.toLocaleDateString(); -} - -function scrollMessagesToBottom() { - if (!el.messageList) return; - el.messageList.scrollTop = el.messageList.scrollHeight; -} - -let audioCtx = null; - -// Global interaction listener to unlock AudioContext (autoplay policy) -window.addEventListener('click', () => { - if (audioCtx && audioCtx.state === 'suspended') { - audioCtx.resume(); - } -}, { once: true }); - -function playSound(type) { - try { - if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)(); - if (audioCtx.state === 'suspended') audioCtx.resume(); - - const sounds = { - message: { freq: 880, type: 'sine', duration: 0.1, volume: 0.1 }, - dm: { freq: [660, 880], type: 'sine', duration: 0.15, volume: 0.1 }, - join: { freq: [440, 880], type: 'sine', duration: 0.2, volume: 0.1 }, - leave: { freq: [880, 440], type: 'sine', duration: 0.2, volume: 0.1 }, - 'peer-join': { freq: [660, 990], type: 'sine', duration: 0.15, volume: 0.05 }, - 'peer-leave': { freq: [990, 660], type: 'sine', duration: 0.15, volume: 0.05 }, - }; - - const s = sounds[type]; - if (!s) return; - - const osc = audioCtx.createOscillator(); - const gain = audioCtx.createGain(); - - osc.type = s.type; - if (Array.isArray(s.freq)) { - osc.frequency.setValueAtTime(s.freq[0], audioCtx.currentTime); - osc.frequency.exponentialRampToValueAtTime(s.freq[1], audioCtx.currentTime + s.duration); - } else { - osc.frequency.setValueAtTime(s.freq, audioCtx.currentTime); - } - - gain.gain.setValueAtTime(s.volume, audioCtx.currentTime); - gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + s.duration); - - osc.connect(gain); - gain.connect(audioCtx.destination); - - osc.start(); - osc.stop(audioCtx.currentTime + s.duration); - } catch (err) { - console.warn("playSound failed", err); - } -} -// --- Renderers --- - -function renderGuilds() { - el.guildList.innerHTML = ""; - - for (const guild of state.guilds) { - const btn = document.createElement("button"); - btn.className = `guild-pill ${state.selectedGuildId === guild.id ? "active" : ""}`; - btn.title = guild.name; - btn.textContent = shortName(guild.name); - btn.onclick = async () => { - state.selectedGuildId = guild.id; - state.selectedTextChannelId = null; - state.selectedVoiceChannelId = null; - state.selectedDmUserId = null; - state.selectedDmDisplayName = null; - storageSet(LAST_GUILD_STORAGE_KEY, guild.id); - renderGuilds(); - renderDMs(); - await loadChannels(); - await loadGuildMembers(); - await refreshVoicePresence(); - startVoicePresencePolling(); - renderMessages([]); - updateHeaderLabels(); - }; - el.guildList.appendChild(btn); - } -} - -function renderChannels() { - el.channelList.innerHTML = ""; - el.voiceChannelList.innerHTML = ""; - - for (const channel of state.channels) { - const row = document.createElement("button"); - row.className = `channel-row ${(channel.kind === 'text' && state.selectedTextChannelId === channel.id) || - (channel.kind === 'voice' && state.selectedVoiceChannelId === channel.id) ? "active" : "" - }`; - - const iconName = channel.kind === 'text' ? 'hash' : 'volume-2'; - row.innerHTML = ` ${escapeHtml(channel.name)}`; - - row.onclick = async () => { - if (channel.kind === 'text') { - state.selectedDmUserId = null; - state.selectedDmDisplayName = null; - state.selectedTextChannelId = channel.id; - state.voice.viewMode = 'chat'; - renderChannels(); - renderDMs(); - updateView(); - updateHeaderLabels(); - const messages = await api(`/channels/${channel.id}/messages?limit=100`); - renderMessages(messages); - } else { - state.selectedVoiceChannelId = channel.id; - state.voice.viewMode = 'video'; - renderChannels(); - renderDMs(); - updateView(); - updateHeaderLabels(); - try { - await joinVoice(); - } catch (err) { - console.error("joinVoice failed from channel click", err); - alert(`Voice join failed: ${err?.message || err}`); - } - } - if (window.innerWidth <= 768) closeMobileMenus(); - }; - - if (channel.kind === 'text') { - el.channelList.appendChild(row); - } else { - el.voiceChannelList.appendChild(row); - - const participants = state.voicePresence.get(channel.id) || []; - if (participants.length > 0) { - const pList = document.createElement("div"); - pList.className = "voice-row-members channel-list"; - pList.style.paddingLeft = "24px"; - for (const p of participants) { - const pRow = document.createElement("div"); - pRow.className = `channel-row voice-participant-row ${p.is_speaking ? 'voice-speaking' : ''}`; - pRow.style.display = "block"; - pRow.style.padding = "2px 8px"; - pRow.style.flexWrap = "wrap"; - - const topRow = document.createElement("div"); - topRow.style.display = "flex"; - topRow.style.alignItems = "center"; - topRow.style.gap = "8px"; - topRow.style.width = "100%"; - - const avatar = document.createElement("div"); - avatar.className = "avatar"; - avatar.style.width = "20px"; - avatar.style.height = "20px"; - avatar.style.fontSize = "10px"; - avatar.textContent = shortName(p.display_name); - topRow.appendChild(avatar); - - const name = document.createElement("span"); - name.style.flex = "1"; - name.style.overflow = "hidden"; - name.style.textOverflow = "ellipsis"; - name.textContent = p.display_name; - topRow.appendChild(name); - - const isRemoteParticipant = p.user_id !== state.me.id; - if (isRemoteParticipant) { - const volumeToggle = document.createElement("button"); - volumeToggle.type = "button"; - volumeToggle.title = "Toggle volume slider"; - volumeToggle.style.display = "grid"; - volumeToggle.style.placeItems = "center"; - volumeToggle.style.width = "20px"; - volumeToggle.style.height = "20px"; - volumeToggle.style.color = "var(--text-muted)"; - volumeToggle.innerHTML = ''; - topRow.appendChild(volumeToggle); - - volumeToggle.addEventListener('click', (e) => { - toggleVolumeSlider(e); - }); - } - - if (p.is_muted) { - const muteIcon = document.createElement("i"); - muteIcon.setAttribute("data-lucide", "mic-off"); - muteIcon.className = "voice-muted-icon"; - topRow.appendChild(muteIcon); - } - - pRow.appendChild(topRow); - - const volumeControl = document.createElement("div"); - volumeControl.className = `user-volume-control ${state.voice.visibleVolumeSliders.has(p.user_id) ? 'show-volume' : ''}`; - volumeControl.dataset.userId = p.user_id; - - if (isRemoteParticipant) { - const volumeIcon = document.createElement("i"); - volumeIcon.setAttribute("data-lucide", "volume-2"); - volumeIcon.style.width = "12px"; - volumeIcon.style.height = "12px"; - volumeIcon.style.opacity = "0.6"; - volumeControl.appendChild(volumeIcon); - - const slider = document.createElement("input"); - slider.type = "range"; - slider.min = "0"; - slider.max = "2"; - slider.step = "0.1"; - slider.value = String(state.userVolumes.get(p.user_id) ?? 1.0); - slider.className = "volume-slider"; - volumeControl.appendChild(slider); - - const volumePct = document.createElement("span"); - volumePct.className = "vol-pct"; - volumePct.textContent = `${Math.round((state.userVolumes.get(p.user_id) ?? 1.0) * 100)}%`; - volumeControl.appendChild(volumePct); - - slider.addEventListener('input', (e) => { - const val = parseFloat(e.target.value); - state.userVolumes.set(p.user_id, val); - volumePct.textContent = `${Math.round(val * 100)}%`; - - const gainNode = state.voice.peerGainNodes.get(p.user_id); - if (gainNode && state.voice.audioContext) { - gainNode.gain.setTargetAtTime(val, state.voice.audioContext.currentTime, 0.05); - } - }); - - volumeControl.addEventListener('click', (e) => e.stopPropagation()); - volumeControl.addEventListener('mousedown', (e) => e.stopPropagation()); - pRow.appendChild(volumeControl); - } - - const toggleVolumeSlider = (e) => { - if (!isRemoteParticipant) return; - e.preventDefault(); - e.stopPropagation(); - if (state.voice.visibleVolumeSliders.has(p.user_id)) { - state.voice.visibleVolumeSliders.delete(p.user_id); - } else { - state.voice.visibleVolumeSliders.add(p.user_id); - } - renderChannels(); - }; - - // Electron can swallow contextmenu events on some platforms; use - // right-button mousedown as a reliable fallback for slider toggle. - pRow.addEventListener('contextmenu', toggleVolumeSlider); - pRow.addEventListener('auxclick', (e) => { - if (e.button === 2) toggleVolumeSlider(e); - }); - pRow.addEventListener('mousedown', (e) => { - if (e.button === 2) toggleVolumeSlider(e); - }); - - pList.appendChild(pRow); - } - el.voiceChannelList.appendChild(pList); - } - } - } - lucide.createIcons(); -} - -function renderDMs() { - el.dmList.innerHTML = ""; - for (const dm of state.dmConversations) { - const isOnline = state.onlineUsers.has(dm.user_id); - const isIdle = state.idleUsers.has(dm.user_id); - const row = document.createElement("button"); - row.className = `channel-row ${state.selectedDmUserId === dm.user_id ? "active" : ""}`; - row.innerHTML = ` -
- -
-
- ${escapeHtml(dm.display_name)} - `; - row.onclick = async () => { - state.selectedDmUserId = dm.user_id; - state.selectedDmDisplayName = dm.display_name; - state.selectedTextChannelId = null; - state.selectedVoiceChannelId = null; - state.voice.viewMode = 'chat'; - renderChannels(); - renderDMs(); - updateView(); - updateHeaderLabels(); - const messages = await api(`/dms/${dm.user_id}/messages?limit=100`); - renderMessages(messages); - }; - el.dmList.appendChild(row); - } - - lucide.createIcons(); -} - -function renderMessages(messages) { - el.messageList.innerHTML = ""; - let lastAuthorId = null; - let lastTime = null; - - for (const m of messages.slice().reverse()) { - const row = document.createElement("div"); - const mDate = new Date(m.created_at); - const isGrouped = lastAuthorId === m.author_user_id && - lastTime && (mDate - lastTime < 300000); // 5 minutes - - row.className = `msg ${isGrouped ? "msg-grouped" : ""}`; - - const displayName = m.author_display_name || "Unknown User"; - const content = document.createElement("div"); - content.className = "msg-content"; - - if (!isGrouped) { - const avatar = document.createElement("div"); - avatar.className = "msg-avatar"; - avatar.textContent = shortName(displayName); - row.appendChild(avatar); - - const header = document.createElement("div"); - header.className = "msg-header"; - - const author = document.createElement("span"); - author.className = "msg-author"; - author.textContent = displayName; - header.appendChild(author); - - const time = document.createElement("span"); - time.className = "msg-time"; - time.textContent = formatDate(m.created_at); - header.appendChild(time); - - content.appendChild(header); - } - - if (m.body) { - const body = document.createElement("div"); - body.className = "msg-body"; - body.appendChild(buildMessageBody(m.body)); - content.appendChild(body); - } - - content.appendChild(buildAttachments(m.attachments)); - row.appendChild(content); - el.messageList.appendChild(row); - lastAuthorId = m.author_user_id; - lastTime = mDate; - } - - if (messages.length > 0) { - state.lastMessageId = messages[0].id; - } - - scrollMessagesToBottom(); - requestAnimationFrame(() => { - scrollMessagesToBottom(); - }); - - // GIF/image height resolves after initial paint; keep chat pinned to latest. - for (const gifImage of el.messageList.querySelectorAll(".msg-gif img")) { - if (gifImage.complete) continue; - gifImage.addEventListener("load", scrollMessagesToBottom, { once: true }); - gifImage.addEventListener("error", scrollMessagesToBottom, { once: true }); - } - - for (const media of el.messageList.querySelectorAll(".msg-attachment img, .msg-attachment video, .msg-attachment audio")) { - if ("complete" in media && media.complete) continue; - media.addEventListener("loadeddata", scrollMessagesToBottom, { once: true }); - media.addEventListener("load", scrollMessagesToBottom, { once: true }); - media.addEventListener("error", scrollMessagesToBottom, { once: true }); - } - - lucide.createIcons(); -} - -function renderMembers() { - el.memberList.innerHTML = ""; - for (const m of state.members) { - const isOnline = state.onlineUsers.has(m.id); - const isIdle = state.idleUsers.has(m.id); - const row = document.createElement("div"); - row.className = "member-row"; - row.innerHTML = ` -
- ${shortName(m.display_name)} -
-
-
${escapeHtml(m.display_name)}
- `; - row.style.cursor = "pointer"; - row.onclick = async () => { - if (state.me && m.id === state.me.id) return; - state.selectedDmUserId = m.id; - state.selectedDmDisplayName = m.display_name; - state.selectedTextChannelId = null; - state.selectedVoiceChannelId = null; - state.voice.viewMode = 'chat'; - renderChannels(); - renderDMs(); - updateView(); - updateHeaderLabels(); - const messages = await api(`/dms/${m.id}/messages?limit=100`); - renderMessages(messages); - }; - el.memberList.appendChild(row); - } -} - -function updateHeaderLabels() { - const guild = state.guilds.find((g) => g.id === state.selectedGuildId); - el.guildTitle.textContent = guild ? guild.name : "No server selected"; - - if (state.selectedDmUserId) { - const dmFromConversations = state.dmConversations.find((u) => u.user_id === state.selectedDmUserId); - const dmFromMembers = state.members.find((m) => m.id === state.selectedDmUserId); - const displayName = dmFromConversations?.display_name || dmFromMembers?.display_name || state.selectedDmDisplayName; - const dmName = displayName ? `@${displayName}` : "Direct Message"; - el.channelTitle.textContent = dmName; - el.messageBody.placeholder = displayName - ? `Message @${displayName}` - : "Message"; - return; - } - - if (state.voice.viewMode === 'video' && state.selectedVoiceChannelId) { - const channel = state.channels.find((c) => c.id === state.selectedVoiceChannelId); - el.channelTitle.textContent = channel ? channel.name : "Voice Arena"; - return; - } - - const channel = state.channels.find((c) => c.id === state.selectedTextChannelId); - el.channelTitle.textContent = channel ? channel.name : "Select a channel"; - el.messageBody.placeholder = channel ? `Message #${channel.name}` : "Select a channel"; -} - -async function createInviteLink() { - if (!state.selectedGuildId) { - alert("Select a server first."); - return; - } - try { - const invite = await api(`/guilds/${state.selectedGuildId}/invites`, { - method: "POST", - body: JSON.stringify({ max_uses: 50, expires_in_hours: 24 }), - }); - // Use the backend URL if available, otherwise fallback to current origin - const link = `${location.origin}/?invite=${encodeURIComponent(invite.code)}`; - - // Use Electron's native clipboard API if available (defined in preload.js) - if (window.electronAPI && window.electronAPI.copyToClipboard) { - try { - await window.electronAPI.copyToClipboard(link); - showCopiedBadge(); - return; - } catch (e) { - console.error("Electron clipboard write failed:", e); - } - } - - // Fallback to navigator.clipboard - try { - await navigator.clipboard.writeText(link); - showCopiedBadge(); - } catch (err) { - console.error("Navigator clipboard write failed:", err); - prompt("Copy invite link:", link); - } - } catch (err) { - alert(err.message); - } -} - -function showCopiedBadge() { - el.inviteCopiedBadge.classList.remove("hidden"); - setTimeout(() => { - el.inviteCopiedBadge.classList.add("hidden"); - }, 2000); -} - -// --- Logic --- - -async function loadGuilds() { - state.guilds = await api("/guilds"); - renderGuilds(); -} - -async function loadDMConversations() { - state.dmConversations = await api("/dms"); - renderDMs(); -} - -async function loadGuildMembers() { - if (!state.selectedGuildId) { - state.members = []; - renderMembers(); - return; - } - state.members = await api(`/guilds/${state.selectedGuildId}/members`); - renderMembers(); -} - -async function loadChannels() { - if (!state.selectedGuildId) { - state.channels = []; - renderChannels(); - return; - } - - state.channels = await api(`/guilds/${state.selectedGuildId}/channels`); - renderChannels(); -} - -async function refreshVoicePresence() { - if (!state.selectedGuildId) { - state.voicePresence.clear(); - renderChannels(); - return; - } - - try { - const res = await api(`/guilds/${state.selectedGuildId}/voice-presence`); - state.voicePresence.clear(); - for (const entry of res.channels || []) { - state.voicePresence.set(entry.channel_id, entry.participants || []); - } - renderChannels(); - } catch (err) { - console.warn("voice presence failed", err); - } -} - -function startVoicePresencePolling() { - stopVoicePresencePolling(); - state.voicePresencePollId = setInterval(() => { - if (!state.sessionActive) return; - refreshVoicePresence().catch(() => { }); - }, 3000); -} - -function initChatWs() { - if (!state.sessionActive) return; - if (state.chatWs) state.chatWs.close(); - const wsUrl = getWsUrl('/ws'); - const ws = new WebSocket(wsUrl); - state.chatWs = ws; - - ws.onmessage = (event) => { - const msg = JSON.parse(event.data); - const authorId = msg.message?.author_user_id; - const isFromMe = authorId && state.me && authorId === state.me.id; - - if (msg.type === "message_created") { - if (!isFromMe) playSound('message'); - if (state.selectedTextChannelId === msg.channel_id) { - api(`/channels/${state.selectedTextChannelId}/messages?limit=100`).then(renderMessages); - } - } else if (msg.type === "dm_created") { - if (!isFromMe) playSound('dm'); - if (state.selectedDmUserId === msg.other_user_id) { - api(`/dms/${state.selectedDmUserId}/messages?limit=100`).then(renderMessages); - playSound('dm'); - loadDMConversations().then(renderDMs); - } else { - loadDMConversations().then(renderDMs); - } - } else if (msg.type === "user_presence") { - if (msg.online) { - state.onlineUsers.add(msg.user_id); - if (msg.idle) { - state.idleUsers.add(msg.user_id); - } else { - state.idleUsers.delete(msg.user_id); - } - } else { - state.onlineUsers.delete(msg.user_id); - state.idleUsers.delete(msg.user_id); - } - renderMembers(); - renderDMs(); - } - }; - - ws.onclose = () => { - if (!state.sessionActive) return; - console.log("Chat WS closed, reconnecting..."); - setTimeout(initChatWs, 3000); - }; -} - -// --- Voice --- - -function getVoiceWsUrl(channelId) { - return getWsUrl(`/channels/${channelId}/voice/ws`); -} - -function shouldInitiateOffer(peerId) { - if (!state.me || !state.me.id) return false; - return state.me.id > peerId; -} - -function disconnectPeerAudioNodes(peerId) { - const nodes = state.voice.peerAudioNodes.get(peerId); - if (!nodes) return; - - for (const node of [nodes.sourceNode, nodes.compressorNode, nodes.gainNode]) { - try { - node?.disconnect(); - } catch { } - } - - state.voice.peerAudioNodes.delete(peerId); - state.voice.peerGainNodes.delete(peerId); -} - -function stopAndClearAudioPipeline() { - for (const peerId of state.voice.peerAudioNodes.keys()) { - disconnectPeerAudioNodes(peerId); - } - if (state.voice.deepFilterProcessor) { - state.voice.deepFilterProcessor.destroy(); - state.voice.deepFilterProcessor = null; - } - if (state.voice.localStream) { - for (const track of state.voice.localStream.getTracks()) track.stop(); - } - if (state.voice.rawStream && state.voice.rawStream !== state.voice.localStream) { - for (const track of state.voice.rawStream.getTracks()) track.stop(); - } - if (state.voice.audioContext) { - state.voice.audioContext.close().catch(() => { }); - } - state.voice.localStream = null; - state.voice.rawStream = null; - state.voice.audioContext = null; -} - -function stopAndClearVideoPipeline() { - if (state.voice.videoStream) { - for (const track of state.voice.videoStream.getTracks()) track.stop(); - } - state.voice.videoStream = null; - state.voice.sharingVideo = false; - document.getElementById(`video-${state.me.id}-camera`)?.parentElement?.remove(); -} - -function stopAndClearScreenPipeline() { - if (state.voice.screenStream) { - for (const track of state.voice.screenStream.getTracks()) track.stop(); - } - state.voice.screenStream = null; - state.voice.sharingScreen = false; - document.getElementById(`video-${state.me.id}-screen`)?.parentElement?.remove(); -} - -function updateVideoGridVisibility() { - // Persistence logic: we always update the grid visibility based on participants - // however the actual container visibility in the UI is managed by updateView() -} - -function updateView() { - if (state.voice.viewMode === 'video') { - el.videoGrid.classList.remove("hidden"); - el.messageList.classList.add("hidden"); - el.messageInputWrapper.classList.add("hidden"); - } else { - el.videoGrid.classList.add("hidden"); - el.messageList.classList.remove("hidden"); - el.messageInputWrapper.classList.remove("hidden"); - } -} - -function renderVideo(peerId, displayName, stream, source) { - const videoId = `video-${peerId}-${source}`; - let videoEl = document.getElementById(videoId); - if (!videoEl) { - const container = document.createElement("div"); - container.className = "video-item"; - const label = source === 'screen' ? `${escapeHtml(displayName)}'s Screen` : escapeHtml(displayName); - container.innerHTML = ` - -
${label}
- `; - container.onclick = () => { - const isFullscreen = container.classList.contains('fullscreen'); - // Reset all - document.querySelectorAll('.video-item').forEach(el => el.classList.remove('fullscreen')); - - if (isFullscreen) { - el.videoGrid.classList.remove('has-fullscreen'); - } else { - container.classList.add('fullscreen'); - el.videoGrid.classList.add('has-fullscreen'); - } - }; - - el.videoGrid.appendChild(container); - videoEl = container.querySelector("video"); - } - videoEl.srcObject = stream; -} - -async function buildAudioPipeline(rawStream) { - const ctx = new AudioContext(); - state.voice.audioContext = ctx; - const source = ctx.createMediaStreamSource(rawStream); - let processedSource = source; - - try { - const deepFilter = await getDeepFilterModule(); - const processor = new deepFilter.DeepFilterNet3Core({ - sampleRate: 48000, - noiseReductionLevel: 70, - assetConfig: { - cdnUrl: resolveDeepFilterAssetsBaseUrl(), - }, - }); - await processor.initialize(); - const workletNode = await processor.createAudioWorkletNode(ctx); - processor.setNoiseSuppressionEnabled(true); - source.connect(workletNode); - processedSource = workletNode; - state.voice.deepFilterProcessor = processor; - console.info('DeepFilterNet3 enabled'); - } catch (err) { - console.warn('DeepFilterNet3 unavailable, falling back to raw mic audio', err); - state.voice.deepFilterProcessor = null; - } - - // Metering/Speaking detection with adaptive threshold and hysteresis. - const analyser = ctx.createAnalyser(); - analyser.fftSize = 1024; - processedSource.connect(analyser); - - const supportsFloatTimeDomain = typeof analyser.getFloatTimeDomainData === 'function'; - const timeData = supportsFloatTimeDomain ? new Float32Array(analyser.fftSize) : new Uint8Array(analyser.fftSize); - let localIsSpeaking = false; - let speechFrames = 0; - let silenceFrames = 0; - let noiseFloor = 0.004; - let levelEma = 0; - - const checkVolume = () => { - if (!state.voice.audioContext || state.voice.audioContext.state === 'closed') return; - - try { - if (supportsFloatTimeDomain) { - analyser.getFloatTimeDomainData(timeData); - } else { - analyser.getByteTimeDomainData(timeData); - } - } catch (err) { - setTimeout(checkVolume, 60); - return; - } - - let sumSquares = 0; - let peak = 0; - for (let i = 0; i < timeData.length; i++) { - const v = supportsFloatTimeDomain - ? timeData[i] - : (timeData[i] - 128) / 128; - sumSquares += v * v; - const abs = Math.abs(v); - if (abs > peak) peak = abs; - } - - const rms = Math.sqrt(sumSquares / timeData.length); - const level = Math.max(rms, peak * 0.5); - levelEma = levelEma * 0.75 + level * 0.25; - - if (!localIsSpeaking) { - // Learn room noise slowly while idle. - noiseFloor = noiseFloor * 0.98 + levelEma * 0.02; - } else { - // Do not let noise floor jump up while speaking. - noiseFloor = Math.min(noiseFloor, levelEma); - } - - const startThreshold = Math.max(noiseFloor * 2.2, 0.010); - const stopThreshold = Math.max(noiseFloor * 1.5, 0.006); - - if (levelEma > startThreshold) { - speechFrames = Math.min(speechFrames + 1, 8); - silenceFrames = 0; - } else if (levelEma < stopThreshold) { - silenceFrames = Math.min(silenceFrames + 1, 8); - speechFrames = Math.max(speechFrames - 1, 0); - } - - const newSpeakingState = localIsSpeaking ? silenceFrames < 3 : speechFrames >= 2; - - if (newSpeakingState !== localIsSpeaking) { - localIsSpeaking = newSpeakingState; - if (state.voice.ws && state.voice.ws.readyState === WebSocket.OPEN) { - state.voice.ws.send(JSON.stringify({ type: 'set_speaking_status', is_speaking: localIsSpeaking })); - } - // Local UI update - state.voicePresence.get(state.selectedVoiceChannelId)?.forEach(p => { - if (p.user_id === state.me.id) p.is_speaking = localIsSpeaking; - }); - renderChannels(); - const myVideo = document.getElementById(`video-${state.me.id}-camera`) || document.getElementById(`video-${state.me.id}-screen`); - if (myVideo) { - myVideo.parentElement.classList.toggle('speaking', localIsSpeaking); - } - } - setTimeout(checkVolume, 60); - }; - checkVolume(); - - const destination = ctx.createMediaStreamDestination(); - processedSource.connect(destination); - return destination.stream; -} - -function resolveDeepFilterModuleUrl() { - if (location.protocol === 'file:') { - return new URL('./vendor/deepfilternet3-noise-filter.esm.js', location.href).toString(); - } - return '/static/vendor/deepfilternet3-noise-filter.esm.js'; -} - -function resolveDeepFilterAssetsBaseUrl() { - if (location.protocol === 'file:') { - return new URL('./vendor/deepfilternet3', location.href).toString(); - } - return '/static/vendor/deepfilternet3'; -} - -async function getDeepFilterModule() { - if (state.voice.deepFilterModule) return state.voice.deepFilterModule; - const moduleUrl = resolveDeepFilterModuleUrl(); - state.voice.deepFilterModule = await import(moduleUrl); - return state.voice.deepFilterModule; -} - -async function createLocalVoiceStream() { - const constraints = { - audio: { - channelCount: 1, - sampleRate: 48000, - echoCancellation: true, - noiseSuppression: false, - autoGainControl: true, - }, - video: false, - }; - const rawStream = await navigator.mediaDevices.getUserMedia(constraints); - let localStream = rawStream; - try { - localStream = await buildAudioPipeline(rawStream); - } catch (err) { - console.warn('voice audio pipeline failed, using raw mic stream', err); - } - state.voice.rawStream = rawStream; - state.voice.localStream = localStream; - if (state.voice.muted) { - state.voice.localStream.getAudioTracks().forEach((t) => { - t.enabled = false; - }); - } -} - -function ensurePeerConnection(peerId) { - if (state.voice.peerConnections.has(peerId)) { - return state.voice.peerConnections.get(peerId); - } - - const pc = new RTCPeerConnection({ - iceServers: state.voice.iceServers - }); - - pc.makingOffer = false; - pc.ignoreOffer = false; - pc.polite = !shouldInitiateOffer(peerId); - - // 1. Audio - if (state.voice.localStream) { - state.voice.localStream.getAudioTracks().forEach(track => { - pc.addTrack(track, state.voice.localStream); - }); - } else { - pc.addTransceiver('audio', { direction: 'recvonly' }); - } - - // 2. Camera Video - if (state.voice.videoStream) { - state.voice.videoStream.getVideoTracks().forEach(track => { - const sender = pc.addTrack(track, state.voice.videoStream); - state.voice.videoSenders.set(peerId, sender); - }); - } - - // 3. Screen Video - if (state.voice.screenStream) { - state.voice.screenStream.getVideoTracks().forEach(track => { - const sender = pc.addTrack(track, state.voice.screenStream); - state.voice.screenSenders.set(peerId, sender); - }); - } - - pc.onicecandidate = (event) => { - if (!event.candidate || !state.voice.ws) return; - state.voice.ws.send(JSON.stringify({ - type: "signal", - to_user_id: peerId, - kind: "ice", - data: event.candidate, - })); - }; - - pc.oniceconnectionstatechange = async () => { - const iceState = pc.iceConnectionState; - console.debug(`voice ice state (${peerId}):`, iceState); - if (iceState !== "failed" || pc.restartingIce) return; - pc.restartingIce = true; - try { - const offer = await pc.createOffer({ iceRestart: true }); - await pc.setLocalDescription(offer); - if (state.voice.ws && state.voice.ws.readyState === WebSocket.OPEN) { - state.voice.ws.send(JSON.stringify({ - type: "signal", - to_user_id: peerId, - kind: "offer", - data: pc.localDescription, - })); - } - } catch (err) { - console.warn("ICE restart failed", err); - } finally { - pc.restartingIce = false; - } - }; - - pc.ontrack = (event) => { - const stream = event.streams[0]; - if (event.track.kind === "audio") { - let audio = document.getElementById(`audio-${peerId}`); - if (!audio) { - audio = document.createElement("audio"); - audio.id = `audio-${peerId}`; - audio.autoplay = true; - audio.playsInline = true; - document.body.appendChild(audio); - } - audio.muted = false; - audio.srcObject = new MediaStream([event.track]); - const tryPlay = () => { - const playPromise = audio.play(); - if (playPromise && typeof playPromise.catch === "function") { - playPromise.catch((err) => { - console.warn(`remote audio playback blocked for ${peerId}`, err); - }); - } - }; - audio.onloadedmetadata = tryPlay; - audio.oncanplay = tryPlay; - tryPlay(); - - // Web Audio Pipeline for Volume Boosting - if (!state.voice.audioContext) { - state.voice.audioContext = new (window.AudioContext || window.webkitAudioContext)(); - } - const ctx = state.voice.audioContext; - if (ctx.state === 'suspended') ctx.resume(); - - disconnectPeerAudioNodes(peerId); - - const sourceNode = ctx.createMediaStreamSource(audio.srcObject); - const compressorNode = ctx.createDynamicsCompressor(); - const gainNode = ctx.createGain(); - - compressorNode.threshold.setValueAtTime(-24, ctx.currentTime); - compressorNode.knee.setValueAtTime(18, ctx.currentTime); - compressorNode.ratio.setValueAtTime(4, ctx.currentTime); - compressorNode.attack.setValueAtTime(0.003, ctx.currentTime); - compressorNode.release.setValueAtTime(0.25, ctx.currentTime); - - const currentVolume = state.userVolumes.get(peerId) ?? 1.0; - gainNode.gain.setValueAtTime(currentVolume, ctx.currentTime); - - sourceNode.connect(compressorNode); - compressorNode.connect(gainNode); - gainNode.connect(ctx.destination); - - state.voice.peerGainNodes.set(peerId, gainNode); - state.voice.peerAudioNodes.set(peerId, { sourceNode, compressorNode, gainNode }); - - // Mute the original element as we play through Web Audio destination - audio.volume = 0; - audio.muted = true; - } else if (event.track.kind === "video") { - const peer = state.members.find(m => m.id === peerId) || { display_name: "Unknown" }; - renderVideo(peerId, peer.display_name, stream, event.track.id); - - event.track.onmute = () => { - document.getElementById(`video-${peerId}-${event.track.id}`)?.parentElement?.remove(); - }; - event.track.onended = () => { - document.getElementById(`video-${peerId}-${event.track.id}`)?.parentElement?.remove(); - }; - } - }; - - pc.onnegotiationneeded = async () => { - try { - pc.makingOffer = true; - const offer = await pc.createOffer(); - await pc.setLocalDescription(offer); - state.voice.ws.send(JSON.stringify({ - type: "signal", - to_user_id: peerId, - kind: "offer", - data: pc.localDescription, - })); - } catch (err) { - console.error("negotiation failed", err); - } finally { - pc.makingOffer = false; - } - }; - - state.voice.peerConnections.set(peerId, pc); - return pc; -} - -async function attachLocalAudioToPeerConnections() { - if (!state.voice.localStream) return; - const localTrack = state.voice.localStream.getAudioTracks()[0]; - if (!localTrack) return; - - await Promise.all( - Array.from(state.voice.peerConnections.values()).map(async (pc) => { - const audioTransceiver = pc.getTransceivers().find((t) => t.receiver?.track?.kind === 'audio'); - if (audioTransceiver?.sender) { - await audioTransceiver.sender.replaceTrack(localTrack); - if (audioTransceiver.direction === 'recvonly') { - audioTransceiver.direction = 'sendrecv'; - } - } else { - pc.addTrack(localTrack, state.voice.localStream); - } - }) - ); -} - -async function handleSignal(fromPeerId, kind, data) { - const pc = ensurePeerConnection(fromPeerId); - - try { - if (kind === "offer") { - const offerCollision = pc.makingOffer || pc.signalingState !== "stable"; - pc.ignoreOffer = !pc.polite && offerCollision; - if (pc.ignoreOffer) return; - - await pc.setRemoteDescription(new RTCSessionDescription(data)); - const answer = await pc.createAnswer(); - await pc.setLocalDescription(answer); - state.voice.ws.send(JSON.stringify({ - type: "signal", - to_user_id: fromPeerId, - kind: "answer", - data: pc.localDescription, - })); - } else if (kind === "answer") { - await pc.setRemoteDescription(new RTCSessionDescription(data)); - } else if (kind === "ice") { - try { - await pc.addIceCandidate(data ? new RTCIceCandidate(data) : null); - } catch (err) { - if (!pc.ignoreOffer) { - console.warn("failed to add ice candidate", err); - } - } - } - } catch (err) { - console.error("handleSignal failed", err); - } -} - -async function joinVoice() { - if (!state.selectedVoiceChannelId) { - alert('No voice channel selected.'); - return; - } - if (state.voice.joinedChannelId === state.selectedVoiceChannelId && - state.voice.ws && - state.voice.ws.readyState === WebSocket.OPEN) { - return; - } - - await leaveVoice(); - - el.voiceConnection.classList.remove('hidden'); - el.vcChannelName.textContent = 'Connecting...'; - - const ws = new WebSocket(getVoiceWsUrl(state.selectedVoiceChannelId)); - const currentWs = ws; - let wsOpened = false; - let micUnavailable = false; - - state.voice.ws = ws; - state.voice.joinedChannelId = state.selectedVoiceChannelId; - storageSet("active_voice_channel", state.selectedVoiceChannelId); - - // Start mic setup in parallel so channel join is not blocked by device init. - createLocalVoiceStream() - .then(async () => { - if (state.voice.ws !== currentWs) { - stopAndClearAudioPipeline(); - return; - } - try { - await attachLocalAudioToPeerConnections(); - } catch (err) { - console.warn('failed to attach local audio to existing peer connections', err); - } - }) - .catch((err) => { - micUnavailable = true; - console.warn('failed to initialize local voice stream, joining as listen-only', err); - state.voice.localStream = null; - state.voice.rawStream = null; - if (state.voice.audioContext) { - state.voice.audioContext.close().catch(() => { }); - state.voice.audioContext = null; - } - }); - - const connectTimer = setTimeout(() => { - if (!wsOpened && state.voice.ws === currentWs) { - console.error('voice websocket connect timeout'); - try { currentWs.close(); } catch (_) { } - el.vcChannelName.textContent = 'Connection timeout'; - alert('Could not connect to voice channel (timeout). Please try again.'); - } - }, 5000); - - ws.onopen = () => { - if (state.voice.ws !== currentWs) return; - wsOpened = true; - clearTimeout(connectTimer); - const channel = state.channels.find(c => c.id === state.selectedVoiceChannelId); - el.vcChannelName.textContent = channel ? channel.name : "Voice"; - if (micUnavailable) { - console.warn('Voice joined in listen-only mode because microphone is unavailable.'); - } - el.voiceConnection.classList.remove("hidden"); - el.soundboard.classList.remove("hidden"); - playSound('join'); - refreshVoicePresence().catch(() => { }); - loadSounds().catch(() => { }); - }; - - ws.onmessage = async (event) => { - if (state.voice.ws !== currentWs) return; - const msg = JSON.parse(event.data); - if (msg.type === "peers") { - for (const peer of msg.peers) { - ensurePeerConnection(peer.user_id); - } - } else if (msg.type === "peer_joined") { - playSound('peer-join'); - ensurePeerConnection(msg.user_id); - } else if (msg.type === "peer_left") { - playSound('peer-leave'); - const pc = state.voice.peerConnections.get(msg.user_id); - if (pc) { - pc.close(); - state.voice.peerConnections.delete(msg.user_id); - } - disconnectPeerAudioNodes(msg.user_id); - document.getElementById(`audio-${msg.user_id}`)?.remove(); - } else if (msg.type === "signal") { - await handleSignal(msg.from_user_id, msg.kind, msg.data); - } else if (msg.type === "video_status_changed") { - if (!msg.is_sharing_video) { - document.getElementById(`video-${msg.user_id}-camera`)?.parentElement?.remove(); - } - } else if (msg.type === "screen_status_changed") { - if (!msg.is_sharing_screen) { - document.getElementById(`video-${msg.user_id}-screen`)?.parentElement?.remove(); - } - } else if (msg.type === "speaking_status_changed") { - state.voicePresence.get(state.selectedVoiceChannelId)?.forEach(p => { - if (p.user_id === msg.user_id) p.is_speaking = msg.is_speaking; - }); - renderChannels(); - const videoEl = document.getElementById(`video-${msg.user_id}-camera`) || document.getElementById(`video-${msg.user_id}-screen`); - if (videoEl) { - videoEl.parentElement.classList.toggle('speaking', msg.is_speaking); - } - } else if (msg.type === "mute_status_changed") { - state.voicePresence.get(state.selectedVoiceChannelId)?.forEach(p => { - if (p.user_id === msg.user_id) p.is_muted = msg.is_muted; - }); - renderChannels(); - } else if (msg.type === "play_sound") { - const audio = new Audio(msg.media_url); - audio.play().catch(console.error); - } - refreshVoicePresence().catch(() => { }); - }; - - ws.onerror = (event) => { - if (state.voice.ws !== currentWs) return; - console.error('voice websocket error', event); - el.vcChannelName.textContent = 'Connection failed'; - }; - - ws.onclose = (event) => { - if (state.voice.ws !== currentWs) return; - clearTimeout(connectTimer); - if (!wsOpened) { - console.error('voice websocket closed before open', event.code, event.reason); - const code = event && typeof event.code === 'number' ? event.code : 'unknown'; - el.vcChannelName.textContent = `Connection failed (${code})`; - alert(`Voice connection failed (code ${code}).`); - } - if (wsOpened) { - el.voiceConnection.classList.add("hidden"); - } - el.soundboard.classList.add("hidden"); - for (const pc of state.voice.peerConnections.values()) pc.close(); - state.voice.peerConnections.clear(); - state.voice.videoSenders.clear(); - state.voice.screenSenders.clear(); - stopAndClearAudioPipeline(); - state.voice.joinedChannelId = null; - state.voice.ws = null; - playSound('leave'); - refreshVoicePresence().catch(() => { }); - }; -} - -async function leaveVoice() { - storageRemove("active_voice_channel"); - if (state.voice.ws) state.voice.ws.close(); -} - -function toggleMute() { - if (!state.voice.localStream) return; - state.voice.muted = !state.voice.muted; - state.voice.localStream.getAudioTracks().forEach((t) => { - t.enabled = !state.voice.muted; - }); - if (state.voice.ws && state.voice.ws.readyState === WebSocket.OPEN) { - state.voice.ws.send(JSON.stringify({ type: "set_mute_status", is_muted: state.voice.muted })); - } - el.voiceMuteBtn.innerHTML = state.voice.muted ? '' : ''; - el.voiceMuteBtn.style.color = state.voice.muted ? 'var(--danger)' : 'var(--text-muted)'; - lucide.createIcons(); -} - -async function toggleVideo() { - if (state.voice.sharingVideo) { - stopAndClearVideoPipeline(); - if (state.voice.ws) { - state.voice.ws.send(JSON.stringify({ type: "set_video_status", is_sharing_video: false })); - } - for (const [peerId, pc] of state.voice.peerConnections) { - const sender = state.voice.videoSenders.get(peerId); - if (sender) { - pc.removeTrack(sender); - state.voice.videoSenders.delete(peerId); - } - } - } else { - try { - const stream = await navigator.mediaDevices.getUserMedia({ video: true }); - state.voice.videoStream = stream; - state.voice.sharingVideo = true; - renderVideo(state.me.id, state.me.display_name, stream, 'camera'); - - if (state.voice.ws) { - state.voice.ws.send(JSON.stringify({ type: "set_video_status", is_sharing_video: true })); - } - - for (const [peerId, pc] of state.voice.peerConnections) { - stream.getVideoTracks().forEach(track => { - const sender = pc.addTrack(track, stream); - state.voice.videoSenders.set(peerId, sender); - }); - } - } catch (err) { - console.error("camera denied", err); - alert("Could not access camera."); - return; - } - } - - el.voiceVideoBtn.innerHTML = state.voice.sharingVideo ? '' : ''; - el.voiceVideoBtn.style.color = state.voice.sharingVideo ? 'var(--green)' : 'var(--text-muted)'; - lucide.createIcons(); -} - -async function toggleScreenShare() { - if (state.voice.sharingScreen) { - stopAndClearScreenPipeline(); - if (state.voice.ws) { - state.voice.ws.send(JSON.stringify({ type: "set_screen_status", is_sharing_screen: false })); - } - for (const [peerId, pc] of state.voice.peerConnections) { - const sender = state.voice.screenSenders.get(peerId); - if (sender) { - pc.removeTrack(sender); - state.voice.screenSenders.delete(peerId); - } - } - } else { - try { - const stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true }); - state.voice.screenStream = stream; - state.voice.sharingScreen = true; - renderVideo(state.me.id, state.me.display_name, stream, 'screen'); - - // Stop sharing if user clicks "Stop sharing" in browser UI - stream.getVideoTracks()[0].onended = () => { - if (state.voice.sharingScreen) toggleScreenShare(); - }; - - if (state.voice.ws) { - state.voice.ws.send(JSON.stringify({ type: "set_screen_status", is_sharing_screen: true })); - } - - for (const [peerId, pc] of state.voice.peerConnections) { - stream.getVideoTracks().forEach(track => { - const sender = pc.addTrack(track, stream); - state.voice.screenSenders.set(peerId, sender); - }); - } - } catch (err) { - console.error("screen share denied", err); - return; - } - } - - el.voiceScreenBtn.innerHTML = state.voice.sharingScreen ? '' : ''; - el.voiceScreenBtn.style.color = state.voice.sharingScreen ? 'var(--green)' : 'var(--text-muted)'; - lucide.createIcons(); -} - -function toggleWatchVideo() { - state.voice.watchingVideo = !state.voice.watchingVideo; - updateVideoGridVisibility(); - - el.voiceWatchBtn.innerHTML = state.voice.watchingVideo ? '' : ''; - el.voiceWatchBtn.style.color = state.voice.watchingVideo ? 'var(--green)' : 'var(--danger)'; - el.voiceWatchBtn.title = state.voice.watchingVideo ? 'Stop Watching' : 'Start Watching'; - lucide.createIcons(); -} - -// --- Sound Board --- - -async function loadSounds() { - if (!state.selectedGuildId) return; - try { - const sounds = await api(`/guilds/${state.selectedGuildId}/sounds`); - renderSounds(sounds); - } catch (err) { - console.error("failed to load sounds", err); - } -} - -function renderSounds(sounds) { - el.soundboardGrid.innerHTML = ''; - sounds.forEach(sound => { - const item = document.createElement('div'); - item.className = 'sound-item'; - - // Only show delete button if user is creator or owner - const canDelete = state.me && (state.me.id === sound.created_by_user_id || (state.guilds.find(g => g.id === state.selectedGuildId)?.owner_user_id === state.me.id)); - - const icon = document.createElement('div'); - icon.className = 'sound-icon'; - icon.textContent = sound.icon; - const name = document.createElement('div'); - name.className = 'sound-name'; - name.textContent = sound.name; - item.appendChild(icon); - item.appendChild(name); - - if (canDelete) { - const deleteBtn = document.createElement('button'); - deleteBtn.className = 'sound-delete'; - deleteBtn.title = 'Delete sound'; - deleteBtn.innerHTML = ''; - item.appendChild(deleteBtn); - } - - item.onclick = (e) => { - if (e.target.closest('.sound-delete')) { - e.stopPropagation(); - if (confirm(`Are you sure you want to delete "${sound.name}"?`)) { - deleteSound(sound.id); - } - return; - } - playRemoteSound(sound.id, sound.media_url); - }; - - el.soundboardGrid.appendChild(item); - }); - lucide.createIcons(); -} - -async function deleteSound(soundId) { - if (!state.selectedGuildId) return; - try { - await api(`/guilds/${state.selectedGuildId}/sounds/${soundId}`, { method: 'DELETE' }); - await loadSounds(); - } catch (err) { - alert(err.message); - } -} - -function playRemoteSound(soundId, mediaUrl) { - if (state.voice.ws && state.voice.ws.readyState === WebSocket.OPEN) { - state.voice.ws.send(JSON.stringify({ type: 'play_sound', sound_id: soundId })); - } - // Also play locally immediately - const audio = new Audio(mediaUrl); - audio.play().catch(console.error); -} - -// --- Mobile Logic --- - -function toggleMobileMenu() { - const isOpen = el.main.classList.contains("menu-open"); - if (isOpen) { - el.main.classList.remove("menu-open"); - el.overlay.classList.add("hidden"); - } else { - el.main.classList.add("menu-open"); - el.utilitySidebar.classList.remove("active"); // close members if open - el.overlay.classList.remove("hidden"); - } -} - -function toggleMobileMembers() { - const isOpen = el.utilitySidebar.classList.contains("active"); - if (isOpen) { - el.utilitySidebar.classList.remove("active"); - el.overlay.classList.add("hidden"); - } else { - el.utilitySidebar.classList.add("active"); - el.main.classList.remove("menu-open"); // close menu if open - el.overlay.classList.remove("hidden"); - } -} - -function closeMobileMenus() { - el.main.classList.remove("menu-open"); - el.utilitySidebar.classList.remove("active"); - el.overlay.classList.add("hidden"); -} - -// --- Initialization --- - -let inactivityTimer = null; -let isCurrentlyIdle = false; -let updaterInitialized = false; - -function resetInactivityTimer() { - if (isCurrentlyIdle) { - isCurrentlyIdle = false; - if (state.chatWs && state.chatWs.readyState === WebSocket.OPEN) { - state.chatWs.send(JSON.stringify({ type: "set_idle_status", is_idle: false })); - } - } - - if (inactivityTimer) clearTimeout(inactivityTimer); - inactivityTimer = setTimeout(() => { - isCurrentlyIdle = true; - if (state.chatWs && state.chatWs.readyState === WebSocket.OPEN) { - state.chatWs.send(JSON.stringify({ type: "set_idle_status", is_idle: true })); - } - }, 5 * 60 * 1000); // 5 minutes -} - -document.addEventListener('mousemove', resetInactivityTimer); -document.addEventListener('keydown', resetInactivityTimer); -document.addEventListener('click', resetInactivityTimer); - -async function init() { - lucide.createIcons(); - initUpdater(); - - // 2. Global Button Handlers - el.loginBtn.onclick = () => { - el.status.textContent = ""; - location.href = "/auth/login"; - }; - - el.logoutBtn.onclick = async () => { - try { - await api("/auth/logout", { method: "POST" }); - } catch (e) { - if (!e?.isAuthError) { - console.warn("logout request failed", e); - } - } - await showLoggedOutState("Signed out."); - }; - - el.addGuildBtn.onclick = () => { el.modalContainer.classList.remove("hidden"); }; - el.createInviteBtn.onclick = createInviteLink; - el.modalCancel.onclick = () => { el.modalContainer.classList.add("hidden"); }; - - el.addTextBtn.onclick = () => { - if (!state.selectedGuildId) { alert("Create or select a server first."); return; } - document.querySelector('input[name="channel-kind"][value="text"]').checked = true; - el.channelModal.classList.remove("hidden"); - }; - el.addVoiceBtn.onclick = () => { - if (!state.selectedGuildId) { alert("Create or select a server first."); return; } - document.querySelector('input[name="channel-kind"][value="voice"]').checked = true; - el.channelModal.classList.remove("hidden"); - }; - el.channelModalCancel.onclick = () => { el.channelModal.classList.add("hidden"); }; - - // Mobile Listeners - if (el.mobileMenuBtn) el.mobileMenuBtn.onclick = toggleMobileMenu; - if (el.mobileMembersBtn) el.mobileMembersBtn.onclick = toggleMobileMembers; - if (el.overlay) el.overlay.onclick = closeMobileMenus; - - // 3. Form Submissions - el.guildForm.onsubmit = async (e) => { - e.preventDefault(); - try { - const guild = await api("/guilds", { method: "POST", body: JSON.stringify({ name: el.guildName.value }) }); - el.guildName.value = ""; - el.modalContainer.classList.add("hidden"); - state.guilds.push(guild); - state.selectedGuildId = guild.id; - state.selectedTextChannelId = null; - state.selectedVoiceChannelId = null; - state.selectedDmUserId = null; - state.selectedDmDisplayName = null; - storageSet(LAST_GUILD_STORAGE_KEY, guild.id); - renderGuilds(); - await loadChannels(); - await loadGuildMembers(); - await refreshVoicePresence(); - renderMessages([]); - updateHeaderLabels(); - } catch (err) { alert(err.message); } - }; - - el.channelForm.onsubmit = async (e) => { - e.preventDefault(); - if (!state.selectedGuildId) { alert("Select a server first."); return; } - const kindInput = document.querySelector('input[name="channel-kind"]:checked'); - const kind = kindInput ? kindInput.value : "text"; - const channelName = el.channelName.value.trim(); - if (!channelName) { alert("Channel name is required."); return; } - try { - const created = await api("/channels", { - method: "POST", - body: JSON.stringify({ guild_id: state.selectedGuildId, name: channelName, kind: kind }), - }); - el.channelName.value = ""; - el.channelModal.classList.add("hidden"); - await loadChannels(); - if (created.kind === "text") { - state.selectedTextChannelId = created.id; - state.selectedVoiceChannelId = null; - state.selectedDmUserId = null; - state.selectedDmDisplayName = null; - renderChannels(); - renderDMs(); - updateHeaderLabels(); - const messages = await api(`/channels/${created.id}/messages?limit=100`); - renderMessages(messages); - } else { - state.selectedVoiceChannelId = created.id; - state.selectedTextChannelId = null; - state.selectedDmUserId = null; - state.selectedDmDisplayName = null; - renderChannels(); - renderDMs(); - updateHeaderLabels(); - await joinVoice(); - } - } catch (err) { alert(err.message); } - }; - - el.messageForm.onsubmit = async (e) => { - e.preventDefault(); - const body = el.messageBody.value.trim(); - if (!body) return; - try { - if (state.selectedTextChannelId) { - await api(`/channels/${state.selectedTextChannelId}/messages`, { method: "POST", body: JSON.stringify({ body }) }); - } else if (state.selectedDmUserId) { - await api(`/dms/${state.selectedDmUserId}/messages`, { method: "POST", body: JSON.stringify({ body }) }); - } else return; - el.messageBody.value = ""; - const messages = state.selectedTextChannelId - ? await api(`/channels/${state.selectedTextChannelId}/messages?limit=100`) - : await api(`/dms/${state.selectedDmUserId}/messages?limit=100`); - renderMessages(messages); - await loadDMConversations(); - renderDMs(); - } catch (err) { alert(err.message); } - }; - - if (el.mediaUploadBtn && el.mediaFileInput) { - el.mediaUploadBtn.onclick = () => { - if (!state.selectedTextChannelId && !state.selectedDmUserId) { - alert("Select a chat first."); - return; - } - el.mediaFileInput.click(); - }; - - el.mediaFileInput.onchange = async () => { - const file = el.mediaFileInput.files?.[0]; - if (!file) return; - try { - await uploadMediaFile(file); - } catch (err) { - alert(err.message); - } finally { - el.mediaFileInput.value = ""; - } - }; - } - - // 4. Voice/Soundboard Controls - el.voiceVideoBtn.onclick = toggleVideo; - el.voiceScreenBtn.onclick = toggleScreenShare; - el.voiceMuteBtn.onclick = toggleMute; - el.voiceLeaveBtn.onclick = leaveVoice; - - el.addSoundBtn.onclick = () => { el.soundModal.classList.remove("hidden"); }; - el.soundModalCancel.onclick = () => { el.soundModal.classList.add("hidden"); }; - - el.soundForm.onsubmit = async (e) => { - e.preventDefault(); - if (!state.selectedGuildId) return; - const formData = new FormData(); - formData.append('name', el.soundName.value); - formData.append('icon', el.soundIcon.value); - formData.append('file', el.soundFile.files[0]); - el.soundSubmitBtn.disabled = true; - el.soundSubmitBtn.textContent = 'Uploading...'; - try { - const response = await fetch(`/guilds/${state.selectedGuildId}/sounds`, { - method: 'POST', - body: formData, - credentials: 'same-origin', - }); - if (!response.ok) { const err = await response.json(); throw new Error(err.error || 'Upload failed'); } - el.soundModal.classList.add("hidden"); - el.soundForm.reset(); - await loadSounds(); - } catch (err) { alert(err.message); } finally { - el.soundSubmitBtn.disabled = false; - el.soundSubmitBtn.textContent = 'Add Sound'; - } - }; - - if (el.uploadLimitOk && el.uploadLimitModal) { - el.uploadLimitOk.onclick = () => { - el.uploadLimitModal.classList.add("hidden"); - }; - el.uploadLimitModal.onclick = (e) => { - if (e.target === el.uploadLimitModal) { - el.uploadLimitModal.classList.add("hidden"); - } - }; - } - - // 5. GIF Picker - const TENOR_API_KEY = "exTiFGKJ0CzESIHzVQWy3pRO8I1MAdpRomg95DBSu2sg6e7YcHgThMI4giGAx8D0"; - const TENOR_CLIENT_KEY = "pavel-discord"; - - el.gifBtn.onclick = () => { el.gifPicker.classList.remove("hidden"); searchGifs(""); }; - el.gifPickerClose.onclick = () => { el.gifPicker.classList.add("hidden"); }; - - let gifSearchTimeout = null; - el.gifSearchInput.oninput = () => { - clearTimeout(gifSearchTimeout); - gifSearchTimeout = setTimeout(() => { searchGifs(el.gifSearchInput.value); }, 500); - }; - - async function searchGifs(query) { - el.gifResults.innerHTML = '
Searching...
'; - const baseUrl = "https://api.klipy.com/v2"; - const endpoint = query - ? `${baseUrl}/search?q=${encodeURIComponent(query)}&key=${TENOR_API_KEY}&client_key=${TENOR_CLIENT_KEY}&limit=20` - : `${baseUrl}/featured?key=${TENOR_API_KEY}&client_key=${TENOR_CLIENT_KEY}&limit=20`; - try { - const res = await fetch(endpoint); - const data = await res.json(); - renderGifs(data.results); - } catch (err) { el.gifResults.innerHTML = '
Error loading GIFs
'; } - } - - function renderGifs(gifs) { - el.gifResults.innerHTML = ""; - if (!gifs || gifs.length === 0) { el.gifResults.innerHTML = '
No GIFs found
'; return; } - gifs.forEach(gif => { - const previewUrl = gif.media_formats.tinygif.url; - const fullUrl = gif.media_formats.gif.url; - const item = document.createElement("div"); - item.className = "gif-item"; - const img = document.createElement("img"); - img.src = previewUrl; - img.loading = "lazy"; - img.onclick = () => { - el.gifPicker.classList.add("hidden"); - el.gifSearchInput.value = ""; - sendGif(fullUrl); - }; - item.appendChild(img); - el.gifResults.appendChild(item); - }); - } - - async function sendGif(url) { - try { - if (state.selectedTextChannelId) { - await api(`/channels/${state.selectedTextChannelId}/messages`, { - method: "POST", - body: JSON.stringify({ body: url }), - }); - } else if (state.selectedDmUserId) { - await api(`/dms/${state.selectedDmUserId}/messages`, { - method: "POST", - body: JSON.stringify({ body: url }), - }); - } - const messages = state.selectedTextChannelId - ? await api(`/channels/${state.selectedTextChannelId}/messages?limit=100`) - : await api(`/dms/${state.selectedDmUserId}/messages?limit=100`); - renderMessages(messages); - } catch (err) { - console.error("Failed to send GIF", err); - } - } - - async function uploadMediaFile(file) { - if (file.size > MAX_MEDIA_UPLOAD_BYTES) { - showMediaUploadLimitError(file); - return; - } - - const path = state.selectedTextChannelId - ? `/channels/${state.selectedTextChannelId}/attachments` - : state.selectedDmUserId - ? `/dms/${state.selectedDmUserId}/attachments` - : null; - if (!path) throw new Error("Select a chat first."); - - el.mediaUploadBtn.disabled = true; - el.mediaUploadBtn.title = "Uploading..."; - - try { - const response = await fetch(path, { - method: "POST", - headers: { - "Content-Type": file.type || "application/octet-stream", - "X-File-Name": file.name, - }, - body: file, - credentials: "same-origin", - }); - - if (!response.ok) { - let detail = "upload failed"; - try { - const payload = await response.json(); - detail = payload.error || detail; - } catch { } - throw new Error(`${response.status}: ${detail}`); - } - - const messages = state.selectedTextChannelId - ? await api(`/channels/${state.selectedTextChannelId}/messages?limit=100`) - : await api(`/dms/${state.selectedDmUserId}/messages?limit=100`); - renderMessages(messages); - await loadDMConversations(); - renderDMs(); - } finally { - el.mediaUploadBtn.disabled = false; - el.mediaUploadBtn.title = "Upload File"; - } - } - - // 6. Initial Data Loading & App Start - try { - state.me = await api("/me"); - state.sessionActive = true; - if (state.me && state.me.display_name) { - el.userName.textContent = state.me.display_name; - el.userAvatar.textContent = shortName(state.me.display_name); - } - el.status.textContent = ""; - el.authScreen.classList.add("hidden"); - el.main.classList.remove("hidden"); - - // Check for invite code in URL - const params = new URLSearchParams(location.search); - const inviteCode = params.get("invite"); - if (inviteCode) { - try { - const joinedGuild = await api(`/invites/${encodeURIComponent(inviteCode)}/join`, { method: "POST" }); - storageSet(LAST_GUILD_STORAGE_KEY, joinedGuild.id); - } catch (err) { alert(`Failed to join invite: ${err.message}`); } finally { - params.delete("invite"); - const nextQuery = params.toString(); - const nextUrl = `${location.pathname}${nextQuery ? `?${nextQuery}` : ""}`; - history.replaceState(null, "", nextUrl); - } - } - - state.guilds = await api("/guilds"); - renderGuilds(); - await loadDMConversations(); - - try { - const online = await api("/presence"); - state.onlineUsers = new Set(online.filter((entry) => entry.online).map((entry) => entry.user_id)); - state.idleUsers = new Set(online.filter((entry) => entry.idle).map((entry) => entry.user_id)); - } catch (err) { console.warn("presence sync failed", err); } - - if (state.guilds.length > 0) { - const lastGuildId = storageGet(LAST_GUILD_STORAGE_KEY); - const guild = state.guilds.find((g) => g.id === lastGuildId) || state.guilds[0]; - state.selectedGuildId = guild.id; - storageSet(LAST_GUILD_STORAGE_KEY, guild.id); - renderGuilds(); - await loadChannels(); - await loadGuildMembers(); - await refreshVoicePresence(); - updateHeaderLabels(); - } else { - state.members = []; - renderMembers(); - updateHeaderLabels(); - } - - initChatWs(); - startVoicePresencePolling(); - - // Auto-reconnect to voice if previously joined - const savedVoiceChannel = storageGet("active_voice_channel"); - if (savedVoiceChannel) { - console.log("Auto-reconnecting to voice channel:", savedVoiceChannel); - state.selectedVoiceChannelId = savedVoiceChannel; - setTimeout(() => { - joinVoice().catch(err => console.error("Auto-reconnect failed", err)); - }, 800); - } - - lucide.createIcons(); - } catch (err) { - if (!err?.isAuthError) { - console.error("init failed", err); - await showLoggedOutState("Unable to load the app."); - } - } -} - -function initUpdater() { - if (!window.electronAPI || !el.updateNotifier || !el.updateDownloadBtn || !el.updateInstallBtn) return; - if (updaterInitialized) return; - updaterInitialized = true; - - const applyUpdateState = (state) => { - if (!state || !state.status) return; - if (state.status === 'available') { - const v = state.info?.version ? ` ${state.info.version}` : ''; - el.updateNotifier.classList.remove("hidden"); - el.updateDownloadBtn.classList.remove("hidden"); - el.updateInstallBtn.classList.add("hidden"); - el.updateDownloadBtn.disabled = false; - el.updateDownloadBtn.style.opacity = ""; - el.updateDownloadBtn.title = `Download Update${v}`; - return; - } - if (state.status === 'downloading') { - el.updateNotifier.classList.remove("hidden"); - el.updateDownloadBtn.classList.remove("hidden"); - el.updateInstallBtn.classList.add("hidden"); - el.updateDownloadBtn.disabled = true; - el.updateDownloadBtn.style.opacity = "0.5"; - el.updateDownloadBtn.title = "Downloading update..."; - return; - } - if (state.status === 'downloaded') { - const v = state.info?.version ? ` ${state.info.version}` : ''; - el.updateNotifier.classList.remove("hidden"); - el.updateDownloadBtn.classList.add("hidden"); - el.updateInstallBtn.classList.remove("hidden"); - el.updateInstallBtn.title = `Install Update${v}`; - return; - } - if (state.status === 'not-available') { - el.updateNotifier.classList.add("hidden"); - el.updateDownloadBtn.disabled = false; - el.updateDownloadBtn.style.opacity = ""; - return; - } - if (state.status === 'error') { - el.updateDownloadBtn.disabled = false; - el.updateDownloadBtn.style.opacity = ""; - } - }; - - window.electronAPI.onUpdateState((state) => { - applyUpdateState(state); - }); - - window.electronAPI.onUpdateAvailable((info) => { - console.log("Update available:", info.version); - el.updateNotifier.classList.remove("hidden"); - el.updateDownloadBtn.classList.remove("hidden"); - el.updateInstallBtn.classList.add("hidden"); - }); - - window.electronAPI.onUpdateDownloaded((info) => { - console.log("Update downloaded:", info.version); - el.updateNotifier.classList.remove("hidden"); - el.updateDownloadBtn.classList.add("hidden"); - el.updateInstallBtn.classList.remove("hidden"); - el.updateInstallBtn.title = `Install Update ${info.version}`; - }); - - window.electronAPI.onUpdateError((err) => { - console.error("Update error:", err); - // Optionally hide indicator on error - // el.updateNotifier.classList.add("hidden"); - }); - - el.updateDownloadBtn.onclick = () => { - el.updateDownloadBtn.disabled = true; - el.updateDownloadBtn.style.opacity = "0.5"; - window.electronAPI.downloadUpdate(); - }; - - el.updateInstallBtn.onclick = () => { - window.electronAPI.quitAndInstall(); - }; - - // Recover missed startup events and then run a fresh check now that listeners exist. - window.electronAPI.getUpdateState?.() - .then((state) => applyUpdateState(state)) - .catch((err) => console.warn("Failed to fetch initial update state", err)) - .finally(() => { - if (window.electronAPI.checkForUpdatesNow) { - void window.electronAPI.checkForUpdatesNow() - .then((state) => applyUpdateState(state)) - .catch((err) => console.warn("Direct update check failed", err)); - } else { - window.electronAPI.checkForUpdates?.(); - } - }); -} - -init(); diff --git a/static/styles.css b/static/styles.css index cc5a4ad..508c91a 100644 --- a/static/styles.css +++ b/static/styles.css @@ -1,42 +1,27 @@ :root { - /* ── Backgrounds ─────────────────────────────────────────── */ - --bg-darker: #16171b; - --bg-sidebar: #1e2025; - --bg-main: #23252b; - --bg-secondary: #1a1c21; - --bg-tertiary: #111216; - --bg-modifier-selected: rgba(99, 102, 241, 0.15); - --bg-modifier-hover: rgba(255, 255, 255, 0.04); - --bg-input: #2a2d35; + --bg-darker: #1e1f22; + --bg-sidebar: #2b2d31; + --bg-main: #313338; + --bg-secondary: #232428; + --bg-tertiary: #111214; + --bg-modifier-selected: rgba(78, 80, 88, 0.6); + --bg-modifier-hover: rgba(78, 80, 88, 0.3); + --bg-input: #383a40; - /* ── Text ────────────────────────────────────────────────── */ - --text-normal: #c9cdd4; - --text-muted: #7c818a; - --text-strong: #eef0f4; - --text-link: #818cf8; + --text-normal: #dbdee1; + --text-muted: #949ba4; + --text-strong: #f2f3f5; + --text-link: #00a8fc; - /* ── Accents ─────────────────────────────────────────────── */ - --brand: #6366f1; - --brand-hover: #4f46e5; - --brand-gradient: linear-gradient(135deg, #6366f1, #a855f7); - --brand-glow: rgba(99, 102, 241, 0.35); - --green: #22c55e; - --danger: #ef4444; - --yellow: #f59e0b; + --brand: #5865f2; + --brand-hover: #4752c4; + --green: #23a559; + --danger: #f23f43; + --yellow: #f0b232; - /* ── Misc ────────────────────────────────────────────────── */ - --font-main: "Inter", "Noto Sans", "Helvetica Neue", Helvetica, Arial, - sans-serif; - --radius-sm: 6px; - --radius-md: 10px; - --radius-lg: 14px; - --radius-xl: 20px; - --transition: 200ms cubic-bezier(0.4, 0, 0.2, 1); + --font-main: "gg sans", "Inter", "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; } -/* ═══════════════════════════════════════════════════════════ */ -/* Reset & Base */ -/* ═══════════════════════════════════════════════════════════ */ * { box-sizing: border-box; } @@ -49,14 +34,12 @@ body { color: var(--text-normal); font-family: var(--font-main); overflow: hidden; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; } -/* ── Scrollbars ────────────────────────────────────────────── */ +/* Scrollbars */ ::-webkit-scrollbar { - width: 6px; - height: 6px; + width: 8px; + height: 8px; } ::-webkit-scrollbar-track { @@ -64,19 +47,18 @@ body { } ::-webkit-scrollbar-thumb { - background: rgba(255, 255, 255, 0.08); - border-radius: 100px; + background: var(--bg-tertiary); + border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { - background: rgba(255, 255, 255, 0.14); + background: #242529; } -/* ── Base Elements ─────────────────────────────────────────── */ button { border: 0; cursor: pointer; - transition: all var(--transition); + transition: all 150ms ease; background: none; color: inherit; font: inherit; @@ -96,135 +78,71 @@ select { display: none !important; } -/* ═══════════════════════════════════════════════════════════ */ -/* Auth Screen */ -/* ═══════════════════════════════════════════════════════════ */ +/* Auth Screen */ .auth-screen { display: grid; place-items: center; height: 100vh; - /* Subtle animated gradient background */ - background: linear-gradient(135deg, #0f0c29, #16171b 40%, #1a1c2e 70%, #0f0c29); - background-size: 400% 400%; - animation: gradientShift 12s ease infinite; -} - -@keyframes gradientShift { - - 0%, - 100% { - background-position: 0% 50%; - } - - 50% { - background-position: 100% 50%; - } + background-image: url("https://discord.com/assets/f9a15998e94589d343f7.png"); + background-size: cover; } .auth-card { - width: min(440px, 92vw); - background: rgba(30, 32, 37, 0.75); - backdrop-filter: blur(24px) saturate(1.4); - -webkit-backdrop-filter: blur(24px) saturate(1.4); - border: 1px solid rgba(255, 255, 255, 0.06); - border-radius: var(--radius-xl); - padding: 40px 36px; - box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5), 0 0 80px rgba(99, 102, 241, 0.08); + width: min(480px, 92vw); + background: var(--bg-sidebar); + border-radius: 8px; + padding: 32px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); text-align: center; } .brand-large { width: 80px; height: 80px; - background: var(--brand-gradient); + background: var(--brand); color: #fff; - border-radius: 22px; + border-radius: 20px; display: grid; place-items: center; - font-size: 38px; + font-size: 40px; font-weight: 800; - margin: 0 auto 24px; - box-shadow: 0 4px 24px var(--brand-glow); - transition: transform var(--transition), box-shadow var(--transition); -} - -.brand-large:hover { - transform: scale(1.05); - box-shadow: 0 6px 32px var(--brand-glow); + margin: 0 auto 20px; } .auth-card h1 { margin: 0 0 8px; color: var(--text-strong); - font-weight: 800; - font-size: 28px; - letter-spacing: -0.5px; } .auth-card p { - margin: 0 0 28px; + margin: 0 0 24px; color: var(--text-muted); - font-size: 15px; } #login-btn { width: 100%; - background: var(--brand-gradient); + background: var(--brand); color: #fff; - padding: 14px; - border-radius: var(--radius-md); + padding: 12px; + border-radius: 3px; font-weight: 600; font-size: 16px; - letter-spacing: 0.2px; - box-shadow: 0 2px 16px var(--brand-glow); - transition: all var(--transition); } #login-btn:hover { - transform: translateY(-1px); - box-shadow: 0 4px 24px var(--brand-glow); - filter: brightness(1.08); + background: var(--brand-hover); } -#login-btn:active { - transform: translateY(0); -} - -.auth-downloads { - margin: 14px 0 6px; - display: flex; - align-items: center; - justify-content: center; - gap: 10px; - flex-wrap: wrap; - font-size: 13px; - color: var(--text-muted); -} - -.auth-downloads a { - color: var(--text-link); - text-decoration: none; - font-weight: 600; -} - -.auth-downloads a:hover { - text-decoration: underline; -} - -/* ═══════════════════════════════════════════════════════════ */ -/* Main Layout */ -/* ═══════════════════════════════════════════════════════════ */ +/* Main Layout */ .shell { height: 100vh; height: 100dvh; display: grid; - grid-template-columns: 72px 248px 1fr 248px; + grid-template-columns: 72px 240px 1fr 240px; background: var(--bg-main); } -/* ═══════════════════════════════════════════════════════════ */ -/* Server Rail */ -/* ═══════════════════════════════════════════════════════════ */ +/* Server Rail */ .server-rail { background: var(--bg-darker); display: flex; @@ -255,28 +173,26 @@ select { display: flex; align-items: center; justify-content: center; - transition: all var(--transition); + transition: all 0.2s ease; position: relative; background: var(--bg-sidebar); } .brand { - background: var(--brand-gradient); + background: var(--brand); color: #fff; border-radius: 16px; margin-bottom: 2px; - box-shadow: 0 2px 12px var(--brand-glow); } .brand:hover { border-radius: 16px; - box-shadow: 0 4px 20px var(--brand-glow); } .separator { width: 32px; height: 2px; - background: rgba(255, 255, 255, 0.06); + background: var(--bg-modifier-selected); margin-bottom: 2px; border-radius: 1px; } @@ -286,7 +202,6 @@ select { border-radius: 16px; background: var(--brand); color: #fff; - box-shadow: 0 2px 12px var(--brand-glow); } .guild-pill::before { @@ -297,7 +212,7 @@ select { height: 0; background: #fff; border-radius: 0 4px 4px 0; - transition: all var(--transition); + transition: all 0.2s ease; } .guild-pill:hover::before { @@ -315,12 +230,9 @@ select { .action-pill:hover { background: var(--green); color: #fff; - box-shadow: 0 2px 12px rgba(34, 197, 94, 0.3); } -/* ═══════════════════════════════════════════════════════════ */ -/* Channel Sidebar */ -/* ═══════════════════════════════════════════════════════════ */ +/* Channel Sidebar */ .channel-sidebar { background: var(--bg-sidebar); display: flex; @@ -333,10 +245,10 @@ select { display: flex; align-items: center; justify-content: space-between; - border-bottom: 1px solid rgba(255, 255, 255, 0.04); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.15); + border-bottom: 1px solid var(--bg-darker); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); cursor: pointer; - transition: background-color var(--transition); + transition: background-color 0.1s; } .sidebar-header:hover { @@ -351,7 +263,6 @@ select { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - letter-spacing: -0.2px; } .sidebar-header-actions { @@ -361,56 +272,17 @@ select { } .header-action-btn { - width: 28px; - height: 28px; - border-radius: var(--radius-sm); + width: 24px; + height: 24px; + border-radius: 4px; display: grid; place-items: center; color: var(--text-muted); - transition: all var(--transition); } .header-action-btn:hover { background: var(--bg-modifier-hover); - color: var(--text-strong); -} - -.copied-badge { - background: var(--brand); - color: #fff; - font-size: 11px; - font-weight: 700; - padding: 2px 6px; - border-radius: 4px; - text-transform: uppercase; - letter-spacing: 0.4px; - animation: fadeInOut 2s ease forwards; - pointer-events: none; - white-space: nowrap; - order: -1; - margin-right: 4px; -} - -@keyframes fadeInOut { - 0% { - opacity: 0; - transform: translateY(4px); - } - - 15% { - opacity: 1; - transform: translateY(0); - } - - 85% { - opacity: 1; - transform: translateY(0); - } - - 100% { - opacity: 0; - transform: translateY(-4px); - } + color: var(--text-normal); } .header-action-btn i { @@ -433,12 +305,11 @@ select { display: flex; align-items: center; color: var(--text-muted); - font-size: 11px; + font-size: 12px; font-weight: 700; text-transform: uppercase; - letter-spacing: 0.5px; + letter-spacing: 0.24px; cursor: pointer; - transition: color var(--transition); } .group-title:hover { @@ -458,10 +329,9 @@ select { .add-btn { width: 20px; height: 20px; - border-radius: var(--radius-sm); - opacity: 0.5; - transition: opacity var(--transition), background-color var(--transition), - transform var(--transition); + border-radius: 4px; + opacity: 0.7; + transition: opacity 0.2s, background-color 0.2s; display: grid; place-items: center; } @@ -469,7 +339,6 @@ select { .add-btn:hover { opacity: 1; background: var(--bg-modifier-hover); - transform: scale(1.1); } .add-btn i { @@ -487,13 +356,11 @@ select { .channel-row { display: flex; align-items: center; - padding: 7px 10px; - border-radius: var(--radius-sm); + padding: 6px 8px; + border-radius: 4px; color: var(--text-muted); font-weight: 500; - gap: 8px; - transition: all var(--transition); - border-left: 3px solid transparent; + gap: 6px; } .channel-row:hover { @@ -504,36 +371,26 @@ select { .channel-row.active { background: var(--bg-modifier-selected); color: var(--text-strong); - border-left-color: var(--brand); } .channel-row i { width: 20px; height: 20px; - opacity: 0.5; + opacity: 0.6; } -.channel-row.active i { - opacity: 0.9; -} - -/* ═══════════════════════════════════════════════════════════ */ -/* Sidebar Footer */ -/* ═══════════════════════════════════════════════════════════ */ +/* Sidebar Footer */ .sidebar-footer { background: var(--bg-secondary); padding: 0; } .user-panel { - padding: 8px 10px; + padding: 8px; display: flex; align-items: center; - gap: 10px; + gap: 8px; height: 52px; - transition: background-color var(--transition); - border-radius: var(--radius-sm); - margin: 2px; } .user-panel:hover { @@ -548,12 +405,12 @@ select { width: 32px; height: 32px; border-radius: 50%; - background: var(--brand-gradient); + background: var(--brand); color: #fff; display: grid; place-items: center; font-weight: 700; - font-size: 13px; + font-size: 14px; } .status-dot { @@ -568,78 +425,6 @@ select { .status-dot.online { background: var(--green); - box-shadow: 0 0 6px rgba(34, 197, 94, 0.4); -} - -.status-dot.idle { - background: var(--yellow); - box-shadow: 0 0 6px rgba(245, 158, 11, 0.4); -} - -.voice-muted-icon { - width: 14px; - height: 14px; - color: var(--danger); - margin-left: 6px; - vertical-align: text-bottom; -} - -.user-volume-control { - width: 100%; - display: none; - /* Hidden by default */ - align-items: center; - gap: 8px; - padding: 4px 8px 4px 28px; - margin-top: 2px; - box-sizing: border-box; - background: rgba(0, 0, 0, 0.2); - border-radius: 4px; - overflow: hidden; -} - -.user-volume-control.show-volume { - display: flex; - /* Show when active */ -} - -.volume-slider { - -webkit-appearance: none; - appearance: none; - background: var(--bg-darker); - border-radius: 2px; - outline: none; - flex: 1; - height: 4px; - cursor: pointer; - min-width: 0; -} - -.vol-pct { - font-size: 10px; - opacity: 0.6; - min-width: 30px; - text-align: right; -} - -.volume-slider::-webkit-slider-thumb { - -webkit-appearance: none; - appearance: none; - width: 10px; - height: 10px; - border-radius: 50%; - background: var(--brand); - cursor: pointer; - box-shadow: 0 0 4px var(--brand-glow); -} - -.volume-slider::-moz-range-thumb { - width: 10px; - height: 10px; - border-radius: 50%; - background: var(--brand); - cursor: pointer; - box-shadow: 0 0 4px var(--brand-glow); } .user-info { @@ -669,16 +454,15 @@ select { .user-actions button { width: 32px; height: 32px; - border-radius: var(--radius-sm); + border-radius: 4px; display: grid; place-items: center; color: var(--text-muted); - transition: all var(--transition); } .user-actions button:hover { background: var(--bg-modifier-hover); - color: var(--text-strong); + color: var(--text-normal); } .user-actions i { @@ -686,13 +470,11 @@ select { height: 20px; } -/* ═══════════════════════════════════════════════════════════ */ -/* Voice Connection */ -/* ═══════════════════════════════════════════════════════════ */ +/* Voice Connection */ .voice-connection { - padding: 10px 12px; + padding: 8px; background: var(--bg-secondary); - border-bottom: 1px solid rgba(255, 255, 255, 0.03); + border-bottom: 1px solid rgba(255, 255, 255, 0.05); } .vc-info { @@ -704,7 +486,6 @@ select { .vc-icon { color: var(--green); width: 20px; - filter: drop-shadow(0 0 4px rgba(34, 197, 94, 0.4)); } .vc-text { @@ -732,479 +513,25 @@ select { .vc-actions button { width: 32px; height: 32px; - border-radius: var(--radius-sm); + border-radius: 4px; color: var(--text-muted); display: grid; place-items: center; - transition: all var(--transition); } .vc-actions button:hover { background: var(--bg-modifier-hover); - color: var(--text-strong); -} - -/* ═══════════════════════════════════════════════════════════ */ -/* Video Grid */ -/* ═══════════════════════════════════════════════════════════ */ -.video-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); - gap: 16px; - padding: 16px; - background: var(--bg-tertiary); - flex: 1; - min-height: 0; - overflow-y: auto; -} - -.video-grid.hidden { - display: none; -} - -.video-item { - position: relative; - aspect-ratio: 16 / 9; - background: #000; - border-radius: var(--radius-lg); - overflow: hidden; - transition: all var(--transition); - cursor: pointer; - z-index: 1; -} - -.video-item:hover { - box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.2); - z-index: 2; -} - -.video-item video { - width: 100%; - height: 100%; - object-fit: contain; - background: #000; - pointer-events: none; -} - -/* Fullscreen Feed Support */ -.video-grid.has-fullscreen { - display: flex; - padding: 0; - overflow: hidden; - position: absolute; - top: 48px; - /* Below chat-header */ - left: 0; - right: 0; - bottom: 0; - z-index: 100; - background: var(--bg-main); -} - -.video-grid.has-fullscreen .video-item { - display: none; -} - -.video-grid.has-fullscreen .video-item.fullscreen { - display: block; - flex: 1; - width: 100%; - height: 100%; - border-radius: 0; - cursor: zoom-out; - z-index: 10; - aspect-ratio: auto; -} - -.video-item .video-label { - position: absolute; - bottom: 8px; - left: 8px; - background: rgba(0, 0, 0, 0.6); - backdrop-filter: blur(8px); - color: #fff; - padding: 3px 10px; - border-radius: 100px; - font-size: 12px; - font-weight: 500; - pointer-events: none; - z-index: 5; -} - -/* Voice Activity */ -.voice-speaking .avatar { - box-shadow: 0 0 0 2px var(--green), 0 0 8px rgba(34, 197, 94, 0.3); -} - -.video-item.speaking { - box-shadow: 0 0 0 3px var(--green), 0 0 16px rgba(34, 197, 94, 0.25); -} - -.video-item.speaking .video-label { - background: var(--green); -} - -/* ═══════════════════════════════════════════════════════════ */ -/* Chat Input */ -/* ═══════════════════════════════════════════════════════════ */ -.chat-input-wrapper { - padding: 0 16px 24px; -} - -.message-form { - background: var(--bg-input); - border-radius: var(--radius-md); - padding: 2px 12px; - display: flex; - align-items: center; - gap: 12px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15); -} - -.input-action-btn { - color: var(--text-muted); - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; - border-radius: var(--radius-sm); -} - -.input-action-btn:hover { - color: var(--text-normal); - background: var(--bg-modifier-hover); -} - -.message-form input { - flex: 1; - background: none; - border: 0; - padding: 12px 0; - font-size: 15px; color: var(--text-normal); } -.hidden-file-input { - display: none; -} - -/* ═══════════════════════════════════════════════════════════ */ -/* GIF Picker Modal */ -/* ═══════════════════════════════════════════════════════════ */ -.gif-modal { - width: min(500px, 95vw) !important; - max-height: 600px; - display: flex; - flex-direction: column; - padding: 0 !important; - overflow: hidden; -} - -.gif-modal .modal-header { - padding: 16px 20px; - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 1px solid rgba(255, 255, 255, 0.05); -} - -.gif-modal .modal-header h2 { - margin: 0; - font-size: 18px; -} - -.gif-search-wrapper { - padding: 16px 20px; - position: relative; -} - -.gif-search-wrapper input { - width: 100%; - background: var(--bg-darker); - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: var(--radius-md); - padding: 12px 14px 12px 40px; - color: #fff; - font-size: 14px; - transition: border-color var(--transition); -} - -.gif-search-wrapper input:focus { - border-color: var(--brand); -} - -.gif-search-wrapper .search-icon { - position: absolute; - left: 32px; - top: 50%; - transform: translateY(-50%); - width: 18px; - height: 18px; - color: var(--text-muted); -} - -.gif-results-grid { - flex: 1; - overflow-y: auto; - padding: 0 20px 20px; - display: grid; - grid-template-columns: repeat(2, 1fr); - grid-auto-rows: min-content; - gap: 8px; - min-height: 300px; -} - -.gif-item { - border-radius: var(--radius-sm); - overflow: hidden; - cursor: pointer; - background: var(--bg-sidebar); - width: 100%; - aspect-ratio: 16 / 9; - transition: transform var(--transition); -} - -.gif-item:hover { - transform: scale(1.02); - filter: brightness(1.1); -} - -.gif-item img { - width: 100%; - height: 100%; - object-fit: cover; -} - -.gif-loading { - grid-column: 1 / -1; - text-align: center; - padding: 40px; - color: var(--text-muted); -} - -/* ── GIF in messages ────────────────────────────────────────── */ -.msg-gif { - margin-top: 8px; - max-width: 100%; - max-height: 300px; - border-radius: var(--radius-md); - overflow: hidden; - display: block; -} - -.msg-gif img { - max-width: 100%; - max-height: 300px; - display: block; - object-fit: contain; -} - -.msg-attachment { - display: block; - margin-top: 8px; -} - -.msg-attachment-image { - max-width: min(440px, 100%); - border-radius: var(--radius-md); - overflow: hidden; -} - -.msg-attachment-image img { - width: 100%; - max-height: 360px; - object-fit: contain; - display: block; - background: rgba(0, 0, 0, 0.18); -} - -.msg-attachment-video { - max-width: min(520px, 100%); -} - -.msg-attachment-video video { - width: 100%; - max-height: 420px; - border-radius: var(--radius-md); - background: #000; -} - -.msg-attachment-audio { - display: flex; - flex-direction: column; - gap: 10px; - padding: 12px 14px; - max-width: min(420px, 100%); - border-radius: var(--radius-md); - background: rgba(255, 255, 255, 0.04); - border: 1px solid rgba(255, 255, 255, 0.06); -} - -.msg-attachment-audio audio { - width: 100%; -} - -.msg-attachment-audio a { - color: var(--text-link); - font-size: 13px; -} - -.msg-attachment-file { - display: inline-flex; - align-items: center; - gap: 10px; - padding: 10px 12px; - max-width: min(420px, 100%); - border-radius: var(--radius-md); - background: rgba(255, 255, 255, 0.04); - border: 1px solid rgba(255, 255, 255, 0.06); - color: var(--text-normal); -} - -.msg-attachment-file:hover { - background: rgba(255, 255, 255, 0.07); -} - -.msg-attachment-file i { - width: 18px; - height: 18px; - color: var(--text-link); - flex-shrink: 0; -} - -.msg-attachment-file span { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.msg-attachment-file small { - color: var(--text-muted); - margin-left: auto; - white-space: nowrap; -} - -/* ═══════════════════════════════════════════════════════════ */ -/* Sound Board */ -/* ═══════════════════════════════════════════════════════════ */ -.soundboard-container { - padding: 12px; - background: var(--bg-secondary); - border-top: 1px solid rgba(255, 255, 255, 0.03); - display: flex; - flex-direction: column; - gap: 8px; -} - -.soundboard-header { - display: flex; - justify-content: space-between; - align-items: center; - font-size: 12px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.4px; - color: var(--text-muted); -} - -.soundboard-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); - gap: 8px; - max-height: 200px; - overflow-y: auto; -} - -.sound-item { - display: flex; - flex-direction: column; - align-items: center; - gap: 4px; - padding: 10px 8px; - background: var(--bg-darker); - border-radius: var(--radius-md); - cursor: pointer; - transition: all var(--transition); - border: 1px solid transparent; - position: relative; -} - -.sound-item:hover { - background: var(--bg-modifier-hover); - transform: translateY(-2px); - border-color: rgba(255, 255, 255, 0.06); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); -} - -.sound-item:active { - transform: scale(0.95); -} - -.sound-delete { - position: absolute; - top: 4px; - right: 4px; - width: 18px; - height: 18px; - border-radius: 50%; - background: rgba(0, 0, 0, 0.6); - color: var(--text-muted); - display: grid; - place-items: center; - opacity: 0; - transition: all var(--transition); - z-index: 2; -} - -.sound-delete:hover { - background: var(--danger); - color: #fff; - transform: scale(1.1); -} - -.sound-item:hover .sound-delete { - opacity: 1; -} - -.sound-icon { - font-size: 24px; - display: block; - object-fit: contain; -} - -.sound-name { - font-size: 11px; - text-align: center; - color: var(--text-normal); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - width: 100%; -} - -.btn-add-sound { - font-size: 12px; - color: var(--brand); - cursor: pointer; - transition: color var(--transition); -} - -.btn-add-sound:hover { - color: var(--text-link); - text-decoration: underline; -} - -/* ═══════════════════════════════════════════════════════════ */ -/* Chat Pane */ -/* ═══════════════════════════════════════════════════════════ */ +/* Chat Pane */ .chat-pane { - position: relative; display: flex; flex-direction: column; background: var(--bg-main); min-width: 0; min-height: 0; + /* Important for flex child overflow */ } .chat-header { @@ -1213,8 +540,8 @@ select { display: flex; align-items: center; gap: 8px; - border-bottom: 1px solid rgba(255, 255, 255, 0.04); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.15); + border-bottom: 1px solid rgba(0, 0, 0, 0.2); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); } .header-icon { @@ -1227,7 +554,6 @@ select { font-size: 16px; font-weight: 700; color: var(--text-strong); - letter-spacing: -0.2px; } .message-list { @@ -1237,31 +563,26 @@ select { } .msg { - padding: 4px 16px; + padding: 2px 16px; display: flex; gap: 16px; margin-top: 1.0625rem; - border-radius: var(--radius-sm); - transition: background-color var(--transition); - border-left: 3px solid transparent; } .msg:hover { - background: rgba(255, 255, 255, 0.015); - border-left-color: rgba(99, 102, 241, 0.3); + background: rgba(0, 0, 0, 0.05); } .msg-avatar { width: 40px; height: 40px; border-radius: 50%; - background: var(--brand-gradient); + background: var(--brand); flex-shrink: 0; display: grid; place-items: center; color: #fff; font-weight: 600; - font-size: 15px; } .msg-content { @@ -1281,22 +602,20 @@ select { color: var(--text-strong); cursor: pointer; font-size: 1rem; - transition: color var(--transition); } .msg-author:hover { - color: var(--text-link); text-decoration: underline; } .msg-time { - font-size: 11px; + font-size: 12px; color: var(--text-muted); } .msg-body { color: var(--text-normal); - line-height: 1.45rem; + line-height: 1.375rem; white-space: pre-wrap; word-wrap: break-word; } @@ -1316,9 +635,7 @@ select { padding-left: 56px; } -/* ═══════════════════════════════════════════════════════════ */ -/* Chat Input */ -/* ═══════════════════════════════════════════════════════════ */ +/* Chat Input */ .chat-input-wrapper { padding: 0 16px 24px; padding-bottom: clamp(24px, calc(24px + env(safe-area-inset-bottom)), 40px); @@ -1326,31 +643,22 @@ select { .message-form { background: var(--bg-input); - border-radius: var(--radius-lg); - padding: 12px 18px; - border: 1px solid rgba(255, 255, 255, 0.04); - transition: border-color var(--transition), box-shadow var(--transition); -} - -.message-form:focus-within { - border-color: rgba(99, 102, 241, 0.4); - box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); + border-radius: 8px; + padding: 11px 16px; } .message-form input { width: 100%; background: transparent; color: var(--text-normal); - font-size: 15px; + font-size: 16px; } .message-form input::placeholder { color: var(--text-muted); } -/* ═══════════════════════════════════════════════════════════ */ -/* Member List / Utility Sidebar */ -/* ═══════════════════════════════════════════════════════════ */ +/* Member List */ .utility-sidebar { background: var(--bg-sidebar); display: flex; @@ -1367,11 +675,10 @@ select { display: flex; align-items: center; gap: 12px; - padding: 7px 10px; - border-radius: var(--radius-sm); + padding: 6px 8px; + border-radius: 4px; color: var(--text-muted); cursor: pointer; - transition: all var(--transition); } .member-row:hover { @@ -1383,11 +690,11 @@ select { width: 32px; height: 32px; border-radius: 50%; - background: var(--brand-gradient); + background: var(--brand); color: #fff; display: grid; place-items: center; - font-size: 13px; + font-size: 14px; font-weight: 600; flex-shrink: 0; } @@ -1397,7 +704,7 @@ select { text-overflow: ellipsis; } -/* ── Presence Badges ───────────────────────────────────────── */ +/* Presence Badges */ .avatar-wrapper { position: relative; display: inline-block; @@ -1412,11 +719,11 @@ select { border-radius: 50%; border: 2px solid var(--bg-sidebar); background: #747f8d; + /* Gray for offline */ } .status-badge.online { background: var(--green); - box-shadow: 0 0 6px rgba(34, 197, 94, 0.4); } .member-avatar, @@ -1437,52 +744,33 @@ select { .status-dot.online { background: var(--green); - box-shadow: 0 0 6px rgba(34, 197, 94, 0.4); } -/* ═══════════════════════════════════════════════════════════ */ -/* Modals */ -/* ═══════════════════════════════════════════════════════════ */ +/* Modals */ .modal-container { position: fixed; top: 0; left: 0; right: 0; bottom: 0; - background: rgba(0, 0, 0, 0.7); - backdrop-filter: blur(6px); - -webkit-backdrop-filter: blur(6px); + background: rgba(0, 0, 0, 0.85); display: grid; place-items: center; z-index: 1000; } .modal { - background: rgba(30, 32, 37, 0.92); - backdrop-filter: blur(20px) saturate(1.4); - -webkit-backdrop-filter: blur(20px) saturate(1.4); - border: 1px solid rgba(255, 255, 255, 0.06); - width: min(460px, 95vw); - border-radius: var(--radius-xl); - padding: 28px; + background: var(--bg-sidebar); + width: min(440px, 95vw); + border-radius: 5px; + padding: 24px; color: var(--text-normal); - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5); } .modal h2 { - margin: 0 0 20px; + margin: 0 0 16px; text-align: center; color: var(--text-strong); - font-weight: 700; - font-size: 22px; - letter-spacing: -0.3px; -} - -.modal-copy { - margin: 0; - text-align: center; - color: var(--text-normal); - line-height: 1.5; } .form-item { @@ -1491,69 +779,49 @@ select { .form-item label { display: block; - font-size: 11px; + font-size: 12px; font-weight: 700; color: var(--text-muted); margin-bottom: 8px; - text-transform: uppercase; - letter-spacing: 0.5px; } .form-item input { width: 100%; - padding: 11px 14px; - border-radius: var(--radius-md); + padding: 10px; + border-radius: 3px; background: var(--bg-darker); - border: 1px solid rgba(255, 255, 255, 0.04); - transition: border-color var(--transition), box-shadow var(--transition); -} - -.form-item input:focus { - border-color: rgba(99, 102, 241, 0.4); - box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } .modal-footer { margin-top: 24px; display: flex; justify-content: flex-end; - gap: 12px; + gap: 16px; } .cancel-btn { padding: 10px 20px; - color: var(--text-muted); + color: var(--text-strong); font-weight: 500; - border-radius: var(--radius-md); - transition: all var(--transition); } .cancel-btn:hover { - color: var(--text-strong); - background: var(--bg-modifier-hover); + text-decoration: underline; } .submit-btn { - background: var(--brand-gradient); + background: var(--brand); color: #fff; padding: 10px 24px; - border-radius: var(--radius-md); + border-radius: 3px; font-weight: 600; - box-shadow: 0 2px 12px var(--brand-glow); - transition: all var(--transition); } .submit-btn:hover { - transform: translateY(-1px); - box-shadow: 0 4px 20px var(--brand-glow); - filter: brightness(1.06); + background: var(--brand-hover); } -.submit-btn:active { - transform: translateY(0); -} - -/* ── Radio Group (Channel Type) ────────────────────────────── */ +/* Radio Group for Channel Type */ .radio-group { display: flex; flex-direction: column; @@ -1574,16 +842,14 @@ select { display: flex; align-items: center; gap: 12px; - padding: 12px; + padding: 10px; background: var(--bg-modifier-hover); - border-radius: var(--radius-md); - border: 1px solid transparent; - transition: all var(--transition); + border-radius: 4px; + transition: all 0.1s; } .radio-item input:checked+.radio-box { background: var(--bg-modifier-selected); - border-color: rgba(99, 102, 241, 0.3); color: var(--text-strong); } @@ -1607,9 +873,7 @@ select { color: var(--text-muted); } -/* ═══════════════════════════════════════════════════════════ */ -/* Mobile Overlay */ -/* ═══════════════════════════════════════════════════════════ */ +/* Mobile Overlay */ .overlay { position: fixed; top: 0; @@ -1628,7 +892,7 @@ select { visibility: hidden; } -/* ── Mobile Toggle Buttons ─────────────────────────────────── */ +/* Mobile Toggle Buttons */ .mobile-toggle-btn { display: none; width: 32px; @@ -1642,15 +906,12 @@ select { .mobile-toggle-btn:hover { background: var(--bg-modifier-hover); - border-radius: var(--radius-sm); + border-radius: 4px; } -/* ═══════════════════════════════════════════════════════════ */ -/* Responsive */ -/* ═══════════════════════════════════════════════════════════ */ @media (max-width: 1100px) { .shell { - grid-template-columns: 72px 248px 1fr; + grid-template-columns: 72px 240px 1fr; } .utility-sidebar { @@ -1658,11 +919,11 @@ select { top: 0; bottom: 0; right: 0; - width: 248px; + width: 240px; z-index: 100; - box-shadow: -2px 0 20px rgba(0, 0, 0, 0.5); + box-shadow: -2px 0 10px rgba(0, 0, 0, 0.5); transform: translateX(100%); - transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1); + transition: transform 0.2s ease; } .utility-sidebar.active { @@ -1680,13 +941,14 @@ select { grid-template-columns: 1fr; } + /* Hide sidebars by default on mobile */ .server-rail, .channel-sidebar { position: fixed; top: 0; bottom: 0; z-index: 100; - transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1); + transition: transform 0.2s ease; } .server-rail { @@ -1697,11 +959,13 @@ select { .channel-sidebar { left: 72px; - width: 248px; - transform: translateX(-320px); - box-shadow: 2px 0 20px rgba(0, 0, 0, 0.5); + width: 240px; + transform: translateX(-312px); + /* 72 + 240 */ + box-shadow: 2px 0 10px rgba(0, 0, 0, 0.5); } + /* When menu is active */ .shell.menu-open .server-rail { transform: translateX(0); } @@ -1709,9 +973,11 @@ select { .shell.menu-open .channel-sidebar { transform: translateX(0); display: flex; + /* Override display: none from previous rule */ } + /* Adjust chat header for mobile */ .chat-header { padding: 0 8px; } -} +} \ No newline at end of file diff --git a/static/vendor/deepfilternet3-noise-filter.esm.js b/static/vendor/deepfilternet3-noise-filter.esm.js deleted file mode 100644 index 7ad3ee9..0000000 --- a/static/vendor/deepfilternet3-noise-filter.esm.js +++ /dev/null @@ -1,249 +0,0 @@ -class AssetLoader { - constructor(config = {}) { - this.cdnUrl = config.cdnUrl ?? 'https://cdn.mezon.ai/AI/models/datas/noise_suppression/deepfilternet3'; - } - getCdnUrl(relativePath) { - return `${this.cdnUrl}/${relativePath}`; - } - getAssetUrls() { - return { - wasm: this.getCdnUrl('v2/pkg/df_bg.wasm'), - model: this.getCdnUrl('v2/models/DeepFilterNet3_onnx.tar.gz') - }; - } - async fetchAsset(url) { - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Failed to fetch asset: ${response.statusText}`); - } - return response.arrayBuffer(); - } -} -let defaultLoader = null; -function getAssetLoader(config) { - if (!defaultLoader || config) { - defaultLoader = new AssetLoader(config); - } - return defaultLoader; -} - -/** - * Creates a worklet module URL from inline code string - * This approach works with all bundlers without special configuration - */ -async function createWorkletModule(audioContext, workletCode) { - const blob = new Blob([workletCode], { type: 'application/javascript' }); - const blobUrl = URL.createObjectURL(blob); - await audioContext.audioWorklet.addModule(blobUrl); -} - -const WorkletMessageTypes = { - SET_SUPPRESSION_LEVEL: 'SET_SUPPRESSION_LEVEL', - SET_BYPASS: 'SET_BYPASS' -}; - -var workletCode = "(function () {\n 'use strict';\n\n let wasm;\n\n const heap = new Array(128).fill(undefined);\n\n heap.push(undefined, null, true, false);\n\n function getObject(idx) { return heap[idx]; }\n\n let heap_next = heap.length;\n\n function dropObject(idx) {\n if (idx < 132) return;\n heap[idx] = heap_next;\n heap_next = idx;\n }\n\n function takeObject(idx) {\n const ret = getObject(idx);\n dropObject(idx);\n return ret;\n }\n\n const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );\n\n if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }\n let cachedUint8Memory0 = null;\n\n function getUint8Memory0() {\n if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {\n cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);\n }\n return cachedUint8Memory0;\n }\n\n function getStringFromWasm0(ptr, len) {\n ptr = ptr >>> 0;\n return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));\n }\n\n function addHeapObject(obj) {\n if (heap_next === heap.length) heap.push(heap.length + 1);\n const idx = heap_next;\n heap_next = heap[idx];\n\n heap[idx] = obj;\n return idx;\n }\n /**\n * Set DeepFilterNet attenuation limit.\n *\n * Args:\n * - lim_db: New attenuation limit in dB.\n * @param {number} st\n * @param {number} lim_db\n */\n function df_set_atten_lim(st, lim_db) {\n wasm.df_set_atten_lim(st, lim_db);\n }\n\n /**\n * Get DeepFilterNet frame size in samples.\n * @param {number} st\n * @returns {number}\n */\n function df_get_frame_length(st) {\n const ret = wasm.df_get_frame_length(st);\n return ret >>> 0;\n }\n\n let WASM_VECTOR_LEN = 0;\n\n function passArray8ToWasm0(arg, malloc) {\n const ptr = malloc(arg.length * 1, 1) >>> 0;\n getUint8Memory0().set(arg, ptr / 1);\n WASM_VECTOR_LEN = arg.length;\n return ptr;\n }\n /**\n * Create a DeepFilterNet Model\n *\n * Args:\n * - path: File path to a DeepFilterNet tar.gz onnx model\n * - atten_lim: Attenuation limit in dB.\n *\n * Returns:\n * - DF state doing the full processing: stft, DNN noise reduction, istft.\n * @param {Uint8Array} model_bytes\n * @param {number} atten_lim\n * @returns {number}\n */\n function df_create(model_bytes, atten_lim) {\n const ptr0 = passArray8ToWasm0(model_bytes, wasm.__wbindgen_malloc);\n const len0 = WASM_VECTOR_LEN;\n const ret = wasm.df_create(ptr0, len0, atten_lim);\n return ret >>> 0;\n }\n\n let cachedFloat32Memory0 = null;\n\n function getFloat32Memory0() {\n if (cachedFloat32Memory0 === null || cachedFloat32Memory0.byteLength === 0) {\n cachedFloat32Memory0 = new Float32Array(wasm.memory.buffer);\n }\n return cachedFloat32Memory0;\n }\n\n function passArrayF32ToWasm0(arg, malloc) {\n const ptr = malloc(arg.length * 4, 4) >>> 0;\n getFloat32Memory0().set(arg, ptr / 4);\n WASM_VECTOR_LEN = arg.length;\n return ptr;\n }\n /**\n * Processes a chunk of samples.\n *\n * Args:\n * - df_state: Created via df_create()\n * - input: Input buffer of length df_get_frame_length()\n * - output: Output buffer of length df_get_frame_length()\n *\n * Returns:\n * - Local SNR of the current frame.\n * @param {number} st\n * @param {Float32Array} input\n * @returns {Float32Array}\n */\n function df_process_frame(st, input) {\n const ptr0 = passArrayF32ToWasm0(input, wasm.__wbindgen_malloc);\n const len0 = WASM_VECTOR_LEN;\n const ret = wasm.df_process_frame(st, ptr0, len0);\n return takeObject(ret);\n }\n\n function handleError(f, args) {\n try {\n return f.apply(this, args);\n } catch (e) {\n wasm.__wbindgen_exn_store(addHeapObject(e));\n }\n }\n\n (typeof FinalizationRegistry === 'undefined')\n ? { }\n : new FinalizationRegistry(ptr => wasm.__wbg_dfstate_free(ptr >>> 0));\n\n function __wbg_get_imports() {\n const imports = {};\n imports.wbg = {};\n imports.wbg.__wbindgen_object_drop_ref = function(arg0) {\n takeObject(arg0);\n };\n imports.wbg.__wbg_crypto_566d7465cdbb6b7a = function(arg0) {\n const ret = getObject(arg0).crypto;\n return addHeapObject(ret);\n };\n imports.wbg.__wbindgen_is_object = function(arg0) {\n const val = getObject(arg0);\n const ret = typeof(val) === 'object' && val !== null;\n return ret;\n };\n imports.wbg.__wbg_process_dc09a8c7d59982f6 = function(arg0) {\n const ret = getObject(arg0).process;\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_versions_d98c6400c6ca2bd8 = function(arg0) {\n const ret = getObject(arg0).versions;\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_node_caaf83d002149bd5 = function(arg0) {\n const ret = getObject(arg0).node;\n return addHeapObject(ret);\n };\n imports.wbg.__wbindgen_is_string = function(arg0) {\n const ret = typeof(getObject(arg0)) === 'string';\n return ret;\n };\n imports.wbg.__wbg_require_94a9da52636aacbf = function() { return handleError(function () {\n const ret = module.require;\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbindgen_is_function = function(arg0) {\n const ret = typeof(getObject(arg0)) === 'function';\n return ret;\n };\n imports.wbg.__wbindgen_string_new = function(arg0, arg1) {\n const ret = getStringFromWasm0(arg0, arg1);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_msCrypto_0b84745e9245cdf6 = function(arg0) {\n const ret = getObject(arg0).msCrypto;\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_randomFillSync_290977693942bf03 = function() { return handleError(function (arg0, arg1) {\n getObject(arg0).randomFillSync(takeObject(arg1));\n }, arguments) };\n imports.wbg.__wbg_getRandomValues_260cc23a41afad9a = function() { return handleError(function (arg0, arg1) {\n getObject(arg0).getRandomValues(getObject(arg1));\n }, arguments) };\n imports.wbg.__wbg_newnoargs_e258087cd0daa0ea = function(arg0, arg1) {\n const ret = new Function(getStringFromWasm0(arg0, arg1));\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_new_63b92bc8671ed464 = function(arg0) {\n const ret = new Uint8Array(getObject(arg0));\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_new_9efabd6b6d2ce46d = function(arg0) {\n const ret = new Float32Array(getObject(arg0));\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_buffer_12d079cc21e14bdb = function(arg0) {\n const ret = getObject(arg0).buffer;\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_newwithbyteoffsetandlength_aa4a17c33a06e5cb = function(arg0, arg1, arg2) {\n const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_newwithlength_e9b4878cebadb3d3 = function(arg0) {\n const ret = new Uint8Array(arg0 >>> 0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_set_a47bac70306a19a7 = function(arg0, arg1, arg2) {\n getObject(arg0).set(getObject(arg1), arg2 >>> 0);\n };\n imports.wbg.__wbg_subarray_a1f73cd4b5b42fe1 = function(arg0, arg1, arg2) {\n const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_newwithbyteoffsetandlength_4a659d079a1650e0 = function(arg0, arg1, arg2) {\n const ret = new Float32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_self_ce0dbfc45cf2f5be = function() { return handleError(function () {\n const ret = self.self;\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbg_window_c6fb939a7f436783 = function() { return handleError(function () {\n const ret = window.window;\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbg_globalThis_d1e6af4856ba331b = function() { return handleError(function () {\n const ret = globalThis.globalThis;\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbg_global_207b558942527489 = function() { return handleError(function () {\n const ret = global.global;\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbindgen_is_undefined = function(arg0) {\n const ret = getObject(arg0) === undefined;\n return ret;\n };\n imports.wbg.__wbg_call_27c0f87801dedf93 = function() { return handleError(function (arg0, arg1) {\n const ret = getObject(arg0).call(getObject(arg1));\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbindgen_object_clone_ref = function(arg0) {\n const ret = getObject(arg0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_call_b3ca7c6051f9bec1 = function() { return handleError(function (arg0, arg1, arg2) {\n const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));\n return addHeapObject(ret);\n }, arguments) };\n imports.wbg.__wbindgen_memory = function() {\n const ret = wasm.memory;\n return addHeapObject(ret);\n };\n imports.wbg.__wbindgen_throw = function(arg0, arg1) {\n throw new Error(getStringFromWasm0(arg0, arg1));\n };\n\n return imports;\n }\n\n function __wbg_finalize_init(instance, module) {\n wasm = instance.exports;\n cachedFloat32Memory0 = null;\n cachedUint8Memory0 = null;\n\n\n return wasm;\n }\n\n function initSync(module) {\n if (wasm !== undefined) return wasm;\n\n const imports = __wbg_get_imports();\n\n if (!(module instanceof WebAssembly.Module)) {\n module = new WebAssembly.Module(module);\n }\n\n const instance = new WebAssembly.Instance(module, imports);\n\n return __wbg_finalize_init(instance);\n }\n\n const WorkletMessageTypes = {\n SET_SUPPRESSION_LEVEL: 'SET_SUPPRESSION_LEVEL',\n SET_BYPASS: 'SET_BYPASS'\n };\n\n class DeepFilterAudioProcessor extends AudioWorkletProcessor {\n constructor(options) {\n super();\n this.dfModel = null;\n this.inputWritePos = 0;\n this.inputReadPos = 0;\n this.outputWritePos = 0;\n this.outputReadPos = 0;\n this.bypass = false;\n this.isInitialized = false;\n this.tempFrame = null;\n this.bufferSize = 8192;\n this.inputBuffer = new Float32Array(this.bufferSize);\n this.outputBuffer = new Float32Array(this.bufferSize);\n try {\n // Initialize WASM from pre-compiled module\n initSync(options.processorOptions.wasmModule);\n const modelBytes = new Uint8Array(options.processorOptions.modelBytes);\n const handle = df_create(modelBytes, options.processorOptions.suppressionLevel ?? 50);\n const frameLength = df_get_frame_length(handle);\n this.dfModel = { handle, frameLength };\n this.bufferSize = frameLength * 4;\n this.inputBuffer = new Float32Array(this.bufferSize);\n this.outputBuffer = new Float32Array(this.bufferSize);\n // Pre-allocate temp frame buffer for processing\n this.tempFrame = new Float32Array(frameLength);\n this.isInitialized = true;\n this.port.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n }\n catch (error) {\n console.error('Failed to initialize DeepFilter in AudioWorklet:', error);\n this.isInitialized = false;\n }\n }\n handleMessage(data) {\n switch (data.type) {\n case WorkletMessageTypes.SET_SUPPRESSION_LEVEL:\n if (this.dfModel && typeof data.value === 'number') {\n const level = Math.max(0, Math.min(100, Math.floor(data.value)));\n df_set_atten_lim(this.dfModel.handle, level);\n }\n break;\n case WorkletMessageTypes.SET_BYPASS:\n this.bypass = Boolean(data.value);\n break;\n }\n }\n getInputAvailable() {\n return (this.inputWritePos - this.inputReadPos + this.bufferSize) % this.bufferSize;\n }\n getOutputAvailable() {\n return (this.outputWritePos - this.outputReadPos + this.bufferSize) % this.bufferSize;\n }\n process(inputList, outputList) {\n const sourceLimit = Math.min(inputList.length, outputList.length);\n const input = inputList[0]?.[0];\n if (!input) {\n return true;\n }\n // Passthrough mode - copy input to all output channels\n if (!this.isInitialized || !this.dfModel || this.bypass || !this.tempFrame) {\n for (let inputNum = 0; inputNum < sourceLimit; inputNum++) {\n const output = outputList[inputNum];\n const channelCount = output.length;\n for (let channelNum = 0; channelNum < channelCount; channelNum++) {\n output[channelNum].set(input);\n }\n }\n return true;\n }\n // Write input to ring buffer\n for (let i = 0; i < input.length; i++) {\n this.inputBuffer[this.inputWritePos] = input[i];\n this.inputWritePos = (this.inputWritePos + 1) % this.bufferSize;\n }\n const frameLength = this.dfModel.frameLength;\n while (this.getInputAvailable() >= frameLength) {\n // Extract frame from ring buffer\n for (let i = 0; i < frameLength; i++) {\n this.tempFrame[i] = this.inputBuffer[this.inputReadPos];\n this.inputReadPos = (this.inputReadPos + 1) % this.bufferSize;\n }\n const processed = df_process_frame(this.dfModel.handle, this.tempFrame);\n // Write to output ring buffer\n for (let i = 0; i < processed.length; i++) {\n this.outputBuffer[this.outputWritePos] = processed[i];\n this.outputWritePos = (this.outputWritePos + 1) % this.bufferSize;\n }\n }\n const outputAvailable = this.getOutputAvailable();\n if (outputAvailable >= 128) {\n for (let inputNum = 0; inputNum < sourceLimit; inputNum++) {\n const output = outputList[inputNum];\n const channelCount = output.length;\n for (let channelNum = 0; channelNum < channelCount; channelNum++) {\n const outputChannel = output[channelNum];\n let readPos = this.outputReadPos;\n for (let i = 0; i < 128; i++) {\n outputChannel[i] = this.outputBuffer[readPos];\n readPos = (readPos + 1) % this.bufferSize;\n }\n }\n }\n this.outputReadPos = (this.outputReadPos + 128) % this.bufferSize;\n }\n return true;\n }\n }\n registerProcessor('deepfilter-audio-processor', DeepFilterAudioProcessor);\n\n})();\n"; - -class DeepFilterNet3Core { - constructor(config = {}) { - this.assets = null; - this.workletNode = null; - this.isInitialized = false; - this.bypassEnabled = false; - this.config = { - sampleRate: config.sampleRate ?? 48000, - noiseReductionLevel: config.noiseReductionLevel ?? 50, - assetConfig: config.assetConfig - }; - this.assetLoader = getAssetLoader(config.assetConfig); - } - async initialize() { - if (this.isInitialized) - return; - // Fetch and compile WASM on main thread - const assetUrls = this.assetLoader.getAssetUrls(); - const [wasmBytes, modelBytes] = await Promise.all([ - this.assetLoader.fetchAsset(assetUrls.wasm), - this.assetLoader.fetchAsset(assetUrls.model) - ]); - // Compile WASM module - const wasmModule = await WebAssembly.compile(wasmBytes); - this.assets = { wasmModule, modelBytes }; - this.isInitialized = true; - } - async createAudioWorkletNode(audioContext) { - this.ensureInitialized(); - if (!this.assets) { - throw new Error('Assets not loaded'); - } - await createWorkletModule(audioContext, workletCode); - this.workletNode = new AudioWorkletNode(audioContext, 'deepfilter-audio-processor', { - processorOptions: { - wasmModule: this.assets.wasmModule, - modelBytes: this.assets.modelBytes, - suppressionLevel: this.config.noiseReductionLevel - } - }); - return this.workletNode; - } - setSuppressionLevel(level) { - if (!this.workletNode || typeof level !== 'number' || isNaN(level)) - return; - const clampedLevel = Math.max(0, Math.min(100, Math.floor(level))); - this.workletNode.port.postMessage({ - type: WorkletMessageTypes.SET_SUPPRESSION_LEVEL, - value: clampedLevel - }); - } - destroy() { - if (!this.isInitialized) - return; - if (this.workletNode) { - this.workletNode.disconnect(); - this.workletNode = null; - } - this.assets = null; - this.isInitialized = false; - } - isReady() { - return this.isInitialized && this.workletNode !== null; - } - setNoiseSuppressionEnabled(enabled) { - if (!this.workletNode) - return; - this.bypassEnabled = !enabled; - this.workletNode.port.postMessage({ - type: WorkletMessageTypes.SET_BYPASS, - value: !enabled - }); - } - isNoiseSuppressionEnabled() { - return !this.bypassEnabled; - } - ensureInitialized() { - if (!this.isInitialized) { - throw new Error('Processor not initialized. Call initialize() first.'); - } - } -} - -class DeepFilterNoiseFilterProcessor { - constructor(options = {}) { - this.name = 'deepfilternet3-noise-filter'; - this.audioContext = null; - this.sourceNode = null; - this.workletNode = null; - this.destination = null; - this.enabled = true; - this.init = async (opts) => { - const track = opts.track ?? opts.mediaStreamTrack; - if (!track) { - throw new Error('DeepFilterNoiseFilterProcessor.init: missing MediaStreamTrack'); - } - this.originalTrack = track; - await this.ensureGraph(); - }; - this.restart = async (opts) => { - const track = opts.track ?? opts.mediaStreamTrack; - if (track) { - this.originalTrack = track; - } - await this.ensureGraph(); - }; - this.setEnabled = async (enable) => { - this.enabled = enable; - this.processor.setNoiseSuppressionEnabled(enable); - return this.enabled; - }; - this.suspend = async () => { - if (this.audioContext && this.audioContext.state === 'running') { - await this.audioContext.suspend(); - } - }; - this.resume = async () => { - if (this.audioContext && this.audioContext.state === 'suspended') { - await this.audioContext.resume(); - } - }; - this.destroy = async () => { - await this.teardownGraph(); - this.processor.destroy(); - }; - const cfg = { - sampleRate: options.sampleRate ?? 48000, - noiseReductionLevel: options.noiseReductionLevel ?? 80, - assetConfig: options.assetConfig - }; - this.enabled = options.enabled ?? true; - this.processor = new DeepFilterNet3Core(cfg); - } - static isSupported() { - return typeof AudioContext !== 'undefined' && typeof WebAssembly !== 'undefined'; - } - setSuppressionLevel(level) { - this.processor.setSuppressionLevel(level); - } - isEnabled() { - return this.enabled; - } - isNoiseSuppressionEnabled() { - return this.processor.isNoiseSuppressionEnabled(); - } - async ensureGraph() { - if (!this.originalTrack) { - throw new Error('No source track'); - } - this.audioContext ?? (this.audioContext = new AudioContext({ sampleRate: 48000 })); - if (this.audioContext.state !== 'running') { - try { - await this.audioContext.resume(); - } - catch { - // Ignore resume errors - } - } - await this.processor.initialize(); - if (!this.workletNode) { - const node = await this.processor.createAudioWorkletNode(this.audioContext); - this.workletNode = node; - } - if (!this.destination) { - this.destination = this.audioContext.createMediaStreamDestination(); - this.processedTrack = this.destination.stream.getAudioTracks()[0]; - } - if (this.sourceNode) { - this.sourceNode.disconnect(); - } - this.sourceNode = this.audioContext.createMediaStreamSource(new MediaStream([this.originalTrack])); - this.sourceNode.connect(this.workletNode).connect(this.destination); - await this.setEnabled(this.enabled); - } - async teardownGraph() { - try { - if (this.workletNode) { - this.workletNode.disconnect(); - this.workletNode = null; - } - if (this.sourceNode) { - this.sourceNode.disconnect(); - this.sourceNode = null; - } - if (this.destination) { - this.destination.disconnect(); - this.destination = null; - } - if (this.audioContext) { - void this.audioContext.close(); - this.audioContext = null; - } - } - catch { - // Ignore disconnect errors - } - } -} -function DeepFilterNoiseFilter(options) { - return new DeepFilterNoiseFilterProcessor(options); -} - -export { AssetLoader, DeepFilterNet3Core, DeepFilterNoiseFilter, DeepFilterNoiseFilterProcessor, getAssetLoader }; diff --git a/static/vendor/deepfilternet3/v2/models/DeepFilterNet3_onnx.tar.gz b/static/vendor/deepfilternet3/v2/models/DeepFilterNet3_onnx.tar.gz deleted file mode 100644 index 1c4f4ff..0000000 Binary files a/static/vendor/deepfilternet3/v2/models/DeepFilterNet3_onnx.tar.gz and /dev/null differ diff --git a/static/vendor/deepfilternet3/v2/pkg/df_bg.wasm b/static/vendor/deepfilternet3/v2/pkg/df_bg.wasm deleted file mode 100644 index 0d02360..0000000 Binary files a/static/vendor/deepfilternet3/v2/pkg/df_bg.wasm and /dev/null differ diff --git a/static/vendor/lucide.min.js b/static/vendor/lucide.min.js deleted file mode 100644 index 7c7d8cd..0000000 --- a/static/vendor/lucide.min.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @license lucide v0.474.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */ - -(function(a,n){typeof exports=="object"&&typeof module<"u"?n(exports):typeof define=="function"&&define.amd?define(["exports"],n):(a=typeof globalThis<"u"?globalThis:a||self,n(a.lucide={}))})(this,function(a){"use strict";const n=(t,d,c=[])=>{const p=document.createElementNS("http://www.w3.org/2000/svg",t);return Object.keys(d).forEach(M=>{p.setAttribute(M,String(d[M]))}),c.length&&c.forEach(M=>{const v=n(...M);p.appendChild(v)}),p};var W0=([t,d,c])=>n(t,d,c);const am=t=>Array.from(t.attributes).reduce((d,c)=>(d[c.name]=c.value,d),{}),hm=t=>typeof t=="string"?t:!t||!t.class?"":t.class&&typeof t.class=="string"?t.class.split(" "):t.class&&Array.isArray(t.class)?t.class:"",tm=t=>t.flatMap(hm).map(d=>d.trim()).filter(Boolean).filter((d,c,p)=>p.indexOf(d)===c).join(" "),dm=t=>t.replace(/(\w)(\w*)(_|-|\s*)/g,(d,c,p)=>c.toUpperCase()+p.toLowerCase()),x0=(t,{nameAttr:d,icons:c,attrs:p})=>{const M=t.getAttribute(d);if(M==null)return;const v=dm(M),Q$=c[v];if(!Q$)return console.warn(`${t.outerHTML} icon name was not found in the provided icons object.`);const j$=am(t),[Mm,pm,em]=Q$,Y$={...pm,"data-lucide":M,...p,...j$},_$=tm(["lucide",`lucide-${M}`,j$,p]);_$&&Object.assign(Y$,{class:_$});const nm=W0([Mm,Y$,em]);return t.parentNode?.replaceChild(nm,t)},h={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"},X0=["svg",h,[["path",{d:"M3.5 13h6"}],["path",{d:"m2 16 4.5-9 4.5 9"}],["path",{d:"M18 7v9"}],["path",{d:"m14 12 4 4 4-4"}]]],N0=["svg",h,[["path",{d:"M3.5 13h6"}],["path",{d:"m2 16 4.5-9 4.5 9"}],["path",{d:"M18 16V7"}],["path",{d:"m14 11 4-4 4 4"}]]],K0=["svg",h,[["path",{d:"M21 14h-5"}],["path",{d:"M16 16v-3.5a2.5 2.5 0 0 1 5 0V16"}],["path",{d:"M4.5 13h6"}],["path",{d:"m3 16 4.5-9 4.5 9"}]]],J0=["svg",h,[["circle",{cx:"16",cy:"4",r:"1"}],["path",{d:"m18 19 1-7-6 1"}],["path",{d:"m5 8 3-3 5.5 3-2.36 3.5"}],["path",{d:"M4.24 14.5a5 5 0 0 0 6.88 6"}],["path",{d:"M13.76 17.5a5 5 0 0 0-6.88-6"}]]],Q0=["svg",h,[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"}]]],j0=["svg",h,[["path",{d:"M6 12H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"}],["path",{d:"M6 8h12"}],["path",{d:"M18.3 17.7a2.5 2.5 0 0 1-3.16 3.83 2.53 2.53 0 0 1-1.14-2V12"}],["path",{d:"M6.6 15.6A2 2 0 1 0 10 17v-5"}]]],Y0=["svg",h,[["path",{d:"M5 17H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-1"}],["path",{d:"m12 15 5 6H7Z"}]]],o=["svg",h,[["circle",{cx:"12",cy:"13",r:"8"}],["path",{d:"M5 3 2 6"}],["path",{d:"m22 6-3-3"}],["path",{d:"M6.38 18.7 4 21"}],["path",{d:"M17.64 18.67 20 21"}],["path",{d:"m9 13 2 2 4-4"}]]],s=["svg",h,[["circle",{cx:"12",cy:"13",r:"8"}],["path",{d:"M5 3 2 6"}],["path",{d:"m22 6-3-3"}],["path",{d:"M6.38 18.7 4 21"}],["path",{d:"M17.64 18.67 20 21"}],["path",{d:"M9 13h6"}]]],_0=["svg",h,[["path",{d:"M6.87 6.87a8 8 0 1 0 11.26 11.26"}],["path",{d:"M19.9 14.25a8 8 0 0 0-9.15-9.15"}],["path",{d:"m22 6-3-3"}],["path",{d:"M6.26 18.67 4 21"}],["path",{d:"m2 2 20 20"}],["path",{d:"M4 4 2 6"}]]],r=["svg",h,[["circle",{cx:"12",cy:"13",r:"8"}],["path",{d:"M5 3 2 6"}],["path",{d:"m22 6-3-3"}],["path",{d:"M6.38 18.7 4 21"}],["path",{d:"M17.64 18.67 20 21"}],["path",{d:"M12 10v6"}],["path",{d:"M9 13h6"}]]],aa=["svg",h,[["circle",{cx:"12",cy:"13",r:"8"}],["path",{d:"M12 9v4l2 2"}],["path",{d:"M5 3 2 6"}],["path",{d:"m22 6-3-3"}],["path",{d:"M6.38 18.7 4 21"}],["path",{d:"M17.64 18.67 20 21"}]]],ha=["svg",h,[["path",{d:"M11 21c0-2.5 2-2.5 2-5"}],["path",{d:"M16 21c0-2.5 2-2.5 2-5"}],["path",{d:"m19 8-.8 3a1.25 1.25 0 0 1-1.2 1H7a1.25 1.25 0 0 1-1.2-1L5 8"}],["path",{d:"M21 3a1 1 0 0 1 1 1v2a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V4a1 1 0 0 1 1-1z"}],["path",{d:"M6 21c0-2.5 2-2.5 2-5"}]]],ta=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["polyline",{points:"11 3 11 11 14 8 17 11 17 3"}]]],da=["svg",h,[["path",{d:"M2 12h20"}],["path",{d:"M10 16v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-4"}],["path",{d:"M10 8V4a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v4"}],["path",{d:"M20 16v1a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2v-1"}],["path",{d:"M14 8V7c0-1.1.9-2 2-2h2a2 2 0 0 1 2 2v1"}]]],ca=["svg",h,[["path",{d:"M12 2v20"}],["path",{d:"M8 10H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2h4"}],["path",{d:"M16 10h4a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-4"}],["path",{d:"M8 20H7a2 2 0 0 1-2-2v-2c0-1.1.9-2 2-2h1"}],["path",{d:"M16 14h1a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2h-1"}]]],Ma=["svg",h,[["path",{d:"M17 12H7"}],["path",{d:"M19 18H5"}],["path",{d:"M21 6H3"}]]],pa=["svg",h,[["rect",{width:"6",height:"16",x:"4",y:"2",rx:"2"}],["rect",{width:"6",height:"9",x:"14",y:"9",rx:"2"}],["path",{d:"M22 22H2"}]]],ea=["svg",h,[["rect",{width:"16",height:"6",x:"2",y:"4",rx:"2"}],["rect",{width:"9",height:"6",x:"9",y:"14",rx:"2"}],["path",{d:"M22 22V2"}]]],na=["svg",h,[["rect",{width:"6",height:"14",x:"4",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"14",y:"7",rx:"2"}],["path",{d:"M17 22v-5"}],["path",{d:"M17 7V2"}],["path",{d:"M7 22v-3"}],["path",{d:"M7 5V2"}]]],ia=["svg",h,[["rect",{width:"6",height:"14",x:"4",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"14",y:"7",rx:"2"}],["path",{d:"M10 2v20"}],["path",{d:"M20 2v20"}]]],la=["svg",h,[["rect",{width:"6",height:"14",x:"4",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"14",y:"7",rx:"2"}],["path",{d:"M4 2v20"}],["path",{d:"M14 2v20"}]]],va=["svg",h,[["rect",{width:"6",height:"14",x:"2",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"16",y:"7",rx:"2"}],["path",{d:"M12 2v20"}]]],oa=["svg",h,[["rect",{width:"6",height:"14",x:"2",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"12",y:"7",rx:"2"}],["path",{d:"M22 2v20"}]]],sa=["svg",h,[["rect",{width:"6",height:"14",x:"6",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"16",y:"7",rx:"2"}],["path",{d:"M2 2v20"}]]],ra=["svg",h,[["rect",{width:"6",height:"10",x:"9",y:"7",rx:"2"}],["path",{d:"M4 22V2"}],["path",{d:"M20 22V2"}]]],ga=["svg",h,[["rect",{width:"6",height:"14",x:"3",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"15",y:"7",rx:"2"}],["path",{d:"M3 2v20"}],["path",{d:"M21 2v20"}]]],ya=["svg",h,[["path",{d:"M3 12h18"}],["path",{d:"M3 18h18"}],["path",{d:"M3 6h18"}]]],$a=["svg",h,[["path",{d:"M15 12H3"}],["path",{d:"M17 18H3"}],["path",{d:"M21 6H3"}]]],ma=["svg",h,[["path",{d:"M21 12H9"}],["path",{d:"M21 18H7"}],["path",{d:"M21 6H3"}]]],Ca=["svg",h,[["rect",{width:"6",height:"16",x:"4",y:"6",rx:"2"}],["rect",{width:"6",height:"9",x:"14",y:"6",rx:"2"}],["path",{d:"M22 2H2"}]]],ua=["svg",h,[["rect",{width:"9",height:"6",x:"6",y:"14",rx:"2"}],["rect",{width:"16",height:"6",x:"6",y:"4",rx:"2"}],["path",{d:"M2 2v20"}]]],Ha=["svg",h,[["path",{d:"M22 17h-3"}],["path",{d:"M22 7h-5"}],["path",{d:"M5 17H2"}],["path",{d:"M7 7H2"}],["rect",{x:"5",y:"14",width:"14",height:"6",rx:"2"}],["rect",{x:"7",y:"4",width:"10",height:"6",rx:"2"}]]],wa=["svg",h,[["rect",{width:"14",height:"6",x:"5",y:"14",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"4",rx:"2"}],["path",{d:"M2 20h20"}],["path",{d:"M2 10h20"}]]],Va=["svg",h,[["rect",{width:"14",height:"6",x:"5",y:"14",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"4",rx:"2"}],["path",{d:"M2 14h20"}],["path",{d:"M2 4h20"}]]],Aa=["svg",h,[["rect",{width:"14",height:"6",x:"5",y:"16",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"2",rx:"2"}],["path",{d:"M2 12h20"}]]],Sa=["svg",h,[["rect",{width:"14",height:"6",x:"5",y:"12",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"2",rx:"2"}],["path",{d:"M2 22h20"}]]],La=["svg",h,[["rect",{width:"14",height:"6",x:"5",y:"16",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"6",rx:"2"}],["path",{d:"M2 2h20"}]]],fa=["svg",h,[["rect",{width:"10",height:"6",x:"7",y:"9",rx:"2"}],["path",{d:"M22 20H2"}],["path",{d:"M22 4H2"}]]],Pa=["svg",h,[["rect",{width:"14",height:"6",x:"5",y:"15",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"3",rx:"2"}],["path",{d:"M2 21h20"}],["path",{d:"M2 3h20"}]]],ka=["svg",h,[["path",{d:"M10 10H6"}],["path",{d:"M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2"}],["path",{d:"M19 18h2a1 1 0 0 0 1-1v-3.28a1 1 0 0 0-.684-.948l-1.923-.641a1 1 0 0 1-.578-.502l-1.539-3.076A1 1 0 0 0 16.382 8H14"}],["path",{d:"M8 8v4"}],["path",{d:"M9 18h6"}],["circle",{cx:"17",cy:"18",r:"2"}],["circle",{cx:"7",cy:"18",r:"2"}]]],Ba=["svg",h,[["path",{d:"M17.5 12c0 4.4-3.6 8-8 8A4.5 4.5 0 0 1 5 15.5c0-6 8-4 8-8.5a3 3 0 1 0-6 0c0 3 2.5 8.5 12 13"}],["path",{d:"M16 12h3"}]]],Fa=["svg",h,[["path",{d:"M10 17c-5-3-7-7-7-9a2 2 0 0 1 4 0c0 2.5-5 2.5-5 6 0 1.7 1.3 3 3 3 2.8 0 5-2.2 5-5"}],["path",{d:"M22 17c-5-3-7-7-7-9a2 2 0 0 1 4 0c0 2.5-5 2.5-5 6 0 1.7 1.3 3 3 3 2.8 0 5-2.2 5-5"}]]],Da=["svg",h,[["path",{d:"M10 2v5.632c0 .424-.272.795-.653.982A6 6 0 0 0 6 14c.006 4 3 7 5 8"}],["path",{d:"M10 5H8a2 2 0 0 0 0 4h.68"}],["path",{d:"M14 2v5.632c0 .424.272.795.652.982A6 6 0 0 1 18 14c0 4-3 7-5 8"}],["path",{d:"M14 5h2a2 2 0 0 1 0 4h-.68"}],["path",{d:"M18 22H6"}],["path",{d:"M9 2h6"}]]],Ra=["svg",h,[["path",{d:"M12 22V8"}],["path",{d:"M5 12H2a10 10 0 0 0 20 0h-3"}],["circle",{cx:"12",cy:"5",r:"3"}]]],za=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M16 16s-1.5-2-4-2-4 2-4 2"}],["path",{d:"M7.5 8 10 9"}],["path",{d:"m14 9 2.5-1"}],["path",{d:"M9 10h.01"}],["path",{d:"M15 10h.01"}]]],qa=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M8 15h8"}],["path",{d:"M8 9h2"}],["path",{d:"M14 9h2"}]]],Ta=["svg",h,[["path",{d:"M2 12 7 2"}],["path",{d:"m7 12 5-10"}],["path",{d:"m12 12 5-10"}],["path",{d:"m17 12 5-10"}],["path",{d:"M4.5 7h15"}],["path",{d:"M12 16v6"}]]],Za=["svg",h,[["path",{d:"M7 10H6a4 4 0 0 1-4-4 1 1 0 0 1 1-1h4"}],["path",{d:"M7 5a1 1 0 0 1 1-1h13a1 1 0 0 1 1 1 7 7 0 0 1-7 7H8a1 1 0 0 1-1-1z"}],["path",{d:"M9 12v5"}],["path",{d:"M15 12v5"}],["path",{d:"M5 20a3 3 0 0 1 3-3h8a3 3 0 0 1 3 3 1 1 0 0 1-1 1H6a1 1 0 0 1-1-1"}]]],ba=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m14.31 8 5.74 9.94"}],["path",{d:"M9.69 8h11.48"}],["path",{d:"m7.38 12 5.74-9.94"}],["path",{d:"M9.69 16 3.95 6.06"}],["path",{d:"M14.31 16H2.83"}],["path",{d:"m16.62 12-5.74 9.94"}]]],Ua=["svg",h,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M6 8h.01"}],["path",{d:"M10 8h.01"}],["path",{d:"M14 8h.01"}]]],Oa=["svg",h,[["rect",{x:"2",y:"4",width:"20",height:"16",rx:"2"}],["path",{d:"M10 4v4"}],["path",{d:"M2 8h20"}],["path",{d:"M6 4v4"}]]],Ga=["svg",h,[["path",{d:"M12 20.94c1.5 0 2.75 1.06 4 1.06 3 0 6-8 6-12.22A4.91 4.91 0 0 0 17 5c-2.22 0-4 1.44-5 2-1-.56-2.78-2-5-2a4.9 4.9 0 0 0-5 4.78C2 14 5 22 8 22c1.25 0 2.5-1.06 4-1.06Z"}],["path",{d:"M10 2c1 .5 2 2 2 5"}]]],Ia=["svg",h,[["rect",{width:"20",height:"5",x:"2",y:"3",rx:"1"}],["path",{d:"M4 8v11a2 2 0 0 0 2 2h2"}],["path",{d:"M20 8v11a2 2 0 0 1-2 2h-2"}],["path",{d:"m9 15 3-3 3 3"}],["path",{d:"M12 12v9"}]]],Ea=["svg",h,[["rect",{width:"20",height:"5",x:"2",y:"3",rx:"1"}],["path",{d:"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"}],["path",{d:"m9.5 17 5-5"}],["path",{d:"m9.5 12 5 5"}]]],Wa=["svg",h,[["rect",{width:"20",height:"5",x:"2",y:"3",rx:"1"}],["path",{d:"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"}],["path",{d:"M10 12h4"}]]],xa=["svg",h,[["path",{d:"M19 9V6a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v3"}],["path",{d:"M3 16a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-5a2 2 0 0 0-4 0v1.5a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5V11a2 2 0 0 0-4 0z"}],["path",{d:"M5 18v2"}],["path",{d:"M19 18v2"}]]],Xa=["svg",h,[["path",{d:"M15 5H9"}],["path",{d:"M15 9v3h4l-7 7-7-7h4V9z"}]]],Na=["svg",h,[["path",{d:"M15 6v6h4l-7 7-7-7h4V6h6z"}]]],Ka=["svg",h,[["path",{d:"M19 15V9"}],["path",{d:"M15 15h-3v4l-7-7 7-7v4h3v6z"}]]],Ja=["svg",h,[["path",{d:"M18 15h-6v4l-7-7 7-7v4h6v6z"}]]],Qa=["svg",h,[["path",{d:"M5 9v6"}],["path",{d:"M9 9h3V5l7 7-7 7v-4H9V9z"}]]],ja=["svg",h,[["path",{d:"M6 9h6V5l7 7-7 7v-4H6V9z"}]]],Ya=["svg",h,[["path",{d:"M9 19h6"}],["path",{d:"M9 15v-3H5l7-7 7 7h-4v3H9z"}]]],_a=["svg",h,[["path",{d:"M9 18v-6H5l7-7 7 7h-4v6H9z"}]]],ah=["svg",h,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["rect",{x:"15",y:"4",width:"4",height:"6",ry:"2"}],["path",{d:"M17 20v-6h-2"}],["path",{d:"M15 20h4"}]]],hh=["svg",h,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["path",{d:"M17 10V4h-2"}],["path",{d:"M15 10h4"}],["rect",{x:"15",y:"14",width:"4",height:"6",ry:"2"}]]],g=["svg",h,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["path",{d:"M20 8h-5"}],["path",{d:"M15 10V6.5a2.5 2.5 0 0 1 5 0V10"}],["path",{d:"M15 14h5l-5 6h5"}]]],th=["svg",h,[["path",{d:"M19 3H5"}],["path",{d:"M12 21V7"}],["path",{d:"m6 15 6 6 6-6"}]]],dh=["svg",h,[["path",{d:"M17 7 7 17"}],["path",{d:"M17 17H7V7"}]]],ch=["svg",h,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["path",{d:"M11 4h4"}],["path",{d:"M11 8h7"}],["path",{d:"M11 12h10"}]]],Mh=["svg",h,[["path",{d:"m7 7 10 10"}],["path",{d:"M17 7v10H7"}]]],ph=["svg",h,[["path",{d:"M12 2v14"}],["path",{d:"m19 9-7 7-7-7"}],["circle",{cx:"12",cy:"21",r:"1"}]]],eh=["svg",h,[["path",{d:"M12 17V3"}],["path",{d:"m6 11 6 6 6-6"}],["path",{d:"M19 21H5"}]]],nh=["svg",h,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["path",{d:"m21 8-4-4-4 4"}],["path",{d:"M17 4v16"}]]],y=["svg",h,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["path",{d:"M11 4h10"}],["path",{d:"M11 8h7"}],["path",{d:"M11 12h4"}]]],$=["svg",h,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 4v16"}],["path",{d:"M15 4h5l-5 6h5"}],["path",{d:"M15 20v-3.5a2.5 2.5 0 0 1 5 0V20"}],["path",{d:"M20 18h-5"}]]],ih=["svg",h,[["path",{d:"M12 5v14"}],["path",{d:"m19 12-7 7-7-7"}]]],lh=["svg",h,[["path",{d:"m9 6-6 6 6 6"}],["path",{d:"M3 12h14"}],["path",{d:"M21 19V5"}]]],vh=["svg",h,[["path",{d:"M8 3 4 7l4 4"}],["path",{d:"M4 7h16"}],["path",{d:"m16 21 4-4-4-4"}],["path",{d:"M20 17H4"}]]],oh=["svg",h,[["path",{d:"M3 19V5"}],["path",{d:"m13 6-6 6 6 6"}],["path",{d:"M7 12h14"}]]],sh=["svg",h,[["path",{d:"m12 19-7-7 7-7"}],["path",{d:"M19 12H5"}]]],rh=["svg",h,[["path",{d:"M3 5v14"}],["path",{d:"M21 12H7"}],["path",{d:"m15 18 6-6-6-6"}]]],gh=["svg",h,[["path",{d:"m16 3 4 4-4 4"}],["path",{d:"M20 7H4"}],["path",{d:"m8 21-4-4 4-4"}],["path",{d:"M4 17h16"}]]],yh=["svg",h,[["path",{d:"M17 12H3"}],["path",{d:"m11 18 6-6-6-6"}],["path",{d:"M21 5v14"}]]],$h=["svg",h,[["path",{d:"M5 12h14"}],["path",{d:"m12 5 7 7-7 7"}]]],mh=["svg",h,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["rect",{x:"15",y:"4",width:"4",height:"6",ry:"2"}],["path",{d:"M17 20v-6h-2"}],["path",{d:"M15 20h4"}]]],Ch=["svg",h,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["path",{d:"M17 10V4h-2"}],["path",{d:"M15 10h4"}],["rect",{x:"15",y:"14",width:"4",height:"6",ry:"2"}]]],m=["svg",h,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["path",{d:"M20 8h-5"}],["path",{d:"M15 10V6.5a2.5 2.5 0 0 1 5 0V10"}],["path",{d:"M15 14h5l-5 6h5"}]]],uh=["svg",h,[["path",{d:"m21 16-4 4-4-4"}],["path",{d:"M17 20V4"}],["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}]]],Hh=["svg",h,[["path",{d:"m5 9 7-7 7 7"}],["path",{d:"M12 16V2"}],["circle",{cx:"12",cy:"21",r:"1"}]]],wh=["svg",h,[["path",{d:"m18 9-6-6-6 6"}],["path",{d:"M12 3v14"}],["path",{d:"M5 21h14"}]]],Vh=["svg",h,[["path",{d:"M7 17V7h10"}],["path",{d:"M17 17 7 7"}]]],C=["svg",h,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["path",{d:"M11 12h4"}],["path",{d:"M11 16h7"}],["path",{d:"M11 20h10"}]]],Ah=["svg",h,[["path",{d:"M7 7h10v10"}],["path",{d:"M7 17 17 7"}]]],Sh=["svg",h,[["path",{d:"M5 3h14"}],["path",{d:"m18 13-6-6-6 6"}],["path",{d:"M12 7v14"}]]],Lh=["svg",h,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["path",{d:"M11 12h10"}],["path",{d:"M11 16h7"}],["path",{d:"M11 20h4"}]]],u=["svg",h,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["path",{d:"M15 4h5l-5 6h5"}],["path",{d:"M15 20v-3.5a2.5 2.5 0 0 1 5 0V20"}],["path",{d:"M20 18h-5"}]]],fh=["svg",h,[["path",{d:"m5 12 7-7 7 7"}],["path",{d:"M12 19V5"}]]],Ph=["svg",h,[["path",{d:"m4 6 3-3 3 3"}],["path",{d:"M7 17V3"}],["path",{d:"m14 6 3-3 3 3"}],["path",{d:"M17 17V3"}],["path",{d:"M4 21h16"}]]],kh=["svg",h,[["path",{d:"M12 6v12"}],["path",{d:"M17.196 9 6.804 15"}],["path",{d:"m6.804 9 10.392 6"}]]],Bh=["svg",h,[["circle",{cx:"12",cy:"12",r:"4"}],["path",{d:"M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8"}]]],Fh=["svg",h,[["circle",{cx:"12",cy:"12",r:"1"}],["path",{d:"M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z"}],["path",{d:"M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z"}]]],Dh=["svg",h,[["path",{d:"M2 10v3"}],["path",{d:"M6 6v11"}],["path",{d:"M10 3v18"}],["path",{d:"M14 8v7"}],["path",{d:"M18 5v13"}],["path",{d:"M22 10v3"}]]],Rh=["svg",h,[["path",{d:"M2 13a2 2 0 0 0 2-2V7a2 2 0 0 1 4 0v13a2 2 0 0 0 4 0V4a2 2 0 0 1 4 0v13a2 2 0 0 0 4 0v-4a2 2 0 0 1 2-2"}]]],zh=["svg",h,[["path",{d:"m15.477 12.89 1.515 8.526a.5.5 0 0 1-.81.47l-3.58-2.687a1 1 0 0 0-1.197 0l-3.586 2.686a.5.5 0 0 1-.81-.469l1.514-8.526"}],["circle",{cx:"12",cy:"8",r:"6"}]]],qh=["svg",h,[["path",{d:"m14 12-8.5 8.5a2.12 2.12 0 1 1-3-3L11 9"}],["path",{d:"M15 13 9 7l4-4 6 6h3a8 8 0 0 1-7 7z"}]]],H=["svg",h,[["path",{d:"M4 4v16h16"}],["path",{d:"m4 20 7-7"}]]],Th=["svg",h,[["path",{d:"M9 12h.01"}],["path",{d:"M15 12h.01"}],["path",{d:"M10 16c.5.3 1.2.5 2 .5s1.5-.2 2-.5"}],["path",{d:"M19 6.3a9 9 0 0 1 1.8 3.9 2 2 0 0 1 0 3.6 9 9 0 0 1-17.6 0 2 2 0 0 1 0-3.6A9 9 0 0 1 12 3c2 0 3.5 1.1 3.5 2.5s-.9 2.5-2 2.5c-.8 0-1.5-.4-1.5-1"}]]],Zh=["svg",h,[["path",{d:"M4 10a4 4 0 0 1 4-4h8a4 4 0 0 1 4 4v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z"}],["path",{d:"M8 10h8"}],["path",{d:"M8 18h8"}],["path",{d:"M8 22v-6a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v6"}],["path",{d:"M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2"}]]],bh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16"}]]],Uh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M12 7v10"}],["path",{d:"M15.4 10a4 4 0 1 0 0 4"}]]],w=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"m9 12 2 2 4-4"}]]],Oh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"}],["path",{d:"M12 18V6"}]]],Gh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M7 12h5"}],["path",{d:"M15 9.4a4 4 0 1 0 0 5.2"}]]],Ih=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"}],["line",{x1:"12",x2:"12.01",y1:"17",y2:"17"}]]],Eh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M8 8h8"}],["path",{d:"M8 12h8"}],["path",{d:"m13 17-5-1h1a4 4 0 0 0 0-8"}]]],Wh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["line",{x1:"12",x2:"12",y1:"16",y2:"12"}],["line",{x1:"12",x2:"12.01",y1:"8",y2:"8"}]]],xh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"m9 8 3 3v7"}],["path",{d:"m12 11 3-3"}],["path",{d:"M9 12h6"}],["path",{d:"M9 16h6"}]]],Xh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12"}]]],Nh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"m15 9-6 6"}],["path",{d:"M9 9h.01"}],["path",{d:"M15 15h.01"}]]],Kh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["line",{x1:"12",x2:"12",y1:"8",y2:"16"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12"}]]],Jh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M8 12h4"}],["path",{d:"M10 16V9.5a2.5 2.5 0 0 1 5 0"}],["path",{d:"M8 16h7"}]]],Qh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M9 16h5"}],["path",{d:"M9 12h5a2 2 0 1 0 0-4h-3v9"}]]],jh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M11 17V8h4"}],["path",{d:"M11 12h3"}],["path",{d:"M9 16h4"}]]],Yh=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["line",{x1:"15",x2:"9",y1:"9",y2:"15"}],["line",{x1:"9",x2:"15",y1:"9",y2:"15"}]]],_h=["svg",h,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}]]],at=["svg",h,[["path",{d:"M22 18H6a2 2 0 0 1-2-2V7a2 2 0 0 0-2-2"}],["path",{d:"M17 14V4a2 2 0 0 0-2-2h-1a2 2 0 0 0-2 2v10"}],["rect",{width:"13",height:"8",x:"8",y:"6",rx:"1"}],["circle",{cx:"18",cy:"20",r:"2"}],["circle",{cx:"9",cy:"20",r:"2"}]]],ht=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m4.9 4.9 14.2 14.2"}]]],tt=["svg",h,[["path",{d:"M4 13c3.5-2 8-2 10 2a5.5 5.5 0 0 1 8 5"}],["path",{d:"M5.15 17.89c5.52-1.52 8.65-6.89 7-12C11.55 4 11.5 2 13 2c3.22 0 5 5.5 5 8 0 6.5-4.2 12-10.49 12C5.11 22 2 22 2 20c0-1.5 1.14-1.55 3.15-2.11Z"}]]],dt=["svg",h,[["path",{d:"M10 10.01h.01"}],["path",{d:"M10 14.01h.01"}],["path",{d:"M14 10.01h.01"}],["path",{d:"M14 14.01h.01"}],["path",{d:"M18 6v11.5"}],["path",{d:"M6 6v12"}],["rect",{x:"2",y:"6",width:"20",height:"12",rx:"2"}]]],ct=["svg",h,[["rect",{width:"20",height:"12",x:"2",y:"6",rx:"2"}],["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"M6 12h.01M18 12h.01"}]]],Mt=["svg",h,[["path",{d:"M3 5v14"}],["path",{d:"M8 5v14"}],["path",{d:"M12 5v14"}],["path",{d:"M17 5v14"}],["path",{d:"M21 5v14"}]]],pt=["svg",h,[["path",{d:"M4 20h16"}],["path",{d:"m6 16 6-12 6 12"}],["path",{d:"M8 12h8"}]]],et=["svg",h,[["path",{d:"M10 4 8 6"}],["path",{d:"M17 19v2"}],["path",{d:"M2 12h20"}],["path",{d:"M7 19v2"}],["path",{d:"M9 5 7.621 3.621A2.121 2.121 0 0 0 4 5v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5"}]]],nt=["svg",h,[["path",{d:"M15 7h1a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2h-2"}],["path",{d:"M6 7H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h1"}],["path",{d:"m11 7-3 5h4l-3 5"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}]]],it=["svg",h,[["rect",{width:"16",height:"10",x:"2",y:"7",rx:"2",ry:"2"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}],["line",{x1:"6",x2:"6",y1:"11",y2:"13"}],["line",{x1:"10",x2:"10",y1:"11",y2:"13"}],["line",{x1:"14",x2:"14",y1:"11",y2:"13"}]]],lt=["svg",h,[["rect",{width:"16",height:"10",x:"2",y:"7",rx:"2",ry:"2"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}],["line",{x1:"6",x2:"6",y1:"11",y2:"13"}]]],vt=["svg",h,[["rect",{width:"16",height:"10",x:"2",y:"7",rx:"2",ry:"2"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}],["line",{x1:"6",x2:"6",y1:"11",y2:"13"}],["line",{x1:"10",x2:"10",y1:"11",y2:"13"}]]],ot=["svg",h,[["path",{d:"M10 9v6"}],["path",{d:"M13.5 7H16a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2h-2.5"}],["path",{d:"M22 11v2"}],["path",{d:"M6.5 17H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2.5"}],["path",{d:"M7 12h6"}]]],st=["svg",h,[["path",{d:"M10 17h.01"}],["path",{d:"M10 7v6"}],["path",{d:"M14 7h2a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2h-2"}],["path",{d:"M22 11v2"}],["path",{d:"M6 7H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2"}]]],rt=["svg",h,[["rect",{width:"16",height:"10",x:"2",y:"7",rx:"2",ry:"2"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}]]],gt=["svg",h,[["path",{d:"M4.5 3h15"}],["path",{d:"M6 3v16a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V3"}],["path",{d:"M6 14h12"}]]],yt=["svg",h,[["path",{d:"M9 9c-.64.64-1.521.954-2.402 1.165A6 6 0 0 0 8 22a13.96 13.96 0 0 0 9.9-4.1"}],["path",{d:"M10.75 5.093A6 6 0 0 1 22 8c0 2.411-.61 4.68-1.683 6.66"}],["path",{d:"M5.341 10.62a4 4 0 0 0 6.487 1.208M10.62 5.341a4.015 4.015 0 0 1 2.039 2.04"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],$t=["svg",h,[["path",{d:"M10.165 6.598C9.954 7.478 9.64 8.36 9 9c-.64.64-1.521.954-2.402 1.165A6 6 0 0 0 8 22c7.732 0 14-6.268 14-14a6 6 0 0 0-11.835-1.402Z"}],["path",{d:"M5.341 10.62a4 4 0 1 0 5.279-5.28"}]]],mt=["svg",h,[["path",{d:"M2 20v-8a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v8"}],["path",{d:"M4 10V6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v4"}],["path",{d:"M12 4v6"}],["path",{d:"M2 18h20"}]]],Ct=["svg",h,[["path",{d:"M3 20v-8a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v8"}],["path",{d:"M5 10V6a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v4"}],["path",{d:"M3 18h18"}]]],ut=["svg",h,[["path",{d:"M2 4v16"}],["path",{d:"M2 8h18a2 2 0 0 1 2 2v10"}],["path",{d:"M2 17h20"}],["path",{d:"M6 8v9"}]]],Ht=["svg",h,[["circle",{cx:"12.5",cy:"8.5",r:"2.5"}],["path",{d:"M12.5 2a6.5 6.5 0 0 0-6.22 4.6c-1.1 3.13-.78 3.9-3.18 6.08A3 3 0 0 0 5 18c4 0 8.4-1.8 11.4-4.3A6.5 6.5 0 0 0 12.5 2Z"}],["path",{d:"m18.5 6 2.19 4.5a6.48 6.48 0 0 1 .31 2 6.49 6.49 0 0 1-2.6 5.2C15.4 20.2 11 22 7 22a3 3 0 0 1-2.68-1.66L2.4 16.5"}]]],wt=["svg",h,[["path",{d:"M13 13v5"}],["path",{d:"M17 11.47V8"}],["path",{d:"M17 11h1a3 3 0 0 1 2.745 4.211"}],["path",{d:"m2 2 20 20"}],["path",{d:"M5 8v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-3"}],["path",{d:"M7.536 7.535C6.766 7.649 6.154 8 5.5 8a2.5 2.5 0 0 1-1.768-4.268"}],["path",{d:"M8.727 3.204C9.306 2.767 9.885 2 11 2c1.56 0 2 1.5 3 1.5s1.72-.5 2.5-.5a1 1 0 1 1 0 5c-.78 0-1.5-.5-2.5-.5a3.149 3.149 0 0 0-.842.12"}],["path",{d:"M9 14.6V18"}]]],Vt=["svg",h,[["path",{d:"M17 11h1a3 3 0 0 1 0 6h-1"}],["path",{d:"M9 12v6"}],["path",{d:"M13 12v6"}],["path",{d:"M14 7.5c-1 0-1.44.5-3 .5s-2-.5-3-.5-1.72.5-2.5.5a2.5 2.5 0 0 1 0-5c.78 0 1.57.5 2.5.5S9.44 2 11 2s2 1.5 3 1.5 1.72-.5 2.5-.5a2.5 2.5 0 0 1 0 5c-.78 0-1.5-.5-2.5-.5Z"}],["path",{d:"M5 8v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8"}]]],At=["svg",h,[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0"}],["path",{d:"M13.916 2.314A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.74 7.327A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673 9 9 0 0 1-.585-.665"}],["circle",{cx:"18",cy:"8",r:"3"}]]],St=["svg",h,[["path",{d:"M18.8 4A6.3 8.7 0 0 1 20 9"}],["path",{d:"M9 9h.01"}],["circle",{cx:"9",cy:"9",r:"7"}],["rect",{width:"10",height:"6",x:"4",y:"16",rx:"2"}],["path",{d:"M14 19c3 0 4.6-1.6 4.6-1.6"}],["circle",{cx:"20",cy:"16",r:"2"}]]],Lt=["svg",h,[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0"}],["path",{d:"M15 8h6"}],["path",{d:"M16.243 3.757A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673A9.4 9.4 0 0 1 18.667 12"}]]],ft=["svg",h,[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0"}],["path",{d:"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742"}],["path",{d:"m2 2 20 20"}],["path",{d:"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05"}]]],Pt=["svg",h,[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0"}],["path",{d:"M15 8h6"}],["path",{d:"M18 5v6"}],["path",{d:"M20.002 14.464a9 9 0 0 0 .738.863A1 1 0 0 1 20 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 8.75-5.332"}]]],kt=["svg",h,[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0"}],["path",{d:"M22 8c0-2.3-.8-4.3-2-6"}],["path",{d:"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"}],["path",{d:"M4 2C2.8 3.7 2 5.7 2 8"}]]],Bt=["svg",h,[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0"}],["path",{d:"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"}]]],V=["svg",h,[["rect",{width:"13",height:"7",x:"3",y:"3",rx:"1"}],["path",{d:"m22 15-3-3 3-3"}],["rect",{width:"13",height:"7",x:"3",y:"14",rx:"1"}]]],A=["svg",h,[["rect",{width:"13",height:"7",x:"8",y:"3",rx:"1"}],["path",{d:"m2 9 3 3-3 3"}],["rect",{width:"13",height:"7",x:"8",y:"14",rx:"1"}]]],Ft=["svg",h,[["rect",{width:"7",height:"13",x:"3",y:"3",rx:"1"}],["path",{d:"m9 22 3-3 3 3"}],["rect",{width:"7",height:"13",x:"14",y:"3",rx:"1"}]]],Dt=["svg",h,[["rect",{width:"7",height:"13",x:"3",y:"8",rx:"1"}],["path",{d:"m15 2-3 3-3-3"}],["rect",{width:"7",height:"13",x:"14",y:"8",rx:"1"}]]],Rt=["svg",h,[["path",{d:"M12.409 13.017A5 5 0 0 1 22 15c0 3.866-4 7-9 7-4.077 0-8.153-.82-10.371-2.462-.426-.316-.631-.832-.62-1.362C2.118 12.723 2.627 2 10 2a3 3 0 0 1 3 3 2 2 0 0 1-2 2c-1.105 0-1.64-.444-2-1"}],["path",{d:"M15 14a5 5 0 0 0-7.584 2"}],["path",{d:"M9.964 6.825C8.019 7.977 9.5 13 8 15"}]]],zt=["svg",h,[["circle",{cx:"18.5",cy:"17.5",r:"3.5"}],["circle",{cx:"5.5",cy:"17.5",r:"3.5"}],["circle",{cx:"15",cy:"5",r:"1"}],["path",{d:"M12 17.5V14l-3-3 4-3 2 3h2"}]]],qt=["svg",h,[["rect",{x:"14",y:"14",width:"4",height:"6",rx:"2"}],["rect",{x:"6",y:"4",width:"4",height:"6",rx:"2"}],["path",{d:"M6 20h4"}],["path",{d:"M14 10h4"}],["path",{d:"M6 14h2v6"}],["path",{d:"M14 4h2v6"}]]],Tt=["svg",h,[["path",{d:"M10 10h4"}],["path",{d:"M19 7V4a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v3"}],["path",{d:"M20 21a2 2 0 0 0 2-2v-3.851c0-1.39-2-2.962-2-4.829V8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v11a2 2 0 0 0 2 2z"}],["path",{d:"M 22 16 L 2 16"}],["path",{d:"M4 21a2 2 0 0 1-2-2v-3.851c0-1.39 2-2.962 2-4.829V8a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v11a2 2 0 0 1-2 2z"}],["path",{d:"M9 7V4a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1v3"}]]],Zt=["svg",h,[["circle",{cx:"12",cy:"11.9",r:"2"}],["path",{d:"M6.7 3.4c-.9 2.5 0 5.2 2.2 6.7C6.5 9 3.7 9.6 2 11.6"}],["path",{d:"m8.9 10.1 1.4.8"}],["path",{d:"M17.3 3.4c.9 2.5 0 5.2-2.2 6.7 2.4-1.2 5.2-.6 6.9 1.5"}],["path",{d:"m15.1 10.1-1.4.8"}],["path",{d:"M16.7 20.8c-2.6-.4-4.6-2.6-4.7-5.3-.2 2.6-2.1 4.8-4.7 5.2"}],["path",{d:"M12 13.9v1.6"}],["path",{d:"M13.5 5.4c-1-.2-2-.2-3 0"}],["path",{d:"M17 16.4c.7-.7 1.2-1.6 1.5-2.5"}],["path",{d:"M5.5 13.9c.3.9.8 1.8 1.5 2.5"}]]],bt=["svg",h,[["path",{d:"M16 7h.01"}],["path",{d:"M3.4 18H12a8 8 0 0 0 8-8V7a4 4 0 0 0-7.28-2.3L2 20"}],["path",{d:"m20 7 2 .5-2 .5"}],["path",{d:"M10 18v3"}],["path",{d:"M14 17.75V21"}],["path",{d:"M7 18a6 6 0 0 0 3.84-10.61"}]]],Ut=["svg",h,[["path",{d:"M11.767 19.089c4.924.868 6.14-6.025 1.216-6.894m-1.216 6.894L5.86 18.047m5.908 1.042-.347 1.97m1.563-8.864c4.924.869 6.14-6.025 1.215-6.893m-1.215 6.893-3.94-.694m5.155-6.2L8.29 4.26m5.908 1.042.348-1.97M7.48 20.364l3.126-17.727"}]]],Ot=["svg",h,[["circle",{cx:"9",cy:"9",r:"7"}],["circle",{cx:"15",cy:"15",r:"7"}]]],Gt=["svg",h,[["path",{d:"M3 3h18"}],["path",{d:"M20 7H8"}],["path",{d:"M20 11H8"}],["path",{d:"M10 19h10"}],["path",{d:"M8 15h12"}],["path",{d:"M4 3v14"}],["circle",{cx:"4",cy:"19",r:"2"}]]],It=["svg",h,[["rect",{width:"7",height:"7",x:"14",y:"3",rx:"1"}],["path",{d:"M10 21V8a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H3"}]]],Et=["svg",h,[["path",{d:"m7 7 10 10-5 5V2l5 5L7 17"}],["line",{x1:"18",x2:"21",y1:"12",y2:"12"}],["line",{x1:"3",x2:"6",y1:"12",y2:"12"}]]],Wt=["svg",h,[["path",{d:"m17 17-5 5V12l-5 5"}],["path",{d:"m2 2 20 20"}],["path",{d:"M14.5 9.5 17 7l-5-5v4.5"}]]],xt=["svg",h,[["path",{d:"m7 7 10 10-5 5V2l5 5L7 17"}],["path",{d:"M20.83 14.83a4 4 0 0 0 0-5.66"}],["path",{d:"M18 12h.01"}]]],Xt=["svg",h,[["path",{d:"m7 7 10 10-5 5V2l5 5L7 17"}]]],Nt=["svg",h,[["path",{d:"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8"}]]],Kt=["svg",h,[["path",{d:"M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"}],["circle",{cx:"12",cy:"12",r:"4"}]]],Jt=["svg",h,[["circle",{cx:"11",cy:"13",r:"9"}],["path",{d:"M14.35 4.65 16.3 2.7a2.41 2.41 0 0 1 3.4 0l1.6 1.6a2.4 2.4 0 0 1 0 3.4l-1.95 1.95"}],["path",{d:"m22 2-1.5 1.5"}]]],Qt=["svg",h,[["path",{d:"M17 10c.7-.7 1.69 0 2.5 0a2.5 2.5 0 1 0 0-5 .5.5 0 0 1-.5-.5 2.5 2.5 0 1 0-5 0c0 .81.7 1.8 0 2.5l-7 7c-.7.7-1.69 0-2.5 0a2.5 2.5 0 0 0 0 5c.28 0 .5.22.5.5a2.5 2.5 0 1 0 5 0c0-.81-.7-1.8 0-2.5Z"}]]],jt=["svg",h,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"m8 13 4-7 4 7"}],["path",{d:"M9.1 11h5.7"}]]],Yt=["svg",h,[["path",{d:"M12 6v7"}],["path",{d:"M16 8v3"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M8 8v3"}]]],_t=["svg",h,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"m9 9.5 2 2 4-4"}]]],a4=["svg",h,[["path",{d:"M2 16V4a2 2 0 0 1 2-2h11"}],["path",{d:"M22 18H11a2 2 0 1 0 0 4h10.5a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5H11a2 2 0 0 0-2 2v12"}],["path",{d:"M5 14H4a2 2 0 1 0 0 4h1"}]]],S=["svg",h,[["path",{d:"M12 17h1.5"}],["path",{d:"M12 22h1.5"}],["path",{d:"M12 2h1.5"}],["path",{d:"M17.5 22H19a1 1 0 0 0 1-1"}],["path",{d:"M17.5 2H19a1 1 0 0 1 1 1v1.5"}],["path",{d:"M20 14v3h-2.5"}],["path",{d:"M20 8.5V10"}],["path",{d:"M4 10V8.5"}],["path",{d:"M4 19.5V14"}],["path",{d:"M4 4.5A2.5 2.5 0 0 1 6.5 2H8"}],["path",{d:"M8 22H6.5a1 1 0 0 1 0-5H8"}]]],h4=["svg",h,[["path",{d:"M12 13V7"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"m9 10 3 3 3-3"}]]],t4=["svg",h,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M8 12v-2a4 4 0 0 1 8 0v2"}],["circle",{cx:"15",cy:"12",r:"1"}],["circle",{cx:"9",cy:"12",r:"1"}]]],d4=["svg",h,[["path",{d:"M16 8.2A2.22 2.22 0 0 0 13.8 6c-.8 0-1.4.3-1.8.9-.4-.6-1-.9-1.8-.9A2.22 2.22 0 0 0 8 8.2c0 .6.3 1.2.7 1.6A226.652 226.652 0 0 0 12 13a404 404 0 0 0 3.3-3.1 2.413 2.413 0 0 0 .7-1.7"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}]]],c4=["svg",h,[["path",{d:"m20 13.7-2.1-2.1a2 2 0 0 0-2.8 0L9.7 17"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["circle",{cx:"10",cy:"8",r:"2"}]]],M4=["svg",h,[["path",{d:"m19 3 1 1"}],["path",{d:"m20 2-4.5 4.5"}],["path",{d:"M20 8v13a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H14"}],["circle",{cx:"14",cy:"8",r:"2"}]]],p4=["svg",h,[["path",{d:"M18 6V4a2 2 0 1 0-4 0v2"}],["path",{d:"M20 15v6a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H10"}],["rect",{x:"12",y:"6",width:"8",height:"5",rx:"1"}]]],e4=["svg",h,[["path",{d:"M10 2v8l3-3 3 3V2"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}]]],n4=["svg",h,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M9 10h6"}]]],i4=["svg",h,[["path",{d:"M12 21V7"}],["path",{d:"m16 12 2 2 4-4"}],["path",{d:"M22 6V4a1 1 0 0 0-1-1h-5a4 4 0 0 0-4 4 4 4 0 0 0-4-4H3a1 1 0 0 0-1 1v13a1 1 0 0 0 1 1h6a3 3 0 0 1 3 3 3 3 0 0 1 3-3h6a1 1 0 0 0 1-1v-1.3"}]]],l4=["svg",h,[["path",{d:"M12 7v14"}],["path",{d:"M16 12h2"}],["path",{d:"M16 8h2"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"}],["path",{d:"M6 12h2"}],["path",{d:"M6 8h2"}]]],v4=["svg",h,[["path",{d:"M12 7v14"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"}]]],o4=["svg",h,[["path",{d:"M12 7v6"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M9 10h6"}]]],s4=["svg",h,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M8 11h8"}],["path",{d:"M8 7h6"}]]],r4=["svg",h,[["path",{d:"M10 13h4"}],["path",{d:"M12 6v7"}],["path",{d:"M16 8V6H8v2"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}]]],g4=["svg",h,[["path",{d:"M12 13V7"}],["path",{d:"M18 2h1a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2"}],["path",{d:"m9 10 3-3 3 3"}],["path",{d:"m9 5 3-3 3 3"}]]],y4=["svg",h,[["path",{d:"M12 13V7"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"m9 10 3-3 3 3"}]]],$4=["svg",h,[["path",{d:"M15 13a3 3 0 1 0-6 0"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["circle",{cx:"12",cy:"8",r:"2"}]]],m4=["svg",h,[["path",{d:"m14.5 7-5 5"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"m9.5 7 5 5"}]]],C4=["svg",h,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}]]],u4=["svg",h,[["path",{d:"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2Z"}],["path",{d:"m9 10 2 2 4-4"}]]],H4=["svg",h,[["path",{d:"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"}],["line",{x1:"15",x2:"9",y1:"10",y2:"10"}]]],w4=["svg",h,[["path",{d:"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"}],["line",{x1:"12",x2:"12",y1:"7",y2:"13"}],["line",{x1:"15",x2:"9",y1:"10",y2:"10"}]]],V4=["svg",h,[["path",{d:"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2Z"}],["path",{d:"m14.5 7.5-5 5"}],["path",{d:"m9.5 7.5 5 5"}]]],A4=["svg",h,[["path",{d:"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"}]]],S4=["svg",h,[["path",{d:"M4 9V5a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v4"}],["path",{d:"M8 8v1"}],["path",{d:"M12 8v1"}],["path",{d:"M16 8v1"}],["rect",{width:"20",height:"12",x:"2",y:"9",rx:"2"}],["circle",{cx:"8",cy:"15",r:"2"}],["circle",{cx:"16",cy:"15",r:"2"}]]],L4=["svg",h,[["path",{d:"M12 6V2H8"}],["path",{d:"m8 18-4 4V8a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2Z"}],["path",{d:"M2 12h2"}],["path",{d:"M9 11v2"}],["path",{d:"M15 11v2"}],["path",{d:"M20 12h2"}]]],f4=["svg",h,[["path",{d:"M13.67 8H18a2 2 0 0 1 2 2v4.33"}],["path",{d:"M2 14h2"}],["path",{d:"M20 14h2"}],["path",{d:"M22 22 2 2"}],["path",{d:"M8 8H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 1.414-.586"}],["path",{d:"M9 13v2"}],["path",{d:"M9.67 4H12v2.33"}]]],P4=["svg",h,[["path",{d:"M12 8V4H8"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}],["path",{d:"M2 14h2"}],["path",{d:"M20 14h2"}],["path",{d:"M15 13v2"}],["path",{d:"M9 13v2"}]]],k4=["svg",h,[["path",{d:"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"}],["path",{d:"m3.3 7 8.7 5 8.7-5"}],["path",{d:"M12 22V12"}]]],B4=["svg",h,[["path",{d:"M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z"}],["path",{d:"m7 16.5-4.74-2.85"}],["path",{d:"m7 16.5 5-3"}],["path",{d:"M7 16.5v5.17"}],["path",{d:"M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z"}],["path",{d:"m17 16.5-5-3"}],["path",{d:"m17 16.5 4.74-2.85"}],["path",{d:"M17 16.5v5.17"}],["path",{d:"M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z"}],["path",{d:"M12 8 7.26 5.15"}],["path",{d:"m12 8 4.74-2.85"}],["path",{d:"M12 13.5V8"}]]],L=["svg",h,[["path",{d:"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1"}],["path",{d:"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1"}]]],F4=["svg",h,[["path",{d:"M16 3h3v18h-3"}],["path",{d:"M8 21H5V3h3"}]]],D4=["svg",h,[["path",{d:"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"}],["path",{d:"M9 13a4.5 4.5 0 0 0 3-4"}],["path",{d:"M6.003 5.125A3 3 0 0 0 6.401 6.5"}],["path",{d:"M3.477 10.896a4 4 0 0 1 .585-.396"}],["path",{d:"M6 18a4 4 0 0 1-1.967-.516"}],["path",{d:"M12 13h4"}],["path",{d:"M12 18h6a2 2 0 0 1 2 2v1"}],["path",{d:"M12 8h8"}],["path",{d:"M16 8V5a2 2 0 0 1 2-2"}],["circle",{cx:"16",cy:"13",r:".5"}],["circle",{cx:"18",cy:"3",r:".5"}],["circle",{cx:"20",cy:"21",r:".5"}],["circle",{cx:"20",cy:"8",r:".5"}]]],R4=["svg",h,[["path",{d:"M12 5a3 3 0 1 0-5.997.142 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588 4 4 0 0 0 7.636 2.106 3.2 3.2 0 0 0 .164-.546c.028-.13.306-.13.335 0a3.2 3.2 0 0 0 .163.546 4 4 0 0 0 7.636-2.106 4 4 0 0 0 .556-6.588 4 4 0 0 0-2.526-5.77A3 3 0 1 0 12 5"}],["path",{d:"M17.599 6.5a3 3 0 0 0 .399-1.375"}],["path",{d:"M6.003 5.125A3 3 0 0 0 6.401 6.5"}],["path",{d:"M3.477 10.896a4 4 0 0 1 .585-.396"}],["path",{d:"M19.938 10.5a4 4 0 0 1 .585.396"}],["path",{d:"M6 18a4 4 0 0 1-1.967-.516"}],["path",{d:"M19.967 17.484A4 4 0 0 1 18 18"}],["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"m15.7 10.4-.9.4"}],["path",{d:"m9.2 13.2-.9.4"}],["path",{d:"m13.6 15.7-.4-.9"}],["path",{d:"m10.8 9.2-.4-.9"}],["path",{d:"m15.7 13.5-.9-.4"}],["path",{d:"m9.2 10.9-.9-.4"}],["path",{d:"m10.5 15.7.4-.9"}],["path",{d:"m13.1 9.2.4-.9"}]]],z4=["svg",h,[["path",{d:"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"}],["path",{d:"M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"}],["path",{d:"M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"}],["path",{d:"M17.599 6.5a3 3 0 0 0 .399-1.375"}],["path",{d:"M6.003 5.125A3 3 0 0 0 6.401 6.5"}],["path",{d:"M3.477 10.896a4 4 0 0 1 .585-.396"}],["path",{d:"M19.938 10.5a4 4 0 0 1 .585.396"}],["path",{d:"M6 18a4 4 0 0 1-1.967-.516"}],["path",{d:"M19.967 17.484A4 4 0 0 1 18 18"}]]],q4=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M12 9v6"}],["path",{d:"M16 15v6"}],["path",{d:"M16 3v6"}],["path",{d:"M3 15h18"}],["path",{d:"M3 9h18"}],["path",{d:"M8 15v6"}],["path",{d:"M8 3v6"}]]],T4=["svg",h,[["path",{d:"M12 12h.01"}],["path",{d:"M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"}],["path",{d:"M22 13a18.15 18.15 0 0 1-20 0"}],["rect",{width:"20",height:"14",x:"2",y:"6",rx:"2"}]]],Z4=["svg",h,[["path",{d:"M10 20v2"}],["path",{d:"M14 20v2"}],["path",{d:"M18 20v2"}],["path",{d:"M21 20H3"}],["path",{d:"M6 20v2"}],["path",{d:"M8 16V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v12"}],["rect",{x:"4",y:"6",width:"16",height:"10",rx:"2"}]]],b4=["svg",h,[["path",{d:"M12 11v4"}],["path",{d:"M14 13h-4"}],["path",{d:"M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"}],["path",{d:"M18 6v14"}],["path",{d:"M6 6v14"}],["rect",{width:"20",height:"14",x:"2",y:"6",rx:"2"}]]],U4=["svg",h,[["path",{d:"M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"}],["rect",{width:"20",height:"14",x:"2",y:"6",rx:"2"}]]],O4=["svg",h,[["rect",{x:"8",y:"8",width:"8",height:"8",rx:"2"}],["path",{d:"M4 10a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2"}],["path",{d:"M14 20a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2"}]]],G4=["svg",h,[["path",{d:"m9.06 11.9 8.07-8.06a2.85 2.85 0 1 1 4.03 4.03l-8.06 8.08"}],["path",{d:"M7.07 14.94c-1.66 0-3 1.35-3 3.02 0 1.33-2.5 1.52-2 2.02 1.08 1.1 2.49 2.02 4 2.02 2.2 0 4-1.8 4-4.04a3.01 3.01 0 0 0-3-3.02z"}]]],I4=["svg",h,[["path",{d:"M15 7.13V6a3 3 0 0 0-5.14-2.1L8 2"}],["path",{d:"M14.12 3.88 16 2"}],["path",{d:"M22 13h-4v-2a4 4 0 0 0-4-4h-1.3"}],["path",{d:"M20.97 5c0 2.1-1.6 3.8-3.5 4"}],["path",{d:"m2 2 20 20"}],["path",{d:"M7.7 7.7A4 4 0 0 0 6 11v3a6 6 0 0 0 11.13 3.13"}],["path",{d:"M12 20v-8"}],["path",{d:"M6 13H2"}],["path",{d:"M3 21c0-2.1 1.7-3.9 3.8-4"}]]],E4=["svg",h,[["path",{d:"M12.765 21.522a.5.5 0 0 1-.765-.424v-8.196a.5.5 0 0 1 .765-.424l5.878 3.674a1 1 0 0 1 0 1.696z"}],["path",{d:"M14.12 3.88 16 2"}],["path",{d:"M18 11a4 4 0 0 0-4-4h-4a4 4 0 0 0-4 4v3a6.1 6.1 0 0 0 2 4.5"}],["path",{d:"M20.97 5c0 2.1-1.6 3.8-3.5 4"}],["path",{d:"M3 21c0-2.1 1.7-3.9 3.8-4"}],["path",{d:"M6 13H2"}],["path",{d:"M6.53 9C4.6 8.8 3 7.1 3 5"}],["path",{d:"m8 2 1.88 1.88"}],["path",{d:"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"}]]],W4=["svg",h,[["path",{d:"m8 2 1.88 1.88"}],["path",{d:"M14.12 3.88 16 2"}],["path",{d:"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"}],["path",{d:"M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6"}],["path",{d:"M12 20v-9"}],["path",{d:"M6.53 9C4.6 8.8 3 7.1 3 5"}],["path",{d:"M6 13H2"}],["path",{d:"M3 21c0-2.1 1.7-3.9 3.8-4"}],["path",{d:"M20.97 5c0 2.1-1.6 3.8-3.5 4"}],["path",{d:"M22 13h-4"}],["path",{d:"M17.2 17c2.1.1 3.8 1.9 3.8 4"}]]],x4=["svg",h,[["path",{d:"M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z"}],["path",{d:"M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2"}],["path",{d:"M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2"}],["path",{d:"M10 6h4"}],["path",{d:"M10 10h4"}],["path",{d:"M10 14h4"}],["path",{d:"M10 18h4"}]]],X4=["svg",h,[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2",ry:"2"}],["path",{d:"M9 22v-4h6v4"}],["path",{d:"M8 6h.01"}],["path",{d:"M16 6h.01"}],["path",{d:"M12 6h.01"}],["path",{d:"M12 10h.01"}],["path",{d:"M12 14h.01"}],["path",{d:"M16 10h.01"}],["path",{d:"M16 14h.01"}],["path",{d:"M8 10h.01"}],["path",{d:"M8 14h.01"}]]],N4=["svg",h,[["path",{d:"M4 6 2 7"}],["path",{d:"M10 6h4"}],["path",{d:"m22 7-2-1"}],["rect",{width:"16",height:"16",x:"4",y:"3",rx:"2"}],["path",{d:"M4 11h16"}],["path",{d:"M8 15h.01"}],["path",{d:"M16 15h.01"}],["path",{d:"M6 19v2"}],["path",{d:"M18 21v-2"}]]],K4=["svg",h,[["path",{d:"M8 6v6"}],["path",{d:"M15 6v6"}],["path",{d:"M2 12h19.6"}],["path",{d:"M18 18h3s.5-1.7.8-2.8c.1-.4.2-.8.2-1.2 0-.4-.1-.8-.2-1.2l-1.4-5C20.1 6.8 19.1 6 18 6H4a2 2 0 0 0-2 2v10h3"}],["circle",{cx:"7",cy:"18",r:"2"}],["path",{d:"M9 18h5"}],["circle",{cx:"16",cy:"18",r:"2"}]]],J4=["svg",h,[["path",{d:"M10 3h.01"}],["path",{d:"M14 2h.01"}],["path",{d:"m2 9 20-5"}],["path",{d:"M12 12V6.5"}],["rect",{width:"16",height:"10",x:"4",y:"12",rx:"3"}],["path",{d:"M9 12v5"}],["path",{d:"M15 12v5"}],["path",{d:"M4 17h16"}]]],Q4=["svg",h,[["path",{d:"M17 21v-2a1 1 0 0 1-1-1v-1a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1"}],["path",{d:"M19 15V6.5a1 1 0 0 0-7 0v11a1 1 0 0 1-7 0V9"}],["path",{d:"M21 21v-2h-4"}],["path",{d:"M3 5h4V3"}],["path",{d:"M7 5a1 1 0 0 1 1 1v1a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a1 1 0 0 1 1-1V3"}]]],j4=["svg",h,[["circle",{cx:"9",cy:"7",r:"2"}],["path",{d:"M7.2 7.9 3 11v9c0 .6.4 1 1 1h16c.6 0 1-.4 1-1v-9c0-2-3-6-7-8l-3.6 2.6"}],["path",{d:"M16 13H3"}],["path",{d:"M16 17H3"}]]],Y4=["svg",h,[["path",{d:"M20 21v-8a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8"}],["path",{d:"M4 16s.5-1 2-1 2.5 2 4 2 2.5-2 4-2 2.5 2 4 2 2-1 2-1"}],["path",{d:"M2 21h20"}],["path",{d:"M7 8v3"}],["path",{d:"M12 8v3"}],["path",{d:"M17 8v3"}],["path",{d:"M7 4h.01"}],["path",{d:"M12 4h.01"}],["path",{d:"M17 4h.01"}]]],_4=["svg",h,[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2"}],["line",{x1:"8",x2:"16",y1:"6",y2:"6"}],["line",{x1:"16",x2:"16",y1:"14",y2:"18"}],["path",{d:"M16 10h.01"}],["path",{d:"M12 10h.01"}],["path",{d:"M8 10h.01"}],["path",{d:"M12 14h.01"}],["path",{d:"M8 14h.01"}],["path",{d:"M12 18h.01"}],["path",{d:"M8 18h.01"}]]],a5=["svg",h,[["path",{d:"M11 14h1v4"}],["path",{d:"M16 2v4"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}],["rect",{x:"3",y:"4",width:"18",height:"18",rx:"2"}]]],h5=["svg",h,[["path",{d:"m14 18 4 4 4-4"}],["path",{d:"M16 2v4"}],["path",{d:"M18 14v8"}],["path",{d:"M21 11.354V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7.343"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}]]],t5=["svg",h,[["path",{d:"m14 18 4-4 4 4"}],["path",{d:"M16 2v4"}],["path",{d:"M18 22v-8"}],["path",{d:"M21 11.343V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h9"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}]]],d5=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M21 14V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8"}],["path",{d:"M3 10h18"}],["path",{d:"m16 20 2 2 4-4"}]]],c5=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}],["path",{d:"m9 16 2 2 4-4"}]]],M5=["svg",h,[["path",{d:"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5"}],["path",{d:"M16 2v4"}],["path",{d:"M8 2v4"}],["path",{d:"M3 10h5"}],["path",{d:"M17.5 17.5 16 16.3V14"}],["circle",{cx:"16",cy:"16",r:"6"}]]],p5=["svg",h,[["path",{d:"m15.2 16.9-.9-.4"}],["path",{d:"m15.2 19.1-.9.4"}],["path",{d:"M16 2v4"}],["path",{d:"m16.9 15.2-.4-.9"}],["path",{d:"m16.9 20.8-.4.9"}],["path",{d:"m19.5 14.3-.4.9"}],["path",{d:"m19.5 21.7-.4-.9"}],["path",{d:"M21 10.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6"}],["path",{d:"m21.7 16.5-.9.4"}],["path",{d:"m21.7 19.5-.9-.4"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}],["circle",{cx:"18",cy:"18",r:"3"}]]],e5=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}],["path",{d:"M8 14h.01"}],["path",{d:"M12 14h.01"}],["path",{d:"M16 14h.01"}],["path",{d:"M8 18h.01"}],["path",{d:"M12 18h.01"}],["path",{d:"M16 18h.01"}]]],n5=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M21 17V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11Z"}],["path",{d:"M3 10h18"}],["path",{d:"M15 22v-4a2 2 0 0 1 2-2h4"}]]],i5=["svg",h,[["path",{d:"M3 10h18V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7"}],["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M21.29 14.7a2.43 2.43 0 0 0-2.65-.52c-.3.12-.57.3-.8.53l-.34.34-.35-.34a2.43 2.43 0 0 0-2.65-.53c-.3.12-.56.3-.79.53-.95.94-1 2.53.2 3.74L17.5 22l3.6-3.55c1.2-1.21 1.14-2.8.19-3.74Z"}]]],l5=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}],["path",{d:"M10 16h4"}]]],v5=["svg",h,[["path",{d:"M16 19h6"}],["path",{d:"M16 2v4"}],["path",{d:"M21 15V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8.5"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}]]],o5=["svg",h,[["path",{d:"M4.2 4.2A2 2 0 0 0 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 1.82-1.18"}],["path",{d:"M21 15.5V6a2 2 0 0 0-2-2H9.5"}],["path",{d:"M16 2v4"}],["path",{d:"M3 10h7"}],["path",{d:"M21 10h-5.5"}],["path",{d:"m2 2 20 20"}]]],s5=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}],["path",{d:"M10 16h4"}],["path",{d:"M12 14v4"}]]],r5=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M21 13V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8"}],["path",{d:"M3 10h18"}],["path",{d:"M16 19h6"}],["path",{d:"M19 16v6"}]]],g5=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M16 2v4"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}],["path",{d:"M17 14h-6"}],["path",{d:"M13 18H7"}],["path",{d:"M7 14h.01"}],["path",{d:"M17 18h.01"}]]],y5=["svg",h,[["path",{d:"M16 2v4"}],["path",{d:"M21 11.75V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7.25"}],["path",{d:"m22 22-1.875-1.875"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}],["circle",{cx:"18",cy:"18",r:"3"}]]],$5=["svg",h,[["path",{d:"M11 10v4h4"}],["path",{d:"m11 14 1.535-1.605a5 5 0 0 1 8 1.5"}],["path",{d:"M16 2v4"}],["path",{d:"m21 18-1.535 1.605a5 5 0 0 1-8-1.5"}],["path",{d:"M21 22v-4h-4"}],["path",{d:"M21 8.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h4.3"}],["path",{d:"M3 10h4"}],["path",{d:"M8 2v4"}]]],m5=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M21 13V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8"}],["path",{d:"M3 10h18"}],["path",{d:"m17 22 5-5"}],["path",{d:"m17 17 5 5"}]]],C5=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}],["path",{d:"m14 14-4 4"}],["path",{d:"m10 14 4 4"}]]],u5=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}]]],H5=["svg",h,[["line",{x1:"2",x2:"22",y1:"2",y2:"22"}],["path",{d:"M7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16"}],["path",{d:"M9.5 4h5L17 7h3a2 2 0 0 1 2 2v7.5"}],["path",{d:"M14.121 15.121A3 3 0 1 1 9.88 10.88"}]]],w5=["svg",h,[["path",{d:"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"}],["circle",{cx:"12",cy:"13",r:"3"}]]],V5=["svg",h,[["path",{d:"M5.7 21a2 2 0 0 1-3.5-2l8.6-14a6 6 0 0 1 10.4 6 2 2 0 1 1-3.464-2 2 2 0 1 0-3.464-2Z"}],["path",{d:"M17.75 7 15 2.1"}],["path",{d:"M10.9 4.8 13 9"}],["path",{d:"m7.9 9.7 2 4.4"}],["path",{d:"M4.9 14.7 7 18.9"}]]],A5=["svg",h,[["path",{d:"m8.5 8.5-1 1a4.95 4.95 0 0 0 7 7l1-1"}],["path",{d:"M11.843 6.187A4.947 4.947 0 0 1 16.5 7.5a4.947 4.947 0 0 1 1.313 4.657"}],["path",{d:"M14 16.5V14"}],["path",{d:"M14 6.5v1.843"}],["path",{d:"M10 10v7.5"}],["path",{d:"m16 7 1-5 1.367.683A3 3 0 0 0 19.708 3H21v1.292a3 3 0 0 0 .317 1.341L22 7l-5 1"}],["path",{d:"m8 17-1 5-1.367-.683A3 3 0 0 0 4.292 21H3v-1.292a3 3 0 0 0-.317-1.341L2 17l5-1"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],S5=["svg",h,[["path",{d:"m9.5 7.5-2 2a4.95 4.95 0 1 0 7 7l2-2a4.95 4.95 0 1 0-7-7Z"}],["path",{d:"M14 6.5v10"}],["path",{d:"M10 7.5v10"}],["path",{d:"m16 7 1-5 1.37.68A3 3 0 0 0 19.7 3H21v1.3c0 .46.1.92.32 1.33L22 7l-5 1"}],["path",{d:"m8 17-1 5-1.37-.68A3 3 0 0 0 4.3 21H3v-1.3a3 3 0 0 0-.32-1.33L2 17l5-1"}]]],L5=["svg",h,[["path",{d:"M12 22v-4"}],["path",{d:"M7 12c-1.5 0-4.5 1.5-5 3 3.5 1.5 6 1 6 1-1.5 1.5-2 3.5-2 5 2.5 0 4.5-1.5 6-3 1.5 1.5 3.5 3 6 3 0-1.5-.5-3.5-2-5 0 0 2.5.5 6-1-.5-1.5-3.5-3-5-3 1.5-1 4-4 4-6-2.5 0-5.5 1.5-7 3 0-2.5-.5-5-2-7-1.5 2-2 4.5-2 7-1.5-1.5-4.5-3-7-3 0 2 2.5 5 4 6"}]]],f5=["svg",h,[["path",{d:"M10.5 5H19a2 2 0 0 1 2 2v8.5"}],["path",{d:"M17 11h-.5"}],["path",{d:"M19 19H5a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2"}],["path",{d:"m2 2 20 20"}],["path",{d:"M7 11h4"}],["path",{d:"M7 15h2.5"}]]],f=["svg",h,[["rect",{width:"18",height:"14",x:"3",y:"5",rx:"2",ry:"2"}],["path",{d:"M7 15h4M15 15h2M7 11h2M13 11h4"}]]],P5=["svg",h,[["path",{d:"m21 8-2 2-1.5-3.7A2 2 0 0 0 15.646 5H8.4a2 2 0 0 0-1.903 1.257L5 10 3 8"}],["path",{d:"M7 14h.01"}],["path",{d:"M17 14h.01"}],["rect",{width:"18",height:"8",x:"3",y:"10",rx:"2"}],["path",{d:"M5 18v2"}],["path",{d:"M19 18v2"}]]],k5=["svg",h,[["path",{d:"M10 2h4"}],["path",{d:"m21 8-2 2-1.5-3.7A2 2 0 0 0 15.646 5H8.4a2 2 0 0 0-1.903 1.257L5 10 3 8"}],["path",{d:"M7 14h.01"}],["path",{d:"M17 14h.01"}],["rect",{width:"18",height:"8",x:"3",y:"10",rx:"2"}],["path",{d:"M5 18v2"}],["path",{d:"M19 18v2"}]]],B5=["svg",h,[["path",{d:"M19 17h2c.6 0 1-.4 1-1v-3c0-.9-.7-1.7-1.5-1.9C18.7 10.6 16 10 16 10s-1.3-1.4-2.2-2.3c-.5-.4-1.1-.7-1.8-.7H5c-.6 0-1.1.4-1.4.9l-1.4 2.9A3.7 3.7 0 0 0 2 12v4c0 .6.4 1 1 1h2"}],["circle",{cx:"7",cy:"17",r:"2"}],["path",{d:"M9 17h6"}],["circle",{cx:"17",cy:"17",r:"2"}]]],F5=["svg",h,[["path",{d:"M18 19V9a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v8a2 2 0 0 0 2 2h2"}],["path",{d:"M2 9h3a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H2"}],["path",{d:"M22 17v1a1 1 0 0 1-1 1H10v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9"}],["circle",{cx:"8",cy:"19",r:"2"}]]],D5=["svg",h,[["path",{d:"M2.27 21.7s9.87-3.5 12.73-6.36a4.5 4.5 0 0 0-6.36-6.37C5.77 11.84 2.27 21.7 2.27 21.7zM8.64 14l-2.05-2.04M15.34 15l-2.46-2.46"}],["path",{d:"M22 9s-1.33-2-3.5-2C16.86 7 15 9 15 9s1.33 2 3.5 2S22 9 22 9z"}],["path",{d:"M15 2s-2 1.33-2 3.5S15 9 15 9s2-1.84 2-3.5C17 3.33 15 2 15 2z"}]]],R5=["svg",h,[["circle",{cx:"7",cy:"12",r:"3"}],["path",{d:"M10 9v6"}],["circle",{cx:"17",cy:"12",r:"3"}],["path",{d:"M14 7v8"}]]],z5=["svg",h,[["path",{d:"m3 15 4-8 4 8"}],["path",{d:"M4 13h6"}],["circle",{cx:"18",cy:"12",r:"3"}],["path",{d:"M21 9v6"}]]],q5=["svg",h,[["path",{d:"m3 15 4-8 4 8"}],["path",{d:"M4 13h6"}],["path",{d:"M15 11h4.5a2 2 0 0 1 0 4H15V7h4a2 2 0 0 1 0 4"}]]],T5=["svg",h,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["circle",{cx:"8",cy:"10",r:"2"}],["path",{d:"M8 12h8"}],["circle",{cx:"16",cy:"10",r:"2"}],["path",{d:"m6 20 .7-2.9A1.4 1.4 0 0 1 8.1 16h7.8a1.4 1.4 0 0 1 1.4 1l.7 3"}]]],Z5=["svg",h,[["path",{d:"M2 8V6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6"}],["path",{d:"M2 12a9 9 0 0 1 8 8"}],["path",{d:"M2 16a5 5 0 0 1 4 4"}],["line",{x1:"2",x2:"2.01",y1:"20",y2:"20"}]]],b5=["svg",h,[["path",{d:"M22 20v-9H2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2Z"}],["path",{d:"M18 11V4H6v7"}],["path",{d:"M15 22v-4a3 3 0 0 0-3-3a3 3 0 0 0-3 3v4"}],["path",{d:"M22 11V9"}],["path",{d:"M2 11V9"}],["path",{d:"M6 4V2"}],["path",{d:"M18 4V2"}],["path",{d:"M10 4V2"}],["path",{d:"M14 4V2"}]]],U5=["svg",h,[["path",{d:"M12 5c.67 0 1.35.09 2 .26 1.78-2 5.03-2.84 6.42-2.26 1.4.58-.42 7-.42 7 .57 1.07 1 2.24 1 3.44C21 17.9 16.97 21 12 21s-9-3-9-7.56c0-1.25.5-2.4 1-3.44 0 0-1.89-6.42-.5-7 1.39-.58 4.72.23 6.5 2.23A9.04 9.04 0 0 1 12 5Z"}],["path",{d:"M8 14v.5"}],["path",{d:"M16 14v.5"}],["path",{d:"M11.25 16.25h1.5L12 17l-.75-.75Z"}]]],O5=["svg",h,[["path",{d:"M16.75 12h3.632a1 1 0 0 1 .894 1.447l-2.034 4.069a1 1 0 0 1-1.708.134l-2.124-2.97"}],["path",{d:"M17.106 9.053a1 1 0 0 1 .447 1.341l-3.106 6.211a1 1 0 0 1-1.342.447L3.61 12.3a2.92 2.92 0 0 1-1.3-3.91L3.69 5.6a2.92 2.92 0 0 1 3.92-1.3z"}],["path",{d:"M2 19h3.76a2 2 0 0 0 1.8-1.1L9 15"}],["path",{d:"M2 21v-4"}],["path",{d:"M7 9h.01"}]]],P=["svg",h,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M7 11.207a.5.5 0 0 1 .146-.353l2-2a.5.5 0 0 1 .708 0l3.292 3.292a.5.5 0 0 0 .708 0l4.292-4.292a.5.5 0 0 1 .854.353V16a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1z"}]]],k=["svg",h,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["rect",{x:"7",y:"13",width:"9",height:"4",rx:"1"}],["rect",{x:"7",y:"5",width:"12",height:"4",rx:"1"}]]],G5=["svg",h,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M7 11h8"}],["path",{d:"M7 16h3"}],["path",{d:"M7 6h12"}]]],I5=["svg",h,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M7 11h8"}],["path",{d:"M7 16h12"}],["path",{d:"M7 6h3"}]]],E5=["svg",h,[["path",{d:"M11 13v4"}],["path",{d:"M15 5v4"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["rect",{x:"7",y:"13",width:"9",height:"4",rx:"1"}],["rect",{x:"7",y:"5",width:"12",height:"4",rx:"1"}]]],B=["svg",h,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M7 16h8"}],["path",{d:"M7 11h12"}],["path",{d:"M7 6h3"}]]],F=["svg",h,[["path",{d:"M9 5v4"}],["rect",{width:"4",height:"6",x:"7",y:"9",rx:"1"}],["path",{d:"M9 15v2"}],["path",{d:"M17 3v2"}],["rect",{width:"4",height:"8",x:"15",y:"5",rx:"1"}],["path",{d:"M17 13v3"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}]]],D=["svg",h,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["rect",{x:"15",y:"5",width:"4",height:"12",rx:"1"}],["rect",{x:"7",y:"8",width:"4",height:"9",rx:"1"}]]],W5=["svg",h,[["path",{d:"M13 17V9"}],["path",{d:"M18 17v-3"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M8 17V5"}]]],R=["svg",h,[["path",{d:"M13 17V9"}],["path",{d:"M18 17V5"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M8 17v-3"}]]],x5=["svg",h,[["path",{d:"M11 13H7"}],["path",{d:"M19 9h-4"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["rect",{x:"15",y:"5",width:"4",height:"12",rx:"1"}],["rect",{x:"7",y:"8",width:"4",height:"9",rx:"1"}]]],z=["svg",h,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M18 17V9"}],["path",{d:"M13 17V5"}],["path",{d:"M8 17v-3"}]]],X5=["svg",h,[["path",{d:"M10 6h8"}],["path",{d:"M12 16h6"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M8 11h7"}]]],q=["svg",h,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"m19 9-5 5-4-4-3 3"}]]],N5=["svg",h,[["path",{d:"m13.11 7.664 1.78 2.672"}],["path",{d:"m14.162 12.788-3.324 1.424"}],["path",{d:"m20 4-6.06 1.515"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["circle",{cx:"12",cy:"6",r:"2"}],["circle",{cx:"16",cy:"12",r:"2"}],["circle",{cx:"9",cy:"15",r:"2"}]]],K5=["svg",h,[["path",{d:"M12 20V10"}],["path",{d:"M18 20v-4"}],["path",{d:"M6 20V4"}]]],T=["svg",h,[["line",{x1:"12",x2:"12",y1:"20",y2:"10"}],["line",{x1:"18",x2:"18",y1:"20",y2:"4"}],["line",{x1:"6",x2:"6",y1:"20",y2:"16"}]]],Z=["svg",h,[["line",{x1:"18",x2:"18",y1:"20",y2:"10"}],["line",{x1:"12",x2:"12",y1:"20",y2:"4"}],["line",{x1:"6",x2:"6",y1:"20",y2:"14"}]]],J5=["svg",h,[["path",{d:"M12 16v5"}],["path",{d:"M16 14v7"}],["path",{d:"M20 10v11"}],["path",{d:"m22 3-8.646 8.646a.5.5 0 0 1-.708 0L9.354 8.354a.5.5 0 0 0-.707 0L2 15"}],["path",{d:"M4 18v3"}],["path",{d:"M8 14v7"}]]],b=["svg",h,[["path",{d:"M8 6h10"}],["path",{d:"M6 12h9"}],["path",{d:"M11 18h7"}]]],U=["svg",h,[["path",{d:"M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z"}],["path",{d:"M21.21 15.89A10 10 0 1 1 8 2.83"}]]],O=["svg",h,[["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor"}],["circle",{cx:"18.5",cy:"5.5",r:".5",fill:"currentColor"}],["circle",{cx:"11.5",cy:"11.5",r:".5",fill:"currentColor"}],["circle",{cx:"7.5",cy:"16.5",r:".5",fill:"currentColor"}],["circle",{cx:"17.5",cy:"14.5",r:".5",fill:"currentColor"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}]]],Q5=["svg",h,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M7 16c.5-2 1.5-7 4-7 2 0 2 3 4 3 2.5 0 4.5-5 5-7"}]]],j5=["svg",h,[["path",{d:"M18 6 7 17l-5-5"}],["path",{d:"m22 10-7.5 7.5L13 16"}]]],Y5=["svg",h,[["path",{d:"M20 6 9 17l-5-5"}]]],_5=["svg",h,[["path",{d:"M17 21a1 1 0 0 0 1-1v-5.35c0-.457.316-.844.727-1.041a4 4 0 0 0-2.134-7.589 5 5 0 0 0-9.186 0 4 4 0 0 0-2.134 7.588c.411.198.727.585.727 1.041V20a1 1 0 0 0 1 1Z"}],["path",{d:"M6 17h12"}]]],ad=["svg",h,[["path",{d:"M2 17a5 5 0 0 0 10 0c0-2.76-2.5-5-5-3-2.5-2-5 .24-5 3Z"}],["path",{d:"M12 17a5 5 0 0 0 10 0c0-2.76-2.5-5-5-3-2.5-2-5 .24-5 3Z"}],["path",{d:"M7 14c3.22-2.91 4.29-8.75 5-12 1.66 2.38 4.94 9 5 12"}],["path",{d:"M22 9c-4.29 0-7.14-2.33-10-7 5.71 0 10 4.67 10 7Z"}]]],hd=["svg",h,[["path",{d:"m6 9 6 6 6-6"}]]],td=["svg",h,[["path",{d:"m17 18-6-6 6-6"}],["path",{d:"M7 6v12"}]]],dd=["svg",h,[["path",{d:"m7 18 6-6-6-6"}],["path",{d:"M17 6v12"}]]],cd=["svg",h,[["path",{d:"m15 18-6-6 6-6"}]]],Md=["svg",h,[["path",{d:"m9 18 6-6-6-6"}]]],pd=["svg",h,[["path",{d:"m18 15-6-6-6 6"}]]],ed=["svg",h,[["path",{d:"m7 20 5-5 5 5"}],["path",{d:"m7 4 5 5 5-5"}]]],nd=["svg",h,[["path",{d:"m7 6 5 5 5-5"}],["path",{d:"m7 13 5 5 5-5"}]]],id=["svg",h,[["path",{d:"m18 8 4 4-4 4"}],["path",{d:"m6 8-4 4 4 4"}],["path",{d:"M8 12h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M16 12h.01"}]]],ld=["svg",h,[["path",{d:"m9 7-5 5 5 5"}],["path",{d:"m15 7 5 5-5 5"}]]],vd=["svg",h,[["path",{d:"m11 17-5-5 5-5"}],["path",{d:"m18 17-5-5 5-5"}]]],od=["svg",h,[["path",{d:"m20 17-5-5 5-5"}],["path",{d:"m4 17 5-5-5-5"}]]],sd=["svg",h,[["path",{d:"m6 17 5-5-5-5"}],["path",{d:"m13 17 5-5-5-5"}]]],rd=["svg",h,[["path",{d:"m7 15 5 5 5-5"}],["path",{d:"m7 9 5-5 5 5"}]]],gd=["svg",h,[["path",{d:"m17 11-5-5-5 5"}],["path",{d:"m17 18-5-5-5 5"}]]],yd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"12",r:"4"}],["line",{x1:"21.17",x2:"12",y1:"8",y2:"8"}],["line",{x1:"3.95",x2:"8.54",y1:"6.06",y2:"14"}],["line",{x1:"10.88",x2:"15.46",y1:"21.94",y2:"14"}]]],$d=["svg",h,[["path",{d:"M10 9h4"}],["path",{d:"M12 7v5"}],["path",{d:"M14 22v-4a2 2 0 0 0-4 0v4"}],["path",{d:"M18 22V5.618a1 1 0 0 0-.553-.894l-4.553-2.277a2 2 0 0 0-1.788 0L6.553 4.724A1 1 0 0 0 6 5.618V22"}],["path",{d:"m18 7 3.447 1.724a1 1 0 0 1 .553.894V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9.618a1 1 0 0 1 .553-.894L6 7"}]]],md=["svg",h,[["path",{d:"M12 12H3a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h13"}],["path",{d:"M18 8c0-2.5-2-2.5-2-5"}],["path",{d:"m2 2 20 20"}],["path",{d:"M21 12a1 1 0 0 1 1 1v2a1 1 0 0 1-.5.866"}],["path",{d:"M22 8c0-2.5-2-2.5-2-5"}],["path",{d:"M7 12v4"}]]],Cd=["svg",h,[["path",{d:"M17 12H3a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h14"}],["path",{d:"M18 8c0-2.5-2-2.5-2-5"}],["path",{d:"M21 16a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1"}],["path",{d:"M22 8c0-2.5-2-2.5-2-5"}],["path",{d:"M7 12v4"}]]],G=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16"}]]],I=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 8v8"}],["path",{d:"m8 12 4 4 4-4"}]]],E=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M16 12H8"}],["path",{d:"m12 8-4 4 4 4"}]]],W=["svg",h,[["path",{d:"M2 12a10 10 0 1 1 10 10"}],["path",{d:"m2 22 10-10"}],["path",{d:"M8 22H2v-6"}]]],x=["svg",h,[["path",{d:"M12 22a10 10 0 1 1 10-10"}],["path",{d:"M22 22 12 12"}],["path",{d:"M22 16v6h-6"}]]],X=["svg",h,[["path",{d:"M2 8V2h6"}],["path",{d:"m2 2 10 10"}],["path",{d:"M12 2A10 10 0 1 1 2 12"}]]],N=["svg",h,[["path",{d:"M22 12A10 10 0 1 1 12 2"}],["path",{d:"M22 2 12 12"}],["path",{d:"M16 2h6v6"}]]],K=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M8 12h8"}],["path",{d:"m12 16 4-4-4-4"}]]],J=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m16 12-4-4-4 4"}],["path",{d:"M12 16V8"}]]],Q=["svg",h,[["path",{d:"M21.801 10A10 10 0 1 1 17 3.335"}],["path",{d:"m9 11 3 3L22 4"}]]],j=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m9 12 2 2 4-4"}]]],Y=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m16 10-4 4-4-4"}]]],_=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m14 16-4-4 4-4"}]]],a1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m10 8 4 4-4 4"}]]],h1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m8 14 4-4 4 4"}]]],ud=["svg",h,[["path",{d:"M10.1 2.182a10 10 0 0 1 3.8 0"}],["path",{d:"M13.9 21.818a10 10 0 0 1-3.8 0"}],["path",{d:"M17.609 3.721a10 10 0 0 1 2.69 2.7"}],["path",{d:"M2.182 13.9a10 10 0 0 1 0-3.8"}],["path",{d:"M20.279 17.609a10 10 0 0 1-2.7 2.69"}],["path",{d:"M21.818 10.1a10 10 0 0 1 0 3.8"}],["path",{d:"M3.721 6.391a10 10 0 0 1 2.7-2.69"}],["path",{d:"M6.391 20.279a10 10 0 0 1-2.69-2.7"}]]],t1=["svg",h,[["line",{x1:"8",x2:"16",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"16",y2:"16"}],["line",{x1:"12",x2:"12",y1:"8",y2:"8"}],["circle",{cx:"12",cy:"12",r:"10"}]]],Hd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"}],["path",{d:"M12 18V6"}]]],wd=["svg",h,[["path",{d:"M10.1 2.18a9.93 9.93 0 0 1 3.8 0"}],["path",{d:"M17.6 3.71a9.95 9.95 0 0 1 2.69 2.7"}],["path",{d:"M21.82 10.1a9.93 9.93 0 0 1 0 3.8"}],["path",{d:"M20.29 17.6a9.95 9.95 0 0 1-2.7 2.69"}],["path",{d:"M13.9 21.82a9.94 9.94 0 0 1-3.8 0"}],["path",{d:"M6.4 20.29a9.95 9.95 0 0 1-2.69-2.7"}],["path",{d:"M2.18 13.9a9.93 9.93 0 0 1 0-3.8"}],["path",{d:"M3.71 6.4a9.95 9.95 0 0 1 2.7-2.69"}],["circle",{cx:"12",cy:"12",r:"1"}]]],Vd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"12",r:"1"}]]],Ad=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M17 12h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M7 12h.01"}]]],Sd=["svg",h,[["path",{d:"M7 10h10"}],["path",{d:"M7 14h10"}],["circle",{cx:"12",cy:"12",r:"10"}]]],Ld=["svg",h,[["path",{d:"M12 2a10 10 0 0 1 7.38 16.75"}],["path",{d:"m16 12-4-4-4 4"}],["path",{d:"M12 16V8"}],["path",{d:"M2.5 8.875a10 10 0 0 0-.5 3"}],["path",{d:"M2.83 16a10 10 0 0 0 2.43 3.4"}],["path",{d:"M4.636 5.235a10 10 0 0 1 .891-.857"}],["path",{d:"M8.644 21.42a10 10 0 0 0 7.631-.38"}]]],fd=["svg",h,[["path",{d:"M12 2a10 10 0 0 1 7.38 16.75"}],["path",{d:"M12 8v8"}],["path",{d:"M16 12H8"}],["path",{d:"M2.5 8.875a10 10 0 0 0-.5 3"}],["path",{d:"M2.83 16a10 10 0 0 0 2.43 3.4"}],["path",{d:"M4.636 5.235a10 10 0 0 1 .891-.857"}],["path",{d:"M8.644 21.42a10 10 0 0 0 7.631-.38"}]]],d1=["svg",h,[["path",{d:"M15.6 2.7a10 10 0 1 0 5.7 5.7"}],["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"M13.4 10.6 19 5"}]]],c1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"}],["path",{d:"M12 17h.01"}]]],M1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M8 12h8"}]]],Pd=["svg",h,[["path",{d:"m2 2 20 20"}],["path",{d:"M8.35 2.69A10 10 0 0 1 21.3 15.65"}],["path",{d:"M19.08 19.08A10 10 0 1 1 4.92 4.92"}]]],p1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m5 5 14 14"}],["path",{d:"M13 13a3 3 0 1 0 0-6H9v2"}],["path",{d:"M9 17v-2.34"}]]],e1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M9 17V7h4a3 3 0 0 1 0 6H9"}]]],n1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"10",x2:"10",y1:"15",y2:"9"}],["line",{x1:"14",x2:"14",y1:"15",y2:"9"}]]],i1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m15 9-6 6"}],["path",{d:"M9 9h.01"}],["path",{d:"M15 15h.01"}]]],l1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polygon",{points:"10 8 16 12 10 16 10 8"}]]],v1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M8 12h8"}],["path",{d:"M12 8v8"}]]],o1=["svg",h,[["path",{d:"M12 7v4"}],["path",{d:"M7.998 9.003a5 5 0 1 0 8-.005"}],["circle",{cx:"12",cy:"12",r:"10"}]]],s1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M22 2 2 22"}]]],kd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"9",x2:"15",y1:"15",y2:"9"}]]],r1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["rect",{x:"9",y:"9",width:"6",height:"6",rx:"1"}]]],g1=["svg",h,[["path",{d:"M18 20a6 6 0 0 0-12 0"}],["circle",{cx:"12",cy:"10",r:"4"}],["circle",{cx:"12",cy:"12",r:"10"}]]],y1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M7 20.662V19a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v1.662"}]]],$1=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m15 9-6 6"}],["path",{d:"m9 9 6 6"}]]],Bd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}]]],Fd=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M11 9h4a2 2 0 0 0 2-2V3"}],["circle",{cx:"9",cy:"9",r:"2"}],["path",{d:"M7 21v-4a2 2 0 0 1 2-2h4"}],["circle",{cx:"15",cy:"15",r:"2"}]]],Dd=["svg",h,[["path",{d:"M21.66 17.67a1.08 1.08 0 0 1-.04 1.6A12 12 0 0 1 4.73 2.38a1.1 1.1 0 0 1 1.61-.04z"}],["path",{d:"M19.65 15.66A8 8 0 0 1 8.35 4.34"}],["path",{d:"m14 10-5.5 5.5"}],["path",{d:"M14 17.85V10H6.15"}]]],Rd=["svg",h,[["path",{d:"M20.2 6 3 11l-.9-2.4c-.3-1.1.3-2.2 1.3-2.5l13.5-4c1.1-.3 2.2.3 2.5 1.3Z"}],["path",{d:"m6.2 5.3 3.1 3.9"}],["path",{d:"m12.4 3.4 3.1 4"}],["path",{d:"M3 11h18v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z"}]]],zd=["svg",h,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"m9 14 2 2 4-4"}]]],qd=["svg",h,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v4"}],["path",{d:"M21 14H11"}],["path",{d:"m15 10-4 4 4 4"}]]],Td=["svg",h,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"M12 11h4"}],["path",{d:"M12 16h4"}],["path",{d:"M8 11h.01"}],["path",{d:"M8 16h.01"}]]],Zd=["svg",h,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"M9 14h6"}]]],bd=["svg",h,[["path",{d:"M15 2H9a1 1 0 0 0-1 1v2c0 .6.4 1 1 1h6c.6 0 1-.4 1-1V3c0-.6-.4-1-1-1Z"}],["path",{d:"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2M16 4h2a2 2 0 0 1 2 2v2M11 14h10"}],["path",{d:"m17 10 4 4-4 4"}]]],m1=["svg",h,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1"}],["path",{d:"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-.5"}],["path",{d:"M16 4h2a2 2 0 0 1 1.73 1"}],["path",{d:"M8 18h1"}],["path",{d:"M21.378 12.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}]]],C1=["svg",h,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-5.5"}],["path",{d:"M4 13.5V6a2 2 0 0 1 2-2h2"}],["path",{d:"M13.378 15.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}]]],Ud=["svg",h,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"M9 14h6"}],["path",{d:"M12 17v-6"}]]],Od=["svg",h,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"M9 12v-1h6v1"}],["path",{d:"M11 17h2"}],["path",{d:"M12 11v6"}]]],Gd=["svg",h,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"m15 11-6 6"}],["path",{d:"m9 11 6 6"}]]],Id=["svg",h,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}]]],Ed=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 14.5 8"}]]],Wd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 8 10"}]]],xd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 9.5 8"}]]],Xd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12"}]]],Nd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 16 10"}]]],Kd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 16.5 12"}]]],Jd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 16 14"}]]],Qd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 14.5 16"}]]],jd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 12 16.5"}]]],Yd=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 9.5 16"}]]],_d=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 8 14"}]]],a3=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 7.5 12"}]]],h3=["svg",h,[["path",{d:"M12 6v6l4 2"}],["path",{d:"M16 21.16a10 10 0 1 1 5-13.516"}],["path",{d:"M20 11.5v6"}],["path",{d:"M20 21.5h.01"}]]],t3=["svg",h,[["path",{d:"M12.338 21.994A10 10 0 1 1 21.925 13.227"}],["path",{d:"M12 6v6l2 1"}],["path",{d:"m14 18 4 4 4-4"}],["path",{d:"M18 14v8"}]]],d3=["svg",h,[["path",{d:"M13.228 21.925A10 10 0 1 1 21.994 12.338"}],["path",{d:"M12 6v6l1.562.781"}],["path",{d:"m14 18 4-4 4 4"}],["path",{d:"M18 22v-8"}]]],c3=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 16 14"}]]],M3=["svg",h,[["path",{d:"M12 12v4"}],["path",{d:"M12 20h.01"}],["path",{d:"M17 18h.5a1 1 0 0 0 0-9h-1.79A7 7 0 1 0 7 17.708"}]]],p3=["svg",h,[["circle",{cx:"12",cy:"17",r:"3"}],["path",{d:"M4.2 15.1A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.2"}],["path",{d:"m15.7 18.4-.9-.3"}],["path",{d:"m9.2 15.9-.9-.3"}],["path",{d:"m10.6 20.7.3-.9"}],["path",{d:"m13.1 14.2.3-.9"}],["path",{d:"m13.6 20.7-.4-1"}],["path",{d:"m10.8 14.3-.4-1"}],["path",{d:"m8.3 18.6 1-.4"}],["path",{d:"m14.7 15.8 1-.4"}]]],u1=["svg",h,[["path",{d:"M12 13v8l-4-4"}],["path",{d:"m12 21 4-4"}],["path",{d:"M4.393 15.269A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.436 8.284"}]]],e3=["svg",h,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"M8 19v1"}],["path",{d:"M8 14v1"}],["path",{d:"M16 19v1"}],["path",{d:"M16 14v1"}],["path",{d:"M12 21v1"}],["path",{d:"M12 16v1"}]]],n3=["svg",h,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"M16 17H7"}],["path",{d:"M17 21H9"}]]],i3=["svg",h,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"M16 14v2"}],["path",{d:"M8 14v2"}],["path",{d:"M16 20h.01"}],["path",{d:"M8 20h.01"}],["path",{d:"M12 16v2"}],["path",{d:"M12 22h.01"}]]],l3=["svg",h,[["path",{d:"M6 16.326A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 .5 8.973"}],["path",{d:"m13 12-3 5h4l-3 5"}]]],v3=["svg",h,[["path",{d:"M10.188 8.5A6 6 0 0 1 16 4a1 1 0 0 0 6 6 6 6 0 0 1-3 5.197"}],["path",{d:"M11 20v2"}],["path",{d:"M3 20a5 5 0 1 1 8.9-4H13a3 3 0 0 1 2 5.24"}],["path",{d:"M7 19v2"}]]],o3=["svg",h,[["path",{d:"M10.188 8.5A6 6 0 0 1 16 4a1 1 0 0 0 6 6 6 6 0 0 1-3 5.197"}],["path",{d:"M13 16a3 3 0 1 1 0 6H7a5 5 0 1 1 4.9-6Z"}]]],s3=["svg",h,[["path",{d:"m2 2 20 20"}],["path",{d:"M5.782 5.782A7 7 0 0 0 9 19h8.5a4.5 4.5 0 0 0 1.307-.193"}],["path",{d:"M21.532 16.5A4.5 4.5 0 0 0 17.5 10h-1.79A7.008 7.008 0 0 0 10 5.07"}]]],r3=["svg",h,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"m9.2 22 3-7"}],["path",{d:"m9 13-3 7"}],["path",{d:"m17 13-3 7"}]]],g3=["svg",h,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"M16 14v6"}],["path",{d:"M8 14v6"}],["path",{d:"M12 16v6"}]]],y3=["svg",h,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"M8 15h.01"}],["path",{d:"M8 19h.01"}],["path",{d:"M12 17h.01"}],["path",{d:"M12 21h.01"}],["path",{d:"M16 15h.01"}],["path",{d:"M16 19h.01"}]]],$3=["svg",h,[["path",{d:"M12 2v2"}],["path",{d:"m4.93 4.93 1.41 1.41"}],["path",{d:"M20 12h2"}],["path",{d:"m19.07 4.93-1.41 1.41"}],["path",{d:"M15.947 12.65a4 4 0 0 0-5.925-4.128"}],["path",{d:"M3 20a5 5 0 1 1 8.9-4H13a3 3 0 0 1 2 5.24"}],["path",{d:"M11 20v2"}],["path",{d:"M7 19v2"}]]],m3=["svg",h,[["path",{d:"M12 2v2"}],["path",{d:"m4.93 4.93 1.41 1.41"}],["path",{d:"M20 12h2"}],["path",{d:"m19.07 4.93-1.41 1.41"}],["path",{d:"M15.947 12.65a4 4 0 0 0-5.925-4.128"}],["path",{d:"M13 22H7a5 5 0 1 1 4.9-6H13a3 3 0 0 1 0 6Z"}]]],H1=["svg",h,[["path",{d:"M12 13v8"}],["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"m8 17 4-4 4 4"}]]],C3=["svg",h,[["path",{d:"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"}]]],u3=["svg",h,[["path",{d:"M17.5 21H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"}],["path",{d:"M22 10a3 3 0 0 0-3-3h-2.207a5.502 5.502 0 0 0-10.702.5"}]]],H3=["svg",h,[["path",{d:"M16.17 7.83 2 22"}],["path",{d:"M4.02 12a2.827 2.827 0 1 1 3.81-4.17A2.827 2.827 0 1 1 12 4.02a2.827 2.827 0 1 1 4.17 3.81A2.827 2.827 0 1 1 19.98 12a2.827 2.827 0 1 1-3.81 4.17A2.827 2.827 0 1 1 12 19.98a2.827 2.827 0 1 1-4.17-3.81A1 1 0 1 1 4 12"}],["path",{d:"m7.83 7.83 8.34 8.34"}]]],w3=["svg",h,[["path",{d:"M17.28 9.05a5.5 5.5 0 1 0-10.56 0A5.5 5.5 0 1 0 12 17.66a5.5 5.5 0 1 0 5.28-8.6Z"}],["path",{d:"M12 17.66L12 22"}]]],w1=["svg",h,[["path",{d:"m18 16 4-4-4-4"}],["path",{d:"m6 8-4 4 4 4"}],["path",{d:"m14.5 4-5 16"}]]],V3=["svg",h,[["polyline",{points:"16 18 22 12 16 6"}],["polyline",{points:"8 6 2 12 8 18"}]]],A3=["svg",h,[["polygon",{points:"12 2 22 8.5 22 15.5 12 22 2 15.5 2 8.5 12 2"}],["line",{x1:"12",x2:"12",y1:"22",y2:"15.5"}],["polyline",{points:"22 8.5 12 15.5 2 8.5"}],["polyline",{points:"2 15.5 12 8.5 22 15.5"}],["line",{x1:"12",x2:"12",y1:"2",y2:"8.5"}]]],S3=["svg",h,[["path",{d:"M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"}],["polyline",{points:"7.5 4.21 12 6.81 16.5 4.21"}],["polyline",{points:"7.5 19.79 7.5 14.6 3 12"}],["polyline",{points:"21 12 16.5 14.6 16.5 19.79"}],["polyline",{points:"3.27 6.96 12 12.01 20.73 6.96"}],["line",{x1:"12",x2:"12",y1:"22.08",y2:"12"}]]],L3=["svg",h,[["path",{d:"M10 2v2"}],["path",{d:"M14 2v2"}],["path",{d:"M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h14a4 4 0 1 1 0 8h-1"}],["path",{d:"M6 2v2"}]]],f3=["svg",h,[["path",{d:"M12 20a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z"}],["path",{d:"M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z"}],["path",{d:"M12 2v2"}],["path",{d:"M12 22v-2"}],["path",{d:"m17 20.66-1-1.73"}],["path",{d:"M11 10.27 7 3.34"}],["path",{d:"m20.66 17-1.73-1"}],["path",{d:"m3.34 7 1.73 1"}],["path",{d:"M14 12h8"}],["path",{d:"M2 12h2"}],["path",{d:"m20.66 7-1.73 1"}],["path",{d:"m3.34 17 1.73-1"}],["path",{d:"m17 3.34-1 1.73"}],["path",{d:"m11 13.73-4 6.93"}]]],P3=["svg",h,[["circle",{cx:"8",cy:"8",r:"6"}],["path",{d:"M18.09 10.37A6 6 0 1 1 10.34 18"}],["path",{d:"M7 6h1v4"}],["path",{d:"m16.71 13.88.7.71-2.82 2.82"}]]],V1=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M12 3v18"}]]],A1=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 3v18"}],["path",{d:"M15 3v18"}]]],k3=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7.5 3v18"}],["path",{d:"M12 3v18"}],["path",{d:"M16.5 3v18"}]]],B3=["svg",h,[["path",{d:"M10 18H5a3 3 0 0 1-3-3v-1"}],["path",{d:"M14 2a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2"}],["path",{d:"M20 2a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2"}],["path",{d:"m7 21 3-3-3-3"}],["rect",{x:"14",y:"14",width:"8",height:"8",rx:"2"}],["rect",{x:"2",y:"2",width:"8",height:"8",rx:"2"}]]],F3=["svg",h,[["path",{d:"M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3"}]]],D3=["svg",h,[["path",{d:"m16.24 7.76-1.804 5.411a2 2 0 0 1-1.265 1.265L7.76 16.24l1.804-5.411a2 2 0 0 1 1.265-1.265z"}],["circle",{cx:"12",cy:"12",r:"10"}]]],R3=["svg",h,[["path",{d:"M15.536 11.293a1 1 0 0 0 0 1.414l2.376 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0z"}],["path",{d:"M2.297 11.293a1 1 0 0 0 0 1.414l2.377 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414L6.088 8.916a1 1 0 0 0-1.414 0z"}],["path",{d:"M8.916 17.912a1 1 0 0 0 0 1.415l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.415l-2.377-2.376a1 1 0 0 0-1.414 0z"}],["path",{d:"M8.916 4.674a1 1 0 0 0 0 1.414l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0z"}]]],z3=["svg",h,[["rect",{width:"14",height:"8",x:"5",y:"2",rx:"2"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2"}],["path",{d:"M6 18h2"}],["path",{d:"M12 18h6"}]]],q3=["svg",h,[["path",{d:"M3 20a1 1 0 0 1-1-1v-1a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1Z"}],["path",{d:"M20 16a8 8 0 1 0-16 0"}],["path",{d:"M12 4v4"}],["path",{d:"M10 4h4"}]]],T3=["svg",h,[["path",{d:"m20.9 18.55-8-15.98a1 1 0 0 0-1.8 0l-8 15.98"}],["ellipse",{cx:"12",cy:"19",rx:"9",ry:"3"}]]],Z3=["svg",h,[["rect",{x:"2",y:"6",width:"20",height:"8",rx:"1"}],["path",{d:"M17 14v7"}],["path",{d:"M7 14v7"}],["path",{d:"M17 3v3"}],["path",{d:"M7 3v3"}],["path",{d:"M10 14 2.3 6.3"}],["path",{d:"m14 6 7.7 7.7"}],["path",{d:"m8 6 8 8"}]]],S1=["svg",h,[["path",{d:"M16 2v2"}],["path",{d:"M17.915 22a6 6 0 0 0-12 0"}],["path",{d:"M8 2v2"}],["circle",{cx:"12",cy:"12",r:"4"}],["rect",{x:"3",y:"4",width:"18",height:"18",rx:"2"}]]],b3=["svg",h,[["path",{d:"M16 2v2"}],["path",{d:"M7 22v-2a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v2"}],["path",{d:"M8 2v2"}],["circle",{cx:"12",cy:"11",r:"3"}],["rect",{x:"3",y:"4",width:"18",height:"18",rx:"2"}]]],U3=["svg",h,[["path",{d:"M22 7.7c0-.6-.4-1.2-.8-1.5l-6.3-3.9a1.72 1.72 0 0 0-1.7 0l-10.3 6c-.5.2-.9.8-.9 1.4v6.6c0 .5.4 1.2.8 1.5l6.3 3.9a1.72 1.72 0 0 0 1.7 0l10.3-6c.5-.3.9-1 .9-1.5Z"}],["path",{d:"M10 21.9V14L2.1 9.1"}],["path",{d:"m10 14 11.9-6.9"}],["path",{d:"M14 19.8v-8.1"}],["path",{d:"M18 17.5V9.4"}]]],O3=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 18a6 6 0 0 0 0-12v12z"}]]],G3=["svg",h,[["path",{d:"M12 2a10 10 0 1 0 10 10 4 4 0 0 1-5-5 4 4 0 0 1-5-5"}],["path",{d:"M8.5 8.5v.01"}],["path",{d:"M16 15.5v.01"}],["path",{d:"M12 12v.01"}],["path",{d:"M11 17v.01"}],["path",{d:"M7 14v.01"}]]],I3=["svg",h,[["path",{d:"M2 12h20"}],["path",{d:"M20 12v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-8"}],["path",{d:"m4 8 16-4"}],["path",{d:"m8.86 6.78-.45-1.81a2 2 0 0 1 1.45-2.43l1.94-.48a2 2 0 0 1 2.43 1.46l.45 1.8"}]]],E3=["svg",h,[["path",{d:"m12 15 2 2 4-4"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]],W3=["svg",h,[["line",{x1:"12",x2:"18",y1:"15",y2:"15"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]],x3=["svg",h,[["line",{x1:"15",x2:"15",y1:"12",y2:"18"}],["line",{x1:"12",x2:"18",y1:"15",y2:"15"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]],X3=["svg",h,[["line",{x1:"12",x2:"18",y1:"18",y2:"12"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]],N3=["svg",h,[["line",{x1:"12",x2:"18",y1:"12",y2:"18"}],["line",{x1:"12",x2:"18",y1:"18",y2:"12"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]],K3=["svg",h,[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]],J3=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M9.17 14.83a4 4 0 1 0 0-5.66"}]]],Q3=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M14.83 14.83a4 4 0 1 1 0-5.66"}]]],j3=["svg",h,[["polyline",{points:"9 10 4 15 9 20"}],["path",{d:"M20 4v7a4 4 0 0 1-4 4H4"}]]],Y3=["svg",h,[["polyline",{points:"15 10 20 15 15 20"}],["path",{d:"M4 4v7a4 4 0 0 0 4 4h12"}]]],_3=["svg",h,[["polyline",{points:"14 15 9 20 4 15"}],["path",{d:"M20 4h-7a4 4 0 0 0-4 4v12"}]]],a6=["svg",h,[["polyline",{points:"14 9 9 4 4 9"}],["path",{d:"M20 20h-7a4 4 0 0 1-4-4V4"}]]],h6=["svg",h,[["polyline",{points:"10 15 15 20 20 15"}],["path",{d:"M4 4h7a4 4 0 0 1 4 4v12"}]]],t6=["svg",h,[["polyline",{points:"10 9 15 4 20 9"}],["path",{d:"M4 20h7a4 4 0 0 0 4-4V4"}]]],d6=["svg",h,[["polyline",{points:"9 14 4 9 9 4"}],["path",{d:"M20 20v-7a4 4 0 0 0-4-4H4"}]]],c6=["svg",h,[["polyline",{points:"15 14 20 9 15 4"}],["path",{d:"M4 20v-7a4 4 0 0 1 4-4h12"}]]],M6=["svg",h,[["rect",{width:"16",height:"16",x:"4",y:"4",rx:"2"}],["rect",{width:"6",height:"6",x:"9",y:"9",rx:"1"}],["path",{d:"M15 2v2"}],["path",{d:"M15 20v2"}],["path",{d:"M2 15h2"}],["path",{d:"M2 9h2"}],["path",{d:"M20 15h2"}],["path",{d:"M20 9h2"}],["path",{d:"M9 2v2"}],["path",{d:"M9 20v2"}]]],p6=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M10 9.3a2.8 2.8 0 0 0-3.5 1 3.1 3.1 0 0 0 0 3.4 2.7 2.7 0 0 0 3.5 1"}],["path",{d:"M17 9.3a2.8 2.8 0 0 0-3.5 1 3.1 3.1 0 0 0 0 3.4 2.7 2.7 0 0 0 3.5 1"}]]],e6=["svg",h,[["rect",{width:"20",height:"14",x:"2",y:"5",rx:"2"}],["line",{x1:"2",x2:"22",y1:"10",y2:"10"}]]],n6=["svg",h,[["path",{d:"m4.6 13.11 5.79-3.21c1.89-1.05 4.79 1.78 3.71 3.71l-3.22 5.81C8.8 23.16.79 15.23 4.6 13.11Z"}],["path",{d:"m10.5 9.5-1-2.29C9.2 6.48 8.8 6 8 6H4.5C2.79 6 2 6.5 2 8.5a7.71 7.71 0 0 0 2 4.83"}],["path",{d:"M8 6c0-1.55.24-4-2-4-2 0-2.5 2.17-2.5 4"}],["path",{d:"m14.5 13.5 2.29 1c.73.3 1.21.7 1.21 1.5v3.5c0 1.71-.5 2.5-2.5 2.5a7.71 7.71 0 0 1-4.83-2"}],["path",{d:"M18 16c1.55 0 4-.24 4 2 0 2-2.17 2.5-4 2.5"}]]],i6=["svg",h,[["path",{d:"M6 2v14a2 2 0 0 0 2 2h14"}],["path",{d:"M18 22V8a2 2 0 0 0-2-2H2"}]]],l6=["svg",h,[["path",{d:"M4 9a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h4a1 1 0 0 1 1 1v4a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-4a1 1 0 0 1 1-1h4a2 2 0 0 0 2-2v-2a2 2 0 0 0-2-2h-4a1 1 0 0 1-1-1V4a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v4a1 1 0 0 1-1 1z"}]]],v6=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"22",x2:"18",y1:"12",y2:"12"}],["line",{x1:"6",x2:"2",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"6",y2:"2"}],["line",{x1:"12",x2:"12",y1:"22",y2:"18"}]]],o6=["svg",h,[["path",{d:"M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z"}],["path",{d:"M5 21h14"}]]],s6=["svg",h,[["path",{d:"m21.12 6.4-6.05-4.06a2 2 0 0 0-2.17-.05L2.95 8.41a2 2 0 0 0-.95 1.7v5.82a2 2 0 0 0 .88 1.66l6.05 4.07a2 2 0 0 0 2.17.05l9.95-6.12a2 2 0 0 0 .95-1.7V8.06a2 2 0 0 0-.88-1.66Z"}],["path",{d:"M10 22v-8L2.25 9.15"}],["path",{d:"m10 14 11.77-6.87"}]]],r6=["svg",h,[["path",{d:"m6 8 1.75 12.28a2 2 0 0 0 2 1.72h4.54a2 2 0 0 0 2-1.72L18 8"}],["path",{d:"M5 8h14"}],["path",{d:"M7 15a6.47 6.47 0 0 1 5 0 6.47 6.47 0 0 0 5 0"}],["path",{d:"m12 8 1-6h2"}]]],g6=["svg",h,[["circle",{cx:"12",cy:"12",r:"8"}],["line",{x1:"3",x2:"6",y1:"3",y2:"6"}],["line",{x1:"21",x2:"18",y1:"3",y2:"6"}],["line",{x1:"3",x2:"6",y1:"21",y2:"18"}],["line",{x1:"21",x2:"18",y1:"21",y2:"18"}]]],y6=["svg",h,[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}],["path",{d:"M3 5v14a9 3 0 0 0 18 0V5"}]]],$6=["svg",h,[["path",{d:"M11 11.31c1.17.56 1.54 1.69 3.5 1.69 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}],["path",{d:"M11.75 18c.35.5 1.45 1 2.75 1 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}],["path",{d:"M2 10h4"}],["path",{d:"M2 14h4"}],["path",{d:"M2 18h4"}],["path",{d:"M2 6h4"}],["path",{d:"M7 3a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1L10 4a1 1 0 0 0-1-1z"}]]],m6=["svg",h,[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}],["path",{d:"M3 12a9 3 0 0 0 5 2.69"}],["path",{d:"M21 9.3V5"}],["path",{d:"M3 5v14a9 3 0 0 0 6.47 2.88"}],["path",{d:"M12 12v4h4"}],["path",{d:"M13 20a5 5 0 0 0 9-3 4.5 4.5 0 0 0-4.5-4.5c-1.33 0-2.54.54-3.41 1.41L12 16"}]]],C6=["svg",h,[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}],["path",{d:"M3 5V19A9 3 0 0 0 15 21.84"}],["path",{d:"M21 5V8"}],["path",{d:"M21 12L18 17H22L19 22"}],["path",{d:"M3 12A9 3 0 0 0 14.59 14.87"}]]],u6=["svg",h,[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5"}],["path",{d:"M3 12A9 3 0 0 0 21 12"}]]],H6=["svg",h,[["path",{d:"M10 5a2 2 0 0 0-1.344.519l-6.328 5.74a1 1 0 0 0 0 1.481l6.328 5.741A2 2 0 0 0 10 19h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2z"}],["path",{d:"m12 9 6 6"}],["path",{d:"m18 9-6 6"}]]],w6=["svg",h,[["circle",{cx:"12",cy:"4",r:"2"}],["path",{d:"M10.2 3.2C5.5 4 2 8.1 2 13a2 2 0 0 0 4 0v-1a2 2 0 0 1 4 0v4a2 2 0 0 0 4 0v-4a2 2 0 0 1 4 0v1a2 2 0 0 0 4 0c0-4.9-3.5-9-8.2-9.8"}],["path",{d:"M3.2 14.8a9 9 0 0 0 17.6 0"}]]],V6=["svg",h,[["circle",{cx:"19",cy:"19",r:"2"}],["circle",{cx:"5",cy:"5",r:"2"}],["path",{d:"M6.48 3.66a10 10 0 0 1 13.86 13.86"}],["path",{d:"m6.41 6.41 11.18 11.18"}],["path",{d:"M3.66 6.48a10 10 0 0 0 13.86 13.86"}]]],A6=["svg",h,[["path",{d:"M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0z"}],["path",{d:"M8 12h8"}]]],L1=["svg",h,[["path",{d:"M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0Z"}],["path",{d:"M9.2 9.2h.01"}],["path",{d:"m14.5 9.5-5 5"}],["path",{d:"M14.7 14.8h.01"}]]],S6=["svg",h,[["path",{d:"M12 8v8"}],["path",{d:"M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0z"}],["path",{d:"M8 12h8"}]]],L6=["svg",h,[["path",{d:"M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41l-7.59-7.59a2.41 2.41 0 0 0-3.41 0Z"}]]],f6=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M12 12h.01"}]]],P6=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M15 9h.01"}],["path",{d:"M9 15h.01"}]]],k6=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M16 8h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M8 16h.01"}]]],B6=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M16 8h.01"}],["path",{d:"M8 8h.01"}],["path",{d:"M8 16h.01"}],["path",{d:"M16 16h.01"}]]],F6=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M16 8h.01"}],["path",{d:"M8 8h.01"}],["path",{d:"M8 16h.01"}],["path",{d:"M16 16h.01"}],["path",{d:"M12 12h.01"}]]],D6=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M16 8h.01"}],["path",{d:"M16 12h.01"}],["path",{d:"M16 16h.01"}],["path",{d:"M8 8h.01"}],["path",{d:"M8 12h.01"}],["path",{d:"M8 16h.01"}]]],R6=["svg",h,[["rect",{width:"12",height:"12",x:"2",y:"10",rx:"2",ry:"2"}],["path",{d:"m17.92 14 3.5-3.5a2.24 2.24 0 0 0 0-3l-5-4.92a2.24 2.24 0 0 0-3 0L10 6"}],["path",{d:"M6 18h.01"}],["path",{d:"M10 14h.01"}],["path",{d:"M15 6h.01"}],["path",{d:"M18 9h.01"}]]],z6=["svg",h,[["path",{d:"M12 3v14"}],["path",{d:"M5 10h14"}],["path",{d:"M5 21h14"}]]],q6=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"12",r:"4"}],["path",{d:"M12 12h.01"}]]],T6=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M6 12c0-1.7.7-3.2 1.8-4.2"}],["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"M18 12c0 1.7-.7 3.2-1.8 4.2"}]]],Z6=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["circle",{cx:"12",cy:"12",r:"5"}],["path",{d:"M12 12h.01"}]]],b6=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"12",r:"2"}]]],U6=["svg",h,[["circle",{cx:"12",cy:"6",r:"1"}],["line",{x1:"5",x2:"19",y1:"12",y2:"12"}],["circle",{cx:"12",cy:"18",r:"1"}]]],O6=["svg",h,[["path",{d:"M15 2c-1.35 1.5-2.092 3-2.5 4.5L14 8"}],["path",{d:"m17 6-2.891-2.891"}],["path",{d:"M2 15c3.333-3 6.667-3 10-3"}],["path",{d:"m2 2 20 20"}],["path",{d:"m20 9 .891.891"}],["path",{d:"M22 9c-1.5 1.35-3 2.092-4.5 2.5l-1-1"}],["path",{d:"M3.109 14.109 4 15"}],["path",{d:"m6.5 12.5 1 1"}],["path",{d:"m7 18 2.891 2.891"}],["path",{d:"M9 22c1.35-1.5 2.092-3 2.5-4.5L10 16"}]]],G6=["svg",h,[["path",{d:"m10 16 1.5 1.5"}],["path",{d:"m14 8-1.5-1.5"}],["path",{d:"M15 2c-1.798 1.998-2.518 3.995-2.807 5.993"}],["path",{d:"m16.5 10.5 1 1"}],["path",{d:"m17 6-2.891-2.891"}],["path",{d:"M2 15c6.667-6 13.333 0 20-6"}],["path",{d:"m20 9 .891.891"}],["path",{d:"M3.109 14.109 4 15"}],["path",{d:"m6.5 12.5 1 1"}],["path",{d:"m7 18 2.891 2.891"}],["path",{d:"M9 22c1.798-1.998 2.518-3.995 2.807-5.993"}]]],I6=["svg",h,[["path",{d:"M2 8h20"}],["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M6 16h12"}]]],E6=["svg",h,[["path",{d:"M11.25 16.25h1.5L12 17z"}],["path",{d:"M16 14v.5"}],["path",{d:"M4.42 11.247A13.152 13.152 0 0 0 4 14.556C4 18.728 7.582 21 12 21s8-2.272 8-6.444a11.702 11.702 0 0 0-.493-3.309"}],["path",{d:"M8 14v.5"}],["path",{d:"M8.5 8.5c-.384 1.05-1.083 2.028-2.344 2.5-1.931.722-3.576-.297-3.656-1-.113-.994 1.177-6.53 4-7 1.923-.321 3.651.845 3.651 2.235A7.497 7.497 0 0 1 14 5.277c0-1.39 1.844-2.598 3.767-2.277 2.823.47 4.113 6.006 4 7-.08.703-1.725 1.722-3.656 1-1.261-.472-1.855-1.45-2.239-2.5"}]]],W6=["svg",h,[["line",{x1:"12",x2:"12",y1:"2",y2:"22"}],["path",{d:"M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"}]]],x6=["svg",h,[["path",{d:"M20.5 10a2.5 2.5 0 0 1-2.4-3H18a2.95 2.95 0 0 1-2.6-4.4 10 10 0 1 0 6.3 7.1c-.3.2-.8.3-1.2.3"}],["circle",{cx:"12",cy:"12",r:"3"}]]],X6=["svg",h,[["path",{d:"M18 20V6a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v14"}],["path",{d:"M2 20h20"}],["path",{d:"M14 12v.01"}]]],N6=["svg",h,[["path",{d:"M13 4h3a2 2 0 0 1 2 2v14"}],["path",{d:"M2 20h3"}],["path",{d:"M13 20h9"}],["path",{d:"M10 12v.01"}],["path",{d:"M13 4.562v16.157a1 1 0 0 1-1.242.97L5 20V5.562a2 2 0 0 1 1.515-1.94l4-1A2 2 0 0 1 13 4.561Z"}]]],K6=["svg",h,[["circle",{cx:"12.1",cy:"12.1",r:"1"}]]],J6=["svg",h,[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"}],["polyline",{points:"7 10 12 15 17 10"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3"}]]],Q6=["svg",h,[["path",{d:"m12.99 6.74 1.93 3.44"}],["path",{d:"M19.136 12a10 10 0 0 1-14.271 0"}],["path",{d:"m21 21-2.16-3.84"}],["path",{d:"m3 21 8.02-14.26"}],["circle",{cx:"12",cy:"5",r:"2"}]]],j6=["svg",h,[["path",{d:"M10 11h.01"}],["path",{d:"M14 6h.01"}],["path",{d:"M18 6h.01"}],["path",{d:"M6.5 13.1h.01"}],["path",{d:"M22 5c0 9-4 12-6 12s-6-3-6-12c0-2 2-3 6-3s6 1 6 3"}],["path",{d:"M17.4 9.9c-.8.8-2 .8-2.8 0"}],["path",{d:"M10.1 7.1C9 7.2 7.7 7.7 6 8.6c-3.5 2-4.7 3.9-3.7 5.6 4.5 7.8 9.5 8.4 11.2 7.4.9-.5 1.9-2.1 1.9-4.7"}],["path",{d:"M9.1 16.5c.3-1.1 1.4-1.7 2.4-1.4"}]]],Y6=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M19.13 5.09C15.22 9.14 10 10.44 2.25 10.94"}],["path",{d:"M21.75 12.84c-6.62-1.41-12.14 1-16.38 6.32"}],["path",{d:"M8.56 2.75c4.37 6 6 9.42 8 17.72"}]]],_6=["svg",h,[["path",{d:"M10 18a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H5a3 3 0 0 1-3-3 1 1 0 0 1 1-1z"}],["path",{d:"M13 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1l-.81 3.242a1 1 0 0 1-.97.758H8"}],["path",{d:"M14 4h3a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-3"}],["path",{d:"M18 6h4"}],["path",{d:"m5 10-2 8"}],["path",{d:"m7 18 2-8"}]]],ac=["svg",h,[["path",{d:"M18.715 13.186C18.29 11.858 17.384 10.607 16 9.5c-2-1.6-3.5-4-4-6.5a10.7 10.7 0 0 1-.884 2.586"}],["path",{d:"m2 2 20 20"}],["path",{d:"M8.795 8.797A11 11 0 0 1 8 9.5C6 11.1 5 13 5 15a7 7 0 0 0 13.222 3.208"}]]],hc=["svg",h,[["path",{d:"M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z"}]]],tc=["svg",h,[["path",{d:"M7 16.3c2.2 0 4-1.83 4-4.05 0-1.16-.57-2.26-1.71-3.19S7.29 6.75 7 5.3c-.29 1.45-1.14 2.84-2.29 3.76S3 11.1 3 12.25c0 2.22 1.8 4.05 4 4.05z"}],["path",{d:"M12.56 6.6A10.97 10.97 0 0 0 14 3.02c.5 2.5 2 4.9 4 6.5s3 3.5 3 5.5a6.98 6.98 0 0 1-11.91 4.97"}]]],dc=["svg",h,[["path",{d:"m2 2 8 8"}],["path",{d:"m22 2-8 8"}],["ellipse",{cx:"12",cy:"9",rx:"10",ry:"5"}],["path",{d:"M7 13.4v7.9"}],["path",{d:"M12 14v8"}],["path",{d:"M17 13.4v7.9"}],["path",{d:"M2 9v8a10 5 0 0 0 20 0V9"}]]],cc=["svg",h,[["path",{d:"M15.4 15.63a7.875 6 135 1 1 6.23-6.23 4.5 3.43 135 0 0-6.23 6.23"}],["path",{d:"m8.29 12.71-2.6 2.6a2.5 2.5 0 1 0-1.65 4.65A2.5 2.5 0 1 0 8.7 18.3l2.59-2.59"}]]],Mc=["svg",h,[["path",{d:"M14.4 14.4 9.6 9.6"}],["path",{d:"M18.657 21.485a2 2 0 1 1-2.829-2.828l-1.767 1.768a2 2 0 1 1-2.829-2.829l6.364-6.364a2 2 0 1 1 2.829 2.829l-1.768 1.767a2 2 0 1 1 2.828 2.829z"}],["path",{d:"m21.5 21.5-1.4-1.4"}],["path",{d:"M3.9 3.9 2.5 2.5"}],["path",{d:"M6.404 12.768a2 2 0 1 1-2.829-2.829l1.768-1.767a2 2 0 1 1-2.828-2.829l2.828-2.828a2 2 0 1 1 2.829 2.828l1.767-1.768a2 2 0 1 1 2.829 2.829z"}]]],pc=["svg",h,[["path",{d:"M6 18.5a3.5 3.5 0 1 0 7 0c0-1.57.92-2.52 2.04-3.46"}],["path",{d:"M6 8.5c0-.75.13-1.47.36-2.14"}],["path",{d:"M8.8 3.15A6.5 6.5 0 0 1 19 8.5c0 1.63-.44 2.81-1.09 3.76"}],["path",{d:"M12.5 6A2.5 2.5 0 0 1 15 8.5M10 13a2 2 0 0 0 1.82-1.18"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],ec=["svg",h,[["path",{d:"M6 8.5a6.5 6.5 0 1 1 13 0c0 6-6 6-6 10a3.5 3.5 0 1 1-7 0"}],["path",{d:"M15 8.5a2.5 2.5 0 0 0-5 0v1a2 2 0 1 1 0 4"}]]],nc=["svg",h,[["path",{d:"M7 3.34V5a3 3 0 0 0 3 3"}],["path",{d:"M11 21.95V18a2 2 0 0 0-2-2 2 2 0 0 1-2-2v-1a2 2 0 0 0-2-2H2.05"}],["path",{d:"M21.54 15H17a2 2 0 0 0-2 2v4.54"}],["path",{d:"M12 2a10 10 0 1 0 9.54 13"}],["path",{d:"M20 6V4a2 2 0 1 0-4 0v2"}],["rect",{width:"8",height:"5",x:"14",y:"6",rx:"1"}]]],f1=["svg",h,[["path",{d:"M21.54 15H17a2 2 0 0 0-2 2v4.54"}],["path",{d:"M7 3.34V5a3 3 0 0 0 3 3a2 2 0 0 1 2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2c0-1.1.9-2 2-2h3.17"}],["path",{d:"M11 21.95V18a2 2 0 0 0-2-2a2 2 0 0 1-2-2v-1a2 2 0 0 0-2-2H2.05"}],["circle",{cx:"12",cy:"12",r:"10"}]]],ic=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 2a7 7 0 1 0 10 10"}]]],lc=["svg",h,[["circle",{cx:"11.5",cy:"12.5",r:"3.5"}],["path",{d:"M3 8c0-3.5 2.5-6 6.5-6 5 0 4.83 3 7.5 5s5 2 5 6c0 4.5-2.5 6.5-7 6.5-2.5 0-2.5 2.5-6 2.5s-7-2-7-5.5c0-3 1.5-3 1.5-5C3.5 10 3 9 3 8Z"}]]],vc=["svg",h,[["path",{d:"M6.399 6.399C5.362 8.157 4.65 10.189 4.5 12c-.37 4.43 1.27 9.95 7.5 10 3.256-.026 5.259-1.547 6.375-3.625"}],["path",{d:"M19.532 13.875A14.07 14.07 0 0 0 19.5 12c-.36-4.34-3.95-9.96-7.5-10-1.04.012-2.082.502-3.046 1.297"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],oc=["svg",h,[["path",{d:"M12 22c6.23-.05 7.87-5.57 7.5-10-.36-4.34-3.95-9.96-7.5-10-3.55.04-7.14 5.66-7.5 10-.37 4.43 1.27 9.95 7.5 10z"}]]],P1=["svg",h,[["circle",{cx:"12",cy:"12",r:"1"}],["circle",{cx:"12",cy:"5",r:"1"}],["circle",{cx:"12",cy:"19",r:"1"}]]],k1=["svg",h,[["circle",{cx:"12",cy:"12",r:"1"}],["circle",{cx:"19",cy:"12",r:"1"}],["circle",{cx:"5",cy:"12",r:"1"}]]],sc=["svg",h,[["path",{d:"M5 15a6.5 6.5 0 0 1 7 0 6.5 6.5 0 0 0 7 0"}],["path",{d:"M5 9a6.5 6.5 0 0 1 7 0 6.5 6.5 0 0 0 7 0"}]]],rc=["svg",h,[["line",{x1:"5",x2:"19",y1:"9",y2:"9"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15"}],["line",{x1:"19",x2:"5",y1:"5",y2:"19"}]]],gc=["svg",h,[["line",{x1:"5",x2:"19",y1:"9",y2:"9"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15"}]]],yc=["svg",h,[["path",{d:"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21"}],["path",{d:"M22 21H7"}],["path",{d:"m5 11 9 9"}]]],$c=["svg",h,[["path",{d:"m15 20 3-3h2a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h2l3 3z"}],["path",{d:"M6 8v1"}],["path",{d:"M10 8v1"}],["path",{d:"M14 8v1"}],["path",{d:"M18 8v1"}]]],mc=["svg",h,[["path",{d:"M4 10h12"}],["path",{d:"M4 14h9"}],["path",{d:"M19 6a7.7 7.7 0 0 0-5.2-2A7.9 7.9 0 0 0 6 12c0 4.4 3.5 8 7.8 8 2 0 3.8-.8 5.2-2"}]]],Cc=["svg",h,[["path",{d:"m15 15 6 6"}],["path",{d:"m15 9 6-6"}],["path",{d:"M21 16.2V21h-4.8"}],["path",{d:"M21 7.8V3h-4.8"}],["path",{d:"M3 16.2V21h4.8"}],["path",{d:"m3 21 6-6"}],["path",{d:"M3 7.8V3h4.8"}],["path",{d:"M9 9 3 3"}]]],uc=["svg",h,[["path",{d:"M15 3h6v6"}],["path",{d:"M10 14 21 3"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"}]]],Hc=["svg",h,[["path",{d:"m15 18-.722-3.25"}],["path",{d:"M2 8a10.645 10.645 0 0 0 20 0"}],["path",{d:"m20 15-1.726-2.05"}],["path",{d:"m4 15 1.726-2.05"}],["path",{d:"m9 18 .722-3.25"}]]],wc=["svg",h,[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"}],["path",{d:"m2 2 20 20"}]]],Vc=["svg",h,[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"}],["circle",{cx:"12",cy:"12",r:"3"}]]],Ac=["svg",h,[["path",{d:"M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"}]]],Sc=["svg",h,[["path",{d:"M2 20a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8l-7 5V8l-7 5V4a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"M17 18h1"}],["path",{d:"M12 18h1"}],["path",{d:"M7 18h1"}]]],Lc=["svg",h,[["path",{d:"M10.827 16.379a6.082 6.082 0 0 1-8.618-7.002l5.412 1.45a6.082 6.082 0 0 1 7.002-8.618l-1.45 5.412a6.082 6.082 0 0 1 8.618 7.002l-5.412-1.45a6.082 6.082 0 0 1-7.002 8.618l1.45-5.412Z"}],["path",{d:"M12 12v.01"}]]],fc=["svg",h,[["polygon",{points:"13 19 22 12 13 5 13 19"}],["polygon",{points:"2 19 11 12 2 5 2 19"}]]],Pc=["svg",h,[["path",{d:"M12.67 19a2 2 0 0 0 1.416-.588l6.154-6.172a6 6 0 0 0-8.49-8.49L5.586 9.914A2 2 0 0 0 5 11.328V18a1 1 0 0 0 1 1z"}],["path",{d:"M16 8 2 22"}],["path",{d:"M17.5 15H9"}]]],kc=["svg",h,[["path",{d:"M4 3 2 5v15c0 .6.4 1 1 1h2c.6 0 1-.4 1-1V5Z"}],["path",{d:"M6 8h4"}],["path",{d:"M6 18h4"}],["path",{d:"m12 3-2 2v15c0 .6.4 1 1 1h2c.6 0 1-.4 1-1V5Z"}],["path",{d:"M14 8h4"}],["path",{d:"M14 18h4"}],["path",{d:"m20 3-2 2v15c0 .6.4 1 1 1h2c.6 0 1-.4 1-1V5Z"}]]],Bc=["svg",h,[["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"M12 2v4"}],["path",{d:"m6.8 15-3.5 2"}],["path",{d:"m20.7 7-3.5 2"}],["path",{d:"M6.8 9 3.3 7"}],["path",{d:"m20.7 17-3.5-2"}],["path",{d:"m9 22 3-8 3 8"}],["path",{d:"M8 22h8"}],["path",{d:"M18 18.7a9 9 0 1 0-12 0"}]]],Fc=["svg",h,[["path",{d:"M5 5.5A3.5 3.5 0 0 1 8.5 2H12v7H8.5A3.5 3.5 0 0 1 5 5.5z"}],["path",{d:"M12 2h3.5a3.5 3.5 0 1 1 0 7H12V2z"}],["path",{d:"M12 12.5a3.5 3.5 0 1 1 7 0 3.5 3.5 0 1 1-7 0z"}],["path",{d:"M5 19.5A3.5 3.5 0 0 1 8.5 16H12v3.5a3.5 3.5 0 1 1-7 0z"}],["path",{d:"M5 12.5A3.5 3.5 0 0 1 8.5 9H12v7H8.5A3.5 3.5 0 0 1 5 12.5z"}]]],Dc=["svg",h,[["path",{d:"M10 12v-1"}],["path",{d:"M10 18v-2"}],["path",{d:"M10 7V6"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M15.5 22H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v16a2 2 0 0 0 .274 1.01"}],["circle",{cx:"10",cy:"20",r:"2"}]]],Rc=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v2"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"3",cy:"17",r:"1"}],["path",{d:"M2 17v-3a4 4 0 0 1 8 0v3"}],["circle",{cx:"9",cy:"17",r:"1"}]]],zc=["svg",h,[["path",{d:"M17.5 22h.5a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M2 19a2 2 0 1 1 4 0v1a2 2 0 1 1-4 0v-4a6 6 0 0 1 12 0v4a2 2 0 1 1-4 0v-1a2 2 0 1 1 4 0"}]]],B1=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m8 18 4-4"}],["path",{d:"M8 10v8h8"}]]],qc=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m14 12.5 1 5.5-3-1-3 1 1-5.5"}]]],Tc=["svg",h,[["path",{d:"M12 22h6a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M5 17a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"}],["path",{d:"M7 16.5 8 22l-3-1-3 1 1-5.5"}]]],Zc=["svg",h,[["path",{d:"M14.5 22H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M3 13.1a2 2 0 0 0-1 1.76v3.24a2 2 0 0 0 .97 1.78L6 21.7a2 2 0 0 0 2.03.01L11 19.9a2 2 0 0 0 1-1.76V14.9a2 2 0 0 0-.97-1.78L8 11.3a2 2 0 0 0-2.03-.01Z"}],["path",{d:"M7 17v5"}],["path",{d:"M11.7 14.2 7 17l-4.7-2.8"}]]],F1=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 18v-2"}],["path",{d:"M12 18v-4"}],["path",{d:"M16 18v-6"}]]],D1=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 18v-1"}],["path",{d:"M12 18v-6"}],["path",{d:"M16 18v-3"}]]],R1=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m16 13-3.5 3.5-2-2L8 17"}]]],z1=["svg",h,[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3.5"}],["path",{d:"M4.017 11.512a6 6 0 1 0 8.466 8.475"}],["path",{d:"M9 16a1 1 0 0 1-1-1v-4c0-.552.45-1.008.995-.917a6 6 0 0 1 4.922 4.922c.091.544-.365.995-.917.995z"}]]],bc=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m3 15 2 2 4-4"}]]],Uc=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m9 15 2 2 4-4"}]]],Oc=["svg",h,[["path",{d:"M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"8",cy:"16",r:"6"}],["path",{d:"M9.5 17.5 8 16.25V14"}]]],Gc=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m5 12-3 3 3 3"}],["path",{d:"m9 18 3-3-3-3"}]]],Ic=["svg",h,[["path",{d:"M10 12.5 8 15l2 2.5"}],["path",{d:"m14 12.5 2 2.5-2 2.5"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"}]]],q1=["svg",h,[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m3.2 12.9-.9-.4"}],["path",{d:"m3.2 15.1-.9.4"}],["path",{d:"M4.677 21.5a2 2 0 0 0 1.313.5H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v2.5"}],["path",{d:"m4.9 11.2-.4-.9"}],["path",{d:"m4.9 16.8-.4.9"}],["path",{d:"m7.5 10.3-.4.9"}],["path",{d:"m7.5 17.7-.4-.9"}],["path",{d:"m9.7 12.5-.9.4"}],["path",{d:"m9.7 15.5-.9-.4"}],["circle",{cx:"6",cy:"14",r:"3"}]]],Ec=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M9 10h6"}],["path",{d:"M12 13V7"}],["path",{d:"M9 17h6"}]]],Wc=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["rect",{width:"4",height:"6",x:"2",y:"12",rx:"2"}],["path",{d:"M10 12h2v6"}],["path",{d:"M10 18h4"}]]],xc=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M12 18v-6"}],["path",{d:"m9 15 3 3 3-3"}]]],Xc=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v2"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M10.29 10.7a2.43 2.43 0 0 0-2.66-.52c-.29.12-.56.3-.78.53l-.35.34-.35-.34a2.43 2.43 0 0 0-2.65-.53c-.3.12-.56.3-.79.53-.95.94-1 2.53.2 3.74L6.5 18l3.6-3.55c1.2-1.21 1.14-2.8.19-3.74Z"}]]],Nc=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"10",cy:"12",r:"2"}],["path",{d:"m20 17-1.296-1.296a2.41 2.41 0 0 0-3.408 0L9 22"}]]],Kc=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M2 15h10"}],["path",{d:"m9 18 3-3-3-3"}]]],Jc=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M4 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1"}],["path",{d:"M8 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1"}]]],Qc=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1"}],["path",{d:"M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1"}]]],jc=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v6"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"4",cy:"16",r:"2"}],["path",{d:"m10 10-4.5 4.5"}],["path",{d:"m9 11 1 1"}]]],Yc=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["circle",{cx:"10",cy:"16",r:"2"}],["path",{d:"m16 10-4.5 4.5"}],["path",{d:"m15 11 1 1"}]]],_c=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v1"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["rect",{width:"8",height:"5",x:"2",y:"13",rx:"1"}],["path",{d:"M8 13v-2a2 2 0 1 0-4 0v2"}]]],a8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["rect",{width:"8",height:"6",x:"8",y:"12",rx:"1"}],["path",{d:"M10 12v-2a2 2 0 1 1 4 0v2"}]]],h8=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M3 15h6"}]]],t8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M9 15h6"}]]],d8=["svg",h,[["path",{d:"M10.5 22H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v8.4"}],["path",{d:"M8 18v-7.7L16 9v7"}],["circle",{cx:"14",cy:"16",r:"2"}],["circle",{cx:"6",cy:"18",r:"2"}]]],c8=["svg",h,[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M4 7V4a2 2 0 0 1 2-2 2 2 0 0 0-2 2"}],["path",{d:"M4.063 20.999a2 2 0 0 0 2 1L18 22a2 2 0 0 0 2-2V7l-5-5H6"}],["path",{d:"m5 11-3 3"}],["path",{d:"m5 17-3-3h10"}]]],T1=["svg",h,[["path",{d:"m18 5-2.414-2.414A2 2 0 0 0 14.172 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2"}],["path",{d:"M21.378 12.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}],["path",{d:"M8 18h1"}]]],Z1=["svg",h,[["path",{d:"M12.5 22H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v9.5"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M13.378 15.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}]]],M8=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M3 15h6"}],["path",{d:"M6 12v6"}]]],p8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M9 15h6"}],["path",{d:"M12 18v-6"}]]],e8=["svg",h,[["path",{d:"M12 17h.01"}],["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"}],["path",{d:"M9.1 9a3 3 0 0 1 5.82 1c0 2-3 3-3 3"}]]],n8=["svg",h,[["path",{d:"M20 10V7l-5-5H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M16 14a2 2 0 0 0-2 2"}],["path",{d:"M20 14a2 2 0 0 1 2 2"}],["path",{d:"M20 22a2 2 0 0 0 2-2"}],["path",{d:"M16 22a2 2 0 0 1-2-2"}]]],i8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"11.5",cy:"14.5",r:"2.5"}],["path",{d:"M13.3 16.3 15 18"}]]],l8=["svg",h,[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M4.268 21a2 2 0 0 0 1.727 1H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"}],["path",{d:"m9 18-1.5-1.5"}],["circle",{cx:"5",cy:"14",r:"3"}]]],v8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 12h8"}],["path",{d:"M10 11v2"}],["path",{d:"M8 17h8"}],["path",{d:"M14 16v2"}]]],o8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 13h2"}],["path",{d:"M14 13h2"}],["path",{d:"M8 17h2"}],["path",{d:"M14 17h2"}]]],s8=["svg",h,[["path",{d:"M21 7h-3a2 2 0 0 1-2-2V2"}],["path",{d:"M21 6v6.5c0 .8-.7 1.5-1.5 1.5h-7c-.8 0-1.5-.7-1.5-1.5v-9c0-.8.7-1.5 1.5-1.5H17Z"}],["path",{d:"M7 8v8.8c0 .3.2.6.4.8.2.2.5.4.8.4H15"}],["path",{d:"M3 12v8.8c0 .3.2.6.4.8.2.2.5.4.8.4H11"}]]],r8=["svg",h,[["path",{d:"m10 18 3-3-3-3"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M4 11V4a2 2 0 0 1 2-2h9l5 5v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h7"}]]],g8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m8 16 2-2-2-2"}],["path",{d:"M12 18h4"}]]],y8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M10 9H8"}],["path",{d:"M16 13H8"}],["path",{d:"M16 17H8"}]]],$8=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M2 13v-1h6v1"}],["path",{d:"M5 12v6"}],["path",{d:"M4 18h2"}]]],m8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M9 13v-1h6v1"}],["path",{d:"M12 12v6"}],["path",{d:"M11 18h2"}]]],C8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M12 12v6"}],["path",{d:"m15 15-3-3-3 3"}]]],u8=["svg",h,[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M15 18a3 3 0 1 0-6 0"}],["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"}],["circle",{cx:"12",cy:"13",r:"2"}]]],H8=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["rect",{width:"8",height:"6",x:"2",y:"12",rx:"1"}],["path",{d:"m10 15.5 4 2.5v-6l-4 2.5"}]]],w8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m10 11 5 3-5 3v-6Z"}]]],V8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 15h.01"}],["path",{d:"M11.5 13.5a2.5 2.5 0 0 1 0 3"}],["path",{d:"M15 12a5 5 0 0 1 0 6"}]]],A8=["svg",h,[["path",{d:"M11 11a5 5 0 0 1 0 6"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M4 6.765V4a2 2 0 0 1 2-2h9l5 5v13a2 2 0 0 1-2 2H6a2 2 0 0 1-.93-.23"}],["path",{d:"M7 10.51a.5.5 0 0 0-.826-.38l-1.893 1.628A1 1 0 0 1 3.63 12H2.5a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h1.129a1 1 0 0 1 .652.242l1.893 1.63a.5.5 0 0 0 .826-.38z"}]]],S8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M12 9v4"}],["path",{d:"M12 17h.01"}]]],L8=["svg",h,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m8 12.5-5 5"}],["path",{d:"m3 12.5 5 5"}]]],f8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m14.5 12.5-5 5"}],["path",{d:"m9.5 12.5 5 5"}]]],P8=["svg",h,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}]]],k8=["svg",h,[["path",{d:"M20 7h-3a2 2 0 0 1-2-2V2"}],["path",{d:"M9 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7l4 4v10a2 2 0 0 1-2 2Z"}],["path",{d:"M3 7.6v12.8A1.6 1.6 0 0 0 4.6 22h9.8"}]]],B8=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 3v18"}],["path",{d:"M3 7.5h4"}],["path",{d:"M3 12h18"}],["path",{d:"M3 16.5h4"}],["path",{d:"M17 3v18"}],["path",{d:"M17 7.5h4"}],["path",{d:"M17 16.5h4"}]]],F8=["svg",h,[["path",{d:"M13.013 3H2l8 9.46V19l4 2v-8.54l.9-1.055"}],["path",{d:"m22 3-5 5"}],["path",{d:"m17 3 5 5"}]]],D8=["svg",h,[["polygon",{points:"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"}]]],R8=["svg",h,[["path",{d:"M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4"}],["path",{d:"M14 13.12c0 2.38 0 6.38-1 8.88"}],["path",{d:"M17.29 21.02c.12-.6.43-2.3.5-3.02"}],["path",{d:"M2 12a10 10 0 0 1 18-6"}],["path",{d:"M2 16h.01"}],["path",{d:"M21.8 16c.2-2 .131-5.354 0-6"}],["path",{d:"M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2"}],["path",{d:"M8.65 22c.21-.66.45-1.32.57-2"}],["path",{d:"M9 6.8a6 6 0 0 1 9 5.2v2"}]]],z8=["svg",h,[["path",{d:"M15 6.5V3a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v3.5"}],["path",{d:"M9 18h8"}],["path",{d:"M18 3h-3"}],["path",{d:"M11 3a6 6 0 0 0-6 6v11"}],["path",{d:"M5 13h4"}],["path",{d:"M17 10a4 4 0 0 0-8 0v10a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2Z"}]]],q8=["svg",h,[["path",{d:"M18 12.47v.03m0-.5v.47m-.475 5.056A6.744 6.744 0 0 1 15 18c-3.56 0-7.56-2.53-8.5-6 .348-1.28 1.114-2.433 2.121-3.38m3.444-2.088A8.802 8.802 0 0 1 15 6c3.56 0 6.06 2.54 7 6-.309 1.14-.786 2.177-1.413 3.058"}],["path",{d:"M7 10.67C7 8 5.58 5.97 2.73 5.5c-1 1.5-1 5 .23 6.5-1.24 1.5-1.24 5-.23 6.5C5.58 18.03 7 16 7 13.33m7.48-4.372A9.77 9.77 0 0 1 16 6.07m0 11.86a9.77 9.77 0 0 1-1.728-3.618"}],["path",{d:"m16.01 17.93-.23 1.4A2 2 0 0 1 13.8 21H9.5a5.96 5.96 0 0 0 1.49-3.98M8.53 3h5.27a2 2 0 0 1 1.98 1.67l.23 1.4M2 2l20 20"}]]],T8=["svg",h,[["path",{d:"M2 16s9-15 20-4C11 23 2 8 2 8"}]]],Z8=["svg",h,[["path",{d:"M6.5 12c.94-3.46 4.94-6 8.5-6 3.56 0 6.06 2.54 7 6-.94 3.47-3.44 6-7 6s-7.56-2.53-8.5-6Z"}],["path",{d:"M18 12v.5"}],["path",{d:"M16 17.93a9.77 9.77 0 0 1 0-11.86"}],["path",{d:"M7 10.67C7 8 5.58 5.97 2.73 5.5c-1 1.5-1 5 .23 6.5-1.24 1.5-1.24 5-.23 6.5C5.58 18.03 7 16 7 13.33"}],["path",{d:"M10.46 7.26C10.2 5.88 9.17 4.24 8 3h5.8a2 2 0 0 1 1.98 1.67l.23 1.4"}],["path",{d:"m16.01 17.93-.23 1.4A2 2 0 0 1 13.8 21H9.5a5.96 5.96 0 0 0 1.49-3.98"}]]],b8=["svg",h,[["path",{d:"M8 2c3 0 5 2 8 2s4-1 4-1v11"}],["path",{d:"M4 22V4"}],["path",{d:"M4 15s1-1 4-1 5 2 8 2"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],U8=["svg",h,[["path",{d:"M17 22V2L7 7l10 5"}]]],O8=["svg",h,[["path",{d:"M7 22V2l10 5-10 5"}]]],G8=["svg",h,[["path",{d:"M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"}],["line",{x1:"4",x2:"4",y1:"22",y2:"15"}]]],I8=["svg",h,[["path",{d:"M12 2c1 3 2.5 3.5 3.5 4.5A5 5 0 0 1 17 10a5 5 0 1 1-10 0c0-.3 0-.6.1-.9a2 2 0 1 0 3.3-2C8 4.5 11 2 12 2Z"}],["path",{d:"m5 22 14-4"}],["path",{d:"m5 18 14 4"}]]],E8=["svg",h,[["path",{d:"M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z"}]]],W8=["svg",h,[["path",{d:"M16 16v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2V10c0-2-2-2-2-4"}],["path",{d:"M7 2h11v4c0 2-2 2-2 4v1"}],["line",{x1:"11",x2:"18",y1:"6",y2:"6"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],x8=["svg",h,[["path",{d:"M18 6c0 2-2 2-2 4v10a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2V10c0-2-2-2-2-4V2h12z"}],["line",{x1:"6",x2:"18",y1:"6",y2:"6"}],["line",{x1:"12",x2:"12",y1:"12",y2:"12"}]]],X8=["svg",h,[["path",{d:"M10 2v2.343"}],["path",{d:"M14 2v6.343"}],["path",{d:"m2 2 20 20"}],["path",{d:"M20 20a2 2 0 0 1-2 2H6a2 2 0 0 1-1.755-2.96l5.227-9.563"}],["path",{d:"M6.453 15H15"}],["path",{d:"M8.5 2h7"}]]],N8=["svg",h,[["path",{d:"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2"}],["path",{d:"M6.453 15h11.094"}],["path",{d:"M8.5 2h7"}]]],K8=["svg",h,[["path",{d:"M10 2v6.292a7 7 0 1 0 4 0V2"}],["path",{d:"M5 15h14"}],["path",{d:"M8.5 2h7"}]]],J8=["svg",h,[["path",{d:"m3 7 5 5-5 5V7"}],["path",{d:"m21 7-5 5 5 5V7"}],["path",{d:"M12 20v2"}],["path",{d:"M12 14v2"}],["path",{d:"M12 8v2"}],["path",{d:"M12 2v2"}]]],Q8=["svg",h,[["path",{d:"M8 3H5a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h3"}],["path",{d:"M16 3h3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-3"}],["path",{d:"M12 20v2"}],["path",{d:"M12 14v2"}],["path",{d:"M12 8v2"}],["path",{d:"M12 2v2"}]]],j8=["svg",h,[["path",{d:"m17 3-5 5-5-5h10"}],["path",{d:"m17 21-5-5-5 5h10"}],["path",{d:"M4 12H2"}],["path",{d:"M10 12H8"}],["path",{d:"M16 12h-2"}],["path",{d:"M22 12h-2"}]]],Y8=["svg",h,[["path",{d:"M21 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v3"}],["path",{d:"M21 16v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3"}],["path",{d:"M4 12H2"}],["path",{d:"M10 12H8"}],["path",{d:"M16 12h-2"}],["path",{d:"M22 12h-2"}]]],_8=["svg",h,[["path",{d:"M12 5a3 3 0 1 1 3 3m-3-3a3 3 0 1 0-3 3m3-3v1M9 8a3 3 0 1 0 3 3M9 8h1m5 0a3 3 0 1 1-3 3m3-3h-1m-2 3v-1"}],["circle",{cx:"12",cy:"8",r:"2"}],["path",{d:"M12 10v12"}],["path",{d:"M12 22c4.2 0 7-1.667 7-5-4.2 0-7 1.667-7 5Z"}],["path",{d:"M12 22c-4.2 0-7-1.667-7-5 4.2 0 7 1.667 7 5Z"}]]],a7=["svg",h,[["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"M12 16.5A4.5 4.5 0 1 1 7.5 12 4.5 4.5 0 1 1 12 7.5a4.5 4.5 0 1 1 4.5 4.5 4.5 4.5 0 1 1-4.5 4.5"}],["path",{d:"M12 7.5V9"}],["path",{d:"M7.5 12H9"}],["path",{d:"M16.5 12H15"}],["path",{d:"M12 16.5V15"}],["path",{d:"m8 8 1.88 1.88"}],["path",{d:"M14.12 9.88 16 8"}],["path",{d:"m8 16 1.88-1.88"}],["path",{d:"M14.12 14.12 16 16"}]]],h7=["svg",h,[["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}]]],t7=["svg",h,[["path",{d:"M2 12h6"}],["path",{d:"M22 12h-6"}],["path",{d:"M12 2v2"}],["path",{d:"M12 8v2"}],["path",{d:"M12 14v2"}],["path",{d:"M12 20v2"}],["path",{d:"m19 9-3 3 3 3"}],["path",{d:"m5 15 3-3-3-3"}]]],d7=["svg",h,[["path",{d:"M12 22v-6"}],["path",{d:"M12 8V2"}],["path",{d:"M4 12H2"}],["path",{d:"M10 12H8"}],["path",{d:"M16 12h-2"}],["path",{d:"M22 12h-2"}],["path",{d:"m15 19-3-3-3 3"}],["path",{d:"m15 5-3 3-3-3"}]]],c7=["svg",h,[["circle",{cx:"15",cy:"19",r:"2"}],["path",{d:"M20.9 19.8A2 2 0 0 0 22 18V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h5.1"}],["path",{d:"M15 11v-1"}],["path",{d:"M15 17v-2"}]]],M7=["svg",h,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"m9 13 2 2 4-4"}]]],p7=["svg",h,[["circle",{cx:"16",cy:"16",r:"6"}],["path",{d:"M7 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2"}],["path",{d:"M16 14v2l1 1"}]]],e7=["svg",h,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"M2 10h20"}]]],n7=["svg",h,[["path",{d:"M10 10.5 8 13l2 2.5"}],["path",{d:"m14 10.5 2 2.5-2 2.5"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z"}]]],b1=["svg",h,[["circle",{cx:"18",cy:"18",r:"3"}],["path",{d:"M10.3 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v3.3"}],["path",{d:"m21.7 19.4-.9-.3"}],["path",{d:"m15.2 16.9-.9-.3"}],["path",{d:"m16.6 21.7.3-.9"}],["path",{d:"m19.1 15.2.3-.9"}],["path",{d:"m19.6 21.7-.4-1"}],["path",{d:"m16.8 15.3-.4-1"}],["path",{d:"m14.3 19.6 1-.4"}],["path",{d:"m20.7 16.8 1-.4"}]]],i7=["svg",h,[["path",{d:"M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"}],["circle",{cx:"12",cy:"13",r:"1"}]]],l7=["svg",h,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"M12 10v6"}],["path",{d:"m15 13-3 3-3-3"}]]],v7=["svg",h,[["path",{d:"M9 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v5"}],["circle",{cx:"13",cy:"12",r:"2"}],["path",{d:"M18 19c-2.8 0-5-2.2-5-5v8"}],["circle",{cx:"20",cy:"19",r:"2"}]]],o7=["svg",h,[["circle",{cx:"12",cy:"13",r:"2"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"M14 13h3"}],["path",{d:"M7 13h3"}]]],s7=["svg",h,[["path",{d:"M11 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v1.5"}],["path",{d:"M13.9 17.45c-1.2-1.2-1.14-2.8-.2-3.73a2.43 2.43 0 0 1 3.44 0l.36.34.34-.34a2.43 2.43 0 0 1 3.45-.01c.95.95 1 2.53-.2 3.74L17.5 21Z"}]]],r7=["svg",h,[["path",{d:"M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-1"}],["path",{d:"M2 13h10"}],["path",{d:"m9 16 3-3-3-3"}]]],g7=["svg",h,[["path",{d:"M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"}],["path",{d:"M8 10v4"}],["path",{d:"M12 10v2"}],["path",{d:"M16 10v6"}]]],y7=["svg",h,[["circle",{cx:"16",cy:"20",r:"2"}],["path",{d:"M10 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v2"}],["path",{d:"m22 14-4.5 4.5"}],["path",{d:"m21 15 1 1"}]]],$7=["svg",h,[["rect",{width:"8",height:"5",x:"14",y:"17",rx:"1"}],["path",{d:"M10 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v2.5"}],["path",{d:"M20 17v-2a2 2 0 1 0-4 0v2"}]]],m7=["svg",h,[["path",{d:"M9 13h6"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}]]],C7=["svg",h,[["path",{d:"m6 14 1.45-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.55 6a2 2 0 0 1-1.94 1.5H4a2 2 0 0 1-2-2V5c0-1.1.9-2 2-2h3.93a2 2 0 0 1 1.66.9l.82 1.2a2 2 0 0 0 1.66.9H18a2 2 0 0 1 2 2v2"}],["circle",{cx:"14",cy:"15",r:"1"}]]],u7=["svg",h,[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2"}]]],H7=["svg",h,[["path",{d:"M2 7.5V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-1.5"}],["path",{d:"M2 13h10"}],["path",{d:"m5 10-3 3 3 3"}]]],U1=["svg",h,[["path",{d:"M2 11.5V5a2 2 0 0 1 2-2h3.9c.7 0 1.3.3 1.7.9l.8 1.2c.4.6 1 .9 1.7.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-9.5"}],["path",{d:"M11.378 13.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}]]],w7=["svg",h,[["path",{d:"M12 10v6"}],["path",{d:"M9 13h6"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}]]],V7=["svg",h,[["path",{d:"M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"}],["circle",{cx:"12",cy:"13",r:"2"}],["path",{d:"M12 15v5"}]]],A7=["svg",h,[["circle",{cx:"11.5",cy:"12.5",r:"2.5"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"M13.3 14.3 15 16"}]]],S7=["svg",h,[["path",{d:"M10.7 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v4.1"}],["path",{d:"m21 21-1.9-1.9"}],["circle",{cx:"17",cy:"17",r:"3"}]]],L7=["svg",h,[["path",{d:"M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h7"}],["path",{d:"m8 16 3-3-3-3"}]]],f7=["svg",h,[["path",{d:"M9 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v.5"}],["path",{d:"M12 10v4h4"}],["path",{d:"m12 14 1.535-1.605a5 5 0 0 1 8 1.5"}],["path",{d:"M22 22v-4h-4"}],["path",{d:"m22 18-1.535 1.605a5 5 0 0 1-8-1.5"}]]],P7=["svg",h,[["path",{d:"M20 10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2.5a1 1 0 0 1-.8-.4l-.9-1.2A1 1 0 0 0 15 3h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z"}],["path",{d:"M20 21a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-2.9a1 1 0 0 1-.88-.55l-.42-.85a1 1 0 0 0-.92-.6H13a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z"}],["path",{d:"M3 5a2 2 0 0 0 2 2h3"}],["path",{d:"M3 3v13a2 2 0 0 0 2 2h3"}]]],k7=["svg",h,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"M12 10v6"}],["path",{d:"m9 13 3-3 3 3"}]]],B7=["svg",h,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"m9.5 10.5 5 5"}],["path",{d:"m14.5 10.5-5 5"}]]],F7=["svg",h,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}]]],D7=["svg",h,[["path",{d:"M20 17a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3.9a2 2 0 0 1-1.69-.9l-.81-1.2a2 2 0 0 0-1.67-.9H8a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2Z"}],["path",{d:"M2 8v11a2 2 0 0 0 2 2h14"}]]],R7=["svg",h,[["path",{d:"M4 16v-2.38C4 11.5 2.97 10.5 3 8c.03-2.72 1.49-6 4.5-6C9.37 2 10 3.8 10 5.5c0 3.11-2 5.66-2 8.68V16a2 2 0 1 1-4 0Z"}],["path",{d:"M20 20v-2.38c0-2.12 1.03-3.12 1-5.62-.03-2.72-1.49-6-4.5-6C14.63 6 14 7.8 14 9.5c0 3.11 2 5.66 2 8.68V20a2 2 0 1 0 4 0Z"}],["path",{d:"M16 17h4"}],["path",{d:"M4 13h4"}]]],z7=["svg",h,[["path",{d:"M12 12H5a2 2 0 0 0-2 2v5"}],["circle",{cx:"13",cy:"19",r:"2"}],["circle",{cx:"5",cy:"19",r:"2"}],["path",{d:"M8 19h3m5-17v17h6M6 12V7c0-1.1.9-2 2-2h3l5 5"}]]],q7=["svg",h,[["polyline",{points:"15 17 20 12 15 7"}],["path",{d:"M4 18v-2a4 4 0 0 1 4-4h12"}]]],T7=["svg",h,[["line",{x1:"22",x2:"2",y1:"6",y2:"6"}],["line",{x1:"22",x2:"2",y1:"18",y2:"18"}],["line",{x1:"6",x2:"6",y1:"2",y2:"22"}],["line",{x1:"18",x2:"18",y1:"2",y2:"22"}]]],Z7=["svg",h,[["path",{d:"M5 16V9h14V2H5l14 14h-7m-7 0 7 7v-7m-7 0h7"}]]],b7=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M16 16s-1.5-2-4-2-4 2-4 2"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9"}]]],U7=["svg",h,[["line",{x1:"3",x2:"15",y1:"22",y2:"22"}],["line",{x1:"4",x2:"14",y1:"9",y2:"9"}],["path",{d:"M14 22V4a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v18"}],["path",{d:"M14 13h2a2 2 0 0 1 2 2v2a2 2 0 0 0 2 2a2 2 0 0 0 2-2V9.83a2 2 0 0 0-.59-1.42L18 5"}]]],O7=["svg",h,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["rect",{width:"10",height:"8",x:"7",y:"8",rx:"1"}]]],G7=["svg",h,[["path",{d:"M2 7v10"}],["path",{d:"M6 5v14"}],["rect",{width:"12",height:"18",x:"10",y:"3",rx:"2"}]]],I7=["svg",h,[["path",{d:"M2 3v18"}],["rect",{width:"12",height:"18",x:"6",y:"3",rx:"2"}],["path",{d:"M22 3v18"}]]],E7=["svg",h,[["rect",{width:"18",height:"14",x:"3",y:"3",rx:"2"}],["path",{d:"M4 21h1"}],["path",{d:"M9 21h1"}],["path",{d:"M14 21h1"}],["path",{d:"M19 21h1"}]]],W7=["svg",h,[["path",{d:"M7 2h10"}],["path",{d:"M5 6h14"}],["rect",{width:"18",height:"12",x:"3",y:"10",rx:"2"}]]],x7=["svg",h,[["path",{d:"M3 2h18"}],["rect",{width:"18",height:"12",x:"3",y:"6",rx:"2"}],["path",{d:"M3 22h18"}]]],X7=["svg",h,[["line",{x1:"6",x2:"10",y1:"11",y2:"11"}],["line",{x1:"8",x2:"8",y1:"9",y2:"13"}],["line",{x1:"15",x2:"15.01",y1:"12",y2:"12"}],["line",{x1:"18",x2:"18.01",y1:"10",y2:"10"}],["path",{d:"M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z"}]]],N7=["svg",h,[["line",{x1:"6",x2:"10",y1:"12",y2:"12"}],["line",{x1:"8",x2:"8",y1:"10",y2:"14"}],["line",{x1:"15",x2:"15.01",y1:"13",y2:"13"}],["line",{x1:"18",x2:"18.01",y1:"11",y2:"11"}],["rect",{width:"20",height:"12",x:"2",y:"6",rx:"2"}]]],K7=["svg",h,[["path",{d:"m12 14 4-4"}],["path",{d:"M3.34 19a10 10 0 1 1 17.32 0"}]]],J7=["svg",h,[["path",{d:"m14.5 12.5-8 8a2.119 2.119 0 1 1-3-3l8-8"}],["path",{d:"m16 16 6-6"}],["path",{d:"m8 8 6-6"}],["path",{d:"m9 7 8 8"}],["path",{d:"m21 11-8-8"}]]],Q7=["svg",h,[["path",{d:"M6 3h12l4 6-10 13L2 9Z"}],["path",{d:"M11 3 8 9l4 13 4-13-3-6"}],["path",{d:"M2 9h20"}]]],j7=["svg",h,[["path",{d:"M9 10h.01"}],["path",{d:"M15 10h.01"}],["path",{d:"M12 2a8 8 0 0 0-8 8v12l3-3 2.5 2.5L12 19l2.5 2.5L17 19l3 3V10a8 8 0 0 0-8-8z"}]]],Y7=["svg",h,[["rect",{x:"3",y:"8",width:"18",height:"4",rx:"1"}],["path",{d:"M12 8v13"}],["path",{d:"M19 12v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-7"}],["path",{d:"M7.5 8a2.5 2.5 0 0 1 0-5A4.8 8 0 0 1 12 8a4.8 8 0 0 1 4.5-5 2.5 2.5 0 0 1 0 5"}]]],_7=["svg",h,[["path",{d:"M6 3v12"}],["path",{d:"M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"}],["path",{d:"M6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"}],["path",{d:"M15 6a9 9 0 0 0-9 9"}],["path",{d:"M18 15v6"}],["path",{d:"M21 18h-6"}]]],aM=["svg",h,[["line",{x1:"6",x2:"6",y1:"3",y2:"15"}],["circle",{cx:"18",cy:"6",r:"3"}],["circle",{cx:"6",cy:"18",r:"3"}],["path",{d:"M18 9a9 9 0 0 1-9 9"}]]],O1=["svg",h,[["circle",{cx:"12",cy:"12",r:"3"}],["line",{x1:"3",x2:"9",y1:"12",y2:"12"}],["line",{x1:"15",x2:"21",y1:"12",y2:"12"}]]],hM=["svg",h,[["path",{d:"M12 3v6"}],["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"M12 15v6"}]]],tM=["svg",h,[["circle",{cx:"5",cy:"6",r:"3"}],["path",{d:"M12 6h5a2 2 0 0 1 2 2v7"}],["path",{d:"m15 9-3-3 3-3"}],["circle",{cx:"19",cy:"18",r:"3"}],["path",{d:"M12 18H7a2 2 0 0 1-2-2V9"}],["path",{d:"m9 15 3 3-3 3"}]]],dM=["svg",h,[["circle",{cx:"18",cy:"18",r:"3"}],["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M13 6h3a2 2 0 0 1 2 2v7"}],["path",{d:"M11 18H8a2 2 0 0 1-2-2V9"}]]],cM=["svg",h,[["circle",{cx:"12",cy:"18",r:"3"}],["circle",{cx:"6",cy:"6",r:"3"}],["circle",{cx:"18",cy:"6",r:"3"}],["path",{d:"M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9"}],["path",{d:"M12 12v3"}]]],MM=["svg",h,[["circle",{cx:"5",cy:"6",r:"3"}],["path",{d:"M5 9v6"}],["circle",{cx:"5",cy:"18",r:"3"}],["path",{d:"M12 3v18"}],["circle",{cx:"19",cy:"6",r:"3"}],["path",{d:"M16 15.7A9 9 0 0 0 19 9"}]]],pM=["svg",h,[["circle",{cx:"18",cy:"18",r:"3"}],["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M6 21V9a9 9 0 0 0 9 9"}]]],eM=["svg",h,[["circle",{cx:"5",cy:"6",r:"3"}],["path",{d:"M5 9v12"}],["circle",{cx:"19",cy:"18",r:"3"}],["path",{d:"m15 9-3-3 3-3"}],["path",{d:"M12 6h5a2 2 0 0 1 2 2v7"}]]],nM=["svg",h,[["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M6 9v12"}],["path",{d:"m21 3-6 6"}],["path",{d:"m21 9-6-6"}],["path",{d:"M18 11.5V15"}],["circle",{cx:"18",cy:"18",r:"3"}]]],iM=["svg",h,[["circle",{cx:"5",cy:"6",r:"3"}],["path",{d:"M5 9v12"}],["path",{d:"m15 9-3-3 3-3"}],["path",{d:"M12 6h5a2 2 0 0 1 2 2v3"}],["path",{d:"M19 15v6"}],["path",{d:"M22 18h-6"}]]],lM=["svg",h,[["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M6 9v12"}],["path",{d:"M13 6h3a2 2 0 0 1 2 2v3"}],["path",{d:"M18 15v6"}],["path",{d:"M21 18h-6"}]]],vM=["svg",h,[["circle",{cx:"18",cy:"18",r:"3"}],["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M18 6V5"}],["path",{d:"M18 11v-1"}],["line",{x1:"6",x2:"6",y1:"9",y2:"21"}]]],oM=["svg",h,[["circle",{cx:"18",cy:"18",r:"3"}],["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M13 6h3a2 2 0 0 1 2 2v7"}],["line",{x1:"6",x2:"6",y1:"9",y2:"21"}]]],sM=["svg",h,[["path",{d:"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"}],["path",{d:"M9 18c-4.51 2-5-2-7-2"}]]],rM=["svg",h,[["path",{d:"m22 13.29-3.33-10a.42.42 0 0 0-.14-.18.38.38 0 0 0-.22-.11.39.39 0 0 0-.23.07.42.42 0 0 0-.14.18l-2.26 6.67H8.32L6.1 3.26a.42.42 0 0 0-.1-.18.38.38 0 0 0-.26-.08.39.39 0 0 0-.23.07.42.42 0 0 0-.14.18L2 13.29a.74.74 0 0 0 .27.83L12 21l9.69-6.88a.71.71 0 0 0 .31-.83Z"}]]],gM=["svg",h,[["path",{d:"M5.116 4.104A1 1 0 0 1 6.11 3h11.78a1 1 0 0 1 .994 1.105L17.19 20.21A2 2 0 0 1 15.2 22H8.8a2 2 0 0 1-2-1.79z"}],["path",{d:"M6 12a5 5 0 0 1 6 0 5 5 0 0 0 6 0"}]]],yM=["svg",h,[["circle",{cx:"6",cy:"15",r:"4"}],["circle",{cx:"18",cy:"15",r:"4"}],["path",{d:"M14 15a2 2 0 0 0-2-2 2 2 0 0 0-2 2"}],["path",{d:"M2.5 13 5 7c.7-1.3 1.4-2 3-2"}],["path",{d:"M21.5 13 19 7c-.7-1.3-1.5-2-3-2"}]]],$M=["svg",h,[["path",{d:"M15.686 15A14.5 14.5 0 0 1 12 22a14.5 14.5 0 0 1 0-20 10 10 0 1 0 9.542 13"}],["path",{d:"M2 12h8.5"}],["path",{d:"M20 6V4a2 2 0 1 0-4 0v2"}],["rect",{width:"8",height:"5",x:"14",y:"6",rx:"1"}]]],mM=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"}],["path",{d:"M2 12h20"}]]],CM=["svg",h,[["path",{d:"M12 13V2l8 4-8 4"}],["path",{d:"M20.561 10.222a9 9 0 1 1-12.55-5.29"}],["path",{d:"M8.002 9.997a5 5 0 1 0 8.9 2.02"}]]],uM=["svg",h,[["path",{d:"M18 11.5V9a2 2 0 0 0-2-2a2 2 0 0 0-2 2v1.4"}],["path",{d:"M14 10V8a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2"}],["path",{d:"M10 9.9V9a2 2 0 0 0-2-2a2 2 0 0 0-2 2v5"}],["path",{d:"M6 14a2 2 0 0 0-2-2a2 2 0 0 0-2 2"}],["path",{d:"M18 11a2 2 0 1 1 4 0v3a8 8 0 0 1-8 8h-4a8 8 0 0 1-8-8 2 2 0 1 1 4 0"}]]],HM=["svg",h,[["path",{d:"M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z"}],["path",{d:"M22 10v6"}],["path",{d:"M6 12.5V16a6 3 0 0 0 12 0v-3.5"}]]],wM=["svg",h,[["path",{d:"M22 5V2l-5.89 5.89"}],["circle",{cx:"16.6",cy:"15.89",r:"3"}],["circle",{cx:"8.11",cy:"7.4",r:"3"}],["circle",{cx:"12.35",cy:"11.65",r:"3"}],["circle",{cx:"13.91",cy:"5.85",r:"3"}],["circle",{cx:"18.15",cy:"10.09",r:"3"}],["circle",{cx:"6.56",cy:"13.2",r:"3"}],["circle",{cx:"10.8",cy:"17.44",r:"3"}],["circle",{cx:"5",cy:"19",r:"3"}]]],G1=["svg",h,[["path",{d:"M12 3v17a1 1 0 0 1-1 1H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6a1 1 0 0 1-1 1H3"}],["path",{d:"m16 19 2 2 4-4"}]]],I1=["svg",h,[["path",{d:"M12 3v17a1 1 0 0 1-1 1H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6a1 1 0 0 1-1 1H3"}],["path",{d:"M16 19h6"}],["path",{d:"M19 22v-6"}]]],E1=["svg",h,[["path",{d:"M12 3v17a1 1 0 0 1-1 1H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6a1 1 0 0 1-1 1H3"}],["path",{d:"m16 16 5 5"}],["path",{d:"m16 21 5-5"}]]],W1=["svg",h,[["path",{d:"M12 3v18"}],["path",{d:"M3 12h18"}],["rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}]]],i=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}],["path",{d:"M3 15h18"}],["path",{d:"M9 3v18"}],["path",{d:"M15 3v18"}]]],VM=["svg",h,[["circle",{cx:"12",cy:"9",r:"1"}],["circle",{cx:"19",cy:"9",r:"1"}],["circle",{cx:"5",cy:"9",r:"1"}],["circle",{cx:"12",cy:"15",r:"1"}],["circle",{cx:"19",cy:"15",r:"1"}],["circle",{cx:"5",cy:"15",r:"1"}]]],AM=["svg",h,[["circle",{cx:"9",cy:"12",r:"1"}],["circle",{cx:"9",cy:"5",r:"1"}],["circle",{cx:"9",cy:"19",r:"1"}],["circle",{cx:"15",cy:"12",r:"1"}],["circle",{cx:"15",cy:"5",r:"1"}],["circle",{cx:"15",cy:"19",r:"1"}]]],SM=["svg",h,[["circle",{cx:"12",cy:"5",r:"1"}],["circle",{cx:"19",cy:"5",r:"1"}],["circle",{cx:"5",cy:"5",r:"1"}],["circle",{cx:"12",cy:"12",r:"1"}],["circle",{cx:"19",cy:"12",r:"1"}],["circle",{cx:"5",cy:"12",r:"1"}],["circle",{cx:"12",cy:"19",r:"1"}],["circle",{cx:"19",cy:"19",r:"1"}],["circle",{cx:"5",cy:"19",r:"1"}]]],LM=["svg",h,[["path",{d:"M3 7V5c0-1.1.9-2 2-2h2"}],["path",{d:"M17 3h2c1.1 0 2 .9 2 2v2"}],["path",{d:"M21 17v2c0 1.1-.9 2-2 2h-2"}],["path",{d:"M7 21H5c-1.1 0-2-.9-2-2v-2"}],["rect",{width:"7",height:"5",x:"7",y:"7",rx:"1"}],["rect",{width:"7",height:"5",x:"10",y:"12",rx:"1"}]]],fM=["svg",h,[["path",{d:"m11.9 12.1 4.514-4.514"}],["path",{d:"M20.1 2.3a1 1 0 0 0-1.4 0l-1.114 1.114A2 2 0 0 0 17 4.828v1.344a2 2 0 0 1-.586 1.414A2 2 0 0 1 17.828 7h1.344a2 2 0 0 0 1.414-.586L21.7 5.3a1 1 0 0 0 0-1.4z"}],["path",{d:"m6 16 2 2"}],["path",{d:"M8.2 9.9C8.7 8.8 9.8 8 11 8c2.8 0 5 2.2 5 5 0 1.2-.8 2.3-1.9 2.8l-.9.4A2 2 0 0 0 12 18a4 4 0 0 1-4 4c-3.3 0-6-2.7-6-6a4 4 0 0 1 4-4 2 2 0 0 0 1.8-1.2z"}],["circle",{cx:"11.5",cy:"12.5",r:".5",fill:"currentColor"}]]],PM=["svg",h,[["path",{d:"M13.144 21.144A7.274 10.445 45 1 0 2.856 10.856"}],["path",{d:"M13.144 21.144A7.274 4.365 45 0 0 2.856 10.856a7.274 4.365 45 0 0 10.288 10.288"}],["path",{d:"M16.565 10.435 18.6 8.4a2.501 2.501 0 1 0 1.65-4.65 2.5 2.5 0 1 0-4.66 1.66l-2.024 2.025"}],["path",{d:"m8.5 16.5-1-1"}]]],kM=["svg",h,[["path",{d:"m15 12-8.373 8.373a1 1 0 1 1-3-3L12 9"}],["path",{d:"m18 15 4-4"}],["path",{d:"m21.5 11.5-1.914-1.914A2 2 0 0 1 19 8.172V7l-2.26-2.26a6 6 0 0 0-4.202-1.756L9 2.96l.92.82A6.18 6.18 0 0 1 12 8.4V10l2 2h1.172a2 2 0 0 1 1.414.586L18.5 14.5"}]]],BM=["svg",h,[["path",{d:"M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"}],["path",{d:"m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"}],["path",{d:"m2 16 6 6"}],["circle",{cx:"16",cy:"9",r:"2.9"}],["circle",{cx:"6",cy:"5",r:"3"}]]],FM=["svg",h,[["path",{d:"M11 14h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 16"}],["path",{d:"m7 20 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"}],["path",{d:"m2 15 6 6"}],["path",{d:"M19.5 8.5c.7-.7 1.5-1.6 1.5-2.7A2.73 2.73 0 0 0 16 4a2.78 2.78 0 0 0-5 1.8c0 1.2.8 2 1.5 2.8L16 12Z"}]]],x1=["svg",h,[["path",{d:"M11 12h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 14"}],["path",{d:"m7 18 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"}],["path",{d:"m2 13 6 6"}]]],DM=["svg",h,[["path",{d:"M18 12.5V10a2 2 0 0 0-2-2a2 2 0 0 0-2 2v1.4"}],["path",{d:"M14 11V9a2 2 0 1 0-4 0v2"}],["path",{d:"M10 10.5V5a2 2 0 1 0-4 0v9"}],["path",{d:"m7 15-1.76-1.76a2 2 0 0 0-2.83 2.82l3.6 3.6C7.5 21.14 9.2 22 12 22h2a8 8 0 0 0 8-8V7a2 2 0 1 0-4 0v5"}]]],RM=["svg",h,[["path",{d:"M12 3V2"}],["path",{d:"m15.4 17.4 3.2-2.8a2 2 0 1 1 2.8 2.9l-3.6 3.3c-.7.8-1.7 1.2-2.8 1.2h-4c-1.1 0-2.1-.4-2.8-1.2l-1.302-1.464A1 1 0 0 0 6.151 19H5"}],["path",{d:"M2 14h12a2 2 0 0 1 0 4h-2"}],["path",{d:"M4 10h16"}],["path",{d:"M5 10a7 7 0 0 1 14 0"}],["path",{d:"M5 14v6a1 1 0 0 1-1 1H2"}]]],zM=["svg",h,[["path",{d:"M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2"}],["path",{d:"M14 10V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2"}],["path",{d:"M10 10.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8"}],["path",{d:"M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15"}]]],qM=["svg",h,[["path",{d:"m11 17 2 2a1 1 0 1 0 3-3"}],["path",{d:"m14 14 2.5 2.5a1 1 0 1 0 3-3l-3.88-3.88a3 3 0 0 0-4.24 0l-.88.88a1 1 0 1 1-3-3l2.81-2.81a5.79 5.79 0 0 1 7.06-.87l.47.28a2 2 0 0 0 1.42.25L21 4"}],["path",{d:"m21 3 1 11h-2"}],["path",{d:"M3 3 2 14l6.5 6.5a1 1 0 1 0 3-3"}],["path",{d:"M3 4h8"}]]],TM=["svg",h,[["path",{d:"M12 2v8"}],["path",{d:"m16 6-4 4-4-4"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2"}],["path",{d:"M6 18h.01"}],["path",{d:"M10 18h.01"}]]],ZM=["svg",h,[["path",{d:"m16 6-4-4-4 4"}],["path",{d:"M12 2v8"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2"}],["path",{d:"M6 18h.01"}],["path",{d:"M10 18h.01"}]]],bM=["svg",h,[["line",{x1:"22",x2:"2",y1:"12",y2:"12"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"}],["line",{x1:"6",x2:"6.01",y1:"16",y2:"16"}],["line",{x1:"10",x2:"10.01",y1:"16",y2:"16"}]]],UM=["svg",h,[["path",{d:"M10 10V5a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v5"}],["path",{d:"M14 6a6 6 0 0 1 6 6v3"}],["path",{d:"M4 15v-3a6 6 0 0 1 6-6"}],["rect",{x:"2",y:"15",width:"20",height:"4",rx:"1"}]]],OM=["svg",h,[["line",{x1:"4",x2:"20",y1:"9",y2:"9"}],["line",{x1:"4",x2:"20",y1:"15",y2:"15"}],["line",{x1:"10",x2:"8",y1:"3",y2:"21"}],["line",{x1:"16",x2:"14",y1:"3",y2:"21"}]]],GM=["svg",h,[["path",{d:"m5.2 6.2 1.4 1.4"}],["path",{d:"M2 13h2"}],["path",{d:"M20 13h2"}],["path",{d:"m17.4 7.6 1.4-1.4"}],["path",{d:"M22 17H2"}],["path",{d:"M22 21H2"}],["path",{d:"M16 13a4 4 0 0 0-8 0"}],["path",{d:"M12 5V2.5"}]]],IM=["svg",h,[["path",{d:"M22 9a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h1l2 2h12l2-2h1a1 1 0 0 0 1-1Z"}],["path",{d:"M7.5 12h9"}]]],EM=["svg",h,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["path",{d:"m17 12 3-2v8"}]]],WM=["svg",h,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["path",{d:"M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1"}]]],xM=["svg",h,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["path",{d:"M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2"}],["path",{d:"M17 17.5c2 1.5 4 .3 4-1.5a2 2 0 0 0-2-2"}]]],XM=["svg",h,[["path",{d:"M12 18V6"}],["path",{d:"M17 10v3a1 1 0 0 0 1 1h3"}],["path",{d:"M21 10v8"}],["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}]]],NM=["svg",h,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["path",{d:"M17 13v-3h4"}],["path",{d:"M17 17.7c.4.2.8.3 1.3.3 1.5 0 2.7-1.1 2.7-2.5S19.8 13 18.3 13H17"}]]],KM=["svg",h,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["circle",{cx:"19",cy:"16",r:"2"}],["path",{d:"M20 10c-2 2-3 3.5-3 6"}]]],JM=["svg",h,[["path",{d:"M6 12h12"}],["path",{d:"M6 20V4"}],["path",{d:"M18 20V4"}]]],QM=["svg",h,[["path",{d:"M21 14h-1.343"}],["path",{d:"M9.128 3.47A9 9 0 0 1 21 12v3.343"}],["path",{d:"m2 2 20 20"}],["path",{d:"M20.414 20.414A2 2 0 0 1 19 21h-1a2 2 0 0 1-2-2v-3"}],["path",{d:"M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 2.636-6.364"}]]],jM=["svg",h,[["path",{d:"M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3"}]]],YM=["svg",h,[["path",{d:"M3 11h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Zm0 0a9 9 0 1 1 18 0m0 0v5a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3Z"}],["path",{d:"M21 16v2a4 4 0 0 1-4 4h-5"}]]],_M=["svg",h,[["path",{d:"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"}],["path",{d:"m12 13-1-1 2-2-3-3 2-2"}]]],ap=["svg",h,[["path",{d:"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"}],["path",{d:"M12 5 9.04 7.96a2.17 2.17 0 0 0 0 3.08c.82.82 2.13.85 3 .07l2.07-1.9a2.82 2.82 0 0 1 3.79 0l2.96 2.66"}],["path",{d:"m18 15-2-2"}],["path",{d:"m15 18-2-2"}]]],hp=["svg",h,[["line",{x1:"2",y1:"2",x2:"22",y2:"22"}],["path",{d:"M16.5 16.5 12 21l-7-7c-1.5-1.45-3-3.2-3-5.5a5.5 5.5 0 0 1 2.14-4.35"}],["path",{d:"M8.76 3.1c1.15.22 2.13.78 3.24 1.9 1.5-1.5 2.74-2 4.5-2A5.5 5.5 0 0 1 22 8.5c0 2.12-1.3 3.78-2.67 5.17"}]]],tp=["svg",h,[["path",{d:"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"}],["path",{d:"M3.22 12H9.5l.5-1 2 4.5 2-7 1.5 3.5h5.27"}]]],dp=["svg",h,[["path",{d:"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"}]]],cp=["svg",h,[["path",{d:"M11 8c2-3-2-3 0-6"}],["path",{d:"M15.5 8c2-3-2-3 0-6"}],["path",{d:"M6 10h.01"}],["path",{d:"M6 14h.01"}],["path",{d:"M10 16v-4"}],["path",{d:"M14 16v-4"}],["path",{d:"M18 16v-4"}],["path",{d:"M20 6a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h3"}],["path",{d:"M5 20v2"}],["path",{d:"M19 20v2"}]]],Mp=["svg",h,[["path",{d:"M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"}]]],pp=["svg",h,[["path",{d:"m9 11-6 6v3h9l3-3"}],["path",{d:"m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4"}]]],ep=["svg",h,[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"}],["path",{d:"M3 3v5h5"}],["path",{d:"M12 7v5l4 2"}]]],np=["svg",h,[["path",{d:"M10.82 16.12c1.69.6 3.91.79 5.18.85.28.01.53-.09.7-.27"}],["path",{d:"M11.14 20.57c.52.24 2.44 1.12 4.08 1.37.46.06.86-.25.9-.71.12-1.52-.3-3.43-.5-4.28"}],["path",{d:"M16.13 21.05c1.65.63 3.68.84 4.87.91a.9.9 0 0 0 .7-.26"}],["path",{d:"M17.99 5.52a20.83 20.83 0 0 1 3.15 4.5.8.8 0 0 1-.68 1.13c-1.17.1-2.5.02-3.9-.25"}],["path",{d:"M20.57 11.14c.24.52 1.12 2.44 1.37 4.08.04.3-.08.59-.31.75"}],["path",{d:"M4.93 4.93a10 10 0 0 0-.67 13.4c.35.43.96.4 1.17-.12.69-1.71 1.07-5.07 1.07-6.71 1.34.45 3.1.9 4.88.62a.85.85 0 0 0 .48-.24"}],["path",{d:"M5.52 17.99c1.05.95 2.91 2.42 4.5 3.15a.8.8 0 0 0 1.13-.68c.2-2.34-.33-5.3-1.57-8.28"}],["path",{d:"M8.35 2.68a10 10 0 0 1 9.98 1.58c.43.35.4.96-.12 1.17-1.5.6-4.3.98-6.07 1.05"}],["path",{d:"m2 2 20 20"}]]],ip=["svg",h,[["path",{d:"M10.82 16.12c1.69.6 3.91.79 5.18.85.55.03 1-.42.97-.97-.06-1.27-.26-3.5-.85-5.18"}],["path",{d:"M11.5 6.5c1.64 0 5-.38 6.71-1.07.52-.2.55-.82.12-1.17A10 10 0 0 0 4.26 18.33c.35.43.96.4 1.17-.12.69-1.71 1.07-5.07 1.07-6.71 1.34.45 3.1.9 4.88.62a.88.88 0 0 0 .73-.74c.3-2.14-.15-3.5-.61-4.88"}],["path",{d:"M15.62 16.95c.2.85.62 2.76.5 4.28a.77.77 0 0 1-.9.7 16.64 16.64 0 0 1-4.08-1.36"}],["path",{d:"M16.13 21.05c1.65.63 3.68.84 4.87.91a.9.9 0 0 0 .96-.96 17.68 17.68 0 0 0-.9-4.87"}],["path",{d:"M16.94 15.62c.86.2 2.77.62 4.29.5a.77.77 0 0 0 .7-.9 16.64 16.64 0 0 0-1.36-4.08"}],["path",{d:"M17.99 5.52a20.82 20.82 0 0 1 3.15 4.5.8.8 0 0 1-.68 1.13c-2.33.2-5.3-.32-8.27-1.57"}],["path",{d:"M4.93 4.93 3 3a.7.7 0 0 1 0-1"}],["path",{d:"M9.58 12.18c1.24 2.98 1.77 5.95 1.57 8.28a.8.8 0 0 1-1.13.68 20.82 20.82 0 0 1-4.5-3.15"}]]],lp=["svg",h,[["path",{d:"M12 6v4"}],["path",{d:"M14 14h-4"}],["path",{d:"M14 18h-4"}],["path",{d:"M14 8h-4"}],["path",{d:"M18 12h2a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-9a2 2 0 0 1 2-2h2"}],["path",{d:"M18 22V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v18"}]]],vp=["svg",h,[["path",{d:"M10 22v-6.57"}],["path",{d:"M12 11h.01"}],["path",{d:"M12 7h.01"}],["path",{d:"M14 15.43V22"}],["path",{d:"M15 16a5 5 0 0 0-6 0"}],["path",{d:"M16 11h.01"}],["path",{d:"M16 7h.01"}],["path",{d:"M8 11h.01"}],["path",{d:"M8 7h.01"}],["rect",{x:"4",y:"2",width:"16",height:"20",rx:"2"}]]],op=["svg",h,[["path",{d:"M5 22h14"}],["path",{d:"M5 2h14"}],["path",{d:"M17 22v-4.172a2 2 0 0 0-.586-1.414L12 12l-4.414 4.414A2 2 0 0 0 7 17.828V22"}],["path",{d:"M7 2v4.172a2 2 0 0 0 .586 1.414L12 12l4.414-4.414A2 2 0 0 0 17 6.172V2"}]]],sp=["svg",h,[["path",{d:"M10 12V8.964"}],["path",{d:"M14 12V8.964"}],["path",{d:"M15 12a1 1 0 0 1 1 1v2a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-2a1 1 0 0 1 1-1z"}],["path",{d:"M8.5 21H5a2 2 0 0 1-2-2v-9a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2v-2"}]]],rp=["svg",h,[["path",{d:"M13.22 2.416a2 2 0 0 0-2.511.057l-7 5.999A2 2 0 0 0 3 10v9a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7.354"}],["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"}],["path",{d:"M15 6h6"}],["path",{d:"M18 3v6"}]]],gp=["svg",h,[["path",{d:"M9.5 13.866a4 4 0 0 1 5 .01"}],["path",{d:"M12 17h.01"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"}],["path",{d:"M7 10.754a8 8 0 0 1 10 0"}]]],X1=["svg",h,[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"}]]],N1=["svg",h,[["path",{d:"M12 17c5 0 8-2.69 8-6H4c0 3.31 3 6 8 6m-4 4h8m-4-3v3M5.14 11a3.5 3.5 0 1 1 6.71 0"}],["path",{d:"M12.14 11a3.5 3.5 0 1 1 6.71 0"}],["path",{d:"M15.5 6.5a3.5 3.5 0 1 0-7 0"}]]],K1=["svg",h,[["path",{d:"m7 11 4.08 10.35a1 1 0 0 0 1.84 0L17 11"}],["path",{d:"M17 7A5 5 0 0 0 7 7"}],["path",{d:"M17 7a2 2 0 0 1 0 4H7a2 2 0 0 1 0-4"}]]],yp=["svg",h,[["path",{d:"M16 10h2"}],["path",{d:"M16 14h2"}],["path",{d:"M6.17 15a3 3 0 0 1 5.66 0"}],["circle",{cx:"9",cy:"11",r:"2"}],["rect",{x:"2",y:"5",width:"20",height:"14",rx:"2"}]]],$p=["svg",h,[["path",{d:"M10.3 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10l-3.1-3.1a2 2 0 0 0-2.814.014L6 21"}],["path",{d:"m14 19 3 3v-5.5"}],["path",{d:"m17 22 3-3"}],["circle",{cx:"9",cy:"9",r:"2"}]]],mp=["svg",h,[["path",{d:"M21 9v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7"}],["line",{x1:"16",x2:"22",y1:"5",y2:"5"}],["circle",{cx:"9",cy:"9",r:"2"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"}]]],Cp=["svg",h,[["line",{x1:"2",x2:"22",y1:"2",y2:"22"}],["path",{d:"M10.41 10.41a2 2 0 1 1-2.83-2.83"}],["line",{x1:"13.5",x2:"6",y1:"13.5",y2:"21"}],["line",{x1:"18",x2:"21",y1:"12",y2:"15"}],["path",{d:"M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59"}],["path",{d:"M21 15V5a2 2 0 0 0-2-2H9"}]]],up=["svg",h,[["path",{d:"m11 16-5 5"}],["path",{d:"M11 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6.5"}],["path",{d:"M15.765 22a.5.5 0 0 1-.765-.424V13.38a.5.5 0 0 1 .765-.424l5.878 3.674a1 1 0 0 1 0 1.696z"}],["circle",{cx:"9",cy:"9",r:"2"}]]],Hp=["svg",h,[["path",{d:"M16 5h6"}],["path",{d:"M19 2v6"}],["path",{d:"M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"}],["circle",{cx:"9",cy:"9",r:"2"}]]],wp=["svg",h,[["path",{d:"M10.3 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10l-3.1-3.1a2 2 0 0 0-2.814.014L6 21"}],["path",{d:"m14 19.5 3-3 3 3"}],["path",{d:"M17 22v-5.5"}],["circle",{cx:"9",cy:"9",r:"2"}]]],Vp=["svg",h,[["path",{d:"M16 3h5v5"}],["path",{d:"M17 21h2a2 2 0 0 0 2-2"}],["path",{d:"M21 12v3"}],["path",{d:"m21 3-5 5"}],["path",{d:"M3 7V5a2 2 0 0 1 2-2"}],["path",{d:"m5 21 4.144-4.144a1.21 1.21 0 0 1 1.712 0L13 19"}],["path",{d:"M9 3h3"}],["rect",{x:"3",y:"11",width:"10",height:"10",rx:"1"}]]],Ap=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["circle",{cx:"9",cy:"9",r:"2"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"}]]],Sp=["svg",h,[["path",{d:"M18 22H4a2 2 0 0 1-2-2V6"}],["path",{d:"m22 13-1.296-1.296a2.41 2.41 0 0 0-3.408 0L11 18"}],["circle",{cx:"12",cy:"8",r:"2"}],["rect",{width:"16",height:"16",x:"6",y:"2",rx:"2"}]]],Lp=["svg",h,[["path",{d:"M12 3v12"}],["path",{d:"m8 11 4 4 4-4"}],["path",{d:"M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4"}]]],fp=["svg",h,[["polyline",{points:"22 12 16 12 14 15 10 15 8 12 2 12"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"}]]],J1=["svg",h,[["path",{d:"M21 12H11"}],["path",{d:"M21 18H11"}],["path",{d:"M21 6H11"}],["path",{d:"m7 8-4 4 4 4"}]]],Q1=["svg",h,[["path",{d:"M21 12H11"}],["path",{d:"M21 18H11"}],["path",{d:"M21 6H11"}],["path",{d:"m3 8 4 4-4 4"}]]],Pp=["svg",h,[["path",{d:"M6 3h12"}],["path",{d:"M6 8h12"}],["path",{d:"m6 13 8.5 8"}],["path",{d:"M6 13h3"}],["path",{d:"M9 13c6.667 0 6.667-10 0-10"}]]],kp=["svg",h,[["path",{d:"M12 12c-2-2.67-4-4-6-4a4 4 0 1 0 0 8c2 0 4-1.33 6-4Zm0 0c2 2.67 4 4 6 4a4 4 0 0 0 0-8c-2 0-4 1.33-6 4Z"}]]],Bp=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 16v-4"}],["path",{d:"M12 8h.01"}]]],Fp=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 7h.01"}],["path",{d:"M17 7h.01"}],["path",{d:"M7 17h.01"}],["path",{d:"M17 17h.01"}]]],Dp=["svg",h,[["rect",{width:"20",height:"20",x:"2",y:"2",rx:"5",ry:"5"}],["path",{d:"M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"}],["line",{x1:"17.5",x2:"17.51",y1:"6.5",y2:"6.5"}]]],Rp=["svg",h,[["line",{x1:"19",x2:"10",y1:"4",y2:"4"}],["line",{x1:"14",x2:"5",y1:"20",y2:"20"}],["line",{x1:"15",x2:"9",y1:"4",y2:"20"}]]],zp=["svg",h,[["path",{d:"M20 10c0-4.4-3.6-8-8-8s-8 3.6-8 8 3.6 8 8 8h8"}],["polyline",{points:"16 14 20 18 16 22"}]]],qp=["svg",h,[["path",{d:"M4 10c0-4.4 3.6-8 8-8s8 3.6 8 8-3.6 8-8 8H4"}],["polyline",{points:"8 22 4 18 8 14"}]]],Tp=["svg",h,[["path",{d:"M12 9.5V21m0-11.5L6 3m6 6.5L18 3"}],["path",{d:"M6 15h12"}],["path",{d:"M6 11h12"}]]],Zp=["svg",h,[["path",{d:"M21 17a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-2Z"}],["path",{d:"M6 15v-2"}],["path",{d:"M12 15V9"}],["circle",{cx:"12",cy:"6",r:"3"}]]],bp=["svg",h,[["path",{d:"M6 5v11"}],["path",{d:"M12 5v6"}],["path",{d:"M18 5v14"}]]],Up=["svg",h,[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor"}]]],Op=["svg",h,[["path",{d:"M12.4 2.7a2.5 2.5 0 0 1 3.4 0l5.5 5.5a2.5 2.5 0 0 1 0 3.4l-3.7 3.7a2.5 2.5 0 0 1-3.4 0L8.7 9.8a2.5 2.5 0 0 1 0-3.4z"}],["path",{d:"m14 7 3 3"}],["path",{d:"m9.4 10.6-6.814 6.814A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814"}]]],Gp=["svg",h,[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4"}],["path",{d:"m21 2-9.6 9.6"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5"}]]],Ip=["svg",h,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M6 8h4"}],["path",{d:"M14 8h.01"}],["path",{d:"M18 8h.01"}],["path",{d:"M2 12h20"}],["path",{d:"M6 12v4"}],["path",{d:"M10 12v4"}],["path",{d:"M14 12v4"}],["path",{d:"M18 12v4"}]]],Ep=["svg",h,[["path",{d:"M 20 4 A2 2 0 0 1 22 6"}],["path",{d:"M 22 6 L 22 16.41"}],["path",{d:"M 7 16 L 16 16"}],["path",{d:"M 9.69 4 L 20 4"}],["path",{d:"M14 8h.01"}],["path",{d:"M18 8h.01"}],["path",{d:"m2 2 20 20"}],["path",{d:"M20 20H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2"}],["path",{d:"M6 8h.01"}],["path",{d:"M8 12h.01"}]]],Wp=["svg",h,[["path",{d:"M10 8h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M14 8h.01"}],["path",{d:"M16 12h.01"}],["path",{d:"M18 8h.01"}],["path",{d:"M6 8h.01"}],["path",{d:"M7 16h10"}],["path",{d:"M8 12h.01"}],["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}]]],xp=["svg",h,[["path",{d:"M12 2v5"}],["path",{d:"M6 7h12l4 9H2l4-9Z"}],["path",{d:"M9.17 16a3 3 0 1 0 5.66 0"}]]],Xp=["svg",h,[["path",{d:"m14 5-3 3 2 7 8-8-7-2Z"}],["path",{d:"m14 5-3 3-3-3 3-3 3 3Z"}],["path",{d:"M9.5 6.5 4 12l3 6"}],["path",{d:"M3 22v-2c0-1.1.9-2 2-2h4a2 2 0 0 1 2 2v2H3Z"}]]],Np=["svg",h,[["path",{d:"M9 2h6l3 7H6l3-7Z"}],["path",{d:"M12 9v13"}],["path",{d:"M9 22h6"}]]],Kp=["svg",h,[["path",{d:"M11 13h6l3 7H8l3-7Z"}],["path",{d:"M14 13V8a2 2 0 0 0-2-2H8"}],["path",{d:"M4 9h2a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H4v6Z"}]]],Jp=["svg",h,[["path",{d:"M11 4h6l3 7H8l3-7Z"}],["path",{d:"M14 11v5a2 2 0 0 1-2 2H8"}],["path",{d:"M4 15h2a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H4v-6Z"}]]],Qp=["svg",h,[["path",{d:"M8 2h8l4 10H4L8 2Z"}],["path",{d:"M12 12v6"}],["path",{d:"M8 22v-2c0-1.1.9-2 2-2h4a2 2 0 0 1 2 2v2H8Z"}]]],jp=["svg",h,[["path",{d:"m12 8 6-3-6-3v10"}],["path",{d:"m8 11.99-5.5 3.14a1 1 0 0 0 0 1.74l8.5 4.86a2 2 0 0 0 2 0l8.5-4.86a1 1 0 0 0 0-1.74L16 12"}],["path",{d:"m6.49 12.85 11.02 6.3"}],["path",{d:"M17.51 12.85 6.5 19.15"}]]],Yp=["svg",h,[["line",{x1:"3",x2:"21",y1:"22",y2:"22"}],["line",{x1:"6",x2:"6",y1:"18",y2:"11"}],["line",{x1:"10",x2:"10",y1:"18",y2:"11"}],["line",{x1:"14",x2:"14",y1:"18",y2:"11"}],["line",{x1:"18",x2:"18",y1:"18",y2:"11"}],["polygon",{points:"12 2 20 7 4 7"}]]],_p=["svg",h,[["path",{d:"m5 8 6 6"}],["path",{d:"m4 14 6-6 2-3"}],["path",{d:"M2 5h12"}],["path",{d:"M7 2h1"}],["path",{d:"m22 22-5-10-5 10"}],["path",{d:"M14 18h6"}]]],ae=["svg",h,[["path",{d:"M2 20h20"}],["path",{d:"m9 10 2 2 4-4"}],["rect",{x:"3",y:"4",width:"18",height:"12",rx:"2"}]]],j1=["svg",h,[["rect",{width:"18",height:"12",x:"3",y:"4",rx:"2",ry:"2"}],["line",{x1:"2",x2:"22",y1:"20",y2:"20"}]]],he=["svg",h,[["path",{d:"M20 16V7a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v9m16 0H4m16 0 1.28 2.55a1 1 0 0 1-.9 1.45H3.62a1 1 0 0 1-.9-1.45L4 16"}]]],te=["svg",h,[["path",{d:"M7 22a5 5 0 0 1-2-4"}],["path",{d:"M7 16.93c.96.43 1.96.74 2.99.91"}],["path",{d:"M3.34 14A6.8 6.8 0 0 1 2 10c0-4.42 4.48-8 10-8s10 3.58 10 8a7.19 7.19 0 0 1-.33 2"}],["path",{d:"M5 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"}],["path",{d:"M14.33 22h-.09a.35.35 0 0 1-.24-.32v-10a.34.34 0 0 1 .33-.34c.08 0 .15.03.21.08l7.34 6a.33.33 0 0 1-.21.59h-4.49l-2.57 3.85a.35.35 0 0 1-.28.14z"}]]],de=["svg",h,[["path",{d:"M7 22a5 5 0 0 1-2-4"}],["path",{d:"M3.3 14A6.8 6.8 0 0 1 2 10c0-4.4 4.5-8 10-8s10 3.6 10 8-4.5 8-10 8a12 12 0 0 1-5-1"}],["path",{d:"M5 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"}]]],ce=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M18 13a6 6 0 0 1-6 5 6 6 0 0 1-6-5h12Z"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9"}]]],Me=["svg",h,[["path",{d:"m16.02 12 5.48 3.13a1 1 0 0 1 0 1.74L13 21.74a2 2 0 0 1-2 0l-8.5-4.87a1 1 0 0 1 0-1.74L7.98 12"}],["path",{d:"M13 13.74a2 2 0 0 1-2 0L2.5 8.87a1 1 0 0 1 0-1.74L11 2.26a2 2 0 0 1 2 0l8.5 4.87a1 1 0 0 1 0 1.74Z"}]]],Y1=["svg",h,[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"}]]],pe=["svg",h,[["rect",{width:"7",height:"9",x:"3",y:"3",rx:"1"}],["rect",{width:"7",height:"5",x:"14",y:"3",rx:"1"}],["rect",{width:"7",height:"9",x:"14",y:"12",rx:"1"}],["rect",{width:"7",height:"5",x:"3",y:"16",rx:"1"}]]],ee=["svg",h,[["rect",{width:"7",height:"7",x:"3",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"14",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"14",y:"14",rx:"1"}],["rect",{width:"7",height:"7",x:"3",y:"14",rx:"1"}]]],ne=["svg",h,[["rect",{width:"7",height:"7",x:"3",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"3",y:"14",rx:"1"}],["path",{d:"M14 4h7"}],["path",{d:"M14 9h7"}],["path",{d:"M14 15h7"}],["path",{d:"M14 20h7"}]]],ie=["svg",h,[["rect",{width:"7",height:"18",x:"3",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"14",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"14",y:"14",rx:"1"}]]],le=["svg",h,[["rect",{width:"18",height:"7",x:"3",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"3",y:"14",rx:"1"}],["rect",{width:"7",height:"7",x:"14",y:"14",rx:"1"}]]],ve=["svg",h,[["rect",{width:"18",height:"7",x:"3",y:"3",rx:"1"}],["rect",{width:"9",height:"7",x:"3",y:"14",rx:"1"}],["rect",{width:"5",height:"7",x:"16",y:"14",rx:"1"}]]],oe=["svg",h,[["path",{d:"M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z"}],["path",{d:"M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12"}]]],se=["svg",h,[["path",{d:"M2 22c1.25-.987 2.27-1.975 3.9-2.2a5.56 5.56 0 0 1 3.8 1.5 4 4 0 0 0 6.187-2.353 3.5 3.5 0 0 0 3.69-5.116A3.5 3.5 0 0 0 20.95 8 3.5 3.5 0 1 0 16 3.05a3.5 3.5 0 0 0-5.831 1.373 3.5 3.5 0 0 0-5.116 3.69 4 4 0 0 0-2.348 6.155C3.499 15.42 4.409 16.712 4.2 18.1 3.926 19.743 3.014 20.732 2 22"}],["path",{d:"M2 22 17 7"}]]],re=["svg",h,[["path",{d:"M16 12h3a2 2 0 0 0 1.902-1.38l1.056-3.333A1 1 0 0 0 21 6H3a1 1 0 0 0-.958 1.287l1.056 3.334A2 2 0 0 0 5 12h3"}],["path",{d:"M18 6V3a1 1 0 0 0-1-1h-3"}],["rect",{width:"8",height:"12",x:"8",y:"10",rx:"1"}]]],ge=["svg",h,[["path",{d:"M15 12h6"}],["path",{d:"M15 6h6"}],["path",{d:"m3 13 3.553-7.724a.5.5 0 0 1 .894 0L11 13"}],["path",{d:"M3 18h18"}],["path",{d:"M4 11h6"}]]],ye=["svg",h,[["rect",{width:"8",height:"18",x:"3",y:"3",rx:"1"}],["path",{d:"M7 3v18"}],["path",{d:"M20.4 18.9c.2.5-.1 1.1-.6 1.3l-1.9.7c-.5.2-1.1-.1-1.3-.6L11.1 5.1c-.2-.5.1-1.1.6-1.3l1.9-.7c.5-.2 1.1.1 1.3.6Z"}]]],$e=["svg",h,[["path",{d:"m16 6 4 14"}],["path",{d:"M12 6v14"}],["path",{d:"M8 8v12"}],["path",{d:"M4 4v16"}]]],me=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m4.93 4.93 4.24 4.24"}],["path",{d:"m14.83 9.17 4.24-4.24"}],["path",{d:"m14.83 14.83 4.24 4.24"}],["path",{d:"m9.17 14.83-4.24 4.24"}],["circle",{cx:"12",cy:"12",r:"4"}]]],Ce=["svg",h,[["path",{d:"M8 20V8c0-2.2 1.8-4 4-4 1.5 0 2.8.8 3.5 2"}],["path",{d:"M6 12h4"}],["path",{d:"M14 12h2v8"}],["path",{d:"M6 20h4"}],["path",{d:"M14 20h4"}]]],ue=["svg",h,[["path",{d:"M16.8 11.2c.8-.9 1.2-2 1.2-3.2a6 6 0 0 0-9.3-5"}],["path",{d:"m2 2 20 20"}],["path",{d:"M6.3 6.3a4.67 4.67 0 0 0 1.2 5.2c.7.7 1.3 1.5 1.5 2.5"}],["path",{d:"M9 18h6"}],["path",{d:"M10 22h4"}]]],He=["svg",h,[["path",{d:"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"}],["path",{d:"M9 18h6"}],["path",{d:"M10 22h4"}]]],we=["svg",h,[["path",{d:"M9 17H7A5 5 0 0 1 7 7"}],["path",{d:"M15 7h2a5 5 0 0 1 4 8"}],["line",{x1:"8",x2:"12",y1:"12",y2:"12"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],Ve=["svg",h,[["path",{d:"M9 17H7A5 5 0 0 1 7 7h2"}],["path",{d:"M15 7h2a5 5 0 1 1 0 10h-2"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12"}]]],Ae=["svg",h,[["path",{d:"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"}],["path",{d:"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"}]]],Se=["svg",h,[["path",{d:"M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"}],["rect",{width:"4",height:"12",x:"2",y:"9"}],["circle",{cx:"4",cy:"4",r:"2"}]]],Le=["svg",h,[["path",{d:"M11 18H3"}],["path",{d:"m15 18 2 2 4-4"}],["path",{d:"M16 12H3"}],["path",{d:"M16 6H3"}]]],fe=["svg",h,[["path",{d:"m3 17 2 2 4-4"}],["path",{d:"m3 7 2 2 4-4"}],["path",{d:"M13 6h8"}],["path",{d:"M13 12h8"}],["path",{d:"M13 18h8"}]]],Pe=["svg",h,[["path",{d:"m3 10 2.5-2.5L3 5"}],["path",{d:"m3 19 2.5-2.5L3 14"}],["path",{d:"M10 6h11"}],["path",{d:"M10 12h11"}],["path",{d:"M10 18h11"}]]],ke=["svg",h,[["path",{d:"M16 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M10 18H3"}],["path",{d:"M21 6v10a2 2 0 0 1-2 2h-5"}],["path",{d:"m16 16-2 2 2 2"}]]],Be=["svg",h,[["path",{d:"M10 18h4"}],["path",{d:"M11 6H3"}],["path",{d:"M15 6h6"}],["path",{d:"M18 9V3"}],["path",{d:"M7 12h8"}]]],Fe=["svg",h,[["path",{d:"M3 6h18"}],["path",{d:"M7 12h10"}],["path",{d:"M10 18h4"}]]],De=["svg",h,[["path",{d:"M11 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M16 18H3"}],["path",{d:"M21 12h-6"}]]],Re=["svg",h,[["path",{d:"M21 15V6"}],["path",{d:"M18.5 18a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z"}],["path",{d:"M12 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M12 18H3"}]]],ze=["svg",h,[["path",{d:"M10 12h11"}],["path",{d:"M10 18h11"}],["path",{d:"M10 6h11"}],["path",{d:"M4 10h2"}],["path",{d:"M4 6h1v4"}],["path",{d:"M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"}]]],qe=["svg",h,[["path",{d:"M11 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M16 18H3"}],["path",{d:"M18 9v6"}],["path",{d:"M21 12h-6"}]]],Te=["svg",h,[["path",{d:"M21 6H3"}],["path",{d:"M7 12H3"}],["path",{d:"M7 18H3"}],["path",{d:"M12 18a5 5 0 0 0 9-3 4.5 4.5 0 0 0-4.5-4.5c-1.33 0-2.54.54-3.41 1.41L11 14"}],["path",{d:"M11 10v4h4"}]]],Ze=["svg",h,[["path",{d:"M16 12H3"}],["path",{d:"M16 18H3"}],["path",{d:"M10 6H3"}],["path",{d:"M21 18V8a2 2 0 0 0-2-2h-5"}],["path",{d:"m16 8-2-2 2-2"}]]],be=["svg",h,[["rect",{x:"3",y:"5",width:"6",height:"6",rx:"1"}],["path",{d:"m3 17 2 2 4-4"}],["path",{d:"M13 6h8"}],["path",{d:"M13 12h8"}],["path",{d:"M13 18h8"}]]],Ue=["svg",h,[["path",{d:"M21 12h-8"}],["path",{d:"M21 6H8"}],["path",{d:"M21 18h-8"}],["path",{d:"M3 6v4c0 1.1.9 2 2 2h3"}],["path",{d:"M3 10v6c0 1.1.9 2 2 2h3"}]]],Oe=["svg",h,[["path",{d:"M12 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M12 18H3"}],["path",{d:"m16 12 5 3-5 3v-6Z"}]]],Ge=["svg",h,[["path",{d:"M11 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M16 18H3"}],["path",{d:"m19 10-4 4"}],["path",{d:"m15 10 4 4"}]]],Ie=["svg",h,[["path",{d:"M3 12h.01"}],["path",{d:"M3 18h.01"}],["path",{d:"M3 6h.01"}],["path",{d:"M8 12h13"}],["path",{d:"M8 18h13"}],["path",{d:"M8 6h13"}]]],_1=["svg",h,[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56"}]]],Ee=["svg",h,[["path",{d:"M22 12a1 1 0 0 1-10 0 1 1 0 0 0-10 0"}],["path",{d:"M7 20.7a1 1 0 1 1 5-8.7 1 1 0 1 0 5-8.6"}],["path",{d:"M7 3.3a1 1 0 1 1 5 8.6 1 1 0 1 0 5 8.6"}],["circle",{cx:"12",cy:"12",r:"10"}]]],We=["svg",h,[["path",{d:"M12 2v4"}],["path",{d:"m16.2 7.8 2.9-2.9"}],["path",{d:"M18 12h4"}],["path",{d:"m16.2 16.2 2.9 2.9"}],["path",{d:"M12 18v4"}],["path",{d:"m4.9 19.1 2.9-2.9"}],["path",{d:"M2 12h4"}],["path",{d:"m4.9 4.9 2.9 2.9"}]]],xe=["svg",h,[["line",{x1:"2",x2:"5",y1:"12",y2:"12"}],["line",{x1:"19",x2:"22",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"2",y2:"5"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22"}],["circle",{cx:"12",cy:"12",r:"7"}],["circle",{cx:"12",cy:"12",r:"3"}]]],Xe=["svg",h,[["line",{x1:"2",x2:"5",y1:"12",y2:"12"}],["line",{x1:"19",x2:"22",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"2",y2:"5"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22"}],["path",{d:"M7.11 7.11C5.83 8.39 5 10.1 5 12c0 3.87 3.13 7 7 7 1.9 0 3.61-.83 4.89-2.11"}],["path",{d:"M18.71 13.96c.19-.63.29-1.29.29-1.96 0-3.87-3.13-7-7-7-.67 0-1.33.1-1.96.29"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],Ne=["svg",h,[["line",{x1:"2",x2:"5",y1:"12",y2:"12"}],["line",{x1:"19",x2:"22",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"2",y2:"5"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22"}],["circle",{cx:"12",cy:"12",r:"7"}]]],a2=["svg",h,[["circle",{cx:"12",cy:"16",r:"1"}],["rect",{width:"18",height:"12",x:"3",y:"10",rx:"2"}],["path",{d:"M7 10V7a5 5 0 0 1 9.33-2.5"}]]],Ke=["svg",h,[["circle",{cx:"12",cy:"16",r:"1"}],["rect",{x:"3",y:"10",width:"18",height:"12",rx:"2"}],["path",{d:"M7 10V7a5 5 0 0 1 10 0v3"}]]],h2=["svg",h,[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2"}],["path",{d:"M7 11V7a5 5 0 0 1 9.9-1"}]]],Je=["svg",h,[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4"}]]],Qe=["svg",h,[["path",{d:"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"}],["polyline",{points:"10 17 15 12 10 7"}],["line",{x1:"15",x2:"3",y1:"12",y2:"12"}]]],je=["svg",h,[["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"}],["polyline",{points:"16 17 21 12 16 7"}],["line",{x1:"21",x2:"9",y1:"12",y2:"12"}]]],Ye=["svg",h,[["path",{d:"M13 12h8"}],["path",{d:"M13 18h8"}],["path",{d:"M13 6h8"}],["path",{d:"M3 12h1"}],["path",{d:"M3 18h1"}],["path",{d:"M3 6h1"}],["path",{d:"M8 12h1"}],["path",{d:"M8 18h1"}],["path",{d:"M8 6h1"}]]],_e=["svg",h,[["circle",{cx:"11",cy:"11",r:"8"}],["path",{d:"m21 21-4.3-4.3"}],["path",{d:"M11 11a2 2 0 0 0 4 0 4 4 0 0 0-8 0 6 6 0 0 0 12 0"}]]],a9=["svg",h,[["path",{d:"M6 20a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2"}],["path",{d:"M8 18V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v14"}],["path",{d:"M10 20h4"}],["circle",{cx:"16",cy:"20",r:"2"}],["circle",{cx:"8",cy:"20",r:"2"}]]],h9=["svg",h,[["path",{d:"m6 15-4-4 6.75-6.77a7.79 7.79 0 0 1 11 11L13 22l-4-4 6.39-6.36a2.14 2.14 0 0 0-3-3L6 15"}],["path",{d:"m5 8 4 4"}],["path",{d:"m12 15 4 4"}]]],t9=["svg",h,[["path",{d:"M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"m16 19 2 2 4-4"}]]],d9=["svg",h,[["path",{d:"M22 15V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"M16 19h6"}]]],c9=["svg",h,[["path",{d:"M21.2 8.4c.5.38.8.97.8 1.6v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V10a2 2 0 0 1 .8-1.6l8-6a2 2 0 0 1 2.4 0l8 6Z"}],["path",{d:"m22 10-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 10"}]]],M9=["svg",h,[["path",{d:"M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"M19 16v6"}],["path",{d:"M16 19h6"}]]],p9=["svg",h,[["path",{d:"M22 10.5V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h12.5"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"M18 15.28c.2-.4.5-.8.9-1a2.1 2.1 0 0 1 2.6.4c.3.4.5.8.5 1.3 0 1.3-2 2-2 2"}],["path",{d:"M20 22v.01"}]]],e9=["svg",h,[["path",{d:"M22 12.5V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h7.5"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"M18 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"}],["circle",{cx:"18",cy:"18",r:"3"}],["path",{d:"m22 22-1.5-1.5"}]]],n9=["svg",h,[["path",{d:"M22 10.5V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h12.5"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"M20 14v4"}],["path",{d:"M20 22v.01"}]]],i9=["svg",h,[["path",{d:"M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h9"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"m17 17 4 4"}],["path",{d:"m21 17-4 4"}]]],l9=["svg",h,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}]]],v9=["svg",h,[["path",{d:"M22 17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9.5C2 7 4 5 6.5 5H18c2.2 0 4 1.8 4 4v8Z"}],["polyline",{points:"15,9 18,9 18,11"}],["path",{d:"M6.5 5C9 5 11 7 11 9.5V17a2 2 0 0 1-2 2"}],["line",{x1:"6",x2:"7",y1:"10",y2:"10"}]]],o9=["svg",h,[["rect",{width:"16",height:"13",x:"6",y:"4",rx:"2"}],["path",{d:"m22 7-7.1 3.78c-.57.3-1.23.3-1.8 0L6 7"}],["path",{d:"M2 8v11c0 1.1.9 2 2 2h14"}]]],s9=["svg",h,[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["path",{d:"m9 10 2 2 4-4"}]]],r9=["svg",h,[["path",{d:"M19.43 12.935c.357-.967.57-1.955.57-2.935a8 8 0 0 0-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 0 0 1.202 0 32.197 32.197 0 0 0 .813-.728"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"m16 18 2 2 4-4"}]]],g9=["svg",h,[["path",{d:"M15 22a1 1 0 0 1-1-1v-4a1 1 0 0 1 .445-.832l3-2a1 1 0 0 1 1.11 0l3 2A1 1 0 0 1 22 17v4a1 1 0 0 1-1 1z"}],["path",{d:"M18 10a8 8 0 0 0-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 0 0 .601.2"}],["path",{d:"M18 22v-3"}],["circle",{cx:"10",cy:"10",r:"3"}]]],y9=["svg",h,[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["path",{d:"M9 10h6"}]]],$9=["svg",h,[["path",{d:"M18.977 14C19.6 12.701 20 11.343 20 10a8 8 0 0 0-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 0 0 1.202 0 32 32 0 0 0 .824-.738"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M16 18h6"}]]],m9=["svg",h,[["path",{d:"M12.75 7.09a3 3 0 0 1 2.16 2.16"}],["path",{d:"M17.072 17.072c-1.634 2.17-3.527 3.912-4.471 4.727a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 1.432-4.568"}],["path",{d:"m2 2 20 20"}],["path",{d:"M8.475 2.818A8 8 0 0 1 20 10c0 1.183-.31 2.377-.81 3.533"}],["path",{d:"M9.13 9.13a3 3 0 0 0 3.74 3.74"}]]],C9=["svg",h,[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["path",{d:"M12 7v6"}],["path",{d:"M9 10h6"}]]],u9=["svg",h,[["path",{d:"M19.914 11.105A7.298 7.298 0 0 0 20 10a8 8 0 0 0-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 0 0 1.202 0 32 32 0 0 0 .824-.738"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M16 18h6"}],["path",{d:"M19 15v6"}]]],H9=["svg",h,[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["path",{d:"m14.5 7.5-5 5"}],["path",{d:"m9.5 7.5 5 5"}]]],w9=["svg",h,[["path",{d:"M19.752 11.901A7.78 7.78 0 0 0 20 10a8 8 0 0 0-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 0 0 1.202 0 19 19 0 0 0 .09-.077"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"m21.5 15.5-5 5"}],["path",{d:"m21.5 20.5-5-5"}]]],V9=["svg",h,[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["circle",{cx:"12",cy:"10",r:"3"}]]],A9=["svg",h,[["path",{d:"M18 8c0 3.613-3.869 7.429-5.393 8.795a1 1 0 0 1-1.214 0C9.87 15.429 6 11.613 6 8a6 6 0 0 1 12 0"}],["circle",{cx:"12",cy:"8",r:"2"}],["path",{d:"M8.714 14h-3.71a1 1 0 0 0-.948.683l-2.004 6A1 1 0 0 0 3 22h18a1 1 0 0 0 .948-1.316l-2-6a1 1 0 0 0-.949-.684h-3.712"}]]],S9=["svg",h,[["path",{d:"m11 19-1.106-.552a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0l4.212 2.106a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619V12"}],["path",{d:"M15 5.764V12"}],["path",{d:"M18 15v6"}],["path",{d:"M21 18h-6"}],["path",{d:"M9 3.236v15"}]]],L9=["svg",h,[["path",{d:"M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z"}],["path",{d:"M15 5.764v15"}],["path",{d:"M9 3.236v15"}]]],f9=["svg",h,[["path",{d:"M8 22h8"}],["path",{d:"M12 11v11"}],["path",{d:"m19 3-7 8-7-8Z"}]]],P9=["svg",h,[["polyline",{points:"15 3 21 3 21 9"}],["polyline",{points:"9 21 3 21 3 15"}],["line",{x1:"21",x2:"14",y1:"3",y2:"10"}],["line",{x1:"3",x2:"10",y1:"21",y2:"14"}]]],k9=["svg",h,[["path",{d:"M8 3H5a2 2 0 0 0-2 2v3"}],["path",{d:"M21 8V5a2 2 0 0 0-2-2h-3"}],["path",{d:"M3 16v3a2 2 0 0 0 2 2h3"}],["path",{d:"M16 21h3a2 2 0 0 0 2-2v-3"}]]],B9=["svg",h,[["path",{d:"M7.21 15 2.66 7.14a2 2 0 0 1 .13-2.2L4.4 2.8A2 2 0 0 1 6 2h12a2 2 0 0 1 1.6.8l1.6 2.14a2 2 0 0 1 .14 2.2L16.79 15"}],["path",{d:"M11 12 5.12 2.2"}],["path",{d:"m13 12 5.88-9.8"}],["path",{d:"M8 7h8"}],["circle",{cx:"12",cy:"17",r:"5"}],["path",{d:"M12 18v-2h-.5"}]]],F9=["svg",h,[["path",{d:"M9.26 9.26 3 11v3l14.14 3.14"}],["path",{d:"M21 15.34V6l-7.31 2.03"}],["path",{d:"M11.6 16.8a3 3 0 1 1-5.8-1.6"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],D9=["svg",h,[["path",{d:"m3 11 18-5v12L3 14v-3z"}],["path",{d:"M11.6 16.8a3 3 0 1 1-5.8-1.6"}]]],R9=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"8",x2:"16",y1:"15",y2:"15"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9"}]]],z9=["svg",h,[["path",{d:"M6 19v-3"}],["path",{d:"M10 19v-3"}],["path",{d:"M14 19v-3"}],["path",{d:"M18 19v-3"}],["path",{d:"M8 11V9"}],["path",{d:"M16 11V9"}],["path",{d:"M12 11V9"}],["path",{d:"M2 15h20"}],["path",{d:"M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1.1a2 2 0 0 0 0 3.837V17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5.1a2 2 0 0 0 0-3.837Z"}]]],q9=["svg",h,[["line",{x1:"4",x2:"20",y1:"12",y2:"12"}],["line",{x1:"4",x2:"20",y1:"6",y2:"6"}],["line",{x1:"4",x2:"20",y1:"18",y2:"18"}]]],T9=["svg",h,[["path",{d:"m8 6 4-4 4 4"}],["path",{d:"M12 2v10.3a4 4 0 0 1-1.172 2.872L4 22"}],["path",{d:"m20 22-5-5"}]]],Z9=["svg",h,[["path",{d:"M10 9.5 8 12l2 2.5"}],["path",{d:"m14 9.5 2 2.5-2 2.5"}],["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22z"}]]],b9=["svg",h,[["path",{d:"M13.5 3.1c-.5 0-1-.1-1.5-.1s-1 .1-1.5.1"}],["path",{d:"M19.3 6.8a10.45 10.45 0 0 0-2.1-2.1"}],["path",{d:"M20.9 13.5c.1-.5.1-1 .1-1.5s-.1-1-.1-1.5"}],["path",{d:"M17.2 19.3a10.45 10.45 0 0 0 2.1-2.1"}],["path",{d:"M10.5 20.9c.5.1 1 .1 1.5.1s1-.1 1.5-.1"}],["path",{d:"M3.5 17.5 2 22l4.5-1.5"}],["path",{d:"M3.1 10.5c0 .5-.1 1-.1 1.5s.1 1 .1 1.5"}],["path",{d:"M6.8 4.7a10.45 10.45 0 0 0-2.1 2.1"}]]],U9=["svg",h,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"M15.8 9.2a2.5 2.5 0 0 0-3.5 0l-.3.4-.35-.3a2.42 2.42 0 1 0-3.2 3.6l3.6 3.5 3.6-3.5c1.2-1.2 1.1-2.7.2-3.7"}]]],O9=["svg",h,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"M8 12h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M16 12h.01"}]]],G9=["svg",h,[["path",{d:"M20.5 14.9A9 9 0 0 0 9.1 3.5"}],["path",{d:"m2 2 20 20"}],["path",{d:"M5.6 5.6C3 8.3 2.2 12.5 4 16l-2 6 6-2c3.4 1.8 7.6 1.1 10.3-1.7"}]]],I9=["svg",h,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"M8 12h8"}],["path",{d:"M12 8v8"}]]],E9=["svg",h,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"}],["path",{d:"M12 17h.01"}]]],W9=["svg",h,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"m10 15-3-3 3-3"}],["path",{d:"M7 12h7a2 2 0 0 1 2 2v1"}]]],x9=["svg",h,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"M12 8v4"}],["path",{d:"M12 16h.01"}]]],X9=["svg",h,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"m15 9-6 6"}],["path",{d:"m9 9 6 6"}]]],N9=["svg",h,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}]]],K9=["svg",h,[["path",{d:"M10 7.5 8 10l2 2.5"}],["path",{d:"m14 7.5 2 2.5-2 2.5"}],["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}]]],J9=["svg",h,[["path",{d:"M10 17H7l-4 4v-7"}],["path",{d:"M14 17h1"}],["path",{d:"M14 3h1"}],["path",{d:"M19 3a2 2 0 0 1 2 2"}],["path",{d:"M21 14v1a2 2 0 0 1-2 2"}],["path",{d:"M21 9v1"}],["path",{d:"M3 9v1"}],["path",{d:"M5 3a2 2 0 0 0-2 2"}],["path",{d:"M9 3h1"}]]],Q9=["svg",h,[["path",{d:"m5 19-2 2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2"}],["path",{d:"M9 10h6"}],["path",{d:"M12 7v6"}],["path",{d:"M9 17h6"}]]],j9=["svg",h,[["path",{d:"M11.7 3H5a2 2 0 0 0-2 2v16l4-4h12a2 2 0 0 0 2-2v-2.7"}],["circle",{cx:"18",cy:"6",r:"3"}]]],Y9=["svg",h,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M14.8 7.5a1.84 1.84 0 0 0-2.6 0l-.2.3-.3-.3a1.84 1.84 0 1 0-2.4 2.8L12 13l2.7-2.7c.9-.9.8-2.1.1-2.8"}]]],_9=["svg",h,[["path",{d:"M19 15v-2a2 2 0 1 0-4 0v2"}],["path",{d:"M9 17H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v3.5"}],["rect",{x:"13",y:"15",width:"8",height:"5",rx:"1"}]]],an=["svg",h,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M8 10h.01"}],["path",{d:"M12 10h.01"}],["path",{d:"M16 10h.01"}]]],hn=["svg",h,[["path",{d:"M21 15V5a2 2 0 0 0-2-2H9"}],["path",{d:"m2 2 20 20"}],["path",{d:"M3.6 3.6c-.4.3-.6.8-.6 1.4v16l4-4h10"}]]],tn=["svg",h,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M12 7v6"}],["path",{d:"M9 10h6"}]]],dn=["svg",h,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M8 12a2 2 0 0 0 2-2V8H8"}],["path",{d:"M14 12a2 2 0 0 0 2-2V8h-2"}]]],cn=["svg",h,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"m10 7-3 3 3 3"}],["path",{d:"M17 13v-1a2 2 0 0 0-2-2H7"}]]],Mn=["svg",h,[["path",{d:"M21 12v3a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h7"}],["path",{d:"M16 3h5v5"}],["path",{d:"m16 8 5-5"}]]],pn=["svg",h,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M13 8H7"}],["path",{d:"M17 12H7"}]]],en=["svg",h,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M12 7v2"}],["path",{d:"M12 13h.01"}]]],nn=["svg",h,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"m14.5 7.5-5 5"}],["path",{d:"m9.5 7.5 5 5"}]]],ln=["svg",h,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}]]],vn=["svg",h,[["path",{d:"M14 9a2 2 0 0 1-2 2H6l-4 4V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2z"}],["path",{d:"M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1"}]]],on=["svg",h,[["line",{x1:"2",x2:"22",y1:"2",y2:"22"}],["path",{d:"M18.89 13.23A7.12 7.12 0 0 0 19 12v-2"}],["path",{d:"M5 10v2a7 7 0 0 0 12 5"}],["path",{d:"M15 9.34V5a3 3 0 0 0-5.68-1.33"}],["path",{d:"M9 9v3a3 3 0 0 0 5.12 2.12"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22"}]]],t2=["svg",h,[["path",{d:"m11 7.601-5.994 8.19a1 1 0 0 0 .1 1.298l.817.818a1 1 0 0 0 1.314.087L15.09 12"}],["path",{d:"M16.5 21.174C15.5 20.5 14.372 20 13 20c-2.058 0-3.928 2.356-6 2-2.072-.356-2.775-3.369-1.5-4.5"}],["circle",{cx:"16",cy:"7",r:"5"}]]],sn=["svg",h,[["path",{d:"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"}],["path",{d:"M19 10v2a7 7 0 0 1-14 0v-2"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22"}]]],rn=["svg",h,[["path",{d:"M18 12h2"}],["path",{d:"M18 16h2"}],["path",{d:"M18 20h2"}],["path",{d:"M18 4h2"}],["path",{d:"M18 8h2"}],["path",{d:"M4 12h2"}],["path",{d:"M4 16h2"}],["path",{d:"M4 20h2"}],["path",{d:"M4 4h2"}],["path",{d:"M4 8h2"}],["path",{d:"M8 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-1.5c-.276 0-.494.227-.562.495a2 2 0 0 1-3.876 0C9.994 2.227 9.776 2 9.5 2z"}]]],gn=["svg",h,[["path",{d:"M6 18h8"}],["path",{d:"M3 22h18"}],["path",{d:"M14 22a7 7 0 1 0 0-14h-1"}],["path",{d:"M9 14h2"}],["path",{d:"M9 12a2 2 0 0 1-2-2V6h6v4a2 2 0 0 1-2 2Z"}],["path",{d:"M12 6V3a1 1 0 0 0-1-1H9a1 1 0 0 0-1 1v3"}]]],yn=["svg",h,[["rect",{width:"20",height:"15",x:"2",y:"4",rx:"2"}],["rect",{width:"8",height:"7",x:"6",y:"8",rx:"1"}],["path",{d:"M18 8v7"}],["path",{d:"M6 19v2"}],["path",{d:"M18 19v2"}]]],$n=["svg",h,[["path",{d:"M12 13v8"}],["path",{d:"M12 3v3"}],["path",{d:"M4 6a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h13a2 2 0 0 0 1.152-.365l3.424-2.317a1 1 0 0 0 0-1.635l-3.424-2.318A2 2 0 0 0 17 6z"}]]],mn=["svg",h,[["path",{d:"M8 2h8"}],["path",{d:"M9 2v1.343M15 2v2.789a4 4 0 0 0 .672 2.219l.656.984a4 4 0 0 1 .672 2.22v1.131M7.8 7.8l-.128.192A4 4 0 0 0 7 10.212V20a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2v-3"}],["path",{d:"M7 15a6.47 6.47 0 0 1 5 0 6.472 6.472 0 0 0 3.435.435"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],Cn=["svg",h,[["path",{d:"M8 2h8"}],["path",{d:"M9 2v2.789a4 4 0 0 1-.672 2.219l-.656.984A4 4 0 0 0 7 10.212V20a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2v-9.789a4 4 0 0 0-.672-2.219l-.656-.984A4 4 0 0 1 15 4.788V2"}],["path",{d:"M7 15a6.472 6.472 0 0 1 5 0 6.47 6.47 0 0 0 5 0"}]]],un=["svg",h,[["polyline",{points:"4 14 10 14 10 20"}],["polyline",{points:"20 10 14 10 14 4"}],["line",{x1:"14",x2:"21",y1:"10",y2:"3"}],["line",{x1:"3",x2:"10",y1:"21",y2:"14"}]]],Hn=["svg",h,[["path",{d:"M8 3v3a2 2 0 0 1-2 2H3"}],["path",{d:"M21 8h-3a2 2 0 0 1-2-2V3"}],["path",{d:"M3 16h3a2 2 0 0 1 2 2v3"}],["path",{d:"M16 21v-3a2 2 0 0 1 2-2h3"}]]],wn=["svg",h,[["path",{d:"M5 12h14"}]]],Vn=["svg",h,[["path",{d:"m9 10 2 2 4-4"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]],An=["svg",h,[["path",{d:"M12 17v4"}],["path",{d:"m15.2 4.9-.9-.4"}],["path",{d:"m15.2 7.1-.9.4"}],["path",{d:"m16.9 3.2-.4-.9"}],["path",{d:"m16.9 8.8-.4.9"}],["path",{d:"m19.5 2.3-.4.9"}],["path",{d:"m19.5 9.7-.4-.9"}],["path",{d:"m21.7 4.5-.9.4"}],["path",{d:"m21.7 7.5-.9-.4"}],["path",{d:"M22 13v2a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7"}],["path",{d:"M8 21h8"}],["circle",{cx:"18",cy:"6",r:"3"}]]],Sn=["svg",h,[["circle",{cx:"19",cy:"6",r:"3"}],["path",{d:"M22 12v3a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]],Ln=["svg",h,[["path",{d:"M12 13V7"}],["path",{d:"m15 10-3 3-3-3"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]],fn=["svg",h,[["path",{d:"M17 17H4a2 2 0 0 1-2-2V5c0-1.5 1-2 1-2"}],["path",{d:"M22 15V5a2 2 0 0 0-2-2H9"}],["path",{d:"M8 21h8"}],["path",{d:"M12 17v4"}],["path",{d:"m2 2 20 20"}]]],Pn=["svg",h,[["path",{d:"M10 13V7"}],["path",{d:"M14 13V7"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]],kn=["svg",h,[["path",{d:"M10 7.75a.75.75 0 0 1 1.142-.638l3.664 2.249a.75.75 0 0 1 0 1.278l-3.664 2.25a.75.75 0 0 1-1.142-.64z"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}],["rect",{x:"2",y:"3",width:"20",height:"14",rx:"2"}]]],Bn=["svg",h,[["path",{d:"M18 8V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h8"}],["path",{d:"M10 19v-3.96 3.15"}],["path",{d:"M7 19h5"}],["rect",{width:"6",height:"10",x:"16",y:"12",rx:"2"}]]],Fn=["svg",h,[["path",{d:"M5.5 20H8"}],["path",{d:"M17 9h.01"}],["rect",{width:"10",height:"16",x:"12",y:"4",rx:"2"}],["path",{d:"M8 6H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h4"}],["circle",{cx:"17",cy:"15",r:"1"}]]],Dn=["svg",h,[["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}],["rect",{x:"2",y:"3",width:"20",height:"14",rx:"2"}],["rect",{x:"9",y:"7",width:"6",height:"6",rx:"1"}]]],Rn=["svg",h,[["path",{d:"m9 10 3-3 3 3"}],["path",{d:"M12 13V7"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]],zn=["svg",h,[["path",{d:"m14.5 12.5-5-5"}],["path",{d:"m9.5 12.5 5-5"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]],qn=["svg",h,[["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["line",{x1:"8",x2:"16",y1:"21",y2:"21"}],["line",{x1:"12",x2:"12",y1:"17",y2:"21"}]]],Tn=["svg",h,[["path",{d:"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9"}],["path",{d:"M20 3v4"}],["path",{d:"M22 5h-4"}]]],Zn=["svg",h,[["path",{d:"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"}]]],bn=["svg",h,[["path",{d:"m8 3 4 8 5-5 5 15H2L8 3z"}],["path",{d:"M4.14 15.08c2.62-1.57 5.24-1.43 7.86.42 2.74 1.94 5.49 2 8.23.19"}]]],Un=["svg",h,[["path",{d:"m8 3 4 8 5-5 5 15H2L8 3z"}]]],On=["svg",h,[["path",{d:"M12 6v.343"}],["path",{d:"M18.218 18.218A7 7 0 0 1 5 15V9a7 7 0 0 1 .782-3.218"}],["path",{d:"M19 13.343V9A7 7 0 0 0 8.56 2.902"}],["path",{d:"M22 22 2 2"}]]],Gn=["svg",h,[["path",{d:"M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z"}]]],In=["svg",h,[["path",{d:"M2.034 2.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.944L8.204 7.545a1 1 0 0 0-.66.66l-1.066 3.443a.5.5 0 0 1-.944.033z"}],["circle",{cx:"16",cy:"16",r:"6"}],["path",{d:"m11.8 11.8 8.4 8.4"}]]],En=["svg",h,[["path",{d:"M14 4.1 12 6"}],["path",{d:"m5.1 8-2.9-.8"}],["path",{d:"m6 12-1.9 2"}],["path",{d:"M7.2 2.2 8 5.1"}],["path",{d:"M9.037 9.69a.498.498 0 0 1 .653-.653l11 4.5a.5.5 0 0 1-.074.949l-4.349 1.041a1 1 0 0 0-.74.739l-1.04 4.35a.5.5 0 0 1-.95.074z"}]]],Wn=["svg",h,[["path",{d:"M12.586 12.586 19 19"}],["path",{d:"M3.688 3.037a.497.497 0 0 0-.651.651l6.5 15.999a.501.501 0 0 0 .947-.062l1.569-6.083a2 2 0 0 1 1.448-1.479l6.124-1.579a.5.5 0 0 0 .063-.947z"}]]],xn=["svg",h,[["rect",{x:"5",y:"2",width:"14",height:"20",rx:"7"}],["path",{d:"M12 6v4"}]]],d2=["svg",h,[["path",{d:"M5 3v16h16"}],["path",{d:"m5 19 6-6"}],["path",{d:"m2 6 3-3 3 3"}],["path",{d:"m18 16 3 3-3 3"}]]],Xn=["svg",h,[["path",{d:"M19 13v6h-6"}],["path",{d:"M5 11V5h6"}],["path",{d:"m5 5 14 14"}]]],Nn=["svg",h,[["path",{d:"M11 19H5v-6"}],["path",{d:"M13 5h6v6"}],["path",{d:"M19 5 5 19"}]]],Kn=["svg",h,[["path",{d:"M11 19H5V13"}],["path",{d:"M19 5L5 19"}]]],Jn=["svg",h,[["path",{d:"M19 13V19H13"}],["path",{d:"M5 5L19 19"}]]],Qn=["svg",h,[["path",{d:"M8 18L12 22L16 18"}],["path",{d:"M12 2V22"}]]],jn=["svg",h,[["path",{d:"m18 8 4 4-4 4"}],["path",{d:"M2 12h20"}],["path",{d:"m6 8-4 4 4 4"}]]],Yn=["svg",h,[["path",{d:"M6 8L2 12L6 16"}],["path",{d:"M2 12H22"}]]],_n=["svg",h,[["path",{d:"M18 8L22 12L18 16"}],["path",{d:"M2 12H22"}]]],ai=["svg",h,[["path",{d:"M5 11V5H11"}],["path",{d:"M5 5L19 19"}]]],hi=["svg",h,[["path",{d:"M13 5H19V11"}],["path",{d:"M19 5L5 19"}]]],ti=["svg",h,[["path",{d:"M8 6L12 2L16 6"}],["path",{d:"M12 2V22"}]]],di=["svg",h,[["path",{d:"M12 2v20"}],["path",{d:"m8 18 4 4 4-4"}],["path",{d:"m8 6 4-4 4 4"}]]],ci=["svg",h,[["path",{d:"M12 2v20"}],["path",{d:"m15 19-3 3-3-3"}],["path",{d:"m19 9 3 3-3 3"}],["path",{d:"M2 12h20"}],["path",{d:"m5 9-3 3 3 3"}],["path",{d:"m9 5 3-3 3 3"}]]],Mi=["svg",h,[["circle",{cx:"8",cy:"18",r:"4"}],["path",{d:"M12 18V2l7 4"}]]],pi=["svg",h,[["circle",{cx:"12",cy:"18",r:"4"}],["path",{d:"M16 18V2"}]]],ei=["svg",h,[["path",{d:"M9 18V5l12-2v13"}],["path",{d:"m9 9 12-2"}],["circle",{cx:"6",cy:"18",r:"3"}],["circle",{cx:"18",cy:"16",r:"3"}]]],ni=["svg",h,[["path",{d:"M9 18V5l12-2v13"}],["circle",{cx:"6",cy:"18",r:"3"}],["circle",{cx:"18",cy:"16",r:"3"}]]],ii=["svg",h,[["path",{d:"M9.31 9.31 5 21l7-4 7 4-1.17-3.17"}],["path",{d:"M14.53 8.88 12 2l-1.17 3.17"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],li=["svg",h,[["polygon",{points:"12 2 19 21 12 17 5 21 12 2"}]]],vi=["svg",h,[["path",{d:"M8.43 8.43 3 11l8 2 2 8 2.57-5.43"}],["path",{d:"M17.39 11.73 22 2l-9.73 4.61"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],oi=["svg",h,[["polygon",{points:"3 11 22 2 13 21 11 13 3 11"}]]],si=["svg",h,[["rect",{x:"16",y:"16",width:"6",height:"6",rx:"1"}],["rect",{x:"2",y:"16",width:"6",height:"6",rx:"1"}],["rect",{x:"9",y:"2",width:"6",height:"6",rx:"1"}],["path",{d:"M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3"}],["path",{d:"M12 12V8"}]]],ri=["svg",h,[["path",{d:"M4 22h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v16a2 2 0 0 1-2 2Zm0 0a2 2 0 0 1-2-2v-9c0-1.1.9-2 2-2h2"}],["path",{d:"M18 14h-8"}],["path",{d:"M15 18h-5"}],["path",{d:"M10 6h8v4h-8V6Z"}]]],gi=["svg",h,[["path",{d:"M6 8.32a7.43 7.43 0 0 1 0 7.36"}],["path",{d:"M9.46 6.21a11.76 11.76 0 0 1 0 11.58"}],["path",{d:"M12.91 4.1a15.91 15.91 0 0 1 .01 15.8"}],["path",{d:"M16.37 2a20.16 20.16 0 0 1 0 20"}]]],yi=["svg",h,[["path",{d:"M13.4 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7.4"}],["path",{d:"M2 6h4"}],["path",{d:"M2 10h4"}],["path",{d:"M2 14h4"}],["path",{d:"M2 18h4"}],["path",{d:"M21.378 5.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}]]],$i=["svg",h,[["path",{d:"M2 6h4"}],["path",{d:"M2 10h4"}],["path",{d:"M2 14h4"}],["path",{d:"M2 18h4"}],["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2"}],["path",{d:"M15 2v20"}],["path",{d:"M15 7h5"}],["path",{d:"M15 12h5"}],["path",{d:"M15 17h5"}]]],mi=["svg",h,[["path",{d:"M2 6h4"}],["path",{d:"M2 10h4"}],["path",{d:"M2 14h4"}],["path",{d:"M2 18h4"}],["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2"}],["path",{d:"M9.5 8h5"}],["path",{d:"M9.5 12H16"}],["path",{d:"M9.5 16H14"}]]],Ci=["svg",h,[["path",{d:"M2 6h4"}],["path",{d:"M2 10h4"}],["path",{d:"M2 14h4"}],["path",{d:"M2 18h4"}],["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2"}],["path",{d:"M16 2v20"}]]],ui=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M12 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v2"}],["path",{d:"M20 12v2"}],["path",{d:"M20 18v2a2 2 0 0 1-2 2h-1"}],["path",{d:"M13 22h-2"}],["path",{d:"M7 22H6a2 2 0 0 1-2-2v-2"}],["path",{d:"M4 14v-2"}],["path",{d:"M4 8V6a2 2 0 0 1 2-2h2"}],["path",{d:"M8 10h6"}],["path",{d:"M8 14h8"}],["path",{d:"M8 18h5"}]]],Hi=["svg",h,[["path",{d:"M8 2v4"}],["path",{d:"M12 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"16",height:"18",x:"4",y:"4",rx:"2"}],["path",{d:"M8 10h6"}],["path",{d:"M8 14h8"}],["path",{d:"M8 18h5"}]]],wi=["svg",h,[["path",{d:"M12 4V2"}],["path",{d:"M5 10v4a7.004 7.004 0 0 0 5.277 6.787c.412.104.802.292 1.102.592L12 22l.621-.621c.3-.3.69-.488 1.102-.592a7.01 7.01 0 0 0 4.125-2.939"}],["path",{d:"M19 10v3.343"}],["path",{d:"M12 12c-1.349-.573-1.905-1.005-2.5-2-.546.902-1.048 1.353-2.5 2-1.018-.644-1.46-1.08-2-2-1.028.71-1.69.918-3 1 1.081-1.048 1.757-2.03 2-3 .194-.776.84-1.551 1.79-2.21m11.654 5.997c.887-.457 1.28-.891 1.556-1.787 1.032.916 1.683 1.157 3 1-1.297-1.036-1.758-2.03-2-3-.5-2-4-4-8-4-.74 0-1.461.068-2.15.192"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],Vi=["svg",h,[["path",{d:"M12 4V2"}],["path",{d:"M5 10v4a7.004 7.004 0 0 0 5.277 6.787c.412.104.802.292 1.102.592L12 22l.621-.621c.3-.3.69-.488 1.102-.592A7.003 7.003 0 0 0 19 14v-4"}],["path",{d:"M12 4C8 4 4.5 6 4 8c-.243.97-.919 1.952-2 3 1.31-.082 1.972-.29 3-1 .54.92.982 1.356 2 2 1.452-.647 1.954-1.098 2.5-2 .595.995 1.151 1.427 2.5 2 1.31-.621 1.862-1.058 2.5-2 .629.977 1.162 1.423 2.5 2 1.209-.548 1.68-.967 2-2 1.032.916 1.683 1.157 3 1-1.297-1.036-1.758-2.03-2-3-.5-2-4-4-8-4Z"}]]],c2=["svg",h,[["path",{d:"M12 16h.01"}],["path",{d:"M12 8v4"}],["path",{d:"M15.312 2a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586l-4.688-4.688A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2z"}]]],Ai=["svg",h,[["path",{d:"M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z"}],["path",{d:"M8 12h8"}]]],M2=["svg",h,[["path",{d:"M10 15V9"}],["path",{d:"M14 15V9"}],["path",{d:"M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z"}]]],p2=["svg",h,[["path",{d:"m15 9-6 6"}],["path",{d:"M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z"}],["path",{d:"m9 9 6 6"}]]],Si=["svg",h,[["path",{d:"M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z"}]]],Li=["svg",h,[["path",{d:"M3 20h4.5a.5.5 0 0 0 .5-.5v-.282a.52.52 0 0 0-.247-.437 8 8 0 1 1 8.494-.001.52.52 0 0 0-.247.438v.282a.5.5 0 0 0 .5.5H21"}]]],fi=["svg",h,[["path",{d:"M3 3h6l6 18h6"}],["path",{d:"M14 3h7"}]]],Pi=["svg",h,[["circle",{cx:"12",cy:"12",r:"3"}],["circle",{cx:"19",cy:"5",r:"2"}],["circle",{cx:"5",cy:"19",r:"2"}],["path",{d:"M10.4 21.9a10 10 0 0 0 9.941-15.416"}],["path",{d:"M13.5 2.1a10 10 0 0 0-9.841 15.416"}]]],ki=["svg",h,[["path",{d:"M12 12V4a1 1 0 0 1 1-1h6.297a1 1 0 0 1 .651 1.759l-4.696 4.025"}],["path",{d:"m12 21-7.414-7.414A2 2 0 0 1 4 12.172V6.415a1.002 1.002 0 0 1 1.707-.707L20 20.009"}],["path",{d:"m12.214 3.381 8.414 14.966a1 1 0 0 1-.167 1.199l-1.168 1.163a1 1 0 0 1-.706.291H6.351a1 1 0 0 1-.625-.219L3.25 18.8a1 1 0 0 1 .631-1.781l4.165.027"}]]],Bi=["svg",h,[["path",{d:"M3 9h18v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9Z"}],["path",{d:"m3 9 2.45-4.9A2 2 0 0 1 7.24 3h9.52a2 2 0 0 1 1.8 1.1L21 9"}],["path",{d:"M12 3v6"}]]],Fi=["svg",h,[["path",{d:"m16 16 2 2 4-4"}],["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"}],["path",{d:"m7.5 4.27 9 5.15"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12"}]]],Di=["svg",h,[["path",{d:"M16 16h6"}],["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"}],["path",{d:"m7.5 4.27 9 5.15"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12"}]]],Ri=["svg",h,[["path",{d:"M12 22v-9"}],["path",{d:"M15.17 2.21a1.67 1.67 0 0 1 1.63 0L21 4.57a1.93 1.93 0 0 1 0 3.36L8.82 14.79a1.655 1.655 0 0 1-1.64 0L3 12.43a1.93 1.93 0 0 1 0-3.36z"}],["path",{d:"M20 13v3.87a2.06 2.06 0 0 1-1.11 1.83l-6 3.08a1.93 1.93 0 0 1-1.78 0l-6-3.08A2.06 2.06 0 0 1 4 16.87V13"}],["path",{d:"M21 12.43a1.93 1.93 0 0 0 0-3.36L8.83 2.2a1.64 1.64 0 0 0-1.63 0L3 4.57a1.93 1.93 0 0 0 0 3.36l12.18 6.86a1.636 1.636 0 0 0 1.63 0z"}]]],zi=["svg",h,[["path",{d:"M16 16h6"}],["path",{d:"M19 13v6"}],["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"}],["path",{d:"m7.5 4.27 9 5.15"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12"}]]],qi=["svg",h,[["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"}],["path",{d:"m7.5 4.27 9 5.15"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12"}],["circle",{cx:"18.5",cy:"15.5",r:"2.5"}],["path",{d:"M20.27 17.27 22 19"}]]],Ti=["svg",h,[["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"}],["path",{d:"m7.5 4.27 9 5.15"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12"}],["path",{d:"m17 13 5 5m-5 0 5-5"}]]],Zi=["svg",h,[["path",{d:"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z"}],["path",{d:"M12 22V12"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["path",{d:"m7.5 4.27 9 5.15"}]]],bi=["svg",h,[["path",{d:"m19 11-8-8-8.6 8.6a2 2 0 0 0 0 2.8l5.2 5.2c.8.8 2 .8 2.8 0L19 11Z"}],["path",{d:"m5 2 5 5"}],["path",{d:"M2 13h15"}],["path",{d:"M22 20a2 2 0 1 1-4 0c0-1.6 1.7-2.4 2-4 .3 1.6 2 2.4 2 4Z"}]]],Ui=["svg",h,[["rect",{width:"16",height:"6",x:"2",y:"2",rx:"2"}],["path",{d:"M10 16v-2a2 2 0 0 1 2-2h8a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2"}],["rect",{width:"4",height:"6",x:"8",y:"16",rx:"1"}]]],e2=["svg",h,[["path",{d:"M10 2v2"}],["path",{d:"M14 2v4"}],["path",{d:"M17 2a1 1 0 0 1 1 1v9H6V3a1 1 0 0 1 1-1z"}],["path",{d:"M6 12a1 1 0 0 0-1 1v1a2 2 0 0 0 2 2h2a1 1 0 0 1 1 1v2.9a2 2 0 1 0 4 0V17a1 1 0 0 1 1-1h2a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1"}]]],Oi=["svg",h,[["path",{d:"m14.622 17.897-10.68-2.913"}],["path",{d:"M18.376 2.622a1 1 0 1 1 3.002 3.002L17.36 9.643a.5.5 0 0 0 0 .707l.944.944a2.41 2.41 0 0 1 0 3.408l-.944.944a.5.5 0 0 1-.707 0L8.354 7.348a.5.5 0 0 1 0-.707l.944-.944a2.41 2.41 0 0 1 3.408 0l.944.944a.5.5 0 0 0 .707 0z"}],["path",{d:"M9 8c-1.804 2.71-3.97 3.46-6.583 3.948a.507.507 0 0 0-.302.819l7.32 8.883a1 1 0 0 0 1.185.204C12.735 20.405 16 16.792 16 15"}]]],Gi=["svg",h,[["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor"}],["path",{d:"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"}]]],Ii=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 15h18"}],["path",{d:"m15 8-3 3-3-3"}]]],n2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M14 15h1"}],["path",{d:"M19 15h2"}],["path",{d:"M3 15h2"}],["path",{d:"M9 15h1"}]]],Ei=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 15h18"}],["path",{d:"m9 10 3-3 3 3"}]]],Wi=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 15h18"}]]],i2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 3v18"}],["path",{d:"m16 15-3-3 3-3"}]]],l2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 14v1"}],["path",{d:"M9 19v2"}],["path",{d:"M9 3v2"}],["path",{d:"M9 9v1"}]]],v2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 3v18"}],["path",{d:"m14 9 3 3-3 3"}]]],o2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 3v18"}]]],xi=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M15 3v18"}],["path",{d:"m8 9 3 3-3 3"}]]],s2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M15 14v1"}],["path",{d:"M15 19v2"}],["path",{d:"M15 3v2"}],["path",{d:"M15 9v1"}]]],Xi=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M15 3v18"}],["path",{d:"m10 15-3-3 3-3"}]]],Ni=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M15 3v18"}]]],Ki=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}],["path",{d:"m9 16 3-3 3 3"}]]],r2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M14 9h1"}],["path",{d:"M19 9h2"}],["path",{d:"M3 9h2"}],["path",{d:"M9 9h1"}]]],Ji=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}],["path",{d:"m15 14-3 3-3-3"}]]],Qi=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}]]],ji=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 3v18"}],["path",{d:"M9 15h12"}]]],Yi=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 15h12"}],["path",{d:"M15 3v18"}]]],g2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}],["path",{d:"M9 21V9"}]]],_i=["svg",h,[["path",{d:"M13.234 20.252 21 12.3"}],["path",{d:"m16 6-8.414 8.586a2 2 0 0 0 0 2.828 2 2 0 0 0 2.828 0l8.414-8.586a4 4 0 0 0 0-5.656 4 4 0 0 0-5.656 0l-8.415 8.585a6 6 0 1 0 8.486 8.486"}]]],al=["svg",h,[["path",{d:"M8 21s-4-3-4-9 4-9 4-9"}],["path",{d:"M16 3s4 3 4 9-4 9-4 9"}]]],hl=["svg",h,[["path",{d:"M11 15h2"}],["path",{d:"M12 12v3"}],["path",{d:"M12 19v3"}],["path",{d:"M15.282 19a1 1 0 0 0 .948-.68l2.37-6.988a7 7 0 1 0-13.2 0l2.37 6.988a1 1 0 0 0 .948.68z"}],["path",{d:"M9 9a3 3 0 1 1 6 0"}]]],tl=["svg",h,[["path",{d:"M5.8 11.3 2 22l10.7-3.79"}],["path",{d:"M4 3h.01"}],["path",{d:"M22 8h.01"}],["path",{d:"M15 2h.01"}],["path",{d:"M22 20h.01"}],["path",{d:"m22 2-2.24.75a2.9 2.9 0 0 0-1.96 3.12c.1.86-.57 1.63-1.45 1.63h-.38c-.86 0-1.6.6-1.76 1.44L14 10"}],["path",{d:"m22 13-.82-.33c-.86-.34-1.82.2-1.98 1.11c-.11.7-.72 1.22-1.43 1.22H17"}],["path",{d:"m11 2 .33.82c.34.86-.2 1.82-1.11 1.98C9.52 4.9 9 5.52 9 6.23V7"}],["path",{d:"M11 13c1.93 1.93 2.83 4.17 2 5-.83.83-3.07-.07-5-2-1.93-1.93-2.83-4.17-2-5 .83-.83 3.07.07 5 2Z"}]]],dl=["svg",h,[["rect",{x:"14",y:"4",width:"4",height:"16",rx:"1"}],["rect",{x:"6",y:"4",width:"4",height:"16",rx:"1"}]]],cl=["svg",h,[["circle",{cx:"11",cy:"4",r:"2"}],["circle",{cx:"18",cy:"8",r:"2"}],["circle",{cx:"20",cy:"16",r:"2"}],["path",{d:"M9 10a5 5 0 0 1 5 5v3.5a3.5 3.5 0 0 1-6.84 1.045Q6.52 17.48 4.46 16.84A3.5 3.5 0 0 1 5.5 10Z"}]]],Ml=["svg",h,[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2"}],["path",{d:"M15 14h.01"}],["path",{d:"M9 6h6"}],["path",{d:"M9 10h6"}]]],y2=["svg",h,[["path",{d:"M12 20h9"}],["path",{d:"M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z"}]]],pl=["svg",h,[["path",{d:"m10 10-6.157 6.162a2 2 0 0 0-.5.833l-1.322 4.36a.5.5 0 0 0 .622.624l4.358-1.323a2 2 0 0 0 .83-.5L14 13.982"}],["path",{d:"m12.829 7.172 4.359-4.346a1 1 0 1 1 3.986 3.986l-4.353 4.353"}],["path",{d:"m2 2 20 20"}]]],el=["svg",h,[["path",{d:"M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z"}],["path",{d:"m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18"}],["path",{d:"m2.3 2.3 7.286 7.286"}],["circle",{cx:"11",cy:"11",r:"2"}]]],$2=["svg",h,[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"}]]],nl=["svg",h,[["path",{d:"M12 20h9"}],["path",{d:"M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z"}],["path",{d:"m15 5 3 3"}]]],il=["svg",h,[["path",{d:"m10 10-6.157 6.162a2 2 0 0 0-.5.833l-1.322 4.36a.5.5 0 0 0 .622.624l4.358-1.323a2 2 0 0 0 .83-.5L14 13.982"}],["path",{d:"m12.829 7.172 4.359-4.346a1 1 0 1 1 3.986 3.986l-4.353 4.353"}],["path",{d:"m15 5 4 4"}],["path",{d:"m2 2 20 20"}]]],ll=["svg",h,[["path",{d:"M13 7 8.7 2.7a2.41 2.41 0 0 0-3.4 0L2.7 5.3a2.41 2.41 0 0 0 0 3.4L7 13"}],["path",{d:"m8 6 2-2"}],["path",{d:"m18 16 2-2"}],["path",{d:"m17 11 4.3 4.3c.94.94.94 2.46 0 3.4l-2.6 2.6c-.94.94-2.46.94-3.4 0L11 17"}],["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"}],["path",{d:"m15 5 4 4"}]]],vl=["svg",h,[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"}],["path",{d:"m15 5 4 4"}]]],ol=["svg",h,[["path",{d:"M10.83 2.38a2 2 0 0 1 2.34 0l8 5.74a2 2 0 0 1 .73 2.25l-3.04 9.26a2 2 0 0 1-1.9 1.37H7.04a2 2 0 0 1-1.9-1.37L2.1 10.37a2 2 0 0 1 .73-2.25z"}]]],sl=["svg",h,[["line",{x1:"19",x2:"5",y1:"5",y2:"19"}],["circle",{cx:"6.5",cy:"6.5",r:"2.5"}],["circle",{cx:"17.5",cy:"17.5",r:"2.5"}]]],rl=["svg",h,[["circle",{cx:"12",cy:"5",r:"1"}],["path",{d:"m9 20 3-6 3 6"}],["path",{d:"m6 8 6 2 6-2"}],["path",{d:"M12 10v4"}]]],gl=["svg",h,[["path",{d:"M20 11H4"}],["path",{d:"M20 7H4"}],["path",{d:"M7 21V4a1 1 0 0 1 1-1h4a1 1 0 0 1 0 12H7"}]]],yl=["svg",h,[["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}],["path",{d:"M14.05 2a9 9 0 0 1 8 7.94"}],["path",{d:"M14.05 6A5 5 0 0 1 18 10"}]]],$l=["svg",h,[["polyline",{points:"18 2 22 6 18 10"}],["line",{x1:"14",x2:"22",y1:"6",y2:"6"}],["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}]]],ml=["svg",h,[["polyline",{points:"16 2 16 8 22 8"}],["line",{x1:"22",x2:"16",y1:"2",y2:"8"}],["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}]]],Cl=["svg",h,[["line",{x1:"22",x2:"16",y1:"2",y2:"8"}],["line",{x1:"16",x2:"22",y1:"2",y2:"8"}],["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}]]],ul=["svg",h,[["path",{d:"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-3.33-2.67m-2.67-3.34a19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91"}],["line",{x1:"22",x2:"2",y1:"2",y2:"22"}]]],Hl=["svg",h,[["polyline",{points:"22 8 22 2 16 2"}],["line",{x1:"16",x2:"22",y1:"8",y2:"2"}],["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}]]],wl=["svg",h,[["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}]]],Vl=["svg",h,[["line",{x1:"9",x2:"9",y1:"4",y2:"20"}],["path",{d:"M4 7c0-1.7 1.3-3 3-3h13"}],["path",{d:"M18 20c-1.7 0-3-1.3-3-3V4"}]]],Al=["svg",h,[["path",{d:"M18.5 8c-1.4 0-2.6-.8-3.2-2A6.87 6.87 0 0 0 2 9v11a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-8.5C22 9.6 20.4 8 18.5 8"}],["path",{d:"M2 14h20"}],["path",{d:"M6 14v4"}],["path",{d:"M10 14v4"}],["path",{d:"M14 14v4"}],["path",{d:"M18 14v4"}]]],Sl=["svg",h,[["path",{d:"M14.531 12.469 6.619 20.38a1 1 0 1 1-3-3l7.912-7.912"}],["path",{d:"M15.686 4.314A12.5 12.5 0 0 0 5.461 2.958 1 1 0 0 0 5.58 4.71a22 22 0 0 1 6.318 3.393"}],["path",{d:"M17.7 3.7a1 1 0 0 0-1.4 0l-4.6 4.6a1 1 0 0 0 0 1.4l2.6 2.6a1 1 0 0 0 1.4 0l4.6-4.6a1 1 0 0 0 0-1.4z"}],["path",{d:"M19.686 8.314a12.501 12.501 0 0 1 1.356 10.225 1 1 0 0 1-1.751-.119 22 22 0 0 0-3.393-6.319"}]]],Ll=["svg",h,[["path",{d:"M21 9V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10c0 1.1.9 2 2 2h4"}],["rect",{width:"10",height:"7",x:"12",y:"13",rx:"2"}]]],fl=["svg",h,[["path",{d:"M2 10h6V4"}],["path",{d:"m2 4 6 6"}],["path",{d:"M21 10V7a2 2 0 0 0-2-2h-7"}],["path",{d:"M3 14v2a2 2 0 0 0 2 2h3"}],["rect",{x:"12",y:"14",width:"10",height:"7",rx:"1"}]]],Pl=["svg",h,[["path",{d:"M19 5c-1.5 0-2.8 1.4-3 2-3.5-1.5-11-.3-11 5 0 1.8 0 3 2 4.5V20h4v-2h3v2h4v-4c1-.5 1.7-1 2-2h2v-4h-2c0-1-.5-1.5-1-2V5z"}],["path",{d:"M2 9v1c0 1.1.9 2 2 2h1"}],["path",{d:"M16 11h.01"}]]],kl=["svg",h,[["path",{d:"M14 3v11"}],["path",{d:"M14 9h-3a3 3 0 0 1 0-6h9"}],["path",{d:"M18 3v11"}],["path",{d:"M22 18H2l4-4"}],["path",{d:"m6 22-4-4"}]]],Bl=["svg",h,[["path",{d:"M10 3v11"}],["path",{d:"M10 9H7a1 1 0 0 1 0-6h8"}],["path",{d:"M14 3v11"}],["path",{d:"m18 14 4 4H2"}],["path",{d:"m22 18-4 4"}]]],Fl=["svg",h,[["path",{d:"M13 4v16"}],["path",{d:"M17 4v16"}],["path",{d:"M19 4H9.5a4.5 4.5 0 0 0 0 9H13"}]]],Dl=["svg",h,[["path",{d:"M18 11h-4a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h4"}],["path",{d:"M6 7v13a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7"}],["rect",{width:"16",height:"5",x:"4",y:"2",rx:"1"}]]],Rl=["svg",h,[["path",{d:"m10.5 20.5 10-10a4.95 4.95 0 1 0-7-7l-10 10a4.95 4.95 0 1 0 7 7Z"}],["path",{d:"m8.5 8.5 7 7"}]]],zl=["svg",h,[["path",{d:"M12 17v5"}],["path",{d:"M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89"}],["path",{d:"m2 2 20 20"}],["path",{d:"M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11"}]]],ql=["svg",h,[["path",{d:"M12 17v5"}],["path",{d:"M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"}]]],Tl=["svg",h,[["path",{d:"m2 22 1-1h3l9-9"}],["path",{d:"M3 21v-3l9-9"}],["path",{d:"m15 6 3.4-3.4a2.1 2.1 0 1 1 3 3L18 9l.4.4a2.1 2.1 0 1 1-3 3l-3.8-3.8a2.1 2.1 0 1 1 3-3l.4.4Z"}]]],Zl=["svg",h,[["path",{d:"m12 14-1 1"}],["path",{d:"m13.75 18.25-1.25 1.42"}],["path",{d:"M17.775 5.654a15.68 15.68 0 0 0-12.121 12.12"}],["path",{d:"M18.8 9.3a1 1 0 0 0 2.1 7.7"}],["path",{d:"M21.964 20.732a1 1 0 0 1-1.232 1.232l-18-5a1 1 0 0 1-.695-1.232A19.68 19.68 0 0 1 15.732 2.037a1 1 0 0 1 1.232.695z"}]]],bl=["svg",h,[["path",{d:"M2 22h20"}],["path",{d:"M3.77 10.77 2 9l2-4.5 1.1.55c.55.28.9.84.9 1.45s.35 1.17.9 1.45L8 8.5l3-6 1.05.53a2 2 0 0 1 1.09 1.52l.72 5.4a2 2 0 0 0 1.09 1.52l4.4 2.2c.42.22.78.55 1.01.96l.6 1.03c.49.88-.06 1.98-1.06 2.1l-1.18.15c-.47.06-.95-.02-1.37-.24L4.29 11.15a2 2 0 0 1-.52-.38Z"}]]],Ul=["svg",h,[["path",{d:"M2 22h20"}],["path",{d:"M6.36 17.4 4 17l-2-4 1.1-.55a2 2 0 0 1 1.8 0l.17.1a2 2 0 0 0 1.8 0L8 12 5 6l.9-.45a2 2 0 0 1 2.09.2l4.02 3a2 2 0 0 0 2.1.2l4.19-2.06a2.41 2.41 0 0 1 1.73-.17L21 7a1.4 1.4 0 0 1 .87 1.99l-.38.76c-.23.46-.6.84-1.07 1.08L7.58 17.2a2 2 0 0 1-1.22.18Z"}]]],Ol=["svg",h,[["path",{d:"M17.8 19.2 16 11l3.5-3.5C21 6 21.5 4 21 3c-1-.5-3 0-4.5 1.5L13 8 4.8 6.2c-.5-.1-.9.1-1.1.5l-.3.5c-.2.5-.1 1 .3 1.3L9 12l-2 3H4l-1 1 3 2 2 3 1-1v-3l3-2 3.5 5.3c.3.4.8.5 1.3.3l.5-.2c.4-.3.6-.7.5-1.2z"}]]],Gl=["svg",h,[["polygon",{points:"6 3 20 12 6 21 6 3"}]]],Il=["svg",h,[["path",{d:"M9 2v6"}],["path",{d:"M15 2v6"}],["path",{d:"M12 17v5"}],["path",{d:"M5 8h14"}],["path",{d:"M6 11V8h12v3a6 6 0 1 1-12 0Z"}]]],m2=["svg",h,[["path",{d:"M6.3 20.3a2.4 2.4 0 0 0 3.4 0L12 18l-6-6-2.3 2.3a2.4 2.4 0 0 0 0 3.4Z"}],["path",{d:"m2 22 3-3"}],["path",{d:"M7.5 13.5 10 11"}],["path",{d:"M10.5 16.5 13 14"}],["path",{d:"m18 3-4 4h6l-4 4"}]]],El=["svg",h,[["path",{d:"M12 22v-5"}],["path",{d:"M9 8V2"}],["path",{d:"M15 8V2"}],["path",{d:"M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"}]]],Wl=["svg",h,[["path",{d:"M5 12h14"}],["path",{d:"M12 5v14"}]]],xl=["svg",h,[["path",{d:"M3 2v1c0 1 2 1 2 2S3 6 3 7s2 1 2 2-2 1-2 2 2 1 2 2"}],["path",{d:"M18 6h.01"}],["path",{d:"M6 18h.01"}],["path",{d:"M20.83 8.83a4 4 0 0 0-5.66-5.66l-12 12a4 4 0 1 0 5.66 5.66Z"}],["path",{d:"M18 11.66V22a4 4 0 0 0 4-4V6"}]]],Xl=["svg",h,[["path",{d:"M4 3h16a2 2 0 0 1 2 2v6a10 10 0 0 1-10 10A10 10 0 0 1 2 11V5a2 2 0 0 1 2-2z"}],["polyline",{points:"8 10 12 14 16 10"}]]],Nl=["svg",h,[["path",{d:"M16.85 18.58a9 9 0 1 0-9.7 0"}],["path",{d:"M8 14a5 5 0 1 1 8 0"}],["circle",{cx:"12",cy:"11",r:"1"}],["path",{d:"M13 17a1 1 0 1 0-2 0l.5 4.5a.5.5 0 1 0 1 0Z"}]]],Kl=["svg",h,[["path",{d:"M10 4.5V4a2 2 0 0 0-2.41-1.957"}],["path",{d:"M13.9 8.4a2 2 0 0 0-1.26-1.295"}],["path",{d:"M21.7 16.2A8 8 0 0 0 22 14v-3a2 2 0 1 0-4 0v-1a2 2 0 0 0-3.63-1.158"}],["path",{d:"m7 15-1.8-1.8a2 2 0 0 0-2.79 2.86L6 19.7a7.74 7.74 0 0 0 6 2.3h2a8 8 0 0 0 5.657-2.343"}],["path",{d:"M6 6v8"}],["path",{d:"m2 2 20 20"}]]],Jl=["svg",h,[["path",{d:"M22 14a8 8 0 0 1-8 8"}],["path",{d:"M18 11v-1a2 2 0 0 0-2-2a2 2 0 0 0-2 2"}],["path",{d:"M14 10V9a2 2 0 0 0-2-2a2 2 0 0 0-2 2v1"}],["path",{d:"M10 9.5V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v10"}],["path",{d:"M18 11a2 2 0 1 1 4 0v3a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15"}]]],Ql=["svg",h,[["path",{d:"M18 8a2 2 0 0 0 0-4 2 2 0 0 0-4 0 2 2 0 0 0-4 0 2 2 0 0 0-4 0 2 2 0 0 0 0 4"}],["path",{d:"M10 22 9 8"}],["path",{d:"m14 22 1-14"}],["path",{d:"M20 8c.5 0 .9.4.8 1l-2.6 12c-.1.5-.7 1-1.2 1H7c-.6 0-1.1-.4-1.2-1L3.2 9c-.1-.6.3-1 .8-1Z"}]]],jl=["svg",h,[["path",{d:"M18.6 14.4c.8-.8.8-2 0-2.8l-8.1-8.1a4.95 4.95 0 1 0-7.1 7.1l8.1 8.1c.9.7 2.1.7 2.9-.1Z"}],["path",{d:"m22 22-5.5-5.5"}]]],Yl=["svg",h,[["path",{d:"M18 7c0-5.333-8-5.333-8 0"}],["path",{d:"M10 7v14"}],["path",{d:"M6 21h12"}],["path",{d:"M6 13h10"}]]],_l=["svg",h,[["path",{d:"M18.36 6.64A9 9 0 0 1 20.77 15"}],["path",{d:"M6.16 6.16a9 9 0 1 0 12.68 12.68"}],["path",{d:"M12 2v4"}],["path",{d:"m2 2 20 20"}]]],av=["svg",h,[["path",{d:"M12 2v10"}],["path",{d:"M18.4 6.6a9 9 0 1 1-12.77.04"}]]],hv=["svg",h,[["path",{d:"M2 3h20"}],["path",{d:"M21 3v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V3"}],["path",{d:"m7 21 5-5 5 5"}]]],tv=["svg",h,[["path",{d:"M13.5 22H7a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v.5"}],["path",{d:"m16 19 2 2 4-4"}],["path",{d:"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v2"}],["path",{d:"M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6"}]]],dv=["svg",h,[["path",{d:"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"}],["path",{d:"M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6"}],["rect",{x:"6",y:"14",width:"12",height:"8",rx:"1"}]]],cv=["svg",h,[["path",{d:"M5 7 3 5"}],["path",{d:"M9 6V3"}],["path",{d:"m13 7 2-2"}],["circle",{cx:"9",cy:"13",r:"3"}],["path",{d:"M11.83 12H20a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h2.17"}],["path",{d:"M16 16h2"}]]],Mv=["svg",h,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M12 9v11"}],["path",{d:"M2 9h13a2 2 0 0 1 2 2v9"}]]],pv=["svg",h,[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z"}]]],ev=["svg",h,[["path",{d:"M2.5 16.88a1 1 0 0 1-.32-1.43l9-13.02a1 1 0 0 1 1.64 0l9 13.01a1 1 0 0 1-.32 1.44l-8.51 4.86a2 2 0 0 1-1.98 0Z"}],["path",{d:"M12 2v20"}]]],nv=["svg",h,[["rect",{width:"5",height:"5",x:"3",y:"3",rx:"1"}],["rect",{width:"5",height:"5",x:"16",y:"3",rx:"1"}],["rect",{width:"5",height:"5",x:"3",y:"16",rx:"1"}],["path",{d:"M21 16h-3a2 2 0 0 0-2 2v3"}],["path",{d:"M21 21v.01"}],["path",{d:"M12 7v3a2 2 0 0 1-2 2H7"}],["path",{d:"M3 12h.01"}],["path",{d:"M12 3h.01"}],["path",{d:"M12 16v.01"}],["path",{d:"M16 12h1"}],["path",{d:"M21 12v.01"}],["path",{d:"M12 21v-1"}]]],iv=["svg",h,[["path",{d:"M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z"}],["path",{d:"M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z"}]]],lv=["svg",h,[["path",{d:"M13 16a3 3 0 0 1 2.24 5"}],["path",{d:"M18 12h.01"}],["path",{d:"M18 21h-8a4 4 0 0 1-4-4 7 7 0 0 1 7-7h.2L9.6 6.4a1 1 0 1 1 2.8-2.8L15.8 7h.2c3.3 0 6 2.7 6 6v1a2 2 0 0 1-2 2h-1a3 3 0 0 0-3 3"}],["path",{d:"M20 8.54V4a2 2 0 1 0-4 0v3"}],["path",{d:"M7.612 12.524a3 3 0 1 0-1.6 4.3"}]]],vv=["svg",h,[["path",{d:"M19.07 4.93A10 10 0 0 0 6.99 3.34"}],["path",{d:"M4 6h.01"}],["path",{d:"M2.29 9.62A10 10 0 1 0 21.31 8.35"}],["path",{d:"M16.24 7.76A6 6 0 1 0 8.23 16.67"}],["path",{d:"M12 18h.01"}],["path",{d:"M17.99 11.66A6 6 0 0 1 15.77 16.67"}],["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"m13.41 10.59 5.66-5.66"}]]],ov=["svg",h,[["path",{d:"M12 12h.01"}],["path",{d:"M7.5 4.2c-.3-.5-.9-.7-1.3-.4C3.9 5.5 2.3 8.1 2 11c-.1.5.4 1 1 1h5c0-1.5.8-2.8 2-3.4-1.1-1.9-2-3.5-2.5-4.4z"}],["path",{d:"M21 12c.6 0 1-.4 1-1-.3-2.9-1.8-5.5-4.1-7.1-.4-.3-1.1-.2-1.3.3-.6.9-1.5 2.5-2.6 4.3 1.2.7 2 2 2 3.5h5z"}],["path",{d:"M7.5 19.8c-.3.5-.1 1.1.4 1.3 2.6 1.2 5.6 1.2 8.2 0 .5-.2.7-.8.4-1.3-.5-.9-1.4-2.5-2.5-4.3-1.2.7-2.8.7-4 0-1.1 1.8-2 3.4-2.5 4.3z"}]]],sv=["svg",h,[["path",{d:"M3 12h3.28a1 1 0 0 1 .948.684l2.298 7.934a.5.5 0 0 0 .96-.044L13.82 4.771A1 1 0 0 1 14.792 4H21"}]]],rv=["svg",h,[["path",{d:"M5 16v2"}],["path",{d:"M19 16v2"}],["rect",{width:"20",height:"8",x:"2",y:"8",rx:"2"}],["path",{d:"M18 12h.01"}]]],gv=["svg",h,[["path",{d:"M4.9 16.1C1 12.2 1 5.8 4.9 1.9"}],["path",{d:"M7.8 4.7a6.14 6.14 0 0 0-.8 7.5"}],["circle",{cx:"12",cy:"9",r:"2"}],["path",{d:"M16.2 4.8c2 2 2.26 5.11.8 7.47"}],["path",{d:"M19.1 1.9a9.96 9.96 0 0 1 0 14.1"}],["path",{d:"M9.5 18h5"}],["path",{d:"m8 22 4-11 4 11"}]]],yv=["svg",h,[["path",{d:"M4.9 19.1C1 15.2 1 8.8 4.9 4.9"}],["path",{d:"M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5"}],["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5"}],["path",{d:"M19.1 4.9C23 8.8 23 15.1 19.1 19"}]]],$v=["svg",h,[["path",{d:"M20.34 17.52a10 10 0 1 0-2.82 2.82"}],["circle",{cx:"19",cy:"19",r:"2"}],["path",{d:"m13.41 13.41 4.18 4.18"}],["circle",{cx:"12",cy:"12",r:"2"}]]],mv=["svg",h,[["path",{d:"M5 15h14"}],["path",{d:"M5 9h14"}],["path",{d:"m14 20-5-5 6-6-5-5"}]]],Cv=["svg",h,[["path",{d:"M22 17a10 10 0 0 0-20 0"}],["path",{d:"M6 17a6 6 0 0 1 12 0"}],["path",{d:"M10 17a2 2 0 0 1 4 0"}]]],uv=["svg",h,[["path",{d:"M13 22H4a2 2 0 0 1 0-4h12"}],["path",{d:"M13.236 18a3 3 0 0 0-2.2-5"}],["path",{d:"M16 9h.01"}],["path",{d:"M16.82 3.94a3 3 0 1 1 3.237 4.868l1.815 2.587a1.5 1.5 0 0 1-1.5 2.1l-2.872-.453a3 3 0 0 0-3.5 3"}],["path",{d:"M17 4.988a3 3 0 1 0-5.2 2.052A7 7 0 0 0 4 14.015 4 4 0 0 0 8 18"}]]],Hv=["svg",h,[["rect",{width:"12",height:"20",x:"6",y:"2",rx:"2"}],["rect",{width:"20",height:"12",x:"2",y:"6",rx:"2"}]]],wv=["svg",h,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M12 6.5v11"}],["path",{d:"M15 9.4a4 4 0 1 0 0 5.2"}]]],Vv=["svg",h,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M8 12h5"}],["path",{d:"M16 9.5a4 4 0 1 0 0 5.2"}]]],Av=["svg",h,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M8 7h8"}],["path",{d:"M12 17.5 8 15h1a4 4 0 0 0 0-8"}],["path",{d:"M8 11h8"}]]],Sv=["svg",h,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"m12 10 3-3"}],["path",{d:"m9 7 3 3v7.5"}],["path",{d:"M9 11h6"}],["path",{d:"M9 15h6"}]]],Lv=["svg",h,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M8 13h5"}],["path",{d:"M10 17V9.5a2.5 2.5 0 0 1 5 0"}],["path",{d:"M8 17h7"}]]],fv=["svg",h,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M8 15h5"}],["path",{d:"M8 11h5a2 2 0 1 0 0-4h-3v10"}]]],Pv=["svg",h,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M10 17V7h5"}],["path",{d:"M10 11h4"}],["path",{d:"M8 15h5"}]]],kv=["svg",h,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M14 8H8"}],["path",{d:"M16 12H8"}],["path",{d:"M13 16H8"}]]],Bv=["svg",h,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"}],["path",{d:"M12 17.5v-11"}]]],C2=["svg",h,[["rect",{width:"20",height:"12",x:"2",y:"6",rx:"2"}],["path",{d:"M12 12h.01"}],["path",{d:"M17 12h.01"}],["path",{d:"M7 12h.01"}]]],Fv=["svg",h,[["rect",{width:"20",height:"12",x:"2",y:"6",rx:"2"}]]],Dv=["svg",h,[["rect",{width:"12",height:"20",x:"6",y:"2",rx:"2"}]]],Rv=["svg",h,[["path",{d:"M7 19H4.815a1.83 1.83 0 0 1-1.57-.881 1.785 1.785 0 0 1-.004-1.784L7.196 9.5"}],["path",{d:"M11 19h8.203a1.83 1.83 0 0 0 1.556-.89 1.784 1.784 0 0 0 0-1.775l-1.226-2.12"}],["path",{d:"m14 16-3 3 3 3"}],["path",{d:"M8.293 13.596 7.196 9.5 3.1 10.598"}],["path",{d:"m9.344 5.811 1.093-1.892A1.83 1.83 0 0 1 11.985 3a1.784 1.784 0 0 1 1.546.888l3.943 6.843"}],["path",{d:"m13.378 9.633 4.096 1.098 1.097-4.096"}]]],zv=["svg",h,[["path",{d:"m15 14 5-5-5-5"}],["path",{d:"M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13"}]]],qv=["svg",h,[["circle",{cx:"12",cy:"17",r:"1"}],["path",{d:"M21 7v6h-6"}],["path",{d:"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7"}]]],Tv=["svg",h,[["path",{d:"M21 7v6h-6"}],["path",{d:"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7"}]]],Zv=["svg",h,[["path",{d:"M3 2v6h6"}],["path",{d:"M21 12A9 9 0 0 0 6 5.3L3 8"}],["path",{d:"M21 22v-6h-6"}],["path",{d:"M3 12a9 9 0 0 0 15 6.7l3-2.7"}],["circle",{cx:"12",cy:"12",r:"1"}]]],bv=["svg",h,[["path",{d:"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"}],["path",{d:"M3 3v5h5"}],["path",{d:"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16"}],["path",{d:"M16 16h5v5"}]]],Uv=["svg",h,[["path",{d:"M21 8L18.74 5.74A9.75 9.75 0 0 0 12 3C11 3 10.03 3.16 9.13 3.47"}],["path",{d:"M8 16H3v5"}],["path",{d:"M3 12C3 9.51 4 7.26 5.64 5.64"}],["path",{d:"m3 16 2.26 2.26A9.75 9.75 0 0 0 12 21c2.49 0 4.74-1 6.36-2.64"}],["path",{d:"M21 12c0 1-.16 1.97-.47 2.87"}],["path",{d:"M21 3v5h-5"}],["path",{d:"M22 22 2 2"}]]],Ov=["svg",h,[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}],["path",{d:"M21 3v5h-5"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}],["path",{d:"M8 16H3v5"}]]],Gv=["svg",h,[["path",{d:"M5 6a4 4 0 0 1 4-4h6a4 4 0 0 1 4 4v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6Z"}],["path",{d:"M5 10h14"}],["path",{d:"M15 7v6"}]]],Iv=["svg",h,[["path",{d:"M17 3v10"}],["path",{d:"m12.67 5.5 8.66 5"}],["path",{d:"m12.67 10.5 8.66-5"}],["path",{d:"M9 17a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-2z"}]]],Ev=["svg",h,[["path",{d:"M4 7V4h16v3"}],["path",{d:"M5 20h6"}],["path",{d:"M13 4 8 20"}],["path",{d:"m15 15 5 5"}],["path",{d:"m20 15-5 5"}]]],Wv=["svg",h,[["path",{d:"m17 2 4 4-4 4"}],["path",{d:"M3 11v-1a4 4 0 0 1 4-4h14"}],["path",{d:"m7 22-4-4 4-4"}],["path",{d:"M21 13v1a4 4 0 0 1-4 4H3"}],["path",{d:"M11 10h1v4"}]]],xv=["svg",h,[["path",{d:"m2 9 3-3 3 3"}],["path",{d:"M13 18H7a2 2 0 0 1-2-2V6"}],["path",{d:"m22 15-3 3-3-3"}],["path",{d:"M11 6h6a2 2 0 0 1 2 2v10"}]]],Xv=["svg",h,[["path",{d:"m17 2 4 4-4 4"}],["path",{d:"M3 11v-1a4 4 0 0 1 4-4h14"}],["path",{d:"m7 22-4-4 4-4"}],["path",{d:"M21 13v1a4 4 0 0 1-4 4H3"}]]],Nv=["svg",h,[["path",{d:"M14 14a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2"}],["path",{d:"M14 4a2 2 0 0 1 2-2"}],["path",{d:"M16 10a2 2 0 0 1-2-2"}],["path",{d:"M20 14a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2"}],["path",{d:"M20 2a2 2 0 0 1 2 2"}],["path",{d:"M22 8a2 2 0 0 1-2 2"}],["path",{d:"m3 7 3 3 3-3"}],["path",{d:"M6 10V5a 3 3 0 0 1 3-3h1"}],["rect",{x:"2",y:"14",width:"8",height:"8",rx:"2"}]]],Kv=["svg",h,[["path",{d:"M14 4a2 2 0 0 1 2-2"}],["path",{d:"M16 10a2 2 0 0 1-2-2"}],["path",{d:"M20 2a2 2 0 0 1 2 2"}],["path",{d:"M22 8a2 2 0 0 1-2 2"}],["path",{d:"m3 7 3 3 3-3"}],["path",{d:"M6 10V5a3 3 0 0 1 3-3h1"}],["rect",{x:"2",y:"14",width:"8",height:"8",rx:"2"}]]],Jv=["svg",h,[["polyline",{points:"7 17 2 12 7 7"}],["polyline",{points:"12 17 7 12 12 7"}],["path",{d:"M22 18v-2a4 4 0 0 0-4-4H7"}]]],Qv=["svg",h,[["polyline",{points:"9 17 4 12 9 7"}],["path",{d:"M20 18v-2a4 4 0 0 0-4-4H4"}]]],jv=["svg",h,[["polygon",{points:"11 19 2 12 11 5 11 19"}],["polygon",{points:"22 19 13 12 22 5 22 19"}]]],Yv=["svg",h,[["path",{d:"M12 11.22C11 9.997 10 9 10 8a2 2 0 0 1 4 0c0 1-.998 2.002-2.01 3.22"}],["path",{d:"m12 18 2.57-3.5"}],["path",{d:"M6.243 9.016a7 7 0 0 1 11.507-.009"}],["path",{d:"M9.35 14.53 12 11.22"}],["path",{d:"M9.35 14.53C7.728 12.246 6 10.221 6 7a6 5 0 0 1 12 0c-.005 3.22-1.778 5.235-3.43 7.5l3.557 4.527a1 1 0 0 1-.203 1.43l-1.894 1.36a1 1 0 0 1-1.384-.215L12 18l-2.679 3.593a1 1 0 0 1-1.39.213l-1.865-1.353a1 1 0 0 1-.203-1.422z"}]]],_v=["svg",h,[["path",{d:"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"}],["path",{d:"m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"}],["path",{d:"M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"}],["path",{d:"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"}]]],ao=["svg",h,[["polyline",{points:"3.5 2 6.5 12.5 18 12.5"}],["line",{x1:"9.5",x2:"5.5",y1:"12.5",y2:"20"}],["line",{x1:"15",x2:"18.5",y1:"12.5",y2:"20"}],["path",{d:"M2.75 18a13 13 0 0 0 18.5 0"}]]],ho=["svg",h,[["path",{d:"M6 19V5"}],["path",{d:"M10 19V6.8"}],["path",{d:"M14 19v-7.8"}],["path",{d:"M18 5v4"}],["path",{d:"M18 19v-6"}],["path",{d:"M22 19V9"}],["path",{d:"M2 19V9a4 4 0 0 1 4-4c2 0 4 1.33 6 4s4 4 6 4a4 4 0 1 0-3-6.65"}]]],u2=["svg",h,[["path",{d:"M16.466 7.5C15.643 4.237 13.952 2 12 2 9.239 2 7 6.477 7 12s2.239 10 5 10c.342 0 .677-.069 1-.2"}],["path",{d:"m15.194 13.707 3.814 1.86-1.86 3.814"}],["path",{d:"M19 15.57c-1.804.885-4.274 1.43-7 1.43-5.523 0-10-2.239-10-5s4.477-5 10-5c4.838 0 8.873 1.718 9.8 4"}]]],to=["svg",h,[["path",{d:"M20 9V7a2 2 0 0 0-2-2h-6"}],["path",{d:"m15 2-3 3 3 3"}],["path",{d:"M20 13v5a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h2"}]]],co=["svg",h,[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"}],["path",{d:"M3 3v5h5"}]]],Mo=["svg",h,[["path",{d:"M12 5H6a2 2 0 0 0-2 2v3"}],["path",{d:"m9 8 3-3-3-3"}],["path",{d:"M4 14v4a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2"}]]],po=["svg",h,[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"}],["path",{d:"M21 3v5h-5"}]]],eo=["svg",h,[["circle",{cx:"6",cy:"19",r:"3"}],["path",{d:"M9 19h8.5c.4 0 .9-.1 1.3-.2"}],["path",{d:"M5.2 5.2A3.5 3.53 0 0 0 6.5 12H12"}],["path",{d:"m2 2 20 20"}],["path",{d:"M21 15.3a3.5 3.5 0 0 0-3.3-3.3"}],["path",{d:"M15 5h-4.3"}],["circle",{cx:"18",cy:"5",r:"3"}]]],no=["svg",h,[["circle",{cx:"6",cy:"19",r:"3"}],["path",{d:"M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15"}],["circle",{cx:"18",cy:"5",r:"3"}]]],io=["svg",h,[["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2"}],["path",{d:"M6.01 18H6"}],["path",{d:"M10.01 18H10"}],["path",{d:"M15 10v4"}],["path",{d:"M17.84 7.17a4 4 0 0 0-5.66 0"}],["path",{d:"M20.66 4.34a8 8 0 0 0-11.31 0"}]]],H2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 12h18"}]]],w2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M21 9H3"}],["path",{d:"M21 15H3"}]]],lo=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M21 7.5H3"}],["path",{d:"M21 12H3"}],["path",{d:"M21 16.5H3"}]]],vo=["svg",h,[["path",{d:"M4 11a9 9 0 0 1 9 9"}],["path",{d:"M4 4a16 16 0 0 1 16 16"}],["circle",{cx:"5",cy:"19",r:"1"}]]],oo=["svg",h,[["path",{d:"M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z"}],["path",{d:"m14.5 12.5 2-2"}],["path",{d:"m11.5 9.5 2-2"}],["path",{d:"m8.5 6.5 2-2"}],["path",{d:"m17.5 15.5 2-2"}]]],so=["svg",h,[["path",{d:"M6 11h8a4 4 0 0 0 0-8H9v18"}],["path",{d:"M6 15h8"}]]],ro=["svg",h,[["path",{d:"M22 18H2a4 4 0 0 0 4 4h12a4 4 0 0 0 4-4Z"}],["path",{d:"M21 14 10 2 3 14h18Z"}],["path",{d:"M10 2v16"}]]],go=["svg",h,[["path",{d:"M7 21h10"}],["path",{d:"M12 21a9 9 0 0 0 9-9H3a9 9 0 0 0 9 9Z"}],["path",{d:"M11.38 12a2.4 2.4 0 0 1-.4-4.77 2.4 2.4 0 0 1 3.2-2.77 2.4 2.4 0 0 1 3.47-.63 2.4 2.4 0 0 1 3.37 3.37 2.4 2.4 0 0 1-1.1 3.7 2.51 2.51 0 0 1 .03 1.1"}],["path",{d:"m13 12 4-4"}],["path",{d:"M10.9 7.25A3.99 3.99 0 0 0 4 10c0 .73.2 1.41.54 2"}]]],yo=["svg",h,[["path",{d:"m2.37 11.223 8.372-6.777a2 2 0 0 1 2.516 0l8.371 6.777"}],["path",{d:"M21 15a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-5.25"}],["path",{d:"M3 15a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h9"}],["path",{d:"m6.67 15 6.13 4.6a2 2 0 0 0 2.8-.4l3.15-4.2"}],["rect",{width:"20",height:"4",x:"2",y:"11",rx:"1"}]]],$o=["svg",h,[["path",{d:"M4 10a7.31 7.31 0 0 0 10 10Z"}],["path",{d:"m9 15 3-3"}],["path",{d:"M17 13a6 6 0 0 0-6-6"}],["path",{d:"M21 13A10 10 0 0 0 11 3"}]]],mo=["svg",h,[["path",{d:"M13 7 9 3 5 7l4 4"}],["path",{d:"m17 11 4 4-4 4-4-4"}],["path",{d:"m8 12 4 4 6-6-4-4Z"}],["path",{d:"m16 8 3-3"}],["path",{d:"M9 21a6 6 0 0 0-6-6"}]]],Co=["svg",h,[["path",{d:"M10 2v3a1 1 0 0 0 1 1h5"}],["path",{d:"M18 18v-6a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6"}],["path",{d:"M18 22H4a2 2 0 0 1-2-2V6"}],["path",{d:"M8 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9.172a2 2 0 0 1 1.414.586l2.828 2.828A2 2 0 0 1 22 6.828V16a2 2 0 0 1-2.01 2z"}]]],uo=["svg",h,[["path",{d:"M13 13H8a1 1 0 0 0-1 1v7"}],["path",{d:"M14 8h1"}],["path",{d:"M17 21v-4"}],["path",{d:"m2 2 20 20"}],["path",{d:"M20.41 20.41A2 2 0 0 1 19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 .59-1.41"}],["path",{d:"M29.5 11.5s5 5 4 5"}],["path",{d:"M9 3h6.2a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V15"}]]],Ho=["svg",h,[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7"}]]],V2=["svg",h,[["path",{d:"M5 7v11a1 1 0 0 0 1 1h11"}],["path",{d:"M5.293 18.707 11 13"}],["circle",{cx:"19",cy:"19",r:"2"}],["circle",{cx:"5",cy:"5",r:"2"}]]],wo=["svg",h,[["path",{d:"m16 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z"}],["path",{d:"m2 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z"}],["path",{d:"M7 21h10"}],["path",{d:"M12 3v18"}],["path",{d:"M3 7h2c2 0 5-1 7-2 2 1 5 2 7 2h2"}]]],Vo=["svg",h,[["path",{d:"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"}],["path",{d:"M14 15H9v-5"}],["path",{d:"M16 3h5v5"}],["path",{d:"M21 3 9 15"}]]],Ao=["svg",h,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["path",{d:"M8 7v10"}],["path",{d:"M12 7v10"}],["path",{d:"M17 7v10"}]]],So=["svg",h,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["circle",{cx:"12",cy:"12",r:"1"}],["path",{d:"M18.944 12.33a1 1 0 0 0 0-.66 7.5 7.5 0 0 0-13.888 0 1 1 0 0 0 0 .66 7.5 7.5 0 0 0 13.888 0"}]]],Lo=["svg",h,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["path",{d:"M8 14s1.5 2 4 2 4-2 4-2"}],["path",{d:"M9 9h.01"}],["path",{d:"M15 9h.01"}]]],fo=["svg",h,[["path",{d:"M11.246 16.657a1 1 0 0 0 1.508 0l3.57-4.101A2.75 2.75 0 1 0 12 9.168a2.75 2.75 0 1 0-4.324 3.388z"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}]]],Po=["svg",h,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["path",{d:"M7 12h10"}]]],ko=["svg",h,[["path",{d:"M17 12v4a1 1 0 0 1-1 1h-4"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M17 8V7"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M7 17h.01"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["rect",{x:"7",y:"7",width:"5",height:"5",rx:"1"}]]],Bo=["svg",h,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"m16 16-1.9-1.9"}]]],Fo=["svg",h,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["path",{d:"M7 8h8"}],["path",{d:"M7 12h10"}],["path",{d:"M7 16h6"}]]],Do=["svg",h,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}]]],Ro=["svg",h,[["path",{d:"M14 22v-4a2 2 0 1 0-4 0v4"}],["path",{d:"m18 10 3.447 1.724a1 1 0 0 1 .553.894V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-7.382a1 1 0 0 1 .553-.894L6 10"}],["path",{d:"M18 5v17"}],["path",{d:"m4 6 7.106-3.553a2 2 0 0 1 1.788 0L20 6"}],["path",{d:"M6 5v17"}],["circle",{cx:"12",cy:"9",r:"2"}]]],zo=["svg",h,[["path",{d:"M5.42 9.42 8 12"}],["circle",{cx:"4",cy:"8",r:"2"}],["path",{d:"m14 6-8.58 8.58"}],["circle",{cx:"4",cy:"16",r:"2"}],["path",{d:"M10.8 14.8 14 18"}],["path",{d:"M16 12h-2"}],["path",{d:"M22 12h-2"}]]],qo=["svg",h,[["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M8.12 8.12 12 12"}],["path",{d:"M20 4 8.12 15.88"}],["circle",{cx:"6",cy:"18",r:"3"}],["path",{d:"M14.8 14.8 20 20"}]]],To=["svg",h,[["path",{d:"M13 3H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-3"}],["path",{d:"M8 21h8"}],["path",{d:"M12 17v4"}],["path",{d:"m22 3-5 5"}],["path",{d:"m17 3 5 5"}]]],Zo=["svg",h,[["path",{d:"M13 3H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-3"}],["path",{d:"M8 21h8"}],["path",{d:"M12 17v4"}],["path",{d:"m17 8 5-5"}],["path",{d:"M17 3h5v5"}]]],bo=["svg",h,[["path",{d:"M15 12h-5"}],["path",{d:"M15 8h-5"}],["path",{d:"M19 17V5a2 2 0 0 0-2-2H4"}],["path",{d:"M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3"}]]],Uo=["svg",h,[["path",{d:"M19 17V5a2 2 0 0 0-2-2H4"}],["path",{d:"M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3"}]]],Oo=["svg",h,[["path",{d:"m8 11 2 2 4-4"}],["circle",{cx:"11",cy:"11",r:"8"}],["path",{d:"m21 21-4.3-4.3"}]]],Go=["svg",h,[["path",{d:"m13 13.5 2-2.5-2-2.5"}],["path",{d:"m21 21-4.3-4.3"}],["path",{d:"M9 8.5 7 11l2 2.5"}],["circle",{cx:"11",cy:"11",r:"8"}]]],Io=["svg",h,[["path",{d:"m13.5 8.5-5 5"}],["circle",{cx:"11",cy:"11",r:"8"}],["path",{d:"m21 21-4.3-4.3"}]]],Eo=["svg",h,[["path",{d:"m13.5 8.5-5 5"}],["path",{d:"m8.5 8.5 5 5"}],["circle",{cx:"11",cy:"11",r:"8"}],["path",{d:"m21 21-4.3-4.3"}]]],Wo=["svg",h,[["circle",{cx:"11",cy:"11",r:"8"}],["path",{d:"m21 21-4.3-4.3"}]]],xo=["svg",h,[["path",{d:"M16 5a4 3 0 0 0-8 0c0 4 8 3 8 7a4 3 0 0 1-8 0"}],["path",{d:"M8 19a4 3 0 0 0 8 0c0-4-8-3-8-7a4 3 0 0 1 8 0"}]]],A2=["svg",h,[["path",{d:"M3.714 3.048a.498.498 0 0 0-.683.627l2.843 7.627a2 2 0 0 1 0 1.396l-2.842 7.627a.498.498 0 0 0 .682.627l18-8.5a.5.5 0 0 0 0-.904z"}],["path",{d:"M6 12h16"}]]],Xo=["svg",h,[["rect",{x:"14",y:"14",width:"8",height:"8",rx:"2"}],["rect",{x:"2",y:"2",width:"8",height:"8",rx:"2"}],["path",{d:"M7 14v1a2 2 0 0 0 2 2h1"}],["path",{d:"M14 7h1a2 2 0 0 1 2 2v1"}]]],No=["svg",h,[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"}],["path",{d:"m21.854 2.147-10.94 10.939"}]]],Ko=["svg",h,[["line",{x1:"3",x2:"21",y1:"12",y2:"12"}],["polyline",{points:"8 8 12 4 16 8"}],["polyline",{points:"16 16 12 20 8 16"}]]],Jo=["svg",h,[["line",{x1:"12",x2:"12",y1:"3",y2:"21"}],["polyline",{points:"8 8 4 12 8 16"}],["polyline",{points:"16 16 20 12 16 8"}]]],Qo=["svg",h,[["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5"}],["path",{d:"M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5"}],["path",{d:"M6 6h.01"}],["path",{d:"M6 18h.01"}],["path",{d:"m15.7 13.4-.9-.3"}],["path",{d:"m9.2 10.9-.9-.3"}],["path",{d:"m10.6 15.7.3-.9"}],["path",{d:"m13.6 15.7-.4-1"}],["path",{d:"m10.8 9.3-.4-1"}],["path",{d:"m8.3 13.6 1-.4"}],["path",{d:"m14.7 10.8 1-.4"}],["path",{d:"m13.4 8.3-.3.9"}]]],jo=["svg",h,[["path",{d:"M6 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-2"}],["path",{d:"M6 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-2"}],["path",{d:"M6 6h.01"}],["path",{d:"M6 18h.01"}],["path",{d:"m13 6-4 6h6l-4 6"}]]],Yo=["svg",h,[["path",{d:"M7 2h13a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-5"}],["path",{d:"M10 10 2.5 2.5C2 2 2 2.5 2 5v3a2 2 0 0 0 2 2h6z"}],["path",{d:"M22 17v-1a2 2 0 0 0-2-2h-1"}],["path",{d:"M4 14a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16.5l1-.5.5.5-8-8H4z"}],["path",{d:"M6 18h.01"}],["path",{d:"m2 2 20 20"}]]],_o=["svg",h,[["rect",{width:"20",height:"8",x:"2",y:"2",rx:"2",ry:"2"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",ry:"2"}],["line",{x1:"6",x2:"6.01",y1:"6",y2:"6"}],["line",{x1:"6",x2:"6.01",y1:"18",y2:"18"}]]],as=["svg",h,[["path",{d:"M20 7h-9"}],["path",{d:"M14 17H5"}],["circle",{cx:"17",cy:"17",r:"3"}],["circle",{cx:"7",cy:"7",r:"3"}]]],hs=["svg",h,[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"}],["circle",{cx:"12",cy:"12",r:"3"}]]],ts=["svg",h,[["path",{d:"M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z"}],["rect",{x:"3",y:"14",width:"7",height:"7",rx:"1"}],["circle",{cx:"17.5",cy:"17.5",r:"3.5"}]]],ds=["svg",h,[["circle",{cx:"18",cy:"5",r:"3"}],["circle",{cx:"6",cy:"12",r:"3"}],["circle",{cx:"18",cy:"19",r:"3"}],["line",{x1:"8.59",x2:"15.42",y1:"13.51",y2:"17.49"}],["line",{x1:"15.41",x2:"8.59",y1:"6.51",y2:"10.49"}]]],cs=["svg",h,[["path",{d:"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"}],["polyline",{points:"16 6 12 2 8 6"}],["line",{x1:"12",x2:"12",y1:"2",y2:"15"}]]],Ms=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["line",{x1:"3",x2:"21",y1:"9",y2:"9"}],["line",{x1:"3",x2:"21",y1:"15",y2:"15"}],["line",{x1:"9",x2:"9",y1:"9",y2:"21"}],["line",{x1:"15",x2:"15",y1:"9",y2:"21"}]]],ps=["svg",h,[["path",{d:"M14 11a2 2 0 1 1-4 0 4 4 0 0 1 8 0 6 6 0 0 1-12 0 8 8 0 0 1 16 0 10 10 0 1 1-20 0 11.93 11.93 0 0 1 2.42-7.22 2 2 0 1 1 3.16 2.44"}]]],es=["svg",h,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M12 8v4"}],["path",{d:"M12 16h.01"}]]],ns=["svg",h,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"m4.243 5.21 14.39 12.472"}]]],is=["svg",h,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"m9 12 2 2 4-4"}]]],ls=["svg",h,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M8 12h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M16 12h.01"}]]],vs=["svg",h,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M12 22V2"}]]],os=["svg",h,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M9 12h6"}]]],ss=["svg",h,[["path",{d:"m2 2 20 20"}],["path",{d:"M5 5a1 1 0 0 0-1 1v7c0 5 3.5 7.5 7.67 8.94a1 1 0 0 0 .67.01c2.35-.82 4.48-1.97 5.9-3.71"}],["path",{d:"M9.309 3.652A12.252 12.252 0 0 0 11.24 2.28a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1v7a9.784 9.784 0 0 1-.08 1.264"}]]],rs=["svg",h,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M9 12h6"}],["path",{d:"M12 9v6"}]]],gs=["svg",h,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M9.1 9a3 3 0 0 1 5.82 1c0 2-3 3-3 3"}],["path",{d:"M12 17h.01"}]]],S2=["svg",h,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"m14.5 9.5-5 5"}],["path",{d:"m9.5 9.5 5 5"}]]],ys=["svg",h,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}]]],$s=["svg",h,[["circle",{cx:"12",cy:"12",r:"8"}],["path",{d:"M12 2v7.5"}],["path",{d:"m19 5-5.23 5.23"}],["path",{d:"M22 12h-7.5"}],["path",{d:"m19 19-5.23-5.23"}],["path",{d:"M12 14.5V22"}],["path",{d:"M10.23 13.77 5 19"}],["path",{d:"M9.5 12H2"}],["path",{d:"M10.23 10.23 5 5"}],["circle",{cx:"12",cy:"12",r:"2.5"}]]],ms=["svg",h,[["path",{d:"M12 10.189V14"}],["path",{d:"M12 2v3"}],["path",{d:"M19 13V7a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v6"}],["path",{d:"M19.38 20A11.6 11.6 0 0 0 21 14l-8.188-3.639a2 2 0 0 0-1.624 0L3 14a11.6 11.6 0 0 0 2.81 7.76"}],["path",{d:"M2 21c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1s1.2 1 2.5 1c2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}]]],Cs=["svg",h,[["path",{d:"M20.38 3.46 16 2a4 4 0 0 1-8 0L3.62 3.46a2 2 0 0 0-1.34 2.23l.58 3.47a1 1 0 0 0 .99.84H6v10c0 1.1.9 2 2 2h8a2 2 0 0 0 2-2V10h2.15a1 1 0 0 0 .99-.84l.58-3.47a2 2 0 0 0-1.34-2.23z"}]]],us=["svg",h,[["path",{d:"M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z"}],["path",{d:"M3 6h18"}],["path",{d:"M16 10a4 4 0 0 1-8 0"}]]],Hs=["svg",h,[["path",{d:"m15 11-1 9"}],["path",{d:"m19 11-4-7"}],["path",{d:"M2 11h20"}],["path",{d:"m3.5 11 1.6 7.4a2 2 0 0 0 2 1.6h9.8a2 2 0 0 0 2-1.6l1.7-7.4"}],["path",{d:"M4.5 15.5h15"}],["path",{d:"m5 11 4-7"}],["path",{d:"m9 11 1 9"}]]],ws=["svg",h,[["circle",{cx:"8",cy:"21",r:"1"}],["circle",{cx:"19",cy:"21",r:"1"}],["path",{d:"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"}]]],Vs=["svg",h,[["path",{d:"M2 22v-5l5-5 5 5-5 5z"}],["path",{d:"M9.5 14.5 16 8"}],["path",{d:"m17 2 5 5-.5.5a3.53 3.53 0 0 1-5 0s0 0 0 0a3.53 3.53 0 0 1 0-5L17 2"}]]],As=["svg",h,[["path",{d:"m4 4 2.5 2.5"}],["path",{d:"M13.5 6.5a4.95 4.95 0 0 0-7 7"}],["path",{d:"M15 5 5 15"}],["path",{d:"M14 17v.01"}],["path",{d:"M10 16v.01"}],["path",{d:"M13 13v.01"}],["path",{d:"M16 10v.01"}],["path",{d:"M11 20v.01"}],["path",{d:"M17 14v.01"}],["path",{d:"M20 11v.01"}]]],Ss=["svg",h,[["path",{d:"m15 15 6 6m-6-6v4.8m0-4.8h4.8"}],["path",{d:"M9 19.8V15m0 0H4.2M9 15l-6 6"}],["path",{d:"M15 4.2V9m0 0h4.8M15 9l6-6"}],["path",{d:"M9 4.2V9m0 0H4.2M9 9 3 3"}]]],Ls=["svg",h,[["path",{d:"M12 22v-7l-2-2"}],["path",{d:"M17 8v.8A6 6 0 0 1 13.8 20H10A6.5 6.5 0 0 1 7 8a5 5 0 0 1 10 0Z"}],["path",{d:"m14 14-2 2"}]]],fs=["svg",h,[["path",{d:"m18 14 4 4-4 4"}],["path",{d:"m18 2 4 4-4 4"}],["path",{d:"M2 18h1.973a4 4 0 0 0 3.3-1.7l5.454-8.6a4 4 0 0 1 3.3-1.7H22"}],["path",{d:"M2 6h1.972a4 4 0 0 1 3.6 2.2"}],["path",{d:"M22 18h-6.041a4 4 0 0 1-3.3-1.8l-.359-.45"}]]],Ps=["svg",h,[["path",{d:"M18 7V5a1 1 0 0 0-1-1H6.5a.5.5 0 0 0-.4.8l4.5 6a2 2 0 0 1 0 2.4l-4.5 6a.5.5 0 0 0 .4.8H17a1 1 0 0 0 1-1v-2"}]]],ks=["svg",h,[["path",{d:"M2 20h.01"}],["path",{d:"M7 20v-4"}],["path",{d:"M12 20v-8"}],["path",{d:"M17 20V8"}]]],Bs=["svg",h,[["path",{d:"M2 20h.01"}],["path",{d:"M7 20v-4"}]]],Fs=["svg",h,[["path",{d:"M2 20h.01"}],["path",{d:"M7 20v-4"}],["path",{d:"M12 20v-8"}]]],Ds=["svg",h,[["path",{d:"M2 20h.01"}]]],Rs=["svg",h,[["path",{d:"M2 20h.01"}],["path",{d:"M7 20v-4"}],["path",{d:"M12 20v-8"}],["path",{d:"M17 20V8"}],["path",{d:"M22 4v16"}]]],zs=["svg",h,[["path",{d:"m21 17-2.156-1.868A.5.5 0 0 0 18 15.5v.5a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1c0-2.545-3.991-3.97-8.5-4a1 1 0 0 0 0 5c4.153 0 4.745-11.295 5.708-13.5a2.5 2.5 0 1 1 3.31 3.284"}],["path",{d:"M3 21h18"}]]],qs=["svg",h,[["path",{d:"M10 9H4L2 7l2-2h6"}],["path",{d:"M14 5h6l2 2-2 2h-6"}],["path",{d:"M10 22V4a2 2 0 1 1 4 0v18"}],["path",{d:"M8 22h8"}]]],Ts=["svg",h,[["path",{d:"M12 13v8"}],["path",{d:"M12 3v3"}],["path",{d:"M18 6a2 2 0 0 1 1.387.56l2.307 2.22a1 1 0 0 1 0 1.44l-2.307 2.22A2 2 0 0 1 18 13H6a2 2 0 0 1-1.387-.56l-2.306-2.22a1 1 0 0 1 0-1.44l2.306-2.22A2 2 0 0 1 6 6z"}]]],Zs=["svg",h,[["path",{d:"M7 18v-6a5 5 0 1 1 10 0v6"}],["path",{d:"M5 21a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-1a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2z"}],["path",{d:"M21 12h1"}],["path",{d:"M18.5 4.5 18 5"}],["path",{d:"M2 12h1"}],["path",{d:"M12 2v1"}],["path",{d:"m4.929 4.929.707.707"}],["path",{d:"M12 12v6"}]]],bs=["svg",h,[["polygon",{points:"19 20 9 12 19 4 19 20"}],["line",{x1:"5",x2:"5",y1:"19",y2:"5"}]]],Us=["svg",h,[["polygon",{points:"5 4 15 12 5 20 5 4"}],["line",{x1:"19",x2:"19",y1:"5",y2:"19"}]]],Os=["svg",h,[["path",{d:"m12.5 17-.5-1-.5 1h1z"}],["path",{d:"M15 22a1 1 0 0 0 1-1v-1a2 2 0 0 0 1.56-3.25 8 8 0 1 0-11.12 0A2 2 0 0 0 8 20v1a1 1 0 0 0 1 1z"}],["circle",{cx:"15",cy:"12",r:"1"}],["circle",{cx:"9",cy:"12",r:"1"}]]],Gs=["svg",h,[["rect",{width:"3",height:"8",x:"13",y:"2",rx:"1.5"}],["path",{d:"M19 8.5V10h1.5A1.5 1.5 0 1 0 19 8.5"}],["rect",{width:"3",height:"8",x:"8",y:"14",rx:"1.5"}],["path",{d:"M5 15.5V14H3.5A1.5 1.5 0 1 0 5 15.5"}],["rect",{width:"8",height:"3",x:"14",y:"13",rx:"1.5"}],["path",{d:"M15.5 19H14v1.5a1.5 1.5 0 1 0 1.5-1.5"}],["rect",{width:"8",height:"3",x:"2",y:"8",rx:"1.5"}],["path",{d:"M8.5 5H10V3.5A1.5 1.5 0 1 0 8.5 5"}]]],Is=["svg",h,[["path",{d:"M22 2 2 22"}]]],Es=["svg",h,[["path",{d:"M11 16.586V19a1 1 0 0 1-1 1H2L18.37 3.63a1 1 0 1 1 3 3l-9.663 9.663a1 1 0 0 1-1.414 0L8 14"}]]],Ws=["svg",h,[["line",{x1:"21",x2:"14",y1:"4",y2:"4"}],["line",{x1:"10",x2:"3",y1:"4",y2:"4"}],["line",{x1:"21",x2:"12",y1:"12",y2:"12"}],["line",{x1:"8",x2:"3",y1:"12",y2:"12"}],["line",{x1:"21",x2:"16",y1:"20",y2:"20"}],["line",{x1:"12",x2:"3",y1:"20",y2:"20"}],["line",{x1:"14",x2:"14",y1:"2",y2:"6"}],["line",{x1:"8",x2:"8",y1:"10",y2:"14"}],["line",{x1:"16",x2:"16",y1:"18",y2:"22"}]]],L2=["svg",h,[["line",{x1:"4",x2:"4",y1:"21",y2:"14"}],["line",{x1:"4",x2:"4",y1:"10",y2:"3"}],["line",{x1:"12",x2:"12",y1:"21",y2:"12"}],["line",{x1:"12",x2:"12",y1:"8",y2:"3"}],["line",{x1:"20",x2:"20",y1:"21",y2:"16"}],["line",{x1:"20",x2:"20",y1:"12",y2:"3"}],["line",{x1:"2",x2:"6",y1:"14",y2:"14"}],["line",{x1:"10",x2:"14",y1:"8",y2:"8"}],["line",{x1:"18",x2:"22",y1:"16",y2:"16"}]]],xs=["svg",h,[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2",ry:"2"}],["path",{d:"M12.667 8 10 12h4l-2.667 4"}]]],Xs=["svg",h,[["rect",{width:"7",height:"12",x:"2",y:"6",rx:"1"}],["path",{d:"M13 8.32a7.43 7.43 0 0 1 0 7.36"}],["path",{d:"M16.46 6.21a11.76 11.76 0 0 1 0 11.58"}],["path",{d:"M19.91 4.1a15.91 15.91 0 0 1 .01 15.8"}]]],Ns=["svg",h,[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2",ry:"2"}],["path",{d:"M12 18h.01"}]]],Ks=["svg",h,[["path",{d:"M22 11v1a10 10 0 1 1-9-10"}],["path",{d:"M8 14s1.5 2 4 2 4-2 4-2"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9"}],["path",{d:"M16 5h6"}],["path",{d:"M19 2v6"}]]],Js=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M8 14s1.5 2 4 2 4-2 4-2"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9"}]]],Qs=["svg",h,[["path",{d:"M2 13a6 6 0 1 0 12 0 4 4 0 1 0-8 0 2 2 0 0 0 4 0"}],["circle",{cx:"10",cy:"13",r:"8"}],["path",{d:"M2 21h12c4.4 0 8-3.6 8-8V7a2 2 0 1 0-4 0v6"}],["path",{d:"M18 3 19.1 5.2"}],["path",{d:"M22 3 20.9 5.2"}]]],js=["svg",h,[["path",{d:"m10 20-1.25-2.5L6 18"}],["path",{d:"M10 4 8.75 6.5 6 6"}],["path",{d:"m14 20 1.25-2.5L18 18"}],["path",{d:"m14 4 1.25 2.5L18 6"}],["path",{d:"m17 21-3-6h-4"}],["path",{d:"m17 3-3 6 1.5 3"}],["path",{d:"M2 12h6.5L10 9"}],["path",{d:"m20 10-1.5 2 1.5 2"}],["path",{d:"M22 12h-6.5L14 15"}],["path",{d:"m4 10 1.5 2L4 14"}],["path",{d:"m7 21 3-6-1.5-3"}],["path",{d:"m7 3 3 6h4"}]]],Ys=["svg",h,[["path",{d:"M20 9V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v3"}],["path",{d:"M2 16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5a2 2 0 0 0-4 0v1.5a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5V11a2 2 0 0 0-4 0z"}],["path",{d:"M4 18v2"}],["path",{d:"M20 18v2"}],["path",{d:"M12 4v9"}]]],_s=["svg",h,[["path",{d:"M12 21a9 9 0 0 0 9-9H3a9 9 0 0 0 9 9Z"}],["path",{d:"M7 21h10"}],["path",{d:"M19.5 12 22 6"}],["path",{d:"M16.25 3c.27.1.8.53.75 1.36-.06.83-.93 1.2-1 2.02-.05.78.34 1.24.73 1.62"}],["path",{d:"M11.25 3c.27.1.8.53.74 1.36-.05.83-.93 1.2-.98 2.02-.06.78.33 1.24.72 1.62"}],["path",{d:"M6.25 3c.27.1.8.53.75 1.36-.06.83-.93 1.2-1 2.02-.05.78.34 1.24.74 1.62"}]]],ar=["svg",h,[["path",{d:"M22 17v1c0 .5-.5 1-1 1H3c-.5 0-1-.5-1-1v-1"}]]],hr=["svg",h,[["path",{d:"M5 9c-1.5 1.5-3 3.2-3 5.5A5.5 5.5 0 0 0 7.5 20c1.8 0 3-.5 4.5-2 1.5 1.5 2.7 2 4.5 2a5.5 5.5 0 0 0 5.5-5.5c0-2.3-1.5-4-3-5.5l-7-7-7 7Z"}],["path",{d:"M12 18v4"}]]],tr=["svg",h,[["path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"}]]],f2=["svg",h,[["path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"}],["path",{d:"M20 3v4"}],["path",{d:"M22 5h-4"}],["path",{d:"M4 17v2"}],["path",{d:"M5 18H3"}]]],dr=["svg",h,[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2"}],["path",{d:"M12 6h.01"}],["circle",{cx:"12",cy:"14",r:"4"}],["path",{d:"M12 14h.01"}]]],cr=["svg",h,[["path",{d:"M8.8 20v-4.1l1.9.2a2.3 2.3 0 0 0 2.164-2.1V8.3A5.37 5.37 0 0 0 2 8.25c0 2.8.656 3.054 1 4.55a5.77 5.77 0 0 1 .029 2.758L2 20"}],["path",{d:"M19.8 17.8a7.5 7.5 0 0 0 .003-10.603"}],["path",{d:"M17 15a3.5 3.5 0 0 0-.025-4.975"}]]],Mr=["svg",h,[["path",{d:"m6 16 6-12 6 12"}],["path",{d:"M8 12h8"}],["path",{d:"M4 21c1.1 0 1.1-1 2.3-1s1.1 1 2.3 1c1.1 0 1.1-1 2.3-1 1.1 0 1.1 1 2.3 1 1.1 0 1.1-1 2.3-1 1.1 0 1.1 1 2.3 1 1.1 0 1.1-1 2.3-1"}]]],pr=["svg",h,[["path",{d:"m6 16 6-12 6 12"}],["path",{d:"M8 12h8"}],["path",{d:"m16 20 2 2 4-4"}]]],er=["svg",h,[["circle",{cx:"19",cy:"5",r:"2"}],["circle",{cx:"5",cy:"19",r:"2"}],["path",{d:"M5 17A12 12 0 0 1 17 5"}]]],nr=["svg",h,[["path",{d:"M16 3h5v5"}],["path",{d:"M8 3H3v5"}],["path",{d:"M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3"}],["path",{d:"m15 9 6-6"}]]],ir=["svg",h,[["path",{d:"M3 3h.01"}],["path",{d:"M7 5h.01"}],["path",{d:"M11 7h.01"}],["path",{d:"M3 7h.01"}],["path",{d:"M7 9h.01"}],["path",{d:"M3 11h.01"}],["rect",{width:"4",height:"4",x:"15",y:"5"}],["path",{d:"m19 9 2 2v10c0 .6-.4 1-1 1h-6c-.6 0-1-.4-1-1V11l2-2"}],["path",{d:"m13 14 8-2"}],["path",{d:"m13 19 8-2"}]]],lr=["svg",h,[["path",{d:"M7 20h10"}],["path",{d:"M10 20c5.5-2.5.8-6.4 3-10"}],["path",{d:"M9.5 9.4c1.1.8 1.8 2.2 2.3 3.7-2 .4-3.5.4-4.8-.3-1.2-.6-2.3-1.9-3-4.2 2.8-.5 4.4 0 5.5.8z"}],["path",{d:"M14.1 6a7 7 0 0 0-1.1 4c1.9-.1 3.3-.6 4.3-1.4 1-1 1.6-2.3 1.7-4.6-2.7.1-4 1-4.9 2z"}]]],P2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M17 12h-2l-2 5-2-10-2 5H7"}]]],k2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m16 8-8 8"}],["path",{d:"M16 16H8V8"}]]],B2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m8 8 8 8"}],["path",{d:"M16 8v8H8"}]]],F2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M12 8v8"}],["path",{d:"m8 12 4 4 4-4"}]]],D2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m12 8-4 4 4 4"}],["path",{d:"M16 12H8"}]]],R2=["svg",h,[["path",{d:"M13 21h6a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v6"}],["path",{d:"m3 21 9-9"}],["path",{d:"M9 21H3v-6"}]]],z2=["svg",h,[["path",{d:"M21 11V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6"}],["path",{d:"m21 21-9-9"}],["path",{d:"M21 15v6h-6"}]]],q2=["svg",h,[["path",{d:"M13 3h6a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-6"}],["path",{d:"m3 3 9 9"}],["path",{d:"M3 9V3h6"}]]],T2=["svg",h,[["path",{d:"M21 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h6"}],["path",{d:"m21 3-9 9"}],["path",{d:"M15 3h6v6"}]]],Z2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 12h8"}],["path",{d:"m12 16 4-4-4-4"}]]],b2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 16V8h8"}],["path",{d:"M16 16 8 8"}]]],U2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 8h8v8"}],["path",{d:"m8 16 8-8"}]]],O2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m16 12-4-4-4 4"}],["path",{d:"M12 16V8"}]]],G2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M12 8v8"}],["path",{d:"m8.5 14 7-4"}],["path",{d:"m8.5 10 7 4"}]]],I2=["svg",h,[["path",{d:"M4 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2"}],["path",{d:"M10 22H8"}],["path",{d:"M16 22h-2"}],["circle",{cx:"8",cy:"8",r:"2"}],["path",{d:"M9.414 9.414 12 12"}],["path",{d:"M14.8 14.8 18 18"}],["circle",{cx:"8",cy:"16",r:"2"}],["path",{d:"m18 6-8.586 8.586"}]]],l=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 8h7"}],["path",{d:"M8 12h6"}],["path",{d:"M11 16h5"}]]],E2=["svg",h,[["path",{d:"M21 10.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h12.5"}],["path",{d:"m9 11 3 3L22 4"}]]],W2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m9 12 2 2 4-4"}]]],x2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m16 10-4 4-4-4"}]]],X2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m14 16-4-4 4-4"}]]],N2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m10 8 4 4-4 4"}]]],K2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m8 14 4-4 4 4"}]]],J2=["svg",h,[["path",{d:"M10 9.5 8 12l2 2.5"}],["path",{d:"m14 9.5 2 2.5-2 2.5"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]],vr=["svg",h,[["path",{d:"M10 9.5 8 12l2 2.5"}],["path",{d:"M14 21h1"}],["path",{d:"m14 9.5 2 2.5-2 2.5"}],["path",{d:"M5 21a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2"}],["path",{d:"M9 21h1"}]]],or=["svg",h,[["path",{d:"M5 21a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2"}],["path",{d:"M9 21h1"}],["path",{d:"M14 21h1"}]]],Q2=["svg",h,[["path",{d:"M8 7v7"}],["path",{d:"M12 7v4"}],["path",{d:"M16 7v9"}],["path",{d:"M5 3a2 2 0 0 0-2 2"}],["path",{d:"M9 3h1"}],["path",{d:"M14 3h1"}],["path",{d:"M19 3a2 2 0 0 1 2 2"}],["path",{d:"M21 9v1"}],["path",{d:"M21 14v1"}],["path",{d:"M21 19a2 2 0 0 1-2 2"}],["path",{d:"M14 21h1"}],["path",{d:"M9 21h1"}],["path",{d:"M5 21a2 2 0 0 1-2-2"}],["path",{d:"M3 14v1"}],["path",{d:"M3 9v1"}]]],j2=["svg",h,[["path",{d:"M12.034 12.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.943l-3.444 1.068a1 1 0 0 0-.66.66l-1.067 3.443a.5.5 0 0 1-.943.033z"}],["path",{d:"M5 3a2 2 0 0 0-2 2"}],["path",{d:"M19 3a2 2 0 0 1 2 2"}],["path",{d:"M5 21a2 2 0 0 1-2-2"}],["path",{d:"M9 3h1"}],["path",{d:"M9 21h2"}],["path",{d:"M14 3h1"}],["path",{d:"M3 9v1"}],["path",{d:"M21 9v2"}],["path",{d:"M3 14v1"}]]],Y2=["svg",h,[["path",{d:"M5 3a2 2 0 0 0-2 2"}],["path",{d:"M19 3a2 2 0 0 1 2 2"}],["path",{d:"M21 19a2 2 0 0 1-2 2"}],["path",{d:"M5 21a2 2 0 0 1-2-2"}],["path",{d:"M9 3h1"}],["path",{d:"M9 21h1"}],["path",{d:"M14 3h1"}],["path",{d:"M14 21h1"}],["path",{d:"M3 9v1"}],["path",{d:"M21 9v1"}],["path",{d:"M3 14v1"}],["path",{d:"M21 14v1"}]]],_2=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"16",y2:"16"}],["line",{x1:"12",x2:"12",y1:"8",y2:"8"}]]],a0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["circle",{cx:"12",cy:"12",r:"1"}]]],h0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 10h10"}],["path",{d:"M7 14h10"}]]],t0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M9 17c2 0 2.8-1 2.8-2.8V10c0-2 1-3.3 3.2-3"}],["path",{d:"M9 11.2h5.7"}]]],d0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 7v7"}],["path",{d:"M12 7v4"}],["path",{d:"M16 7v9"}]]],c0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 7v10"}],["path",{d:"M11 7v10"}],["path",{d:"m15 7 2 10"}]]],M0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 16V8l4 4 4-4v8"}]]],p0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 8h10"}],["path",{d:"M7 12h10"}],["path",{d:"M7 16h10"}]]],e0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 12h8"}]]],n0=["svg",h,[["path",{d:"M12.034 12.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.943l-3.444 1.068a1 1 0 0 0-.66.66l-1.067 3.443a.5.5 0 0 1-.943.033z"}],["path",{d:"M21 11V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6"}]]],i0=["svg",h,[["path",{d:"M3.6 3.6A2 2 0 0 1 5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-.59 1.41"}],["path",{d:"M3 8.7V19a2 2 0 0 0 2 2h10.3"}],["path",{d:"m2 2 20 20"}],["path",{d:"M13 13a3 3 0 1 0 0-6H9v2"}],["path",{d:"M9 17v-2.3"}]]],l0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 17V7h4a3 3 0 0 1 0 6H9"}]]],e=["svg",h,[["path",{d:"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"}],["path",{d:"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z"}]]],v0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m15 9-6 6"}],["path",{d:"M9 9h.01"}],["path",{d:"M15 15h.01"}]]],o0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 7h10"}],["path",{d:"M10 7v10"}],["path",{d:"M16 17a2 2 0 0 1-2-2V7"}]]],s0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M12 12H9.5a2.5 2.5 0 0 1 0-5H17"}],["path",{d:"M12 7v10"}],["path",{d:"M16 7v10"}]]],r0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m9 8 6 4-6 4Z"}]]],g0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 12h8"}],["path",{d:"M12 8v8"}]]],y0=["svg",h,[["path",{d:"M12 7v4"}],["path",{d:"M7.998 9.003a5 5 0 1 0 8-.005"}],["rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}]]],sr=["svg",h,[["path",{d:"M7 12h2l2 5 2-10h4"}],["rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}]]],$0=["svg",h,[["rect",{width:"20",height:"20",x:"2",y:"2",rx:"2"}],["circle",{cx:"8",cy:"8",r:"2"}],["path",{d:"M9.414 9.414 12 12"}],["path",{d:"M14.8 14.8 18 18"}],["circle",{cx:"8",cy:"16",r:"2"}],["path",{d:"m18 6-8.586 8.586"}]]],m0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M16 8.9V7H8l4 5-4 5h8v-1.9"}]]],C0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["line",{x1:"9",x2:"15",y1:"15",y2:"9"}]]],u0=["svg",h,[["path",{d:"M8 19H5c-1 0-2-1-2-2V7c0-1 1-2 2-2h3"}],["path",{d:"M16 5h3c1 0 2 1 2 2v10c0 1-1 2-2 2h-3"}],["line",{x1:"12",x2:"12",y1:"4",y2:"20"}]]],H0=["svg",h,[["path",{d:"M5 8V5c0-1 1-2 2-2h10c1 0 2 1 2 2v3"}],["path",{d:"M19 16v3c0 1-1 2-2 2H7c-1 0-2-1-2-2v-3"}],["line",{x1:"4",x2:"20",y1:"12",y2:"12"}]]],rr=["svg",h,[["rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}],["rect",{x:"8",y:"8",width:"8",height:"8",rx:"1"}]]],gr=["svg",h,[["path",{d:"M4 10c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h4c1.1 0 2 .9 2 2"}],["path",{d:"M10 16c-1.1 0-2-.9-2-2v-4c0-1.1.9-2 2-2h4c1.1 0 2 .9 2 2"}],["rect",{width:"8",height:"8",x:"14",y:"14",rx:"2"}]]],w0=["svg",h,[["path",{d:"m7 11 2-2-2-2"}],["path",{d:"M11 13h4"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}]]],V0=["svg",h,[["path",{d:"M18 21a6 6 0 0 0-12 0"}],["circle",{cx:"12",cy:"11",r:"4"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]],A0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M7 21v-2a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v2"}]]],S0=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"m15 9-6 6"}],["path",{d:"m9 9 6 6"}]]],yr=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]],$r=["svg",h,[["path",{d:"M12 3c7.2 0 9 1.8 9 9s-1.8 9-9 9-9-1.8-9-9 1.8-9 9-9"}]]],mr=["svg",h,[["path",{d:"M15.236 22a3 3 0 0 0-2.2-5"}],["path",{d:"M16 20a3 3 0 0 1 3-3h1a2 2 0 0 0 2-2v-2a4 4 0 0 0-4-4V4"}],["path",{d:"M18 13h.01"}],["path",{d:"M18 6a4 4 0 0 0-4 4 7 7 0 0 0-7 7c0-5 4-5 4-10.5a4.5 4.5 0 1 0-9 0 2.5 2.5 0 0 0 5 0C7 10 3 11 3 17c0 2.8 2.2 5 5 5h10"}]]],Cr=["svg",h,[["path",{d:"M5 22h14"}],["path",{d:"M19.27 13.73A2.5 2.5 0 0 0 17.5 13h-11A2.5 2.5 0 0 0 4 15.5V17a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-1.5c0-.66-.26-1.3-.73-1.77Z"}],["path",{d:"M14 13V8.5C14 7 15 7 15 5a3 3 0 0 0-3-3c-1.66 0-3 1-3 3s1 2 1 3.5V13"}]]],ur=["svg",h,[["path",{d:"M12 18.338a2.1 2.1 0 0 0-.987.244L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.12 2.12 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.12 2.12 0 0 0 1.597-1.16l2.309-4.679A.53.53 0 0 1 12 2"}]]],Hr=["svg",h,[["path",{d:"M8.34 8.34 2 9.27l5 4.87L5.82 21 12 17.77 18.18 21l-.59-3.43"}],["path",{d:"M18.42 12.76 22 9.27l-6.91-1L12 2l-1.44 2.91"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],wr=["svg",h,[["path",{d:"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"}]]],Vr=["svg",h,[["line",{x1:"18",x2:"18",y1:"20",y2:"4"}],["polygon",{points:"14,20 4,12 14,4"}]]],Ar=["svg",h,[["line",{x1:"6",x2:"6",y1:"4",y2:"20"}],["polygon",{points:"10,4 20,12 10,20"}]]],Sr=["svg",h,[["path",{d:"M11 2v2"}],["path",{d:"M5 2v2"}],["path",{d:"M5 3H4a2 2 0 0 0-2 2v4a6 6 0 0 0 12 0V5a2 2 0 0 0-2-2h-1"}],["path",{d:"M8 15a6 6 0 0 0 12 0v-3"}],["circle",{cx:"20",cy:"10",r:"2"}]]],Lr=["svg",h,[["path",{d:"M15.5 3H5a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2V8.5L15.5 3Z"}],["path",{d:"M14 3v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 13h.01"}],["path",{d:"M16 13h.01"}],["path",{d:"M10 16s.8 1 2 1c1.3 0 2-1 2-1"}]]],fr=["svg",h,[["path",{d:"M16 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8Z"}],["path",{d:"M15 3v4a2 2 0 0 0 2 2h4"}]]],Pr=["svg",h,[["path",{d:"m2 7 4.41-4.41A2 2 0 0 1 7.83 2h8.34a2 2 0 0 1 1.42.59L22 7"}],["path",{d:"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"}],["path",{d:"M15 22v-4a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v4"}],["path",{d:"M2 7h20"}],["path",{d:"M22 7v3a2 2 0 0 1-2 2a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 16 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 12 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 8 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 4 12a2 2 0 0 1-2-2V7"}]]],kr=["svg",h,[["rect",{width:"20",height:"6",x:"2",y:"4",rx:"2"}],["rect",{width:"20",height:"6",x:"2",y:"14",rx:"2"}]]],Br=["svg",h,[["rect",{width:"6",height:"20",x:"4",y:"2",rx:"2"}],["rect",{width:"6",height:"20",x:"14",y:"2",rx:"2"}]]],Fr=["svg",h,[["path",{d:"M16 4H9a3 3 0 0 0-2.83 4"}],["path",{d:"M14 12a4 4 0 0 1 0 8H6"}],["line",{x1:"4",x2:"20",y1:"12",y2:"12"}]]],Dr=["svg",h,[["path",{d:"m4 5 8 8"}],["path",{d:"m12 5-8 8"}],["path",{d:"M20 19h-4c0-1.5.44-2 1.5-2.5S20 15.33 20 14c0-.47-.17-.93-.48-1.29a2.11 2.11 0 0 0-2.62-.44c-.42.24-.74.62-.9 1.07"}]]],Rr=["svg",h,[["circle",{cx:"12",cy:"12",r:"4"}],["path",{d:"M12 4h.01"}],["path",{d:"M20 12h.01"}],["path",{d:"M12 20h.01"}],["path",{d:"M4 12h.01"}],["path",{d:"M17.657 6.343h.01"}],["path",{d:"M17.657 17.657h.01"}],["path",{d:"M6.343 17.657h.01"}],["path",{d:"M6.343 6.343h.01"}]]],zr=["svg",h,[["circle",{cx:"12",cy:"12",r:"4"}],["path",{d:"M12 3v1"}],["path",{d:"M12 20v1"}],["path",{d:"M3 12h1"}],["path",{d:"M20 12h1"}],["path",{d:"m18.364 5.636-.707.707"}],["path",{d:"m6.343 17.657-.707.707"}],["path",{d:"m5.636 5.636.707.707"}],["path",{d:"m17.657 17.657.707.707"}]]],qr=["svg",h,[["path",{d:"M12 8a2.83 2.83 0 0 0 4 4 4 4 0 1 1-4-4"}],["path",{d:"M12 2v2"}],["path",{d:"M12 20v2"}],["path",{d:"m4.9 4.9 1.4 1.4"}],["path",{d:"m17.7 17.7 1.4 1.4"}],["path",{d:"M2 12h2"}],["path",{d:"M20 12h2"}],["path",{d:"m6.3 17.7-1.4 1.4"}],["path",{d:"m19.1 4.9-1.4 1.4"}]]],Tr=["svg",h,[["path",{d:"M10 21v-1"}],["path",{d:"M10 4V3"}],["path",{d:"M10 9a3 3 0 0 0 0 6"}],["path",{d:"m14 20 1.25-2.5L18 18"}],["path",{d:"m14 4 1.25 2.5L18 6"}],["path",{d:"m17 21-3-6 1.5-3H22"}],["path",{d:"m17 3-3 6 1.5 3"}],["path",{d:"M2 12h1"}],["path",{d:"m20 10-1.5 2 1.5 2"}],["path",{d:"m3.64 18.36.7-.7"}],["path",{d:"m4.34 6.34-.7-.7"}]]],Zr=["svg",h,[["circle",{cx:"12",cy:"12",r:"4"}],["path",{d:"M12 2v2"}],["path",{d:"M12 20v2"}],["path",{d:"m4.93 4.93 1.41 1.41"}],["path",{d:"m17.66 17.66 1.41 1.41"}],["path",{d:"M2 12h2"}],["path",{d:"M20 12h2"}],["path",{d:"m6.34 17.66-1.41 1.41"}],["path",{d:"m19.07 4.93-1.41 1.41"}]]],br=["svg",h,[["path",{d:"M12 2v8"}],["path",{d:"m4.93 10.93 1.41 1.41"}],["path",{d:"M2 18h2"}],["path",{d:"M20 18h2"}],["path",{d:"m19.07 10.93-1.41 1.41"}],["path",{d:"M22 22H2"}],["path",{d:"m8 6 4-4 4 4"}],["path",{d:"M16 18a4 4 0 0 0-8 0"}]]],Ur=["svg",h,[["path",{d:"M12 10V2"}],["path",{d:"m4.93 10.93 1.41 1.41"}],["path",{d:"M2 18h2"}],["path",{d:"M20 18h2"}],["path",{d:"m19.07 10.93-1.41 1.41"}],["path",{d:"M22 22H2"}],["path",{d:"m16 6-4 4-4-4"}],["path",{d:"M16 18a4 4 0 0 0-8 0"}]]],Or=["svg",h,[["path",{d:"m4 19 8-8"}],["path",{d:"m12 19-8-8"}],["path",{d:"M20 12h-4c0-1.5.442-2 1.5-2.5S20 8.334 20 7.002c0-.472-.17-.93-.484-1.29a2.105 2.105 0 0 0-2.617-.436c-.42.239-.738.614-.899 1.06"}]]],Gr=["svg",h,[["path",{d:"M11 17a4 4 0 0 1-8 0V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2Z"}],["path",{d:"M16.7 13H19a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H7"}],["path",{d:"M 7 17h.01"}],["path",{d:"m11 8 2.3-2.3a2.4 2.4 0 0 1 3.404.004L18.6 7.6a2.4 2.4 0 0 1 .026 3.434L9.9 19.8"}]]],Ir=["svg",h,[["path",{d:"M10 21V3h8"}],["path",{d:"M6 16h9"}],["path",{d:"M10 9.5h7"}]]],Er=["svg",h,[["path",{d:"M11 19H4a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h5"}],["path",{d:"M13 5h7a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-5"}],["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"m18 22-3-3 3-3"}],["path",{d:"m6 2 3 3-3 3"}]]],Wr=["svg",h,[["polyline",{points:"14.5 17.5 3 6 3 3 6 3 17.5 14.5"}],["line",{x1:"13",x2:"19",y1:"19",y2:"13"}],["line",{x1:"16",x2:"20",y1:"16",y2:"20"}],["line",{x1:"19",x2:"21",y1:"21",y2:"19"}]]],xr=["svg",h,[["polyline",{points:"14.5 17.5 3 6 3 3 6 3 17.5 14.5"}],["line",{x1:"13",x2:"19",y1:"19",y2:"13"}],["line",{x1:"16",x2:"20",y1:"16",y2:"20"}],["line",{x1:"19",x2:"21",y1:"21",y2:"19"}],["polyline",{points:"14.5 6.5 18 3 21 3 21 6 17.5 9.5"}],["line",{x1:"5",x2:"9",y1:"14",y2:"18"}],["line",{x1:"7",x2:"4",y1:"17",y2:"20"}],["line",{x1:"3",x2:"5",y1:"19",y2:"21"}]]],Xr=["svg",h,[["path",{d:"m18 2 4 4"}],["path",{d:"m17 7 3-3"}],["path",{d:"M19 9 8.7 19.3c-1 1-2.5 1-3.4 0l-.6-.6c-1-1-1-2.5 0-3.4L15 5"}],["path",{d:"m9 11 4 4"}],["path",{d:"m5 19-3 3"}],["path",{d:"m14 4 6 6"}]]],Nr=["svg",h,[["path",{d:"M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18"}]]],Kr=["svg",h,[["path",{d:"M12 21v-6"}],["path",{d:"M12 9V3"}],["path",{d:"M3 15h18"}],["path",{d:"M3 9h18"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]],Jr=["svg",h,[["path",{d:"M12 15V9"}],["path",{d:"M3 15h18"}],["path",{d:"M3 9h18"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]],Qr=["svg",h,[["path",{d:"M14 14v2"}],["path",{d:"M14 20v2"}],["path",{d:"M14 2v2"}],["path",{d:"M14 8v2"}],["path",{d:"M2 15h8"}],["path",{d:"M2 3h6a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H2"}],["path",{d:"M2 9h8"}],["path",{d:"M22 15h-4"}],["path",{d:"M22 3h-2a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h2"}],["path",{d:"M22 9h-4"}],["path",{d:"M5 3v18"}]]],jr=["svg",h,[["path",{d:"M16 12H3"}],["path",{d:"M16 18H3"}],["path",{d:"M16 6H3"}],["path",{d:"M21 12h.01"}],["path",{d:"M21 18h.01"}],["path",{d:"M21 6h.01"}]]],Yr=["svg",h,[["path",{d:"M15 3v18"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M21 9H3"}],["path",{d:"M21 15H3"}]]],_r=["svg",h,[["path",{d:"M14 10h2"}],["path",{d:"M15 22v-8"}],["path",{d:"M15 2v4"}],["path",{d:"M2 10h2"}],["path",{d:"M20 10h2"}],["path",{d:"M3 19h18"}],["path",{d:"M3 22v-6a2 2 135 0 1 2-2h14a2 2 45 0 1 2 2v6"}],["path",{d:"M3 2v2a2 2 45 0 0 2 2h14a2 2 135 0 0 2-2V2"}],["path",{d:"M8 10h2"}],["path",{d:"M9 22v-8"}],["path",{d:"M9 2v4"}]]],ag=["svg",h,[["path",{d:"M12 3v18"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}],["path",{d:"M3 15h18"}]]],hg=["svg",h,[["rect",{width:"10",height:"14",x:"3",y:"8",rx:"2"}],["path",{d:"M5 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2h-2.4"}],["path",{d:"M8 18h.01"}]]],tg=["svg",h,[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2",ry:"2"}],["line",{x1:"12",x2:"12.01",y1:"18",y2:"18"}]]],dg=["svg",h,[["circle",{cx:"7",cy:"7",r:"5"}],["circle",{cx:"17",cy:"17",r:"5"}],["path",{d:"M12 17h10"}],["path",{d:"m3.46 10.54 7.08-7.08"}]]],cg=["svg",h,[["path",{d:"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"}],["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor"}]]],Mg=["svg",h,[["path",{d:"m15 5 6.3 6.3a2.4 2.4 0 0 1 0 3.4L17 19"}],["path",{d:"M9.586 5.586A2 2 0 0 0 8.172 5H3a1 1 0 0 0-1 1v5.172a2 2 0 0 0 .586 1.414L8.29 18.29a2.426 2.426 0 0 0 3.42 0l3.58-3.58a2.426 2.426 0 0 0 0-3.42z"}],["circle",{cx:"6.5",cy:"9.5",r:".5",fill:"currentColor"}]]],pg=["svg",h,[["path",{d:"M4 4v16"}]]],eg=["svg",h,[["path",{d:"M4 4v16"}],["path",{d:"M9 4v16"}]]],ng=["svg",h,[["path",{d:"M4 4v16"}],["path",{d:"M9 4v16"}],["path",{d:"M14 4v16"}]]],ig=["svg",h,[["path",{d:"M4 4v16"}],["path",{d:"M9 4v16"}],["path",{d:"M14 4v16"}],["path",{d:"M19 4v16"}]]],lg=["svg",h,[["path",{d:"M4 4v16"}],["path",{d:"M9 4v16"}],["path",{d:"M14 4v16"}],["path",{d:"M19 4v16"}],["path",{d:"M22 6 2 18"}]]],vg=["svg",h,[["circle",{cx:"17",cy:"4",r:"2"}],["path",{d:"M15.59 5.41 5.41 15.59"}],["circle",{cx:"4",cy:"17",r:"2"}],["path",{d:"M12 22s-4-9-1.5-11.5S22 12 22 12"}]]],og=["svg",h,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"12",r:"6"}],["circle",{cx:"12",cy:"12",r:"2"}]]],sg=["svg",h,[["path",{d:"m10.065 12.493-6.18 1.318a.934.934 0 0 1-1.108-.702l-.537-2.15a1.07 1.07 0 0 1 .691-1.265l13.504-4.44"}],["path",{d:"m13.56 11.747 4.332-.924"}],["path",{d:"m16 21-3.105-6.21"}],["path",{d:"M16.485 5.94a2 2 0 0 1 1.455-2.425l1.09-.272a1 1 0 0 1 1.212.727l1.515 6.06a1 1 0 0 1-.727 1.213l-1.09.272a2 2 0 0 1-2.425-1.455z"}],["path",{d:"m6.158 8.633 1.114 4.456"}],["path",{d:"m8 21 3.105-6.21"}],["circle",{cx:"12",cy:"13",r:"2"}]]],rg=["svg",h,[["circle",{cx:"4",cy:"4",r:"2"}],["path",{d:"m14 5 3-3 3 3"}],["path",{d:"m14 10 3-3 3 3"}],["path",{d:"M17 14V2"}],["path",{d:"M17 14H7l-5 8h20Z"}],["path",{d:"M8 14v8"}],["path",{d:"m9 14 5 8"}]]],gg=["svg",h,[["path",{d:"M3.5 21 14 3"}],["path",{d:"M20.5 21 10 3"}],["path",{d:"M15.5 21 12 15l-3.5 6"}],["path",{d:"M2 21h20"}]]],yg=["svg",h,[["polyline",{points:"4 17 10 11 4 5"}],["line",{x1:"12",x2:"20",y1:"19",y2:"19"}]]],L0=["svg",h,[["path",{d:"M21 7 6.82 21.18a2.83 2.83 0 0 1-3.99-.01a2.83 2.83 0 0 1 0-4L17 3"}],["path",{d:"m16 2 6 6"}],["path",{d:"M12 16H4"}]]],$g=["svg",h,[["path",{d:"M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5c-1.4 0-2.5-1.1-2.5-2.5V2"}],["path",{d:"M8.5 2h7"}],["path",{d:"M14.5 16h-5"}]]],mg=["svg",h,[["path",{d:"M9 2v17.5A2.5 2.5 0 0 1 6.5 22A2.5 2.5 0 0 1 4 19.5V2"}],["path",{d:"M20 2v17.5a2.5 2.5 0 0 1-2.5 2.5a2.5 2.5 0 0 1-2.5-2.5V2"}],["path",{d:"M3 2h7"}],["path",{d:"M14 2h7"}],["path",{d:"M9 16H4"}],["path",{d:"M20 16h-5"}]]],Cg=["svg",h,[["path",{d:"M5 4h1a3 3 0 0 1 3 3 3 3 0 0 1 3-3h1"}],["path",{d:"M13 20h-1a3 3 0 0 1-3-3 3 3 0 0 1-3 3H5"}],["path",{d:"M5 16H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h1"}],["path",{d:"M13 8h7a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-7"}],["path",{d:"M9 7v10"}]]],ug=["svg",h,[["path",{d:"M17 22h-1a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4h1"}],["path",{d:"M7 22h1a4 4 0 0 0 4-4v-1"}],["path",{d:"M7 2h1a4 4 0 0 1 4 4v1"}]]],Hg=["svg",h,[["path",{d:"M17 6H3"}],["path",{d:"M21 12H8"}],["path",{d:"M21 18H8"}],["path",{d:"M3 12v6"}]]],wg=["svg",h,[["path",{d:"M21 6H3"}],["path",{d:"M10 12H3"}],["path",{d:"M10 18H3"}],["circle",{cx:"17",cy:"15",r:"3"}],["path",{d:"m21 19-1.9-1.9"}]]],f0=["svg",h,[["path",{d:"M5 3a2 2 0 0 0-2 2"}],["path",{d:"M19 3a2 2 0 0 1 2 2"}],["path",{d:"M21 19a2 2 0 0 1-2 2"}],["path",{d:"M5 21a2 2 0 0 1-2-2"}],["path",{d:"M9 3h1"}],["path",{d:"M9 21h1"}],["path",{d:"M14 3h1"}],["path",{d:"M14 21h1"}],["path",{d:"M3 9v1"}],["path",{d:"M21 9v1"}],["path",{d:"M3 14v1"}],["path",{d:"M21 14v1"}],["line",{x1:"7",x2:"15",y1:"8",y2:"8"}],["line",{x1:"7",x2:"17",y1:"12",y2:"12"}],["line",{x1:"7",x2:"13",y1:"16",y2:"16"}]]],Vg=["svg",h,[["path",{d:"M17 6.1H3"}],["path",{d:"M21 12.1H3"}],["path",{d:"M15.1 18H3"}]]],Ag=["svg",h,[["path",{d:"M2 10s3-3 3-8"}],["path",{d:"M22 10s-3-3-3-8"}],["path",{d:"M10 2c0 4.4-3.6 8-8 8"}],["path",{d:"M14 2c0 4.4 3.6 8 8 8"}],["path",{d:"M2 10s2 2 2 5"}],["path",{d:"M22 10s-2 2-2 5"}],["path",{d:"M8 15h8"}],["path",{d:"M2 22v-1a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1"}],["path",{d:"M14 22v-1a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1"}]]],Sg=["svg",h,[["path",{d:"m10 20-1.25-2.5L6 18"}],["path",{d:"M10 4 8.75 6.5 6 6"}],["path",{d:"M10.585 15H10"}],["path",{d:"M2 12h6.5L10 9"}],["path",{d:"M20 14.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0z"}],["path",{d:"m4 10 1.5 2L4 14"}],["path",{d:"m7 21 3-6-1.5-3"}],["path",{d:"m7 3 3 6h2"}]]],Lg=["svg",h,[["path",{d:"M12 9a4 4 0 0 0-2 7.5"}],["path",{d:"M12 3v2"}],["path",{d:"m6.6 18.4-1.4 1.4"}],["path",{d:"M20 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0Z"}],["path",{d:"M4 13H2"}],["path",{d:"M6.34 7.34 4.93 5.93"}]]],fg=["svg",h,[["path",{d:"M14 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0Z"}]]],Pg=["svg",h,[["path",{d:"M17 14V2"}],["path",{d:"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z"}]]],kg=["svg",h,[["path",{d:"M7 10v12"}],["path",{d:"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z"}]]],Bg=["svg",h,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"m9 12 2 2 4-4"}]]],Fg=["svg",h,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"M9 12h6"}]]],Dg=["svg",h,[["path",{d:"M2 9a3 3 0 1 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 1 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"M9 9h.01"}],["path",{d:"m15 9-6 6"}],["path",{d:"M15 15h.01"}]]],Rg=["svg",h,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"M9 12h6"}],["path",{d:"M12 9v6"}]]],zg=["svg",h,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"m9.5 14.5 5-5"}]]],qg=["svg",h,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"m9.5 14.5 5-5"}],["path",{d:"m9.5 9.5 5 5"}]]],Tg=["svg",h,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"M13 5v2"}],["path",{d:"M13 17v2"}],["path",{d:"M13 11v2"}]]],Zg=["svg",h,[["path",{d:"M10.5 17h1.227a2 2 0 0 0 1.345-.52L18 12"}],["path",{d:"m12 13.5 3.75.5"}],["path",{d:"m4.5 8 10.58-5.06a1 1 0 0 1 1.342.488L18.5 8"}],["path",{d:"M6 10V8"}],["path",{d:"M6 14v1"}],["path",{d:"M6 19v2"}],["rect",{x:"2",y:"8",width:"20",height:"13",rx:"2"}]]],bg=["svg",h,[["path",{d:"m4.5 8 10.58-5.06a1 1 0 0 1 1.342.488L18.5 8"}],["path",{d:"M6 10V8"}],["path",{d:"M6 14v1"}],["path",{d:"M6 19v2"}],["rect",{x:"2",y:"8",width:"20",height:"13",rx:"2"}]]],Ug=["svg",h,[["path",{d:"M10 2h4"}],["path",{d:"M4.6 11a8 8 0 0 0 1.7 8.7 8 8 0 0 0 8.7 1.7"}],["path",{d:"M7.4 7.4a8 8 0 0 1 10.3 1 8 8 0 0 1 .9 10.2"}],["path",{d:"m2 2 20 20"}],["path",{d:"M12 12v-2"}]]],Og=["svg",h,[["path",{d:"M10 2h4"}],["path",{d:"M12 14v-4"}],["path",{d:"M4 13a8 8 0 0 1 8-7 8 8 0 1 1-5.3 14L4 17.6"}],["path",{d:"M9 17H4v5"}]]],Gg=["svg",h,[["line",{x1:"10",x2:"14",y1:"2",y2:"2"}],["line",{x1:"12",x2:"15",y1:"14",y2:"11"}],["circle",{cx:"12",cy:"14",r:"8"}]]],Ig=["svg",h,[["rect",{width:"20",height:"12",x:"2",y:"6",rx:"6",ry:"6"}],["circle",{cx:"8",cy:"12",r:"2"}]]],Eg=["svg",h,[["rect",{width:"20",height:"12",x:"2",y:"6",rx:"6",ry:"6"}],["circle",{cx:"16",cy:"12",r:"2"}]]],Wg=["svg",h,[["path",{d:"M7 12h13a1 1 0 0 1 1 1 5 5 0 0 1-5 5h-.598a.5.5 0 0 0-.424.765l1.544 2.47a.5.5 0 0 1-.424.765H5.402a.5.5 0 0 1-.424-.765L7 18"}],["path",{d:"M8 18a5 5 0 0 1-5-5V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8"}]]],xg=["svg",h,[["path",{d:"M21 4H3"}],["path",{d:"M18 8H6"}],["path",{d:"M19 12H9"}],["path",{d:"M16 16h-6"}],["path",{d:"M11 20H9"}]]],Xg=["svg",h,[["ellipse",{cx:"12",cy:"11",rx:"3",ry:"2"}],["ellipse",{cx:"12",cy:"12.5",rx:"10",ry:"8.5"}]]],Ng=["svg",h,[["path",{d:"M4 4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16"}],["path",{d:"M2 14h12"}],["path",{d:"M22 14h-2"}],["path",{d:"M12 20v-6"}],["path",{d:"m2 2 20 20"}],["path",{d:"M22 16V6a2 2 0 0 0-2-2H10"}]]],Kg=["svg",h,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M2 14h20"}],["path",{d:"M12 20v-6"}]]],Jg=["svg",h,[["path",{d:"M18.2 12.27 20 6H4l1.8 6.27a1 1 0 0 0 .95.73h10.5a1 1 0 0 0 .96-.73Z"}],["path",{d:"M8 13v9"}],["path",{d:"M16 22v-9"}],["path",{d:"m9 6 1 7"}],["path",{d:"m15 6-1 7"}],["path",{d:"M12 6V2"}],["path",{d:"M13 2h-2"}]]],Qg=["svg",h,[["rect",{width:"18",height:"12",x:"3",y:"8",rx:"1"}],["path",{d:"M10 8V5c0-.6-.4-1-1-1H6a1 1 0 0 0-1 1v3"}],["path",{d:"M19 8V5c0-.6-.4-1-1-1h-3a1 1 0 0 0-1 1v3"}]]],jg=["svg",h,[["path",{d:"m10 11 11 .9a1 1 0 0 1 .8 1.1l-.665 4.158a1 1 0 0 1-.988.842H20"}],["path",{d:"M16 18h-5"}],["path",{d:"M18 5a1 1 0 0 0-1 1v5.573"}],["path",{d:"M3 4h8.129a1 1 0 0 1 .99.863L13 11.246"}],["path",{d:"M4 11V4"}],["path",{d:"M7 15h.01"}],["path",{d:"M8 10.1V4"}],["circle",{cx:"18",cy:"18",r:"2"}],["circle",{cx:"7",cy:"15",r:"5"}]]],Yg=["svg",h,[["path",{d:"M9.3 6.2a4.55 4.55 0 0 0 5.4 0"}],["path",{d:"M7.9 10.7c.9.8 2.4 1.3 4.1 1.3s3.2-.5 4.1-1.3"}],["path",{d:"M13.9 3.5a1.93 1.93 0 0 0-3.8-.1l-3 10c-.1.2-.1.4-.1.6 0 1.7 2.2 3 5 3s5-1.3 5-3c0-.2 0-.4-.1-.5Z"}],["path",{d:"m7.5 12.2-4.7 2.7c-.5.3-.8.7-.8 1.1s.3.8.8 1.1l7.6 4.5c.9.5 2.1.5 3 0l7.6-4.5c.7-.3 1-.7 1-1.1s-.3-.8-.8-1.1l-4.7-2.8"}]]],_g=["svg",h,[["path",{d:"M2 22V12a10 10 0 1 1 20 0v10"}],["path",{d:"M15 6.8v1.4a3 2.8 0 1 1-6 0V6.8"}],["path",{d:"M10 15h.01"}],["path",{d:"M14 15h.01"}],["path",{d:"M10 19a4 4 0 0 1-4-4v-3a6 6 0 1 1 12 0v3a4 4 0 0 1-4 4Z"}],["path",{d:"m9 19-2 3"}],["path",{d:"m15 19 2 3"}]]],ay=["svg",h,[["path",{d:"M8 3.1V7a4 4 0 0 0 8 0V3.1"}],["path",{d:"m9 15-1-1"}],["path",{d:"m15 15 1-1"}],["path",{d:"M9 19c-2.8 0-5-2.2-5-5v-4a8 8 0 0 1 16 0v4c0 2.8-2.2 5-5 5Z"}],["path",{d:"m8 19-2 3"}],["path",{d:"m16 19 2 3"}]]],hy=["svg",h,[["path",{d:"M2 17 17 2"}],["path",{d:"m2 14 8 8"}],["path",{d:"m5 11 8 8"}],["path",{d:"m8 8 8 8"}],["path",{d:"m11 5 8 8"}],["path",{d:"m14 2 8 8"}],["path",{d:"M7 22 22 7"}]]],P0=["svg",h,[["rect",{width:"16",height:"16",x:"4",y:"3",rx:"2"}],["path",{d:"M4 11h16"}],["path",{d:"M12 3v8"}],["path",{d:"m8 19-2 3"}],["path",{d:"m18 22-2-3"}],["path",{d:"M8 15h.01"}],["path",{d:"M16 15h.01"}]]],ty=["svg",h,[["path",{d:"M3 6h18"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17"}]]],dy=["svg",h,[["path",{d:"M3 6h18"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"}]]],cy=["svg",h,[["path",{d:"M8 19a4 4 0 0 1-2.24-7.32A3.5 3.5 0 0 1 9 6.03V6a3 3 0 1 1 6 0v.04a3.5 3.5 0 0 1 3.24 5.65A4 4 0 0 1 16 19Z"}],["path",{d:"M12 19v3"}]]],k0=["svg",h,[["path",{d:"M13 8c0-2.76-2.46-5-5.5-5S2 5.24 2 8h2l1-1 1 1h4"}],["path",{d:"M13 7.14A5.82 5.82 0 0 1 16.5 6c3.04 0 5.5 2.24 5.5 5h-3l-1-1-1 1h-3"}],["path",{d:"M5.89 9.71c-2.15 2.15-2.3 5.47-.35 7.43l4.24-4.25.7-.7.71-.71 2.12-2.12c-1.95-1.96-5.27-1.8-7.42.35"}],["path",{d:"M11 15.5c.5 2.5-.17 4.5-1 6.5h4c2-5.5-.5-12-1-14"}]]],My=["svg",h,[["path",{d:"m17 14 3 3.3a1 1 0 0 1-.7 1.7H4.7a1 1 0 0 1-.7-1.7L7 14h-.3a1 1 0 0 1-.7-1.7L9 9h-.2A1 1 0 0 1 8 7.3L12 3l4 4.3a1 1 0 0 1-.8 1.7H15l3 3.3a1 1 0 0 1-.7 1.7H17Z"}],["path",{d:"M12 22v-3"}]]],py=["svg",h,[["path",{d:"M10 10v.2A3 3 0 0 1 8.9 16H5a3 3 0 0 1-1-5.8V10a3 3 0 0 1 6 0Z"}],["path",{d:"M7 16v6"}],["path",{d:"M13 19v3"}],["path",{d:"M12 19h8.3a1 1 0 0 0 .7-1.7L18 14h.3a1 1 0 0 0 .7-1.7L16 9h.2a1 1 0 0 0 .8-1.7L13 3l-1.4 1.5"}]]],ey=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["rect",{width:"3",height:"9",x:"7",y:"7"}],["rect",{width:"3",height:"5",x:"14",y:"7"}]]],ny=["svg",h,[["polyline",{points:"22 17 13.5 8.5 8.5 13.5 2 7"}],["polyline",{points:"16 17 22 17 22 11"}]]],iy=["svg",h,[["path",{d:"M14.828 14.828 21 21"}],["path",{d:"M21 16v5h-5"}],["path",{d:"m21 3-9 9-4-4-6 6"}],["path",{d:"M21 8V3h-5"}]]],ly=["svg",h,[["polyline",{points:"22 7 13.5 15.5 8.5 10.5 2 17"}],["polyline",{points:"16 7 22 7 22 13"}]]],B0=["svg",h,[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"}],["path",{d:"M12 9v4"}],["path",{d:"M12 17h.01"}]]],vy=["svg",h,[["path",{d:"M10.17 4.193a2 2 0 0 1 3.666.013"}],["path",{d:"M14 21h2"}],["path",{d:"m15.874 7.743 1 1.732"}],["path",{d:"m18.849 12.952 1 1.732"}],["path",{d:"M21.824 18.18a2 2 0 0 1-1.835 2.824"}],["path",{d:"M4.024 21a2 2 0 0 1-1.839-2.839"}],["path",{d:"m5.136 12.952-1 1.732"}],["path",{d:"M8 21h2"}],["path",{d:"m8.102 7.743-1 1.732"}]]],oy=["svg",h,[["path",{d:"M22 18a2 2 0 0 1-2 2H3c-1.1 0-1.3-.6-.4-1.3L20.4 4.3c.9-.7 1.6-.4 1.6.7Z"}]]],sy=["svg",h,[["path",{d:"M13.73 4a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"}]]],ry=["svg",h,[["path",{d:"M6 9H4.5a2.5 2.5 0 0 1 0-5H6"}],["path",{d:"M18 9h1.5a2.5 2.5 0 0 0 0-5H18"}],["path",{d:"M4 22h16"}],["path",{d:"M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22"}],["path",{d:"M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22"}],["path",{d:"M18 2H6v7a6 6 0 0 0 12 0V2Z"}]]],gy=["svg",h,[["path",{d:"M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2"}],["path",{d:"M15 18H9"}],["path",{d:"M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14"}],["circle",{cx:"17",cy:"18",r:"2"}],["circle",{cx:"7",cy:"18",r:"2"}]]],yy=["svg",h,[["path",{d:"m12 10 2 4v3a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-3a8 8 0 1 0-16 0v3a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-3l2-4h4Z"}],["path",{d:"M4.82 7.9 8 10"}],["path",{d:"M15.18 7.9 12 10"}],["path",{d:"M16.93 10H20a2 2 0 0 1 0 4H2"}]]],$y=["svg",h,[["path",{d:"M10 7.75a.75.75 0 0 1 1.142-.638l3.664 2.249a.75.75 0 0 1 0 1.278l-3.664 2.25a.75.75 0 0 1-1.142-.64z"}],["path",{d:"M7 21h10"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}]]],F0=["svg",h,[["path",{d:"M7 21h10"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}]]],my=["svg",h,[["rect",{width:"20",height:"15",x:"2",y:"7",rx:"2",ry:"2"}],["polyline",{points:"17 2 12 7 7 2"}]]],Cy=["svg",h,[["path",{d:"M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7"}]]],uy=["svg",h,[["path",{d:"M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"}]]],Hy=["svg",h,[["path",{d:"M14 16.5a.5.5 0 0 0 .5.5h.5a2 2 0 0 1 0 4H9a2 2 0 0 1 0-4h.5a.5.5 0 0 0 .5-.5v-9a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5V8a2 2 0 0 1-4 0V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v3a2 2 0 0 1-4 0v-.5a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5Z"}]]],wy=["svg",h,[["polyline",{points:"4 7 4 4 20 4 20 7"}],["line",{x1:"9",x2:"15",y1:"20",y2:"20"}],["line",{x1:"12",x2:"12",y1:"4",y2:"20"}]]],Vy=["svg",h,[["path",{d:"M12 2v1"}],["path",{d:"M15.5 21a1.85 1.85 0 0 1-3.5-1v-8H2a10 10 0 0 1 3.428-6.575"}],["path",{d:"M17.5 12H22A10 10 0 0 0 9.004 3.455"}],["path",{d:"m2 2 20 20"}]]],Ay=["svg",h,[["path",{d:"M22 12a10.06 10.06 1 0 0-20 0Z"}],["path",{d:"M12 12v8a2 2 0 0 0 4 0"}],["path",{d:"M12 2v1"}]]],Sy=["svg",h,[["path",{d:"M6 4v6a6 6 0 0 0 12 0V4"}],["line",{x1:"4",x2:"20",y1:"20",y2:"20"}]]],Ly=["svg",h,[["path",{d:"M9 14 4 9l5-5"}],["path",{d:"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11"}]]],fy=["svg",h,[["path",{d:"M21 17a9 9 0 0 0-15-6.7L3 13"}],["path",{d:"M3 7v6h6"}],["circle",{cx:"12",cy:"17",r:"1"}]]],Py=["svg",h,[["path",{d:"M3 7v6h6"}],["path",{d:"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"}]]],ky=["svg",h,[["path",{d:"M16 12h6"}],["path",{d:"M8 12H2"}],["path",{d:"M12 2v2"}],["path",{d:"M12 8v2"}],["path",{d:"M12 14v2"}],["path",{d:"M12 20v2"}],["path",{d:"m19 15 3-3-3-3"}],["path",{d:"m5 9-3 3 3 3"}]]],By=["svg",h,[["path",{d:"M12 22v-6"}],["path",{d:"M12 8V2"}],["path",{d:"M4 12H2"}],["path",{d:"M10 12H8"}],["path",{d:"M16 12h-2"}],["path",{d:"M22 12h-2"}],["path",{d:"m15 19-3 3-3-3"}],["path",{d:"m15 5-3-3-3 3"}]]],Fy=["svg",h,[["rect",{width:"8",height:"6",x:"5",y:"4",rx:"1"}],["rect",{width:"8",height:"6",x:"11",y:"14",rx:"1"}]]],D0=["svg",h,[["circle",{cx:"12",cy:"10",r:"1"}],["path",{d:"M22 20V8h-4l-6-4-6 4H2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2"}],["path",{d:"M6 17v.01"}],["path",{d:"M6 13v.01"}],["path",{d:"M18 17v.01"}],["path",{d:"M18 13v.01"}],["path",{d:"M14 22v-5a2 2 0 0 0-2-2a2 2 0 0 0-2 2v5"}]]],Dy=["svg",h,[["path",{d:"M15 7h2a5 5 0 0 1 0 10h-2m-6 0H7A5 5 0 0 1 7 7h2"}]]],Ry=["svg",h,[["path",{d:"m18.84 12.25 1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71"}],["path",{d:"m5.17 11.75-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71"}],["line",{x1:"8",x2:"8",y1:"2",y2:"5"}],["line",{x1:"2",x2:"5",y1:"8",y2:"8"}],["line",{x1:"16",x2:"16",y1:"19",y2:"22"}],["line",{x1:"19",x2:"22",y1:"16",y2:"16"}]]],zy=["svg",h,[["path",{d:"m19 5 3-3"}],["path",{d:"m2 22 3-3"}],["path",{d:"M6.3 20.3a2.4 2.4 0 0 0 3.4 0L12 18l-6-6-2.3 2.3a2.4 2.4 0 0 0 0 3.4Z"}],["path",{d:"M7.5 13.5 10 11"}],["path",{d:"M10.5 16.5 13 14"}],["path",{d:"m12 6 6 6 2.3-2.3a2.4 2.4 0 0 0 0-3.4l-2.6-2.6a2.4 2.4 0 0 0-3.4 0Z"}]]],qy=["svg",h,[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"}],["polyline",{points:"17 8 12 3 7 8"}],["line",{x1:"12",x2:"12",y1:"3",y2:"15"}]]],Ty=["svg",h,[["circle",{cx:"10",cy:"7",r:"1"}],["circle",{cx:"4",cy:"20",r:"1"}],["path",{d:"M4.7 19.3 19 5"}],["path",{d:"m21 3-3 1 2 2Z"}],["path",{d:"M9.26 7.68 5 12l2 5"}],["path",{d:"m10 14 5 2 3.5-3.5"}],["path",{d:"m18 12 1-1 1 1-1 1Z"}]]],Zy=["svg",h,[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["circle",{cx:"9",cy:"7",r:"4"}],["polyline",{points:"16 11 18 13 22 9"}]]],by=["svg",h,[["circle",{cx:"18",cy:"15",r:"3"}],["circle",{cx:"9",cy:"7",r:"4"}],["path",{d:"M10 15H6a4 4 0 0 0-4 4v2"}],["path",{d:"m21.7 16.4-.9-.3"}],["path",{d:"m15.2 13.9-.9-.3"}],["path",{d:"m16.6 18.7.3-.9"}],["path",{d:"m19.1 12.2.3-.9"}],["path",{d:"m19.6 18.7-.4-1"}],["path",{d:"m16.8 12.3-.4-1"}],["path",{d:"m14.3 16.6 1-.4"}],["path",{d:"m20.7 13.8 1-.4"}]]],Uy=["svg",h,[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["circle",{cx:"9",cy:"7",r:"4"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11"}]]],Oy=["svg",h,[["path",{d:"M11.5 15H7a4 4 0 0 0-4 4v2"}],["path",{d:"M21.378 16.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}],["circle",{cx:"10",cy:"7",r:"4"}]]],Gy=["svg",h,[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["circle",{cx:"9",cy:"7",r:"4"}],["line",{x1:"19",x2:"19",y1:"8",y2:"14"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11"}]]],R0=["svg",h,[["path",{d:"M2 21a8 8 0 0 1 13.292-6"}],["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"m16 19 2 2 4-4"}]]],z0=["svg",h,[["path",{d:"M2 21a8 8 0 0 1 10.434-7.62"}],["circle",{cx:"10",cy:"8",r:"5"}],["circle",{cx:"18",cy:"18",r:"3"}],["path",{d:"m19.5 14.3-.4.9"}],["path",{d:"m16.9 20.8-.4.9"}],["path",{d:"m21.7 19.5-.9-.4"}],["path",{d:"m15.2 16.9-.9-.4"}],["path",{d:"m21.7 16.5-.9.4"}],["path",{d:"m15.2 19.1-.9.4"}],["path",{d:"m19.5 21.7-.4-.9"}],["path",{d:"m16.9 15.2-.4-.9"}]]],q0=["svg",h,[["path",{d:"M2 21a8 8 0 0 1 13.292-6"}],["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"M22 19h-6"}]]],Iy=["svg",h,[["path",{d:"M2 21a8 8 0 0 1 10.821-7.487"}],["path",{d:"M21.378 16.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}],["circle",{cx:"10",cy:"8",r:"5"}]]],T0=["svg",h,[["path",{d:"M2 21a8 8 0 0 1 13.292-6"}],["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"M19 16v6"}],["path",{d:"M22 19h-6"}]]],Ey=["svg",h,[["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"M2 21a8 8 0 0 1 10.434-7.62"}],["circle",{cx:"18",cy:"18",r:"3"}],["path",{d:"m22 22-1.9-1.9"}]]],Z0=["svg",h,[["path",{d:"M2 21a8 8 0 0 1 11.873-7"}],["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"m17 17 5 5"}],["path",{d:"m22 17-5 5"}]]],b0=["svg",h,[["circle",{cx:"12",cy:"8",r:"5"}],["path",{d:"M20 21a8 8 0 0 0-16 0"}]]],Wy=["svg",h,[["circle",{cx:"10",cy:"7",r:"4"}],["path",{d:"M10.3 15H7a4 4 0 0 0-4 4v2"}],["circle",{cx:"17",cy:"17",r:"3"}],["path",{d:"m21 21-1.9-1.9"}]]],xy=["svg",h,[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["circle",{cx:"9",cy:"7",r:"4"}],["line",{x1:"17",x2:"22",y1:"8",y2:"13"}],["line",{x1:"22",x2:"17",y1:"8",y2:"13"}]]],Xy=["svg",h,[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"}],["circle",{cx:"12",cy:"7",r:"4"}]]],U0=["svg",h,[["path",{d:"M18 21a8 8 0 0 0-16 0"}],["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"M22 20c0-3.37-2-6.5-4-8a5 5 0 0 0-.45-8.3"}]]],Ny=["svg",h,[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["circle",{cx:"9",cy:"7",r:"4"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87"}],["path",{d:"M16 3.13a4 4 0 0 1 0 7.75"}]]],O0=["svg",h,[["path",{d:"m16 2-2.3 2.3a3 3 0 0 0 0 4.2l1.8 1.8a3 3 0 0 0 4.2 0L22 8"}],["path",{d:"M15 15 3.3 3.3a4.2 4.2 0 0 0 0 6l7.3 7.3c.7.7 2 .7 2.8 0L15 15Zm0 0 7 7"}],["path",{d:"m2.1 21.8 6.4-6.3"}],["path",{d:"m19 5-7 7"}]]],G0=["svg",h,[["path",{d:"M3 2v7c0 1.1.9 2 2 2h4a2 2 0 0 0 2-2V2"}],["path",{d:"M7 2v20"}],["path",{d:"M21 15V2a5 5 0 0 0-5 5v6c0 1.1.9 2 2 2h3Zm0 0v7"}]]],Ky=["svg",h,[["path",{d:"M12 2v20"}],["path",{d:"M2 5h20"}],["path",{d:"M3 3v2"}],["path",{d:"M7 3v2"}],["path",{d:"M17 3v2"}],["path",{d:"M21 3v2"}],["path",{d:"m19 5-7 7-7-7"}]]],Jy=["svg",h,[["path",{d:"M8 21s-4-3-4-9 4-9 4-9"}],["path",{d:"M16 3s4 3 4 9-4 9-4 9"}],["line",{x1:"15",x2:"9",y1:"9",y2:"15"}],["line",{x1:"9",x2:"15",y1:"9",y2:"15"}]]],Qy=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor"}],["path",{d:"m7.9 7.9 2.7 2.7"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor"}],["path",{d:"m13.4 10.6 2.7-2.7"}],["circle",{cx:"7.5",cy:"16.5",r:".5",fill:"currentColor"}],["path",{d:"m7.9 16.1 2.7-2.7"}],["circle",{cx:"16.5",cy:"16.5",r:".5",fill:"currentColor"}],["path",{d:"m13.4 13.4 2.7 2.7"}],["circle",{cx:"12",cy:"12",r:"2"}]]],jy=["svg",h,[["path",{d:"M16 8q6 0 6-6-6 0-6 6"}],["path",{d:"M17.41 3.59a10 10 0 1 0 3 3"}],["path",{d:"M2 2a26.6 26.6 0 0 1 10 20c.9-6.82 1.5-9.5 4-14"}]]],Yy=["svg",h,[["path",{d:"M18 11c-1.5 0-2.5.5-3 2"}],["path",{d:"M4 6a2 2 0 0 0-2 2v4a5 5 0 0 0 5 5 8 8 0 0 1 5 2 8 8 0 0 1 5-2 5 5 0 0 0 5-5V8a2 2 0 0 0-2-2h-3a8 8 0 0 0-5 2 8 8 0 0 0-5-2z"}],["path",{d:"M6 11c1.5 0 2.5.5 3 2"}]]],_y=["svg",h,[["path",{d:"m2 8 2 2-2 2 2 2-2 2"}],["path",{d:"m22 8-2 2 2 2-2 2 2 2"}],["path",{d:"M8 8v10c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2"}],["path",{d:"M16 10.34V6c0-.55-.45-1-1-1h-4.34"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],a$=["svg",h,[["path",{d:"m2 8 2 2-2 2 2 2-2 2"}],["path",{d:"m22 8-2 2 2 2-2 2 2 2"}],["rect",{width:"8",height:"14",x:"8",y:"5",rx:"1"}]]],h$=["svg",h,[["path",{d:"M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196"}],["path",{d:"M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2"}],["path",{d:"m2 2 20 20"}]]],t$=["svg",h,[["path",{d:"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5"}],["rect",{x:"2",y:"6",width:"14",height:"12",rx:"2"}]]],d$=["svg",h,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M2 8h20"}],["circle",{cx:"8",cy:"14",r:"2"}],["path",{d:"M8 12h8"}],["circle",{cx:"16",cy:"14",r:"2"}]]],c$=["svg",h,[["path",{d:"M21 17v2a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-2"}],["path",{d:"M21 7V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v2"}],["circle",{cx:"12",cy:"12",r:"1"}],["path",{d:"M18.944 12.33a1 1 0 0 0 0-.66 7.5 7.5 0 0 0-13.888 0 1 1 0 0 0 0 .66 7.5 7.5 0 0 0 13.888 0"}]]],M$=["svg",h,[["circle",{cx:"6",cy:"12",r:"4"}],["circle",{cx:"18",cy:"12",r:"4"}],["line",{x1:"6",x2:"18",y1:"16",y2:"16"}]]],p$=["svg",h,[["path",{d:"M11.1 7.1a16.55 16.55 0 0 1 10.9 4"}],["path",{d:"M12 12a12.6 12.6 0 0 1-8.7 5"}],["path",{d:"M16.8 13.6a16.55 16.55 0 0 1-9 7.5"}],["path",{d:"M20.7 17a12.8 12.8 0 0 0-8.7-5 13.3 13.3 0 0 1 0-10"}],["path",{d:"M6.3 3.8a16.55 16.55 0 0 0 1.9 11.5"}],["circle",{cx:"12",cy:"12",r:"10"}]]],e$=["svg",h,[["path",{d:"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"}],["path",{d:"M16 9a5 5 0 0 1 0 6"}]]],n$=["svg",h,[["path",{d:"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"}],["path",{d:"M16 9a5 5 0 0 1 0 6"}],["path",{d:"M19.364 18.364a9 9 0 0 0 0-12.728"}]]],i$=["svg",h,[["path",{d:"M16 9a5 5 0 0 1 .95 2.293"}],["path",{d:"M19.364 5.636a9 9 0 0 1 1.889 9.96"}],["path",{d:"m2 2 20 20"}],["path",{d:"m7 7-.587.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298V11"}],["path",{d:"M9.828 4.172A.686.686 0 0 1 11 4.657v.686"}]]],l$=["svg",h,[["path",{d:"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"}],["line",{x1:"22",x2:"16",y1:"9",y2:"15"}],["line",{x1:"16",x2:"22",y1:"9",y2:"15"}]]],v$=["svg",h,[["path",{d:"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"}]]],o$=["svg",h,[["path",{d:"m9 12 2 2 4-4"}],["path",{d:"M5 7c0-1.1.9-2 2-2h10a2 2 0 0 1 2 2v12H5V7Z"}],["path",{d:"M22 19H2"}]]],s$=["svg",h,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2"}],["path",{d:"M3 11h3c.8 0 1.6.3 2.1.9l1.1.9c1.6 1.6 4.1 1.6 5.7 0l1.1-.9c.5-.5 1.3-.9 2.1-.9H21"}]]],I0=["svg",h,[["path",{d:"M17 14h.01"}],["path",{d:"M7 7h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14"}]]],r$=["svg",h,[["path",{d:"M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1"}],["path",{d:"M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4"}]]],g$=["svg",h,[["circle",{cx:"8",cy:"9",r:"2"}],["path",{d:"m9 17 6.1-6.1a2 2 0 0 1 2.81.01L22 15V5a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2"}],["path",{d:"M8 21h8"}],["path",{d:"M12 17v4"}]]],E0=["svg",h,[["path",{d:"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72"}],["path",{d:"m14 7 3 3"}],["path",{d:"M5 6v4"}],["path",{d:"M19 14v4"}],["path",{d:"M10 2v2"}],["path",{d:"M7 8H3"}],["path",{d:"M21 16h-4"}],["path",{d:"M11 3H9"}]]],y$=["svg",h,[["path",{d:"M15 4V2"}],["path",{d:"M15 16v-2"}],["path",{d:"M8 9h2"}],["path",{d:"M20 9h2"}],["path",{d:"M17.8 11.8 19 13"}],["path",{d:"M15 9h.01"}],["path",{d:"M17.8 6.2 19 5"}],["path",{d:"m3 21 9-9"}],["path",{d:"M12.2 6.2 11 5"}]]],$$=["svg",h,[["path",{d:"M22 8.35V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8.35A2 2 0 0 1 3.26 6.5l8-3.2a2 2 0 0 1 1.48 0l8 3.2A2 2 0 0 1 22 8.35Z"}],["path",{d:"M6 18h12"}],["path",{d:"M6 14h12"}],["rect",{width:"12",height:"12",x:"6",y:"10"}]]],m$=["svg",h,[["path",{d:"M3 6h3"}],["path",{d:"M17 6h.01"}],["rect",{width:"18",height:"20",x:"3",y:"2",rx:"2"}],["circle",{cx:"12",cy:"13",r:"5"}],["path",{d:"M12 18a2.5 2.5 0 0 0 0-5 2.5 2.5 0 0 1 0-5"}]]],C$=["svg",h,[["circle",{cx:"12",cy:"12",r:"6"}],["polyline",{points:"12 10 12 12 13 13"}],["path",{d:"m16.13 7.66-.81-4.05a2 2 0 0 0-2-1.61h-2.68a2 2 0 0 0-2 1.61l-.78 4.05"}],["path",{d:"m7.88 16.36.8 4a2 2 0 0 0 2 1.61h2.72a2 2 0 0 0 2-1.61l.81-4.05"}]]],u$=["svg",h,[["path",{d:"M19 5a2 2 0 0 0-2 2v11"}],["path",{d:"M2 18c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}],["path",{d:"M7 13h10"}],["path",{d:"M7 9h10"}],["path",{d:"M9 5a2 2 0 0 0-2 2v11"}]]],H$=["svg",h,[["path",{d:"M2 6c.6.5 1.2 1 2.5 1C7 7 7 5 9.5 5c2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}],["path",{d:"M2 12c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}],["path",{d:"M2 18c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}]]],w$=["svg",h,[["circle",{cx:"12",cy:"4.5",r:"2.5"}],["path",{d:"m10.2 6.3-3.9 3.9"}],["circle",{cx:"4.5",cy:"12",r:"2.5"}],["path",{d:"M7 12h10"}],["circle",{cx:"19.5",cy:"12",r:"2.5"}],["path",{d:"m13.8 17.7 3.9-3.9"}],["circle",{cx:"12",cy:"19.5",r:"2.5"}]]],V$=["svg",h,[["circle",{cx:"12",cy:"10",r:"8"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M7 22h10"}],["path",{d:"M12 22v-4"}]]],A$=["svg",h,[["path",{d:"M17 17h-5c-1.09-.02-1.94.92-2.5 1.9A3 3 0 1 1 2.57 15"}],["path",{d:"M9 3.4a4 4 0 0 1 6.52.66"}],["path",{d:"m6 17 3.1-5.8a2.5 2.5 0 0 0 .057-2.05"}],["path",{d:"M20.3 20.3a4 4 0 0 1-2.3.7"}],["path",{d:"M18.6 13a4 4 0 0 1 3.357 3.414"}],["path",{d:"m12 6 .6 1"}],["path",{d:"m2 2 20 20"}]]],S$=["svg",h,[["path",{d:"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2"}],["path",{d:"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06"}],["path",{d:"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8"}]]],L$=["svg",h,[["circle",{cx:"12",cy:"5",r:"3"}],["path",{d:"M6.5 8a2 2 0 0 0-1.905 1.46L2.1 18.5A2 2 0 0 0 4 21h16a2 2 0 0 0 1.925-2.54L19.4 9.5A2 2 0 0 0 17.48 8Z"}]]],f$=["svg",h,[["path",{d:"m2 22 10-10"}],["path",{d:"m16 8-1.17 1.17"}],["path",{d:"M3.47 12.53 5 11l1.53 1.53a3.5 3.5 0 0 1 0 4.94L5 19l-1.53-1.53a3.5 3.5 0 0 1 0-4.94Z"}],["path",{d:"m8 8-.53.53a3.5 3.5 0 0 0 0 4.94L9 15l1.53-1.53c.55-.55.88-1.25.98-1.97"}],["path",{d:"M10.91 5.26c.15-.26.34-.51.56-.73L13 3l1.53 1.53a3.5 3.5 0 0 1 .28 4.62"}],["path",{d:"M20 2h2v2a4 4 0 0 1-4 4h-2V6a4 4 0 0 1 4-4Z"}],["path",{d:"M11.47 17.47 13 19l-1.53 1.53a3.5 3.5 0 0 1-4.94 0L5 19l1.53-1.53a3.5 3.5 0 0 1 4.94 0Z"}],["path",{d:"m16 16-.53.53a3.5 3.5 0 0 1-4.94 0L9 15l1.53-1.53a3.49 3.49 0 0 1 1.97-.98"}],["path",{d:"M18.74 13.09c.26-.15.51-.34.73-.56L21 11l-1.53-1.53a3.5 3.5 0 0 0-4.62-.28"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],P$=["svg",h,[["path",{d:"M2 22 16 8"}],["path",{d:"M3.47 12.53 5 11l1.53 1.53a3.5 3.5 0 0 1 0 4.94L5 19l-1.53-1.53a3.5 3.5 0 0 1 0-4.94Z"}],["path",{d:"M7.47 8.53 9 7l1.53 1.53a3.5 3.5 0 0 1 0 4.94L9 15l-1.53-1.53a3.5 3.5 0 0 1 0-4.94Z"}],["path",{d:"M11.47 4.53 13 3l1.53 1.53a3.5 3.5 0 0 1 0 4.94L13 11l-1.53-1.53a3.5 3.5 0 0 1 0-4.94Z"}],["path",{d:"M20 2h2v2a4 4 0 0 1-4 4h-2V6a4 4 0 0 1 4-4Z"}],["path",{d:"M11.47 17.47 13 19l-1.53 1.53a3.5 3.5 0 0 1-4.94 0L5 19l1.53-1.53a3.5 3.5 0 0 1 4.94 0Z"}],["path",{d:"M15.47 13.47 17 15l-1.53 1.53a3.5 3.5 0 0 1-4.94 0L9 15l1.53-1.53a3.5 3.5 0 0 1 4.94 0Z"}],["path",{d:"M19.47 9.47 21 11l-1.53 1.53a3.5 3.5 0 0 1-4.94 0L13 11l1.53-1.53a3.5 3.5 0 0 1 4.94 0Z"}]]],k$=["svg",h,[["circle",{cx:"7",cy:"12",r:"3"}],["path",{d:"M10 9v6"}],["circle",{cx:"17",cy:"12",r:"3"}],["path",{d:"M14 7v8"}],["path",{d:"M22 17v1c0 .5-.5 1-1 1H3c-.5 0-1-.5-1-1v-1"}]]],B$=["svg",h,[["path",{d:"M12 20h.01"}],["path",{d:"M5 12.859a10 10 0 0 1 14 0"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0"}]]],F$=["svg",h,[["path",{d:"M12 20h.01"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0"}]]],D$=["svg",h,[["path",{d:"M12 20h.01"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0"}],["path",{d:"M5 12.859a10 10 0 0 1 5.17-2.69"}],["path",{d:"M19 12.859a10 10 0 0 0-2.007-1.523"}],["path",{d:"M2 8.82a15 15 0 0 1 4.177-2.643"}],["path",{d:"M22 8.82a15 15 0 0 0-11.288-3.764"}],["path",{d:"m2 2 20 20"}]]],R$=["svg",h,[["path",{d:"M12 20h.01"}]]],z$=["svg",h,[["path",{d:"M12 20h.01"}],["path",{d:"M2 8.82a15 15 0 0 1 20 0"}],["path",{d:"M5 12.859a10 10 0 0 1 14 0"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0"}]]],q$=["svg",h,[["path",{d:"M10 2v8"}],["path",{d:"M12.8 21.6A2 2 0 1 0 14 18H2"}],["path",{d:"M17.5 10a2.5 2.5 0 1 1 2 4H2"}],["path",{d:"m6 6 4 4 4-4"}]]],T$=["svg",h,[["path",{d:"M12.8 19.6A2 2 0 1 0 14 16H2"}],["path",{d:"M17.5 8a2.5 2.5 0 1 1 2 4H2"}],["path",{d:"M9.8 4.4A2 2 0 1 1 11 8H2"}]]],Z$=["svg",h,[["path",{d:"M8 22h8"}],["path",{d:"M7 10h3m7 0h-1.343"}],["path",{d:"M12 15v7"}],["path",{d:"M7.307 7.307A12.33 12.33 0 0 0 7 10a5 5 0 0 0 7.391 4.391M8.638 2.981C8.75 2.668 8.872 2.34 9 2h6c1.5 4 2 6 2 8 0 .407-.05.809-.145 1.198"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]],b$=["svg",h,[["path",{d:"M8 22h8"}],["path",{d:"M7 10h10"}],["path",{d:"M12 15v7"}],["path",{d:"M12 15a5 5 0 0 0 5-5c0-2-.5-4-2-8H9c-1.5 4-2 6-2 8a5 5 0 0 0 5 5Z"}]]],U$=["svg",h,[["rect",{width:"8",height:"8",x:"3",y:"3",rx:"2"}],["path",{d:"M7 11v4a2 2 0 0 0 2 2h4"}],["rect",{width:"8",height:"8",x:"13",y:"13",rx:"2"}]]],O$=["svg",h,[["path",{d:"m19 12-1.5 3"}],["path",{d:"M19.63 18.81 22 20"}],["path",{d:"M6.47 8.23a1.68 1.68 0 0 1 2.44 1.93l-.64 2.08a6.76 6.76 0 0 0 10.16 7.67l.42-.27a1 1 0 1 0-2.73-4.21l-.42.27a1.76 1.76 0 0 1-2.63-1.99l.64-2.08A6.66 6.66 0 0 0 3.94 3.9l-.7.4a1 1 0 1 0 2.55 4.34z"}]]],G$=["svg",h,[["line",{x1:"3",x2:"21",y1:"6",y2:"6"}],["path",{d:"M3 12h15a3 3 0 1 1 0 6h-4"}],["polyline",{points:"16 16 14 18 16 20"}],["line",{x1:"3",x2:"10",y1:"18",y2:"18"}]]],I$=["svg",h,[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"}]]],E$=["svg",h,[["path",{d:"M18 6 6 18"}],["path",{d:"m6 6 12 12"}]]],W$=["svg",h,[["path",{d:"M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17"}],["path",{d:"m10 15 5-3-5-3z"}]]],x$=["svg",h,[["path",{d:"M10.513 4.856 13.12 2.17a.5.5 0 0 1 .86.46l-1.377 4.317"}],["path",{d:"M15.656 10H20a1 1 0 0 1 .78 1.63l-1.72 1.773"}],["path",{d:"M16.273 16.273 10.88 21.83a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14H4a1 1 0 0 1-.78-1.63l4.507-4.643"}],["path",{d:"m2 2 20 20"}]]],X$=["svg",h,[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"}]]],N$=["svg",h,[["circle",{cx:"11",cy:"11",r:"8"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65"}],["line",{x1:"11",x2:"11",y1:"8",y2:"14"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11"}]]],K$=["svg",h,[["circle",{cx:"11",cy:"11",r:"8"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11"}]]];var J$=Object.freeze({__proto__:null,AArrowDown:X0,AArrowUp:N0,ALargeSmall:K0,Accessibility:J0,Activity:Q0,ActivitySquare:P2,AirVent:j0,Airplay:Y0,AlarmCheck:o,AlarmClock:aa,AlarmClockCheck:o,AlarmClockMinus:s,AlarmClockOff:_0,AlarmClockPlus:r,AlarmMinus:s,AlarmPlus:r,AlarmSmoke:ha,Album:ta,AlertCircle:G,AlertOctagon:c2,AlertTriangle:B0,AlignCenter:Ma,AlignCenterHorizontal:da,AlignCenterVertical:ca,AlignEndHorizontal:pa,AlignEndVertical:ea,AlignHorizontalDistributeCenter:na,AlignHorizontalDistributeEnd:ia,AlignHorizontalDistributeStart:la,AlignHorizontalJustifyCenter:va,AlignHorizontalJustifyEnd:oa,AlignHorizontalJustifyStart:sa,AlignHorizontalSpaceAround:ra,AlignHorizontalSpaceBetween:ga,AlignJustify:ya,AlignLeft:$a,AlignRight:ma,AlignStartHorizontal:Ca,AlignStartVertical:ua,AlignVerticalDistributeCenter:Ha,AlignVerticalDistributeEnd:wa,AlignVerticalDistributeStart:Va,AlignVerticalJustifyCenter:Aa,AlignVerticalJustifyEnd:Sa,AlignVerticalJustifyStart:La,AlignVerticalSpaceAround:fa,AlignVerticalSpaceBetween:Pa,Ambulance:ka,Ampersand:Ba,Ampersands:Fa,Amphora:Da,Anchor:Ra,Angry:za,Annoyed:qa,Antenna:Ta,Anvil:Za,Aperture:ba,AppWindow:Oa,AppWindowMac:Ua,Apple:Ga,Archive:Wa,ArchiveRestore:Ia,ArchiveX:Ea,AreaChart:P,Armchair:xa,ArrowBigDown:Na,ArrowBigDownDash:Xa,ArrowBigLeft:Ja,ArrowBigLeftDash:Ka,ArrowBigRight:ja,ArrowBigRightDash:Qa,ArrowBigUp:_a,ArrowBigUpDash:Ya,ArrowDown:ih,ArrowDown01:ah,ArrowDown10:hh,ArrowDownAZ:g,ArrowDownAz:g,ArrowDownCircle:I,ArrowDownFromLine:th,ArrowDownLeft:dh,ArrowDownLeftFromCircle:W,ArrowDownLeftFromSquare:R2,ArrowDownLeftSquare:k2,ArrowDownNarrowWide:ch,ArrowDownRight:Mh,ArrowDownRightFromCircle:x,ArrowDownRightFromSquare:z2,ArrowDownRightSquare:B2,ArrowDownSquare:F2,ArrowDownToDot:ph,ArrowDownToLine:eh,ArrowDownUp:nh,ArrowDownWideNarrow:y,ArrowDownZA:$,ArrowDownZa:$,ArrowLeft:sh,ArrowLeftCircle:E,ArrowLeftFromLine:lh,ArrowLeftRight:vh,ArrowLeftSquare:D2,ArrowLeftToLine:oh,ArrowRight:$h,ArrowRightCircle:K,ArrowRightFromLine:rh,ArrowRightLeft:gh,ArrowRightSquare:Z2,ArrowRightToLine:yh,ArrowUp:fh,ArrowUp01:mh,ArrowUp10:Ch,ArrowUpAZ:m,ArrowUpAz:m,ArrowUpCircle:J,ArrowUpDown:uh,ArrowUpFromDot:Hh,ArrowUpFromLine:wh,ArrowUpLeft:Vh,ArrowUpLeftFromCircle:X,ArrowUpLeftFromSquare:q2,ArrowUpLeftSquare:b2,ArrowUpNarrowWide:C,ArrowUpRight:Ah,ArrowUpRightFromCircle:N,ArrowUpRightFromSquare:T2,ArrowUpRightSquare:U2,ArrowUpSquare:O2,ArrowUpToLine:Sh,ArrowUpWideNarrow:Lh,ArrowUpZA:u,ArrowUpZa:u,ArrowsUpFromLine:Ph,Asterisk:kh,AsteriskSquare:G2,AtSign:Bh,Atom:Fh,AudioLines:Dh,AudioWaveform:Rh,Award:zh,Axe:qh,Axis3D:H,Axis3d:H,Baby:Th,Backpack:Zh,Badge:_h,BadgeAlert:bh,BadgeCent:Uh,BadgeCheck:w,BadgeDollarSign:Oh,BadgeEuro:Gh,BadgeHelp:Ih,BadgeIndianRupee:Eh,BadgeInfo:Wh,BadgeJapaneseYen:xh,BadgeMinus:Xh,BadgePercent:Nh,BadgePlus:Kh,BadgePoundSterling:Jh,BadgeRussianRuble:Qh,BadgeSwissFranc:jh,BadgeX:Yh,BaggageClaim:at,Ban:ht,Banana:tt,Bandage:dt,Banknote:ct,BarChart:T,BarChart2:Z,BarChart3:z,BarChart4:R,BarChartBig:D,BarChartHorizontal:B,BarChartHorizontalBig:k,Barcode:Mt,Baseline:pt,Bath:et,Battery:rt,BatteryCharging:nt,BatteryFull:it,BatteryLow:lt,BatteryMedium:vt,BatteryPlus:ot,BatteryWarning:st,Beaker:gt,Bean:$t,BeanOff:yt,Bed:ut,BedDouble:mt,BedSingle:Ct,Beef:Ht,Beer:Vt,BeerOff:wt,Bell:Bt,BellDot:At,BellElectric:St,BellMinus:Lt,BellOff:ft,BellPlus:Pt,BellRing:kt,BetweenHorizonalEnd:V,BetweenHorizonalStart:A,BetweenHorizontalEnd:V,BetweenHorizontalStart:A,BetweenVerticalEnd:Ft,BetweenVerticalStart:Dt,BicepsFlexed:Rt,Bike:zt,Binary:qt,Binoculars:Tt,Biohazard:Zt,Bird:bt,Bitcoin:Ut,Blend:Ot,Blinds:Gt,Blocks:It,Bluetooth:Xt,BluetoothConnected:Et,BluetoothOff:Wt,BluetoothSearching:xt,Bold:Nt,Bolt:Kt,Bomb:Jt,Bone:Qt,Book:C4,BookA:jt,BookAudio:Yt,BookCheck:_t,BookCopy:a4,BookDashed:S,BookDown:h4,BookHeadphones:t4,BookHeart:d4,BookImage:c4,BookKey:M4,BookLock:p4,BookMarked:e4,BookMinus:n4,BookOpen:v4,BookOpenCheck:i4,BookOpenText:l4,BookPlus:o4,BookTemplate:S,BookText:s4,BookType:r4,BookUp:y4,BookUp2:g4,BookUser:$4,BookX:m4,Bookmark:A4,BookmarkCheck:u4,BookmarkMinus:H4,BookmarkPlus:w4,BookmarkX:V4,BoomBox:S4,Bot:P4,BotMessageSquare:L4,BotOff:f4,Box:k4,BoxSelect:Y2,Boxes:B4,Braces:L,Brackets:F4,Brain:z4,BrainCircuit:D4,BrainCog:R4,BrickWall:q4,Briefcase:U4,BriefcaseBusiness:T4,BriefcaseConveyorBelt:Z4,BriefcaseMedical:b4,BringToFront:O4,Brush:G4,Bug:W4,BugOff:I4,BugPlay:E4,Building:X4,Building2:x4,Bus:K4,BusFront:N4,Cable:Q4,CableCar:J4,Cake:Y4,CakeSlice:j4,Calculator:_4,Calendar:u5,Calendar1:a5,CalendarArrowDown:h5,CalendarArrowUp:t5,CalendarCheck:c5,CalendarCheck2:d5,CalendarClock:M5,CalendarCog:p5,CalendarDays:e5,CalendarFold:n5,CalendarHeart:i5,CalendarMinus:v5,CalendarMinus2:l5,CalendarOff:o5,CalendarPlus:r5,CalendarPlus2:s5,CalendarRange:g5,CalendarSearch:y5,CalendarSync:$5,CalendarX:C5,CalendarX2:m5,Camera:w5,CameraOff:H5,CandlestickChart:F,Candy:S5,CandyCane:V5,CandyOff:A5,Cannabis:L5,Captions:f,CaptionsOff:f5,Car:B5,CarFront:P5,CarTaxiFront:k5,Caravan:F5,Carrot:D5,CaseLower:R5,CaseSensitive:z5,CaseUpper:q5,CassetteTape:T5,Cast:Z5,Castle:b5,Cat:U5,Cctv:O5,ChartArea:P,ChartBar:B,ChartBarBig:k,ChartBarDecreasing:G5,ChartBarIncreasing:I5,ChartBarStacked:E5,ChartCandlestick:F,ChartColumn:z,ChartColumnBig:D,ChartColumnDecreasing:W5,ChartColumnIncreasing:R,ChartColumnStacked:x5,ChartGantt:X5,ChartLine:q,ChartNetwork:N5,ChartNoAxesColumn:Z,ChartNoAxesColumnDecreasing:K5,ChartNoAxesColumnIncreasing:T,ChartNoAxesCombined:J5,ChartNoAxesGantt:b,ChartPie:U,ChartScatter:O,ChartSpline:Q5,Check:Y5,CheckCheck:j5,CheckCircle:Q,CheckCircle2:j,CheckSquare:E2,CheckSquare2:W2,ChefHat:_5,Cherry:ad,ChevronDown:hd,ChevronDownCircle:Y,ChevronDownSquare:x2,ChevronFirst:td,ChevronLast:dd,ChevronLeft:cd,ChevronLeftCircle:_,ChevronLeftSquare:X2,ChevronRight:Md,ChevronRightCircle:a1,ChevronRightSquare:N2,ChevronUp:pd,ChevronUpCircle:h1,ChevronUpSquare:K2,ChevronsDown:nd,ChevronsDownUp:ed,ChevronsLeft:vd,ChevronsLeftRight:ld,ChevronsLeftRightEllipsis:id,ChevronsRight:sd,ChevronsRightLeft:od,ChevronsUp:gd,ChevronsUpDown:rd,Chrome:yd,Church:$d,Cigarette:Cd,CigaretteOff:md,Circle:Bd,CircleAlert:G,CircleArrowDown:I,CircleArrowLeft:E,CircleArrowOutDownLeft:W,CircleArrowOutDownRight:x,CircleArrowOutUpLeft:X,CircleArrowOutUpRight:N,CircleArrowRight:K,CircleArrowUp:J,CircleCheck:j,CircleCheckBig:Q,CircleChevronDown:Y,CircleChevronLeft:_,CircleChevronRight:a1,CircleChevronUp:h1,CircleDashed:ud,CircleDivide:t1,CircleDollarSign:Hd,CircleDot:Vd,CircleDotDashed:wd,CircleEllipsis:Ad,CircleEqual:Sd,CircleFadingArrowUp:Ld,CircleFadingPlus:fd,CircleGauge:d1,CircleHelp:c1,CircleMinus:M1,CircleOff:Pd,CircleParking:e1,CircleParkingOff:p1,CirclePause:n1,CirclePercent:i1,CirclePlay:l1,CirclePlus:v1,CirclePower:o1,CircleSlash:kd,CircleSlash2:s1,CircleSlashed:s1,CircleStop:r1,CircleUser:y1,CircleUserRound:g1,CircleX:$1,CircuitBoard:Fd,Citrus:Dd,Clapperboard:Rd,Clipboard:Id,ClipboardCheck:zd,ClipboardCopy:qd,ClipboardEdit:C1,ClipboardList:Td,ClipboardMinus:Zd,ClipboardPaste:bd,ClipboardPen:C1,ClipboardPenLine:m1,ClipboardPlus:Ud,ClipboardSignature:m1,ClipboardType:Od,ClipboardX:Gd,Clock:c3,Clock1:Ed,Clock10:Wd,Clock11:xd,Clock12:Xd,Clock2:Nd,Clock3:Kd,Clock4:Jd,Clock5:Qd,Clock6:jd,Clock7:Yd,Clock8:_d,Clock9:a3,ClockAlert:h3,ClockArrowDown:t3,ClockArrowUp:d3,Cloud:C3,CloudAlert:M3,CloudCog:p3,CloudDownload:u1,CloudDrizzle:e3,CloudFog:n3,CloudHail:i3,CloudLightning:l3,CloudMoon:o3,CloudMoonRain:v3,CloudOff:s3,CloudRain:g3,CloudRainWind:r3,CloudSnow:y3,CloudSun:m3,CloudSunRain:$3,CloudUpload:H1,Cloudy:u3,Clover:H3,Club:w3,Code:V3,Code2:w1,CodeSquare:J2,CodeXml:w1,Codepen:A3,Codesandbox:S3,Coffee:L3,Cog:f3,Coins:P3,Columns:V1,Columns2:V1,Columns3:A1,Columns4:k3,Combine:B3,Command:F3,Compass:D3,Component:R3,Computer:z3,ConciergeBell:q3,Cone:T3,Construction:Z3,Contact:b3,Contact2:S1,ContactRound:S1,Container:U3,Contrast:O3,Cookie:G3,CookingPot:I3,Copy:K3,CopyCheck:E3,CopyMinus:W3,CopyPlus:x3,CopySlash:X3,CopyX:N3,Copyleft:J3,Copyright:Q3,CornerDownLeft:j3,CornerDownRight:Y3,CornerLeftDown:_3,CornerLeftUp:a6,CornerRightDown:h6,CornerRightUp:t6,CornerUpLeft:d6,CornerUpRight:c6,Cpu:M6,CreativeCommons:p6,CreditCard:e6,Croissant:n6,Crop:i6,Cross:l6,Crosshair:v6,Crown:o6,Cuboid:s6,CupSoda:r6,CurlyBraces:L,Currency:g6,Cylinder:y6,Dam:$6,Database:u6,DatabaseBackup:m6,DatabaseZap:C6,Delete:H6,Dessert:w6,Diameter:V6,Diamond:L6,DiamondMinus:A6,DiamondPercent:L1,DiamondPlus:S6,Dice1:f6,Dice2:P6,Dice3:k6,Dice4:B6,Dice5:F6,Dice6:D6,Dices:R6,Diff:z6,Disc:b6,Disc2:q6,Disc3:T6,DiscAlbum:Z6,Divide:U6,DivideCircle:t1,DivideSquare:_2,Dna:G6,DnaOff:O6,Dock:I6,Dog:E6,DollarSign:W6,Donut:x6,DoorClosed:X6,DoorOpen:N6,Dot:K6,DotSquare:a0,Download:J6,DownloadCloud:u1,DraftingCompass:Q6,Drama:j6,Dribbble:Y6,Drill:_6,Droplet:hc,DropletOff:ac,Droplets:tc,Drum:dc,Drumstick:cc,Dumbbell:Mc,Ear:ec,EarOff:pc,Earth:f1,EarthLock:nc,Eclipse:ic,Edit:e,Edit2:$2,Edit3:y2,Egg:oc,EggFried:lc,EggOff:vc,Ellipsis:k1,EllipsisVertical:P1,Equal:gc,EqualApproximately:sc,EqualNot:rc,EqualSquare:h0,Eraser:yc,EthernetPort:$c,Euro:mc,Expand:Cc,ExternalLink:uc,Eye:Vc,EyeClosed:Hc,EyeOff:wc,Facebook:Ac,Factory:Sc,Fan:Lc,FastForward:fc,Feather:Pc,Fence:kc,FerrisWheel:Bc,Figma:Fc,File:P8,FileArchive:Dc,FileAudio:zc,FileAudio2:Rc,FileAxis3D:B1,FileAxis3d:B1,FileBadge:Tc,FileBadge2:qc,FileBarChart:F1,FileBarChart2:D1,FileBox:Zc,FileChartColumn:D1,FileChartColumnIncreasing:F1,FileChartLine:R1,FileChartPie:z1,FileCheck:Uc,FileCheck2:bc,FileClock:Oc,FileCode:Ic,FileCode2:Gc,FileCog:q1,FileCog2:q1,FileDiff:Ec,FileDigit:Wc,FileDown:xc,FileEdit:Z1,FileHeart:Xc,FileImage:Nc,FileInput:Kc,FileJson:Qc,FileJson2:Jc,FileKey:Yc,FileKey2:jc,FileLineChart:R1,FileLock:a8,FileLock2:_c,FileMinus:t8,FileMinus2:h8,FileMusic:d8,FileOutput:c8,FilePen:Z1,FilePenLine:T1,FilePieChart:z1,FilePlus:p8,FilePlus2:M8,FileQuestion:e8,FileScan:n8,FileSearch:l8,FileSearch2:i8,FileSignature:T1,FileSliders:v8,FileSpreadsheet:o8,FileStack:s8,FileSymlink:r8,FileTerminal:g8,FileText:y8,FileType:m8,FileType2:$8,FileUp:C8,FileUser:u8,FileVideo:w8,FileVideo2:H8,FileVolume:A8,FileVolume2:V8,FileWarning:S8,FileX:f8,FileX2:L8,Files:k8,Film:B8,Filter:D8,FilterX:F8,Fingerprint:R8,FireExtinguisher:z8,Fish:Z8,FishOff:q8,FishSymbol:T8,Flag:G8,FlagOff:b8,FlagTriangleLeft:U8,FlagTriangleRight:O8,Flame:E8,FlameKindling:I8,Flashlight:x8,FlashlightOff:W8,FlaskConical:N8,FlaskConicalOff:X8,FlaskRound:K8,FlipHorizontal:Q8,FlipHorizontal2:J8,FlipVertical:Y8,FlipVertical2:j8,Flower:a7,Flower2:_8,Focus:h7,FoldHorizontal:t7,FoldVertical:d7,Folder:F7,FolderArchive:c7,FolderCheck:M7,FolderClock:p7,FolderClosed:e7,FolderCode:n7,FolderCog:b1,FolderCog2:b1,FolderDot:i7,FolderDown:l7,FolderEdit:U1,FolderGit:o7,FolderGit2:v7,FolderHeart:s7,FolderInput:r7,FolderKanban:g7,FolderKey:y7,FolderLock:$7,FolderMinus:m7,FolderOpen:u7,FolderOpenDot:C7,FolderOutput:H7,FolderPen:U1,FolderPlus:w7,FolderRoot:V7,FolderSearch:S7,FolderSearch2:A7,FolderSymlink:L7,FolderSync:f7,FolderTree:P7,FolderUp:k7,FolderX:B7,Folders:D7,Footprints:R7,ForkKnife:G0,ForkKnifeCrossed:O0,Forklift:z7,FormInput:C2,Forward:q7,Frame:T7,Framer:Z7,Frown:b7,Fuel:U7,Fullscreen:O7,FunctionSquare:t0,GalleryHorizontal:I7,GalleryHorizontalEnd:G7,GalleryThumbnails:E7,GalleryVertical:x7,GalleryVerticalEnd:W7,Gamepad:N7,Gamepad2:X7,GanttChart:b,GanttChartSquare:l,Gauge:K7,GaugeCircle:d1,Gavel:J7,Gem:Q7,Ghost:j7,Gift:Y7,GitBranch:aM,GitBranchPlus:_7,GitCommit:O1,GitCommitHorizontal:O1,GitCommitVertical:hM,GitCompare:dM,GitCompareArrows:tM,GitFork:cM,GitGraph:MM,GitMerge:pM,GitPullRequest:oM,GitPullRequestArrow:eM,GitPullRequestClosed:nM,GitPullRequestCreate:lM,GitPullRequestCreateArrow:iM,GitPullRequestDraft:vM,Github:sM,Gitlab:rM,GlassWater:gM,Glasses:yM,Globe:mM,Globe2:f1,GlobeLock:$M,Goal:CM,Grab:uM,GraduationCap:HM,Grape:wM,Grid:i,Grid2X2:W1,Grid2X2Check:G1,Grid2X2Plus:I1,Grid2X2X:E1,Grid2x2:W1,Grid2x2Check:G1,Grid2x2Plus:I1,Grid2x2X:E1,Grid3X3:i,Grid3x3:i,Grip:SM,GripHorizontal:VM,GripVertical:AM,Group:LM,Guitar:fM,Ham:PM,Hammer:kM,Hand:zM,HandCoins:BM,HandHeart:FM,HandHelping:x1,HandMetal:DM,HandPlatter:RM,Handshake:qM,HardDrive:bM,HardDriveDownload:TM,HardDriveUpload:ZM,HardHat:UM,Hash:OM,Haze:GM,HdmiPort:IM,Heading:JM,Heading1:EM,Heading2:WM,Heading3:xM,Heading4:XM,Heading5:NM,Heading6:KM,HeadphoneOff:QM,Headphones:jM,Headset:YM,Heart:dp,HeartCrack:_M,HeartHandshake:ap,HeartOff:hp,HeartPulse:tp,Heater:cp,HelpCircle:c1,HelpingHand:x1,Hexagon:Mp,Highlighter:pp,History:ep,Home:X1,Hop:ip,HopOff:np,Hospital:lp,Hotel:vp,Hourglass:op,House:X1,HousePlug:sp,HousePlus:rp,HouseWifi:gp,IceCream:K1,IceCream2:N1,IceCreamBowl:N1,IceCreamCone:K1,IdCard:yp,Image:Ap,ImageDown:$p,ImageMinus:mp,ImageOff:Cp,ImagePlay:up,ImagePlus:Hp,ImageUp:wp,ImageUpscale:Vp,Images:Sp,Import:Lp,Inbox:fp,Indent:Q1,IndentDecrease:J1,IndentIncrease:Q1,IndianRupee:Pp,Infinity:kp,Info:Bp,Inspect:n0,InspectionPanel:Fp,Instagram:Dp,Italic:Rp,IterationCcw:zp,IterationCw:qp,JapaneseYen:Tp,Joystick:Zp,Kanban:bp,KanbanSquare:d0,KanbanSquareDashed:Q2,Key:Gp,KeyRound:Up,KeySquare:Op,Keyboard:Wp,KeyboardMusic:Ip,KeyboardOff:Ep,Lamp:Qp,LampCeiling:xp,LampDesk:Xp,LampFloor:Np,LampWallDown:Kp,LampWallUp:Jp,LandPlot:jp,Landmark:Yp,Languages:_p,Laptop:he,Laptop2:j1,LaptopMinimal:j1,LaptopMinimalCheck:ae,Lasso:de,LassoSelect:te,Laugh:ce,Layers:Y1,Layers2:Me,Layers3:Y1,Layout:g2,LayoutDashboard:pe,LayoutGrid:ee,LayoutList:ne,LayoutPanelLeft:ie,LayoutPanelTop:le,LayoutTemplate:ve,Leaf:oe,LeafyGreen:se,Lectern:re,LetterText:ge,Library:$e,LibraryBig:ye,LibrarySquare:c0,LifeBuoy:me,Ligature:Ce,Lightbulb:He,LightbulbOff:ue,LineChart:q,Link:Ae,Link2:Ve,Link2Off:we,Linkedin:Se,List:Ie,ListCheck:Le,ListChecks:fe,ListCollapse:Pe,ListEnd:ke,ListFilter:Fe,ListFilterPlus:Be,ListMinus:De,ListMusic:Re,ListOrdered:ze,ListPlus:qe,ListRestart:Te,ListStart:Ze,ListTodo:be,ListTree:Ue,ListVideo:Oe,ListX:Ge,Loader:We,Loader2:_1,LoaderCircle:_1,LoaderPinwheel:Ee,Locate:Ne,LocateFixed:xe,LocateOff:Xe,Lock:Je,LockKeyhole:Ke,LockKeyholeOpen:a2,LockOpen:h2,LogIn:Qe,LogOut:je,Logs:Ye,Lollipop:_e,Luggage:a9,MSquare:M0,Magnet:h9,Mail:l9,MailCheck:t9,MailMinus:d9,MailOpen:c9,MailPlus:M9,MailQuestion:p9,MailSearch:e9,MailWarning:n9,MailX:i9,Mailbox:v9,Mails:o9,Map:L9,MapPin:V9,MapPinCheck:r9,MapPinCheckInside:s9,MapPinHouse:g9,MapPinMinus:$9,MapPinMinusInside:y9,MapPinOff:m9,MapPinPlus:u9,MapPinPlusInside:C9,MapPinX:w9,MapPinXInside:H9,MapPinned:A9,MapPlus:S9,Martini:f9,Maximize:k9,Maximize2:P9,Medal:B9,Megaphone:D9,MegaphoneOff:F9,Meh:R9,MemoryStick:z9,Menu:q9,MenuSquare:p0,Merge:T9,MessageCircle:N9,MessageCircleCode:Z9,MessageCircleDashed:b9,MessageCircleHeart:U9,MessageCircleMore:O9,MessageCircleOff:G9,MessageCirclePlus:I9,MessageCircleQuestion:E9,MessageCircleReply:W9,MessageCircleWarning:x9,MessageCircleX:X9,MessageSquare:ln,MessageSquareCode:K9,MessageSquareDashed:J9,MessageSquareDiff:Q9,MessageSquareDot:j9,MessageSquareHeart:Y9,MessageSquareLock:_9,MessageSquareMore:an,MessageSquareOff:hn,MessageSquarePlus:tn,MessageSquareQuote:dn,MessageSquareReply:cn,MessageSquareShare:Mn,MessageSquareText:pn,MessageSquareWarning:en,MessageSquareX:nn,MessagesSquare:vn,Mic:sn,Mic2:t2,MicOff:on,MicVocal:t2,Microchip:rn,Microscope:gn,Microwave:yn,Milestone:$n,Milk:Cn,MilkOff:mn,Minimize:Hn,Minimize2:un,Minus:wn,MinusCircle:M1,MinusSquare:e0,Monitor:qn,MonitorCheck:Vn,MonitorCog:An,MonitorDot:Sn,MonitorDown:Ln,MonitorOff:fn,MonitorPause:Pn,MonitorPlay:kn,MonitorSmartphone:Bn,MonitorSpeaker:Fn,MonitorStop:Dn,MonitorUp:Rn,MonitorX:zn,Moon:Zn,MoonStar:Tn,MoreHorizontal:k1,MoreVertical:P1,Mountain:Un,MountainSnow:bn,Mouse:xn,MouseOff:On,MousePointer:Wn,MousePointer2:Gn,MousePointerBan:In,MousePointerClick:En,MousePointerSquareDashed:j2,Move:ci,Move3D:d2,Move3d:d2,MoveDiagonal:Nn,MoveDiagonal2:Xn,MoveDown:Qn,MoveDownLeft:Kn,MoveDownRight:Jn,MoveHorizontal:jn,MoveLeft:Yn,MoveRight:_n,MoveUp:ti,MoveUpLeft:ai,MoveUpRight:hi,MoveVertical:di,Music:ni,Music2:Mi,Music3:pi,Music4:ei,Navigation:oi,Navigation2:li,Navigation2Off:ii,NavigationOff:vi,Network:si,Newspaper:ri,Nfc:gi,Notebook:Ci,NotebookPen:yi,NotebookTabs:$i,NotebookText:mi,NotepadText:Hi,NotepadTextDashed:ui,Nut:Vi,NutOff:wi,Octagon:Si,OctagonAlert:c2,OctagonMinus:Ai,OctagonPause:M2,OctagonX:p2,Omega:Li,Option:fi,Orbit:Pi,Origami:ki,Outdent:J1,Package:Zi,Package2:Bi,PackageCheck:Fi,PackageMinus:Di,PackageOpen:Ri,PackagePlus:zi,PackageSearch:qi,PackageX:Ti,PaintBucket:bi,PaintRoller:Ui,Paintbrush:Oi,Paintbrush2:e2,PaintbrushVertical:e2,Palette:Gi,Palmtree:k0,PanelBottom:Wi,PanelBottomClose:Ii,PanelBottomDashed:n2,PanelBottomInactive:n2,PanelBottomOpen:Ei,PanelLeft:o2,PanelLeftClose:i2,PanelLeftDashed:l2,PanelLeftInactive:l2,PanelLeftOpen:v2,PanelRight:Ni,PanelRightClose:xi,PanelRightDashed:s2,PanelRightInactive:s2,PanelRightOpen:Xi,PanelTop:Qi,PanelTopClose:Ki,PanelTopDashed:r2,PanelTopInactive:r2,PanelTopOpen:Ji,PanelsLeftBottom:ji,PanelsLeftRight:A1,PanelsRightBottom:Yi,PanelsTopBottom:w2,PanelsTopLeft:g2,Paperclip:_i,Parentheses:al,ParkingCircle:e1,ParkingCircleOff:p1,ParkingMeter:hl,ParkingSquare:l0,ParkingSquareOff:i0,PartyPopper:tl,Pause:dl,PauseCircle:n1,PauseOctagon:M2,PawPrint:cl,PcCase:Ml,Pen:$2,PenBox:e,PenLine:y2,PenOff:pl,PenSquare:e,PenTool:el,Pencil:vl,PencilLine:nl,PencilOff:il,PencilRuler:ll,Pentagon:ol,Percent:sl,PercentCircle:i1,PercentDiamond:L1,PercentSquare:v0,PersonStanding:rl,PhilippinePeso:gl,Phone:wl,PhoneCall:yl,PhoneForwarded:$l,PhoneIncoming:ml,PhoneMissed:Cl,PhoneOff:ul,PhoneOutgoing:Hl,Pi:Vl,PiSquare:o0,Piano:Al,Pickaxe:Sl,PictureInPicture:fl,PictureInPicture2:Ll,PieChart:U,PiggyBank:Pl,Pilcrow:Fl,PilcrowLeft:kl,PilcrowRight:Bl,PilcrowSquare:s0,Pill:Rl,PillBottle:Dl,Pin:ql,PinOff:zl,Pipette:Tl,Pizza:Zl,Plane:Ol,PlaneLanding:bl,PlaneTakeoff:Ul,Play:Gl,PlayCircle:l1,PlaySquare:r0,Plug:El,Plug2:Il,PlugZap:m2,PlugZap2:m2,Plus:Wl,PlusCircle:v1,PlusSquare:g0,Pocket:Xl,PocketKnife:xl,Podcast:Nl,Pointer:Jl,PointerOff:Kl,Popcorn:Ql,Popsicle:jl,PoundSterling:Yl,Power:av,PowerCircle:o1,PowerOff:_l,PowerSquare:y0,Presentation:hv,Printer:dv,PrinterCheck:tv,Projector:cv,Proportions:Mv,Puzzle:pv,Pyramid:ev,QrCode:nv,Quote:iv,Rabbit:lv,Radar:vv,Radiation:ov,Radical:sv,Radio:yv,RadioReceiver:rv,RadioTower:gv,Radius:$v,RailSymbol:mv,Rainbow:Cv,Rat:uv,Ratio:Hv,Receipt:Bv,ReceiptCent:wv,ReceiptEuro:Vv,ReceiptIndianRupee:Av,ReceiptJapaneseYen:Sv,ReceiptPoundSterling:Lv,ReceiptRussianRuble:fv,ReceiptSwissFranc:Pv,ReceiptText:kv,RectangleEllipsis:C2,RectangleHorizontal:Fv,RectangleVertical:Dv,Recycle:Rv,Redo:Tv,Redo2:zv,RedoDot:qv,RefreshCcw:bv,RefreshCcwDot:Zv,RefreshCw:Ov,RefreshCwOff:Uv,Refrigerator:Gv,Regex:Iv,RemoveFormatting:Ev,Repeat:Xv,Repeat1:Wv,Repeat2:xv,Replace:Kv,ReplaceAll:Nv,Reply:Qv,ReplyAll:Jv,Rewind:jv,Ribbon:Yv,Rocket:_v,RockingChair:ao,RollerCoaster:ho,Rotate3D:u2,Rotate3d:u2,RotateCcw:co,RotateCcwSquare:to,RotateCw:po,RotateCwSquare:Mo,Route:no,RouteOff:eo,Router:io,Rows:H2,Rows2:H2,Rows3:w2,Rows4:lo,Rss:vo,Ruler:oo,RussianRuble:so,Sailboat:ro,Salad:go,Sandwich:yo,Satellite:mo,SatelliteDish:$o,Save:Ho,SaveAll:Co,SaveOff:uo,Scale:wo,Scale3D:V2,Scale3d:V2,Scaling:Vo,Scan:Do,ScanBarcode:Ao,ScanEye:So,ScanFace:Lo,ScanHeart:fo,ScanLine:Po,ScanQrCode:ko,ScanSearch:Bo,ScanText:Fo,ScatterChart:O,School:Ro,School2:D0,Scissors:qo,ScissorsLineDashed:zo,ScissorsSquare:$0,ScissorsSquareDashedBottom:I2,ScreenShare:Zo,ScreenShareOff:To,Scroll:Uo,ScrollText:bo,Search:Wo,SearchCheck:Oo,SearchCode:Go,SearchSlash:Io,SearchX:Eo,Section:xo,Send:No,SendHorizonal:A2,SendHorizontal:A2,SendToBack:Xo,SeparatorHorizontal:Ko,SeparatorVertical:Jo,Server:_o,ServerCog:Qo,ServerCrash:jo,ServerOff:Yo,Settings:hs,Settings2:as,Shapes:ts,Share:cs,Share2:ds,Sheet:Ms,Shell:ps,Shield:ys,ShieldAlert:es,ShieldBan:ns,ShieldCheck:is,ShieldClose:S2,ShieldEllipsis:ls,ShieldHalf:vs,ShieldMinus:os,ShieldOff:ss,ShieldPlus:rs,ShieldQuestion:gs,ShieldX:S2,Ship:ms,ShipWheel:$s,Shirt:Cs,ShoppingBag:us,ShoppingBasket:Hs,ShoppingCart:ws,Shovel:Vs,ShowerHead:As,Shrink:Ss,Shrub:Ls,Shuffle:fs,Sidebar:o2,SidebarClose:i2,SidebarOpen:v2,Sigma:Ps,SigmaSquare:m0,Signal:Rs,SignalHigh:ks,SignalLow:Bs,SignalMedium:Fs,SignalZero:Ds,Signature:zs,Signpost:Ts,SignpostBig:qs,Siren:Zs,SkipBack:bs,SkipForward:Us,Skull:Os,Slack:Gs,Slash:Is,SlashSquare:C0,Slice:Es,Sliders:L2,SlidersHorizontal:Ws,SlidersVertical:L2,Smartphone:Ns,SmartphoneCharging:xs,SmartphoneNfc:Xs,Smile:Js,SmilePlus:Ks,Snail:Qs,Snowflake:js,Sofa:Ys,SortAsc:C,SortDesc:y,Soup:_s,Space:ar,Spade:hr,Sparkle:tr,Sparkles:f2,Speaker:dr,Speech:cr,SpellCheck:pr,SpellCheck2:Mr,Spline:er,Split:nr,SplitSquareHorizontal:u0,SplitSquareVertical:H0,SprayCan:ir,Sprout:lr,Square:yr,SquareActivity:P2,SquareArrowDown:F2,SquareArrowDownLeft:k2,SquareArrowDownRight:B2,SquareArrowLeft:D2,SquareArrowOutDownLeft:R2,SquareArrowOutDownRight:z2,SquareArrowOutUpLeft:q2,SquareArrowOutUpRight:T2,SquareArrowRight:Z2,SquareArrowUp:O2,SquareArrowUpLeft:b2,SquareArrowUpRight:U2,SquareAsterisk:G2,SquareBottomDashedScissors:I2,SquareChartGantt:l,SquareCheck:W2,SquareCheckBig:E2,SquareChevronDown:x2,SquareChevronLeft:X2,SquareChevronRight:N2,SquareChevronUp:K2,SquareCode:J2,SquareDashed:Y2,SquareDashedBottom:or,SquareDashedBottomCode:vr,SquareDashedKanban:Q2,SquareDashedMousePointer:j2,SquareDivide:_2,SquareDot:a0,SquareEqual:h0,SquareFunction:t0,SquareGanttChart:l,SquareKanban:d0,SquareLibrary:c0,SquareM:M0,SquareMenu:p0,SquareMinus:e0,SquareMousePointer:n0,SquareParking:l0,SquareParkingOff:i0,SquarePen:e,SquarePercent:v0,SquarePi:o0,SquarePilcrow:s0,SquarePlay:r0,SquarePlus:g0,SquarePower:y0,SquareRadical:sr,SquareScissors:$0,SquareSigma:m0,SquareSlash:C0,SquareSplitHorizontal:u0,SquareSplitVertical:H0,SquareSquare:rr,SquareStack:gr,SquareTerminal:w0,SquareUser:A0,SquareUserRound:V0,SquareX:S0,Squircle:$r,Squirrel:mr,Stamp:Cr,Star:wr,StarHalf:ur,StarOff:Hr,Stars:f2,StepBack:Vr,StepForward:Ar,Stethoscope:Sr,Sticker:Lr,StickyNote:fr,StopCircle:r1,Store:Pr,StretchHorizontal:kr,StretchVertical:Br,Strikethrough:Fr,Subscript:Dr,Subtitles:f,Sun:Zr,SunDim:Rr,SunMedium:zr,SunMoon:qr,SunSnow:Tr,Sunrise:br,Sunset:Ur,Superscript:Or,SwatchBook:Gr,SwissFranc:Ir,SwitchCamera:Er,Sword:Wr,Swords:xr,Syringe:Xr,Table:ag,Table2:Nr,TableCellsMerge:Kr,TableCellsSplit:Jr,TableColumnsSplit:Qr,TableOfContents:jr,TableProperties:Yr,TableRowsSplit:_r,Tablet:tg,TabletSmartphone:hg,Tablets:dg,Tag:cg,Tags:Mg,Tally1:pg,Tally2:eg,Tally3:ng,Tally4:ig,Tally5:lg,Tangent:vg,Target:og,Telescope:sg,Tent:gg,TentTree:rg,Terminal:yg,TerminalSquare:w0,TestTube:$g,TestTube2:L0,TestTubeDiagonal:L0,TestTubes:mg,Text:Vg,TextCursor:ug,TextCursorInput:Cg,TextQuote:Hg,TextSearch:wg,TextSelect:f0,TextSelection:f0,Theater:Ag,Thermometer:fg,ThermometerSnowflake:Sg,ThermometerSun:Lg,ThumbsDown:Pg,ThumbsUp:kg,Ticket:Tg,TicketCheck:Bg,TicketMinus:Fg,TicketPercent:Dg,TicketPlus:Rg,TicketSlash:zg,TicketX:qg,Tickets:bg,TicketsPlane:Zg,Timer:Gg,TimerOff:Ug,TimerReset:Og,ToggleLeft:Ig,ToggleRight:Eg,Toilet:Wg,Tornado:xg,Torus:Xg,Touchpad:Kg,TouchpadOff:Ng,TowerControl:Jg,ToyBrick:Qg,Tractor:jg,TrafficCone:Yg,Train:P0,TrainFront:ay,TrainFrontTunnel:_g,TrainTrack:hy,TramFront:P0,Trash:dy,Trash2:ty,TreeDeciduous:cy,TreePalm:k0,TreePine:My,Trees:py,Trello:ey,TrendingDown:ny,TrendingUp:ly,TrendingUpDown:iy,Triangle:sy,TriangleAlert:B0,TriangleDashed:vy,TriangleRight:oy,Trophy:ry,Truck:gy,Turtle:yy,Tv:my,Tv2:F0,TvMinimal:F0,TvMinimalPlay:$y,Twitch:Cy,Twitter:uy,Type:wy,TypeOutline:Hy,Umbrella:Ay,UmbrellaOff:Vy,Underline:Sy,Undo:Py,Undo2:Ly,UndoDot:fy,UnfoldHorizontal:ky,UnfoldVertical:By,Ungroup:Fy,University:D0,Unlink:Ry,Unlink2:Dy,Unlock:h2,UnlockKeyhole:a2,Unplug:zy,Upload:qy,UploadCloud:H1,Usb:Ty,User:Xy,User2:b0,UserCheck:Zy,UserCheck2:R0,UserCircle:y1,UserCircle2:g1,UserCog:by,UserCog2:z0,UserMinus:Uy,UserMinus2:q0,UserPen:Oy,UserPlus:Gy,UserPlus2:T0,UserRound:b0,UserRoundCheck:R0,UserRoundCog:z0,UserRoundMinus:q0,UserRoundPen:Iy,UserRoundPlus:T0,UserRoundSearch:Ey,UserRoundX:Z0,UserSearch:Wy,UserSquare:A0,UserSquare2:V0,UserX:xy,UserX2:Z0,Users:Ny,Users2:U0,UsersRound:U0,Utensils:G0,UtensilsCrossed:O0,UtilityPole:Ky,Variable:Jy,Vault:Qy,Vegan:jy,VenetianMask:Yy,Verified:w,Vibrate:a$,VibrateOff:_y,Video:t$,VideoOff:h$,Videotape:d$,View:c$,Voicemail:M$,Volleyball:p$,Volume:v$,Volume1:e$,Volume2:n$,VolumeOff:i$,VolumeX:l$,Vote:o$,Wallet:r$,Wallet2:I0,WalletCards:s$,WalletMinimal:I0,Wallpaper:g$,Wand:y$,Wand2:E0,WandSparkles:E0,Warehouse:$$,WashingMachine:m$,Watch:C$,Waves:H$,WavesLadder:u$,Waypoints:w$,Webcam:V$,Webhook:S$,WebhookOff:A$,Weight:L$,Wheat:P$,WheatOff:f$,WholeWord:k$,Wifi:z$,WifiHigh:B$,WifiLow:F$,WifiOff:D$,WifiZero:R$,Wind:T$,WindArrowDown:q$,Wine:b$,WineOff:Z$,Workflow:U$,Worm:O$,WrapText:G$,Wrench:I$,X:E$,XCircle:$1,XOctagon:p2,XSquare:S0,Youtube:W$,Zap:X$,ZapOff:x$,ZoomIn:N$,ZoomOut:K$});const cm=({icons:t=J$,nameAttr:d="data-lucide",attrs:c={}}={})=>{if(!Object.values(t).length)throw new Error(`Please provide an icons object. -If you want to use all the icons you can import it like: - \`import { createIcons, icons } from 'lucide'; -lucide.createIcons({icons});\``);if(typeof document>"u")throw new Error("`createIcons()` only works in a browser environment.");const p=document.querySelectorAll(`[${d}]`);if(Array.from(p).forEach(M=>x0(M,{nameAttr:d,icons:t,attrs:c})),d==="data-lucide"){const M=document.querySelectorAll("[icon-name]");M.length>0&&(console.warn("[Lucide] Some icons were found with the now deprecated icon-name attribute. These will still be replaced for backwards compatibility, but will no longer be supported in v1.0 and you should switch to data-lucide"),Array.from(M).forEach(v=>x0(v,{nameAttr:"icon-name",icons:t,attrs:c})))}};a.AArrowDown=X0,a.AArrowUp=N0,a.ALargeSmall=K0,a.Accessibility=J0,a.Activity=Q0,a.ActivitySquare=P2,a.AirVent=j0,a.Airplay=Y0,a.AlarmCheck=o,a.AlarmClock=aa,a.AlarmClockCheck=o,a.AlarmClockMinus=s,a.AlarmClockOff=_0,a.AlarmClockPlus=r,a.AlarmMinus=s,a.AlarmPlus=r,a.AlarmSmoke=ha,a.Album=ta,a.AlertCircle=G,a.AlertOctagon=c2,a.AlertTriangle=B0,a.AlignCenter=Ma,a.AlignCenterHorizontal=da,a.AlignCenterVertical=ca,a.AlignEndHorizontal=pa,a.AlignEndVertical=ea,a.AlignHorizontalDistributeCenter=na,a.AlignHorizontalDistributeEnd=ia,a.AlignHorizontalDistributeStart=la,a.AlignHorizontalJustifyCenter=va,a.AlignHorizontalJustifyEnd=oa,a.AlignHorizontalJustifyStart=sa,a.AlignHorizontalSpaceAround=ra,a.AlignHorizontalSpaceBetween=ga,a.AlignJustify=ya,a.AlignLeft=$a,a.AlignRight=ma,a.AlignStartHorizontal=Ca,a.AlignStartVertical=ua,a.AlignVerticalDistributeCenter=Ha,a.AlignVerticalDistributeEnd=wa,a.AlignVerticalDistributeStart=Va,a.AlignVerticalJustifyCenter=Aa,a.AlignVerticalJustifyEnd=Sa,a.AlignVerticalJustifyStart=La,a.AlignVerticalSpaceAround=fa,a.AlignVerticalSpaceBetween=Pa,a.Ambulance=ka,a.Ampersand=Ba,a.Ampersands=Fa,a.Amphora=Da,a.Anchor=Ra,a.Angry=za,a.Annoyed=qa,a.Antenna=Ta,a.Anvil=Za,a.Aperture=ba,a.AppWindow=Oa,a.AppWindowMac=Ua,a.Apple=Ga,a.Archive=Wa,a.ArchiveRestore=Ia,a.ArchiveX=Ea,a.AreaChart=P,a.Armchair=xa,a.ArrowBigDown=Na,a.ArrowBigDownDash=Xa,a.ArrowBigLeft=Ja,a.ArrowBigLeftDash=Ka,a.ArrowBigRight=ja,a.ArrowBigRightDash=Qa,a.ArrowBigUp=_a,a.ArrowBigUpDash=Ya,a.ArrowDown=ih,a.ArrowDown01=ah,a.ArrowDown10=hh,a.ArrowDownAZ=g,a.ArrowDownAz=g,a.ArrowDownCircle=I,a.ArrowDownFromLine=th,a.ArrowDownLeft=dh,a.ArrowDownLeftFromCircle=W,a.ArrowDownLeftFromSquare=R2,a.ArrowDownLeftSquare=k2,a.ArrowDownNarrowWide=ch,a.ArrowDownRight=Mh,a.ArrowDownRightFromCircle=x,a.ArrowDownRightFromSquare=z2,a.ArrowDownRightSquare=B2,a.ArrowDownSquare=F2,a.ArrowDownToDot=ph,a.ArrowDownToLine=eh,a.ArrowDownUp=nh,a.ArrowDownWideNarrow=y,a.ArrowDownZA=$,a.ArrowDownZa=$,a.ArrowLeft=sh,a.ArrowLeftCircle=E,a.ArrowLeftFromLine=lh,a.ArrowLeftRight=vh,a.ArrowLeftSquare=D2,a.ArrowLeftToLine=oh,a.ArrowRight=$h,a.ArrowRightCircle=K,a.ArrowRightFromLine=rh,a.ArrowRightLeft=gh,a.ArrowRightSquare=Z2,a.ArrowRightToLine=yh,a.ArrowUp=fh,a.ArrowUp01=mh,a.ArrowUp10=Ch,a.ArrowUpAZ=m,a.ArrowUpAz=m,a.ArrowUpCircle=J,a.ArrowUpDown=uh,a.ArrowUpFromDot=Hh,a.ArrowUpFromLine=wh,a.ArrowUpLeft=Vh,a.ArrowUpLeftFromCircle=X,a.ArrowUpLeftFromSquare=q2,a.ArrowUpLeftSquare=b2,a.ArrowUpNarrowWide=C,a.ArrowUpRight=Ah,a.ArrowUpRightFromCircle=N,a.ArrowUpRightFromSquare=T2,a.ArrowUpRightSquare=U2,a.ArrowUpSquare=O2,a.ArrowUpToLine=Sh,a.ArrowUpWideNarrow=Lh,a.ArrowUpZA=u,a.ArrowUpZa=u,a.ArrowsUpFromLine=Ph,a.Asterisk=kh,a.AsteriskSquare=G2,a.AtSign=Bh,a.Atom=Fh,a.AudioLines=Dh,a.AudioWaveform=Rh,a.Award=zh,a.Axe=qh,a.Axis3D=H,a.Axis3d=H,a.Baby=Th,a.Backpack=Zh,a.Badge=_h,a.BadgeAlert=bh,a.BadgeCent=Uh,a.BadgeCheck=w,a.BadgeDollarSign=Oh,a.BadgeEuro=Gh,a.BadgeHelp=Ih,a.BadgeIndianRupee=Eh,a.BadgeInfo=Wh,a.BadgeJapaneseYen=xh,a.BadgeMinus=Xh,a.BadgePercent=Nh,a.BadgePlus=Kh,a.BadgePoundSterling=Jh,a.BadgeRussianRuble=Qh,a.BadgeSwissFranc=jh,a.BadgeX=Yh,a.BaggageClaim=at,a.Ban=ht,a.Banana=tt,a.Bandage=dt,a.Banknote=ct,a.BarChart=T,a.BarChart2=Z,a.BarChart3=z,a.BarChart4=R,a.BarChartBig=D,a.BarChartHorizontal=B,a.BarChartHorizontalBig=k,a.Barcode=Mt,a.Baseline=pt,a.Bath=et,a.Battery=rt,a.BatteryCharging=nt,a.BatteryFull=it,a.BatteryLow=lt,a.BatteryMedium=vt,a.BatteryPlus=ot,a.BatteryWarning=st,a.Beaker=gt,a.Bean=$t,a.BeanOff=yt,a.Bed=ut,a.BedDouble=mt,a.BedSingle=Ct,a.Beef=Ht,a.Beer=Vt,a.BeerOff=wt,a.Bell=Bt,a.BellDot=At,a.BellElectric=St,a.BellMinus=Lt,a.BellOff=ft,a.BellPlus=Pt,a.BellRing=kt,a.BetweenHorizonalEnd=V,a.BetweenHorizonalStart=A,a.BetweenHorizontalEnd=V,a.BetweenHorizontalStart=A,a.BetweenVerticalEnd=Ft,a.BetweenVerticalStart=Dt,a.BicepsFlexed=Rt,a.Bike=zt,a.Binary=qt,a.Binoculars=Tt,a.Biohazard=Zt,a.Bird=bt,a.Bitcoin=Ut,a.Blend=Ot,a.Blinds=Gt,a.Blocks=It,a.Bluetooth=Xt,a.BluetoothConnected=Et,a.BluetoothOff=Wt,a.BluetoothSearching=xt,a.Bold=Nt,a.Bolt=Kt,a.Bomb=Jt,a.Bone=Qt,a.Book=C4,a.BookA=jt,a.BookAudio=Yt,a.BookCheck=_t,a.BookCopy=a4,a.BookDashed=S,a.BookDown=h4,a.BookHeadphones=t4,a.BookHeart=d4,a.BookImage=c4,a.BookKey=M4,a.BookLock=p4,a.BookMarked=e4,a.BookMinus=n4,a.BookOpen=v4,a.BookOpenCheck=i4,a.BookOpenText=l4,a.BookPlus=o4,a.BookTemplate=S,a.BookText=s4,a.BookType=r4,a.BookUp=y4,a.BookUp2=g4,a.BookUser=$4,a.BookX=m4,a.Bookmark=A4,a.BookmarkCheck=u4,a.BookmarkMinus=H4,a.BookmarkPlus=w4,a.BookmarkX=V4,a.BoomBox=S4,a.Bot=P4,a.BotMessageSquare=L4,a.BotOff=f4,a.Box=k4,a.BoxSelect=Y2,a.Boxes=B4,a.Braces=L,a.Brackets=F4,a.Brain=z4,a.BrainCircuit=D4,a.BrainCog=R4,a.BrickWall=q4,a.Briefcase=U4,a.BriefcaseBusiness=T4,a.BriefcaseConveyorBelt=Z4,a.BriefcaseMedical=b4,a.BringToFront=O4,a.Brush=G4,a.Bug=W4,a.BugOff=I4,a.BugPlay=E4,a.Building=X4,a.Building2=x4,a.Bus=K4,a.BusFront=N4,a.Cable=Q4,a.CableCar=J4,a.Cake=Y4,a.CakeSlice=j4,a.Calculator=_4,a.Calendar=u5,a.Calendar1=a5,a.CalendarArrowDown=h5,a.CalendarArrowUp=t5,a.CalendarCheck=c5,a.CalendarCheck2=d5,a.CalendarClock=M5,a.CalendarCog=p5,a.CalendarDays=e5,a.CalendarFold=n5,a.CalendarHeart=i5,a.CalendarMinus=v5,a.CalendarMinus2=l5,a.CalendarOff=o5,a.CalendarPlus=r5,a.CalendarPlus2=s5,a.CalendarRange=g5,a.CalendarSearch=y5,a.CalendarSync=$5,a.CalendarX=C5,a.CalendarX2=m5,a.Camera=w5,a.CameraOff=H5,a.CandlestickChart=F,a.Candy=S5,a.CandyCane=V5,a.CandyOff=A5,a.Cannabis=L5,a.Captions=f,a.CaptionsOff=f5,a.Car=B5,a.CarFront=P5,a.CarTaxiFront=k5,a.Caravan=F5,a.Carrot=D5,a.CaseLower=R5,a.CaseSensitive=z5,a.CaseUpper=q5,a.CassetteTape=T5,a.Cast=Z5,a.Castle=b5,a.Cat=U5,a.Cctv=O5,a.ChartArea=P,a.ChartBar=B,a.ChartBarBig=k,a.ChartBarDecreasing=G5,a.ChartBarIncreasing=I5,a.ChartBarStacked=E5,a.ChartCandlestick=F,a.ChartColumn=z,a.ChartColumnBig=D,a.ChartColumnDecreasing=W5,a.ChartColumnIncreasing=R,a.ChartColumnStacked=x5,a.ChartGantt=X5,a.ChartLine=q,a.ChartNetwork=N5,a.ChartNoAxesColumn=Z,a.ChartNoAxesColumnDecreasing=K5,a.ChartNoAxesColumnIncreasing=T,a.ChartNoAxesCombined=J5,a.ChartNoAxesGantt=b,a.ChartPie=U,a.ChartScatter=O,a.ChartSpline=Q5,a.Check=Y5,a.CheckCheck=j5,a.CheckCircle=Q,a.CheckCircle2=j,a.CheckSquare=E2,a.CheckSquare2=W2,a.ChefHat=_5,a.Cherry=ad,a.ChevronDown=hd,a.ChevronDownCircle=Y,a.ChevronDownSquare=x2,a.ChevronFirst=td,a.ChevronLast=dd,a.ChevronLeft=cd,a.ChevronLeftCircle=_,a.ChevronLeftSquare=X2,a.ChevronRight=Md,a.ChevronRightCircle=a1,a.ChevronRightSquare=N2,a.ChevronUp=pd,a.ChevronUpCircle=h1,a.ChevronUpSquare=K2,a.ChevronsDown=nd,a.ChevronsDownUp=ed,a.ChevronsLeft=vd,a.ChevronsLeftRight=ld,a.ChevronsLeftRightEllipsis=id,a.ChevronsRight=sd,a.ChevronsRightLeft=od,a.ChevronsUp=gd,a.ChevronsUpDown=rd,a.Chrome=yd,a.Church=$d,a.Cigarette=Cd,a.CigaretteOff=md,a.Circle=Bd,a.CircleAlert=G,a.CircleArrowDown=I,a.CircleArrowLeft=E,a.CircleArrowOutDownLeft=W,a.CircleArrowOutDownRight=x,a.CircleArrowOutUpLeft=X,a.CircleArrowOutUpRight=N,a.CircleArrowRight=K,a.CircleArrowUp=J,a.CircleCheck=j,a.CircleCheckBig=Q,a.CircleChevronDown=Y,a.CircleChevronLeft=_,a.CircleChevronRight=a1,a.CircleChevronUp=h1,a.CircleDashed=ud,a.CircleDivide=t1,a.CircleDollarSign=Hd,a.CircleDot=Vd,a.CircleDotDashed=wd,a.CircleEllipsis=Ad,a.CircleEqual=Sd,a.CircleFadingArrowUp=Ld,a.CircleFadingPlus=fd,a.CircleGauge=d1,a.CircleHelp=c1,a.CircleMinus=M1,a.CircleOff=Pd,a.CircleParking=e1,a.CircleParkingOff=p1,a.CirclePause=n1,a.CirclePercent=i1,a.CirclePlay=l1,a.CirclePlus=v1,a.CirclePower=o1,a.CircleSlash=kd,a.CircleSlash2=s1,a.CircleSlashed=s1,a.CircleStop=r1,a.CircleUser=y1,a.CircleUserRound=g1,a.CircleX=$1,a.CircuitBoard=Fd,a.Citrus=Dd,a.Clapperboard=Rd,a.Clipboard=Id,a.ClipboardCheck=zd,a.ClipboardCopy=qd,a.ClipboardEdit=C1,a.ClipboardList=Td,a.ClipboardMinus=Zd,a.ClipboardPaste=bd,a.ClipboardPen=C1,a.ClipboardPenLine=m1,a.ClipboardPlus=Ud,a.ClipboardSignature=m1,a.ClipboardType=Od,a.ClipboardX=Gd,a.Clock=c3,a.Clock1=Ed,a.Clock10=Wd,a.Clock11=xd,a.Clock12=Xd,a.Clock2=Nd,a.Clock3=Kd,a.Clock4=Jd,a.Clock5=Qd,a.Clock6=jd,a.Clock7=Yd,a.Clock8=_d,a.Clock9=a3,a.ClockAlert=h3,a.ClockArrowDown=t3,a.ClockArrowUp=d3,a.Cloud=C3,a.CloudAlert=M3,a.CloudCog=p3,a.CloudDownload=u1,a.CloudDrizzle=e3,a.CloudFog=n3,a.CloudHail=i3,a.CloudLightning=l3,a.CloudMoon=o3,a.CloudMoonRain=v3,a.CloudOff=s3,a.CloudRain=g3,a.CloudRainWind=r3,a.CloudSnow=y3,a.CloudSun=m3,a.CloudSunRain=$3,a.CloudUpload=H1,a.Cloudy=u3,a.Clover=H3,a.Club=w3,a.Code=V3,a.Code2=w1,a.CodeSquare=J2,a.CodeXml=w1,a.Codepen=A3,a.Codesandbox=S3,a.Coffee=L3,a.Cog=f3,a.Coins=P3,a.Columns=V1,a.Columns2=V1,a.Columns3=A1,a.Columns4=k3,a.Combine=B3,a.Command=F3,a.Compass=D3,a.Component=R3,a.Computer=z3,a.ConciergeBell=q3,a.Cone=T3,a.Construction=Z3,a.Contact=b3,a.Contact2=S1,a.ContactRound=S1,a.Container=U3,a.Contrast=O3,a.Cookie=G3,a.CookingPot=I3,a.Copy=K3,a.CopyCheck=E3,a.CopyMinus=W3,a.CopyPlus=x3,a.CopySlash=X3,a.CopyX=N3,a.Copyleft=J3,a.Copyright=Q3,a.CornerDownLeft=j3,a.CornerDownRight=Y3,a.CornerLeftDown=_3,a.CornerLeftUp=a6,a.CornerRightDown=h6,a.CornerRightUp=t6,a.CornerUpLeft=d6,a.CornerUpRight=c6,a.Cpu=M6,a.CreativeCommons=p6,a.CreditCard=e6,a.Croissant=n6,a.Crop=i6,a.Cross=l6,a.Crosshair=v6,a.Crown=o6,a.Cuboid=s6,a.CupSoda=r6,a.CurlyBraces=L,a.Currency=g6,a.Cylinder=y6,a.Dam=$6,a.Database=u6,a.DatabaseBackup=m6,a.DatabaseZap=C6,a.Delete=H6,a.Dessert=w6,a.Diameter=V6,a.Diamond=L6,a.DiamondMinus=A6,a.DiamondPercent=L1,a.DiamondPlus=S6,a.Dice1=f6,a.Dice2=P6,a.Dice3=k6,a.Dice4=B6,a.Dice5=F6,a.Dice6=D6,a.Dices=R6,a.Diff=z6,a.Disc=b6,a.Disc2=q6,a.Disc3=T6,a.DiscAlbum=Z6,a.Divide=U6,a.DivideCircle=t1,a.DivideSquare=_2,a.Dna=G6,a.DnaOff=O6,a.Dock=I6,a.Dog=E6,a.DollarSign=W6,a.Donut=x6,a.DoorClosed=X6,a.DoorOpen=N6,a.Dot=K6,a.DotSquare=a0,a.Download=J6,a.DownloadCloud=u1,a.DraftingCompass=Q6,a.Drama=j6,a.Dribbble=Y6,a.Drill=_6,a.Droplet=hc,a.DropletOff=ac,a.Droplets=tc,a.Drum=dc,a.Drumstick=cc,a.Dumbbell=Mc,a.Ear=ec,a.EarOff=pc,a.Earth=f1,a.EarthLock=nc,a.Eclipse=ic,a.Edit=e,a.Edit2=$2,a.Edit3=y2,a.Egg=oc,a.EggFried=lc,a.EggOff=vc,a.Ellipsis=k1,a.EllipsisVertical=P1,a.Equal=gc,a.EqualApproximately=sc,a.EqualNot=rc,a.EqualSquare=h0,a.Eraser=yc,a.EthernetPort=$c,a.Euro=mc,a.Expand=Cc,a.ExternalLink=uc,a.Eye=Vc,a.EyeClosed=Hc,a.EyeOff=wc,a.Facebook=Ac,a.Factory=Sc,a.Fan=Lc,a.FastForward=fc,a.Feather=Pc,a.Fence=kc,a.FerrisWheel=Bc,a.Figma=Fc,a.File=P8,a.FileArchive=Dc,a.FileAudio=zc,a.FileAudio2=Rc,a.FileAxis3D=B1,a.FileAxis3d=B1,a.FileBadge=Tc,a.FileBadge2=qc,a.FileBarChart=F1,a.FileBarChart2=D1,a.FileBox=Zc,a.FileChartColumn=D1,a.FileChartColumnIncreasing=F1,a.FileChartLine=R1,a.FileChartPie=z1,a.FileCheck=Uc,a.FileCheck2=bc,a.FileClock=Oc,a.FileCode=Ic,a.FileCode2=Gc,a.FileCog=q1,a.FileCog2=q1,a.FileDiff=Ec,a.FileDigit=Wc,a.FileDown=xc,a.FileEdit=Z1,a.FileHeart=Xc,a.FileImage=Nc,a.FileInput=Kc,a.FileJson=Qc,a.FileJson2=Jc,a.FileKey=Yc,a.FileKey2=jc,a.FileLineChart=R1,a.FileLock=a8,a.FileLock2=_c,a.FileMinus=t8,a.FileMinus2=h8,a.FileMusic=d8,a.FileOutput=c8,a.FilePen=Z1,a.FilePenLine=T1,a.FilePieChart=z1,a.FilePlus=p8,a.FilePlus2=M8,a.FileQuestion=e8,a.FileScan=n8,a.FileSearch=l8,a.FileSearch2=i8,a.FileSignature=T1,a.FileSliders=v8,a.FileSpreadsheet=o8,a.FileStack=s8,a.FileSymlink=r8,a.FileTerminal=g8,a.FileText=y8,a.FileType=m8,a.FileType2=$8,a.FileUp=C8,a.FileUser=u8,a.FileVideo=w8,a.FileVideo2=H8,a.FileVolume=A8,a.FileVolume2=V8,a.FileWarning=S8,a.FileX=f8,a.FileX2=L8,a.Files=k8,a.Film=B8,a.Filter=D8,a.FilterX=F8,a.Fingerprint=R8,a.FireExtinguisher=z8,a.Fish=Z8,a.FishOff=q8,a.FishSymbol=T8,a.Flag=G8,a.FlagOff=b8,a.FlagTriangleLeft=U8,a.FlagTriangleRight=O8,a.Flame=E8,a.FlameKindling=I8,a.Flashlight=x8,a.FlashlightOff=W8,a.FlaskConical=N8,a.FlaskConicalOff=X8,a.FlaskRound=K8,a.FlipHorizontal=Q8,a.FlipHorizontal2=J8,a.FlipVertical=Y8,a.FlipVertical2=j8,a.Flower=a7,a.Flower2=_8,a.Focus=h7,a.FoldHorizontal=t7,a.FoldVertical=d7,a.Folder=F7,a.FolderArchive=c7,a.FolderCheck=M7,a.FolderClock=p7,a.FolderClosed=e7,a.FolderCode=n7,a.FolderCog=b1,a.FolderCog2=b1,a.FolderDot=i7,a.FolderDown=l7,a.FolderEdit=U1,a.FolderGit=o7,a.FolderGit2=v7,a.FolderHeart=s7,a.FolderInput=r7,a.FolderKanban=g7,a.FolderKey=y7,a.FolderLock=$7,a.FolderMinus=m7,a.FolderOpen=u7,a.FolderOpenDot=C7,a.FolderOutput=H7,a.FolderPen=U1,a.FolderPlus=w7,a.FolderRoot=V7,a.FolderSearch=S7,a.FolderSearch2=A7,a.FolderSymlink=L7,a.FolderSync=f7,a.FolderTree=P7,a.FolderUp=k7,a.FolderX=B7,a.Folders=D7,a.Footprints=R7,a.ForkKnife=G0,a.ForkKnifeCrossed=O0,a.Forklift=z7,a.FormInput=C2,a.Forward=q7,a.Frame=T7,a.Framer=Z7,a.Frown=b7,a.Fuel=U7,a.Fullscreen=O7,a.FunctionSquare=t0,a.GalleryHorizontal=I7,a.GalleryHorizontalEnd=G7,a.GalleryThumbnails=E7,a.GalleryVertical=x7,a.GalleryVerticalEnd=W7,a.Gamepad=N7,a.Gamepad2=X7,a.GanttChart=b,a.GanttChartSquare=l,a.Gauge=K7,a.GaugeCircle=d1,a.Gavel=J7,a.Gem=Q7,a.Ghost=j7,a.Gift=Y7,a.GitBranch=aM,a.GitBranchPlus=_7,a.GitCommit=O1,a.GitCommitHorizontal=O1,a.GitCommitVertical=hM,a.GitCompare=dM,a.GitCompareArrows=tM,a.GitFork=cM,a.GitGraph=MM,a.GitMerge=pM,a.GitPullRequest=oM,a.GitPullRequestArrow=eM,a.GitPullRequestClosed=nM,a.GitPullRequestCreate=lM,a.GitPullRequestCreateArrow=iM,a.GitPullRequestDraft=vM,a.Github=sM,a.Gitlab=rM,a.GlassWater=gM,a.Glasses=yM,a.Globe=mM,a.Globe2=f1,a.GlobeLock=$M,a.Goal=CM,a.Grab=uM,a.GraduationCap=HM,a.Grape=wM,a.Grid=i,a.Grid2X2=W1,a.Grid2X2Check=G1,a.Grid2X2Plus=I1,a.Grid2X2X=E1,a.Grid2x2=W1,a.Grid2x2Check=G1,a.Grid2x2Plus=I1,a.Grid2x2X=E1,a.Grid3X3=i,a.Grid3x3=i,a.Grip=SM,a.GripHorizontal=VM,a.GripVertical=AM,a.Group=LM,a.Guitar=fM,a.Ham=PM,a.Hammer=kM,a.Hand=zM,a.HandCoins=BM,a.HandHeart=FM,a.HandHelping=x1,a.HandMetal=DM,a.HandPlatter=RM,a.Handshake=qM,a.HardDrive=bM,a.HardDriveDownload=TM,a.HardDriveUpload=ZM,a.HardHat=UM,a.Hash=OM,a.Haze=GM,a.HdmiPort=IM,a.Heading=JM,a.Heading1=EM,a.Heading2=WM,a.Heading3=xM,a.Heading4=XM,a.Heading5=NM,a.Heading6=KM,a.HeadphoneOff=QM,a.Headphones=jM,a.Headset=YM,a.Heart=dp,a.HeartCrack=_M,a.HeartHandshake=ap,a.HeartOff=hp,a.HeartPulse=tp,a.Heater=cp,a.HelpCircle=c1,a.HelpingHand=x1,a.Hexagon=Mp,a.Highlighter=pp,a.History=ep,a.Home=X1,a.Hop=ip,a.HopOff=np,a.Hospital=lp,a.Hotel=vp,a.Hourglass=op,a.House=X1,a.HousePlug=sp,a.HousePlus=rp,a.HouseWifi=gp,a.IceCream=K1,a.IceCream2=N1,a.IceCreamBowl=N1,a.IceCreamCone=K1,a.IdCard=yp,a.Image=Ap,a.ImageDown=$p,a.ImageMinus=mp,a.ImageOff=Cp,a.ImagePlay=up,a.ImagePlus=Hp,a.ImageUp=wp,a.ImageUpscale=Vp,a.Images=Sp,a.Import=Lp,a.Inbox=fp,a.Indent=Q1,a.IndentDecrease=J1,a.IndentIncrease=Q1,a.IndianRupee=Pp,a.Infinity=kp,a.Info=Bp,a.Inspect=n0,a.InspectionPanel=Fp,a.Instagram=Dp,a.Italic=Rp,a.IterationCcw=zp,a.IterationCw=qp,a.JapaneseYen=Tp,a.Joystick=Zp,a.Kanban=bp,a.KanbanSquare=d0,a.KanbanSquareDashed=Q2,a.Key=Gp,a.KeyRound=Up,a.KeySquare=Op,a.Keyboard=Wp,a.KeyboardMusic=Ip,a.KeyboardOff=Ep,a.Lamp=Qp,a.LampCeiling=xp,a.LampDesk=Xp,a.LampFloor=Np,a.LampWallDown=Kp,a.LampWallUp=Jp,a.LandPlot=jp,a.Landmark=Yp,a.Languages=_p,a.Laptop=he,a.Laptop2=j1,a.LaptopMinimal=j1,a.LaptopMinimalCheck=ae,a.Lasso=de,a.LassoSelect=te,a.Laugh=ce,a.Layers=Y1,a.Layers2=Me,a.Layers3=Y1,a.Layout=g2,a.LayoutDashboard=pe,a.LayoutGrid=ee,a.LayoutList=ne,a.LayoutPanelLeft=ie,a.LayoutPanelTop=le,a.LayoutTemplate=ve,a.Leaf=oe,a.LeafyGreen=se,a.Lectern=re,a.LetterText=ge,a.Library=$e,a.LibraryBig=ye,a.LibrarySquare=c0,a.LifeBuoy=me,a.Ligature=Ce,a.Lightbulb=He,a.LightbulbOff=ue,a.LineChart=q,a.Link=Ae,a.Link2=Ve,a.Link2Off=we,a.Linkedin=Se,a.List=Ie,a.ListCheck=Le,a.ListChecks=fe,a.ListCollapse=Pe,a.ListEnd=ke,a.ListFilter=Fe,a.ListFilterPlus=Be,a.ListMinus=De,a.ListMusic=Re,a.ListOrdered=ze,a.ListPlus=qe,a.ListRestart=Te,a.ListStart=Ze,a.ListTodo=be,a.ListTree=Ue,a.ListVideo=Oe,a.ListX=Ge,a.Loader=We,a.Loader2=_1,a.LoaderCircle=_1,a.LoaderPinwheel=Ee,a.Locate=Ne,a.LocateFixed=xe,a.LocateOff=Xe,a.Lock=Je,a.LockKeyhole=Ke,a.LockKeyholeOpen=a2,a.LockOpen=h2,a.LogIn=Qe,a.LogOut=je,a.Logs=Ye,a.Lollipop=_e,a.Luggage=a9,a.MSquare=M0,a.Magnet=h9,a.Mail=l9,a.MailCheck=t9,a.MailMinus=d9,a.MailOpen=c9,a.MailPlus=M9,a.MailQuestion=p9,a.MailSearch=e9,a.MailWarning=n9,a.MailX=i9,a.Mailbox=v9,a.Mails=o9,a.Map=L9,a.MapPin=V9,a.MapPinCheck=r9,a.MapPinCheckInside=s9,a.MapPinHouse=g9,a.MapPinMinus=$9,a.MapPinMinusInside=y9,a.MapPinOff=m9,a.MapPinPlus=u9,a.MapPinPlusInside=C9,a.MapPinX=w9,a.MapPinXInside=H9,a.MapPinned=A9,a.MapPlus=S9,a.Martini=f9,a.Maximize=k9,a.Maximize2=P9,a.Medal=B9,a.Megaphone=D9,a.MegaphoneOff=F9,a.Meh=R9,a.MemoryStick=z9,a.Menu=q9,a.MenuSquare=p0,a.Merge=T9,a.MessageCircle=N9,a.MessageCircleCode=Z9,a.MessageCircleDashed=b9,a.MessageCircleHeart=U9,a.MessageCircleMore=O9,a.MessageCircleOff=G9,a.MessageCirclePlus=I9,a.MessageCircleQuestion=E9,a.MessageCircleReply=W9,a.MessageCircleWarning=x9,a.MessageCircleX=X9,a.MessageSquare=ln,a.MessageSquareCode=K9,a.MessageSquareDashed=J9,a.MessageSquareDiff=Q9,a.MessageSquareDot=j9,a.MessageSquareHeart=Y9,a.MessageSquareLock=_9,a.MessageSquareMore=an,a.MessageSquareOff=hn,a.MessageSquarePlus=tn,a.MessageSquareQuote=dn,a.MessageSquareReply=cn,a.MessageSquareShare=Mn,a.MessageSquareText=pn,a.MessageSquareWarning=en,a.MessageSquareX=nn,a.MessagesSquare=vn,a.Mic=sn,a.Mic2=t2,a.MicOff=on,a.MicVocal=t2,a.Microchip=rn,a.Microscope=gn,a.Microwave=yn,a.Milestone=$n,a.Milk=Cn,a.MilkOff=mn,a.Minimize=Hn,a.Minimize2=un,a.Minus=wn,a.MinusCircle=M1,a.MinusSquare=e0,a.Monitor=qn,a.MonitorCheck=Vn,a.MonitorCog=An,a.MonitorDot=Sn,a.MonitorDown=Ln,a.MonitorOff=fn,a.MonitorPause=Pn,a.MonitorPlay=kn,a.MonitorSmartphone=Bn,a.MonitorSpeaker=Fn,a.MonitorStop=Dn,a.MonitorUp=Rn,a.MonitorX=zn,a.Moon=Zn,a.MoonStar=Tn,a.MoreHorizontal=k1,a.MoreVertical=P1,a.Mountain=Un,a.MountainSnow=bn,a.Mouse=xn,a.MouseOff=On,a.MousePointer=Wn,a.MousePointer2=Gn,a.MousePointerBan=In,a.MousePointerClick=En,a.MousePointerSquareDashed=j2,a.Move=ci,a.Move3D=d2,a.Move3d=d2,a.MoveDiagonal=Nn,a.MoveDiagonal2=Xn,a.MoveDown=Qn,a.MoveDownLeft=Kn,a.MoveDownRight=Jn,a.MoveHorizontal=jn,a.MoveLeft=Yn,a.MoveRight=_n,a.MoveUp=ti,a.MoveUpLeft=ai,a.MoveUpRight=hi,a.MoveVertical=di,a.Music=ni,a.Music2=Mi,a.Music3=pi,a.Music4=ei,a.Navigation=oi,a.Navigation2=li,a.Navigation2Off=ii,a.NavigationOff=vi,a.Network=si,a.Newspaper=ri,a.Nfc=gi,a.Notebook=Ci,a.NotebookPen=yi,a.NotebookTabs=$i,a.NotebookText=mi,a.NotepadText=Hi,a.NotepadTextDashed=ui,a.Nut=Vi,a.NutOff=wi,a.Octagon=Si,a.OctagonAlert=c2,a.OctagonMinus=Ai,a.OctagonPause=M2,a.OctagonX=p2,a.Omega=Li,a.Option=fi,a.Orbit=Pi,a.Origami=ki,a.Outdent=J1,a.Package=Zi,a.Package2=Bi,a.PackageCheck=Fi,a.PackageMinus=Di,a.PackageOpen=Ri,a.PackagePlus=zi,a.PackageSearch=qi,a.PackageX=Ti,a.PaintBucket=bi,a.PaintRoller=Ui,a.Paintbrush=Oi,a.Paintbrush2=e2,a.PaintbrushVertical=e2,a.Palette=Gi,a.Palmtree=k0,a.PanelBottom=Wi,a.PanelBottomClose=Ii,a.PanelBottomDashed=n2,a.PanelBottomInactive=n2,a.PanelBottomOpen=Ei,a.PanelLeft=o2,a.PanelLeftClose=i2,a.PanelLeftDashed=l2,a.PanelLeftInactive=l2,a.PanelLeftOpen=v2,a.PanelRight=Ni,a.PanelRightClose=xi,a.PanelRightDashed=s2,a.PanelRightInactive=s2,a.PanelRightOpen=Xi,a.PanelTop=Qi,a.PanelTopClose=Ki,a.PanelTopDashed=r2,a.PanelTopInactive=r2,a.PanelTopOpen=Ji,a.PanelsLeftBottom=ji,a.PanelsLeftRight=A1,a.PanelsRightBottom=Yi,a.PanelsTopBottom=w2,a.PanelsTopLeft=g2,a.Paperclip=_i,a.Parentheses=al,a.ParkingCircle=e1,a.ParkingCircleOff=p1,a.ParkingMeter=hl,a.ParkingSquare=l0,a.ParkingSquareOff=i0,a.PartyPopper=tl,a.Pause=dl,a.PauseCircle=n1,a.PauseOctagon=M2,a.PawPrint=cl,a.PcCase=Ml,a.Pen=$2,a.PenBox=e,a.PenLine=y2,a.PenOff=pl,a.PenSquare=e,a.PenTool=el,a.Pencil=vl,a.PencilLine=nl,a.PencilOff=il,a.PencilRuler=ll,a.Pentagon=ol,a.Percent=sl,a.PercentCircle=i1,a.PercentDiamond=L1,a.PercentSquare=v0,a.PersonStanding=rl,a.PhilippinePeso=gl,a.Phone=wl,a.PhoneCall=yl,a.PhoneForwarded=$l,a.PhoneIncoming=ml,a.PhoneMissed=Cl,a.PhoneOff=ul,a.PhoneOutgoing=Hl,a.Pi=Vl,a.PiSquare=o0,a.Piano=Al,a.Pickaxe=Sl,a.PictureInPicture=fl,a.PictureInPicture2=Ll,a.PieChart=U,a.PiggyBank=Pl,a.Pilcrow=Fl,a.PilcrowLeft=kl,a.PilcrowRight=Bl,a.PilcrowSquare=s0,a.Pill=Rl,a.PillBottle=Dl,a.Pin=ql,a.PinOff=zl,a.Pipette=Tl,a.Pizza=Zl,a.Plane=Ol,a.PlaneLanding=bl,a.PlaneTakeoff=Ul,a.Play=Gl,a.PlayCircle=l1,a.PlaySquare=r0,a.Plug=El,a.Plug2=Il,a.PlugZap=m2,a.PlugZap2=m2,a.Plus=Wl,a.PlusCircle=v1,a.PlusSquare=g0,a.Pocket=Xl,a.PocketKnife=xl,a.Podcast=Nl,a.Pointer=Jl,a.PointerOff=Kl,a.Popcorn=Ql,a.Popsicle=jl,a.PoundSterling=Yl,a.Power=av,a.PowerCircle=o1,a.PowerOff=_l,a.PowerSquare=y0,a.Presentation=hv,a.Printer=dv,a.PrinterCheck=tv,a.Projector=cv,a.Proportions=Mv,a.Puzzle=pv,a.Pyramid=ev,a.QrCode=nv,a.Quote=iv,a.Rabbit=lv,a.Radar=vv,a.Radiation=ov,a.Radical=sv,a.Radio=yv,a.RadioReceiver=rv,a.RadioTower=gv,a.Radius=$v,a.RailSymbol=mv,a.Rainbow=Cv,a.Rat=uv,a.Ratio=Hv,a.Receipt=Bv,a.ReceiptCent=wv,a.ReceiptEuro=Vv,a.ReceiptIndianRupee=Av,a.ReceiptJapaneseYen=Sv,a.ReceiptPoundSterling=Lv,a.ReceiptRussianRuble=fv,a.ReceiptSwissFranc=Pv,a.ReceiptText=kv,a.RectangleEllipsis=C2,a.RectangleHorizontal=Fv,a.RectangleVertical=Dv,a.Recycle=Rv,a.Redo=Tv,a.Redo2=zv,a.RedoDot=qv,a.RefreshCcw=bv,a.RefreshCcwDot=Zv,a.RefreshCw=Ov,a.RefreshCwOff=Uv,a.Refrigerator=Gv,a.Regex=Iv,a.RemoveFormatting=Ev,a.Repeat=Xv,a.Repeat1=Wv,a.Repeat2=xv,a.Replace=Kv,a.ReplaceAll=Nv,a.Reply=Qv,a.ReplyAll=Jv,a.Rewind=jv,a.Ribbon=Yv,a.Rocket=_v,a.RockingChair=ao,a.RollerCoaster=ho,a.Rotate3D=u2,a.Rotate3d=u2,a.RotateCcw=co,a.RotateCcwSquare=to,a.RotateCw=po,a.RotateCwSquare=Mo,a.Route=no,a.RouteOff=eo,a.Router=io,a.Rows=H2,a.Rows2=H2,a.Rows3=w2,a.Rows4=lo,a.Rss=vo,a.Ruler=oo,a.RussianRuble=so,a.Sailboat=ro,a.Salad=go,a.Sandwich=yo,a.Satellite=mo,a.SatelliteDish=$o,a.Save=Ho,a.SaveAll=Co,a.SaveOff=uo,a.Scale=wo,a.Scale3D=V2,a.Scale3d=V2,a.Scaling=Vo,a.Scan=Do,a.ScanBarcode=Ao,a.ScanEye=So,a.ScanFace=Lo,a.ScanHeart=fo,a.ScanLine=Po,a.ScanQrCode=ko,a.ScanSearch=Bo,a.ScanText=Fo,a.ScatterChart=O,a.School=Ro,a.School2=D0,a.Scissors=qo,a.ScissorsLineDashed=zo,a.ScissorsSquare=$0,a.ScissorsSquareDashedBottom=I2,a.ScreenShare=Zo,a.ScreenShareOff=To,a.Scroll=Uo,a.ScrollText=bo,a.Search=Wo,a.SearchCheck=Oo,a.SearchCode=Go,a.SearchSlash=Io,a.SearchX=Eo,a.Section=xo,a.Send=No,a.SendHorizonal=A2,a.SendHorizontal=A2,a.SendToBack=Xo,a.SeparatorHorizontal=Ko,a.SeparatorVertical=Jo,a.Server=_o,a.ServerCog=Qo,a.ServerCrash=jo,a.ServerOff=Yo,a.Settings=hs,a.Settings2=as,a.Shapes=ts,a.Share=cs,a.Share2=ds,a.Sheet=Ms,a.Shell=ps,a.Shield=ys,a.ShieldAlert=es,a.ShieldBan=ns,a.ShieldCheck=is,a.ShieldClose=S2,a.ShieldEllipsis=ls,a.ShieldHalf=vs,a.ShieldMinus=os,a.ShieldOff=ss,a.ShieldPlus=rs,a.ShieldQuestion=gs,a.ShieldX=S2,a.Ship=ms,a.ShipWheel=$s,a.Shirt=Cs,a.ShoppingBag=us,a.ShoppingBasket=Hs,a.ShoppingCart=ws,a.Shovel=Vs,a.ShowerHead=As,a.Shrink=Ss,a.Shrub=Ls,a.Shuffle=fs,a.Sidebar=o2,a.SidebarClose=i2,a.SidebarOpen=v2,a.Sigma=Ps,a.SigmaSquare=m0,a.Signal=Rs,a.SignalHigh=ks,a.SignalLow=Bs,a.SignalMedium=Fs,a.SignalZero=Ds,a.Signature=zs,a.Signpost=Ts,a.SignpostBig=qs,a.Siren=Zs,a.SkipBack=bs,a.SkipForward=Us,a.Skull=Os,a.Slack=Gs,a.Slash=Is,a.SlashSquare=C0,a.Slice=Es,a.Sliders=L2,a.SlidersHorizontal=Ws,a.SlidersVertical=L2,a.Smartphone=Ns,a.SmartphoneCharging=xs,a.SmartphoneNfc=Xs,a.Smile=Js,a.SmilePlus=Ks,a.Snail=Qs,a.Snowflake=js,a.Sofa=Ys,a.SortAsc=C,a.SortDesc=y,a.Soup=_s,a.Space=ar,a.Spade=hr,a.Sparkle=tr,a.Sparkles=f2,a.Speaker=dr,a.Speech=cr,a.SpellCheck=pr,a.SpellCheck2=Mr,a.Spline=er,a.Split=nr,a.SplitSquareHorizontal=u0,a.SplitSquareVertical=H0,a.SprayCan=ir,a.Sprout=lr,a.Square=yr,a.SquareActivity=P2,a.SquareArrowDown=F2,a.SquareArrowDownLeft=k2,a.SquareArrowDownRight=B2,a.SquareArrowLeft=D2,a.SquareArrowOutDownLeft=R2,a.SquareArrowOutDownRight=z2,a.SquareArrowOutUpLeft=q2,a.SquareArrowOutUpRight=T2,a.SquareArrowRight=Z2,a.SquareArrowUp=O2,a.SquareArrowUpLeft=b2,a.SquareArrowUpRight=U2,a.SquareAsterisk=G2,a.SquareBottomDashedScissors=I2,a.SquareChartGantt=l,a.SquareCheck=W2,a.SquareCheckBig=E2,a.SquareChevronDown=x2,a.SquareChevronLeft=X2,a.SquareChevronRight=N2,a.SquareChevronUp=K2,a.SquareCode=J2,a.SquareDashed=Y2,a.SquareDashedBottom=or,a.SquareDashedBottomCode=vr,a.SquareDashedKanban=Q2,a.SquareDashedMousePointer=j2,a.SquareDivide=_2,a.SquareDot=a0,a.SquareEqual=h0,a.SquareFunction=t0,a.SquareGanttChart=l,a.SquareKanban=d0,a.SquareLibrary=c0,a.SquareM=M0,a.SquareMenu=p0,a.SquareMinus=e0,a.SquareMousePointer=n0,a.SquareParking=l0,a.SquareParkingOff=i0,a.SquarePen=e,a.SquarePercent=v0,a.SquarePi=o0,a.SquarePilcrow=s0,a.SquarePlay=r0,a.SquarePlus=g0,a.SquarePower=y0,a.SquareRadical=sr,a.SquareScissors=$0,a.SquareSigma=m0,a.SquareSlash=C0,a.SquareSplitHorizontal=u0,a.SquareSplitVertical=H0,a.SquareSquare=rr,a.SquareStack=gr,a.SquareTerminal=w0,a.SquareUser=A0,a.SquareUserRound=V0,a.SquareX=S0,a.Squircle=$r,a.Squirrel=mr,a.Stamp=Cr,a.Star=wr,a.StarHalf=ur,a.StarOff=Hr,a.Stars=f2,a.StepBack=Vr,a.StepForward=Ar,a.Stethoscope=Sr,a.Sticker=Lr,a.StickyNote=fr,a.StopCircle=r1,a.Store=Pr,a.StretchHorizontal=kr,a.StretchVertical=Br,a.Strikethrough=Fr,a.Subscript=Dr,a.Subtitles=f,a.Sun=Zr,a.SunDim=Rr,a.SunMedium=zr,a.SunMoon=qr,a.SunSnow=Tr,a.Sunrise=br,a.Sunset=Ur,a.Superscript=Or,a.SwatchBook=Gr,a.SwissFranc=Ir,a.SwitchCamera=Er,a.Sword=Wr,a.Swords=xr,a.Syringe=Xr,a.Table=ag,a.Table2=Nr,a.TableCellsMerge=Kr,a.TableCellsSplit=Jr,a.TableColumnsSplit=Qr,a.TableOfContents=jr,a.TableProperties=Yr,a.TableRowsSplit=_r,a.Tablet=tg,a.TabletSmartphone=hg,a.Tablets=dg,a.Tag=cg,a.Tags=Mg,a.Tally1=pg,a.Tally2=eg,a.Tally3=ng,a.Tally4=ig,a.Tally5=lg,a.Tangent=vg,a.Target=og,a.Telescope=sg,a.Tent=gg,a.TentTree=rg,a.Terminal=yg,a.TerminalSquare=w0,a.TestTube=$g,a.TestTube2=L0,a.TestTubeDiagonal=L0,a.TestTubes=mg,a.Text=Vg,a.TextCursor=ug,a.TextCursorInput=Cg,a.TextQuote=Hg,a.TextSearch=wg,a.TextSelect=f0,a.TextSelection=f0,a.Theater=Ag,a.Thermometer=fg,a.ThermometerSnowflake=Sg,a.ThermometerSun=Lg,a.ThumbsDown=Pg,a.ThumbsUp=kg,a.Ticket=Tg,a.TicketCheck=Bg,a.TicketMinus=Fg,a.TicketPercent=Dg,a.TicketPlus=Rg,a.TicketSlash=zg,a.TicketX=qg,a.Tickets=bg,a.TicketsPlane=Zg,a.Timer=Gg,a.TimerOff=Ug,a.TimerReset=Og,a.ToggleLeft=Ig,a.ToggleRight=Eg,a.Toilet=Wg,a.Tornado=xg,a.Torus=Xg,a.Touchpad=Kg,a.TouchpadOff=Ng,a.TowerControl=Jg,a.ToyBrick=Qg,a.Tractor=jg,a.TrafficCone=Yg,a.Train=P0,a.TrainFront=ay,a.TrainFrontTunnel=_g,a.TrainTrack=hy,a.TramFront=P0,a.Trash=dy,a.Trash2=ty,a.TreeDeciduous=cy,a.TreePalm=k0,a.TreePine=My,a.Trees=py,a.Trello=ey,a.TrendingDown=ny,a.TrendingUp=ly,a.TrendingUpDown=iy,a.Triangle=sy,a.TriangleAlert=B0,a.TriangleDashed=vy,a.TriangleRight=oy,a.Trophy=ry,a.Truck=gy,a.Turtle=yy,a.Tv=my,a.Tv2=F0,a.TvMinimal=F0,a.TvMinimalPlay=$y,a.Twitch=Cy,a.Twitter=uy,a.Type=wy,a.TypeOutline=Hy,a.Umbrella=Ay,a.UmbrellaOff=Vy,a.Underline=Sy,a.Undo=Py,a.Undo2=Ly,a.UndoDot=fy,a.UnfoldHorizontal=ky,a.UnfoldVertical=By,a.Ungroup=Fy,a.University=D0,a.Unlink=Ry,a.Unlink2=Dy,a.Unlock=h2,a.UnlockKeyhole=a2,a.Unplug=zy,a.Upload=qy,a.UploadCloud=H1,a.Usb=Ty,a.User=Xy,a.User2=b0,a.UserCheck=Zy,a.UserCheck2=R0,a.UserCircle=y1,a.UserCircle2=g1,a.UserCog=by,a.UserCog2=z0,a.UserMinus=Uy,a.UserMinus2=q0,a.UserPen=Oy,a.UserPlus=Gy,a.UserPlus2=T0,a.UserRound=b0,a.UserRoundCheck=R0,a.UserRoundCog=z0,a.UserRoundMinus=q0,a.UserRoundPen=Iy,a.UserRoundPlus=T0,a.UserRoundSearch=Ey,a.UserRoundX=Z0,a.UserSearch=Wy,a.UserSquare=A0,a.UserSquare2=V0,a.UserX=xy,a.UserX2=Z0,a.Users=Ny,a.Users2=U0,a.UsersRound=U0,a.Utensils=G0,a.UtensilsCrossed=O0,a.UtilityPole=Ky,a.Variable=Jy,a.Vault=Qy,a.Vegan=jy,a.VenetianMask=Yy,a.Verified=w,a.Vibrate=a$,a.VibrateOff=_y,a.Video=t$,a.VideoOff=h$,a.Videotape=d$,a.View=c$,a.Voicemail=M$,a.Volleyball=p$,a.Volume=v$,a.Volume1=e$,a.Volume2=n$,a.VolumeOff=i$,a.VolumeX=l$,a.Vote=o$,a.Wallet=r$,a.Wallet2=I0,a.WalletCards=s$,a.WalletMinimal=I0,a.Wallpaper=g$,a.Wand=y$,a.Wand2=E0,a.WandSparkles=E0,a.Warehouse=$$,a.WashingMachine=m$,a.Watch=C$,a.Waves=H$,a.WavesLadder=u$,a.Waypoints=w$,a.Webcam=V$,a.Webhook=S$,a.WebhookOff=A$,a.Weight=L$,a.Wheat=P$,a.WheatOff=f$,a.WholeWord=k$,a.Wifi=z$,a.WifiHigh=B$,a.WifiLow=F$,a.WifiOff=D$,a.WifiZero=R$,a.Wind=T$,a.WindArrowDown=q$,a.Wine=b$,a.WineOff=Z$,a.Workflow=U$,a.Worm=O$,a.WrapText=G$,a.Wrench=I$,a.X=E$,a.XCircle=$1,a.XOctagon=p2,a.XSquare=S0,a.Youtube=W$,a.Zap=X$,a.ZapOff=x$,a.ZoomIn=N$,a.ZoomOut=K$,a.createElement=W0,a.createIcons=cm,a.icons=J$}); -//# sourceMappingURL=lucide.min.js.map diff --git a/test.html b/test.html deleted file mode 100644 index b7652f7..0000000 --- a/test.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - -
-
Header
-
-
Click me
-
Another
-
-
- - - diff --git a/test_output.txt b/test_output.txt deleted file mode 100644 index 44b2780..0000000 --- a/test_output.txt +++ /dev/null @@ -1,5 +0,0 @@ - -> chattz-electron@0.1.0 start -> electron . - -Loading desktop app from: file:///home/pavel/chattz/desktop/index.html?backend=https%3A%2F%2Fdiscord.flegr.me